js/src/jsapi.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jsapi.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,6451 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +/*
    1.11 + * JavaScript API.
    1.12 + */
    1.13 +
    1.14 +#include "jsapi.h"
    1.15 +
    1.16 +#include "mozilla/FloatingPoint.h"
    1.17 +#include "mozilla/PodOperations.h"
    1.18 +
    1.19 +#include <ctype.h>
    1.20 +#include <stdarg.h>
    1.21 +#include <string.h>
    1.22 +#include <sys/stat.h>
    1.23 +
    1.24 +#include "jsarray.h"
    1.25 +#include "jsatom.h"
    1.26 +#include "jsbool.h"
    1.27 +#include "jscntxt.h"
    1.28 +#include "jsdate.h"
    1.29 +#include "jsexn.h"
    1.30 +#include "jsfun.h"
    1.31 +#include "jsgc.h"
    1.32 +#include "jsiter.h"
    1.33 +#include "jslock.h"
    1.34 +#include "jsmath.h"
    1.35 +#include "jsnum.h"
    1.36 +#include "jsobj.h"
    1.37 +#include "json.h"
    1.38 +#include "jsprf.h"
    1.39 +#include "jsproxy.h"
    1.40 +#include "jsscript.h"
    1.41 +#include "jsstr.h"
    1.42 +#include "jstypes.h"
    1.43 +#include "jsutil.h"
    1.44 +#include "jswatchpoint.h"
    1.45 +#include "jsweakmap.h"
    1.46 +#ifdef JS_THREADSAFE
    1.47 +#include "jsworkers.h"
    1.48 +#endif
    1.49 +#include "jswrapper.h"
    1.50 +#include "prmjtime.h"
    1.51 +
    1.52 +#if ENABLE_YARR_JIT
    1.53 +#include "assembler/jit/ExecutableAllocator.h"
    1.54 +#endif
    1.55 +#include "builtin/Eval.h"
    1.56 +#include "builtin/Intl.h"
    1.57 +#include "builtin/MapObject.h"
    1.58 +#include "builtin/RegExp.h"
    1.59 +#ifdef ENABLE_BINARYDATA
    1.60 +#include "builtin/SIMD.h"
    1.61 +#include "builtin/TypedObject.h"
    1.62 +#endif
    1.63 +#include "frontend/BytecodeCompiler.h"
    1.64 +#include "frontend/FullParseHandler.h"  // for JS_BufferIsCompileableUnit
    1.65 +#include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
    1.66 +#include "gc/Marking.h"
    1.67 +#include "jit/AsmJSLink.h"
    1.68 +#include "jit/JitCommon.h"
    1.69 +#include "js/CharacterEncoding.h"
    1.70 +#include "js/SliceBudget.h"
    1.71 +#include "js/StructuredClone.h"
    1.72 +#if ENABLE_INTL_API
    1.73 +#include "unicode/uclean.h"
    1.74 +#include "unicode/utypes.h"
    1.75 +#endif // ENABLE_INTL_API
    1.76 +#include "vm/DateObject.h"
    1.77 +#include "vm/Debugger.h"
    1.78 +#include "vm/ErrorObject.h"
    1.79 +#include "vm/Interpreter.h"
    1.80 +#include "vm/NumericConversions.h"
    1.81 +#include "vm/RegExpStatics.h"
    1.82 +#include "vm/Runtime.h"
    1.83 +#include "vm/Shape.h"
    1.84 +#include "vm/SharedArrayObject.h"
    1.85 +#include "vm/StopIterationObject.h"
    1.86 +#include "vm/StringBuffer.h"
    1.87 +#include "vm/TypedArrayObject.h"
    1.88 +#include "vm/WeakMapObject.h"
    1.89 +#include "vm/WrapperObject.h"
    1.90 +#include "vm/Xdr.h"
    1.91 +#include "yarr/BumpPointerAllocator.h"
    1.92 +
    1.93 +#include "jsatominlines.h"
    1.94 +#include "jsfuninlines.h"
    1.95 +#include "jsinferinlines.h"
    1.96 +#include "jsscriptinlines.h"
    1.97 +
    1.98 +#include "vm/Interpreter-inl.h"
    1.99 +#include "vm/ObjectImpl-inl.h"
   1.100 +#include "vm/String-inl.h"
   1.101 +
   1.102 +using namespace js;
   1.103 +using namespace js::gc;
   1.104 +using namespace js::types;
   1.105 +
   1.106 +using mozilla::Maybe;
   1.107 +using mozilla::PodCopy;
   1.108 +using mozilla::PodZero;
   1.109 +
   1.110 +using js::frontend::Parser;
   1.111 +
   1.112 +#ifdef HAVE_VA_LIST_AS_ARRAY
   1.113 +#define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
   1.114 +#else
   1.115 +#define JS_ADDRESSOF_VA_LIST(ap) (&(ap))
   1.116 +#endif
   1.117 +
   1.118 +/* Make sure that jschar is two bytes unsigned integer */
   1.119 +JS_STATIC_ASSERT((jschar)-1 > 0);
   1.120 +JS_STATIC_ASSERT(sizeof(jschar) == 2);
   1.121 +
   1.122 +JS_PUBLIC_API(int64_t)
   1.123 +JS_Now()
   1.124 +{
   1.125 +    return PRMJ_Now();
   1.126 +}
   1.127 +
   1.128 +JS_PUBLIC_API(jsval)
   1.129 +JS_GetNaNValue(JSContext *cx)
   1.130 +{
   1.131 +    return cx->runtime()->NaNValue;
   1.132 +}
   1.133 +
   1.134 +JS_PUBLIC_API(jsval)
   1.135 +JS_GetNegativeInfinityValue(JSContext *cx)
   1.136 +{
   1.137 +    return cx->runtime()->negativeInfinityValue;
   1.138 +}
   1.139 +
   1.140 +JS_PUBLIC_API(jsval)
   1.141 +JS_GetPositiveInfinityValue(JSContext *cx)
   1.142 +{
   1.143 +    return cx->runtime()->positiveInfinityValue;
   1.144 +}
   1.145 +
   1.146 +JS_PUBLIC_API(jsval)
   1.147 +JS_GetEmptyStringValue(JSContext *cx)
   1.148 +{
   1.149 +    return STRING_TO_JSVAL(cx->runtime()->emptyString);
   1.150 +}
   1.151 +
   1.152 +JS_PUBLIC_API(JSString *)
   1.153 +JS_GetEmptyString(JSRuntime *rt)
   1.154 +{
   1.155 +    JS_ASSERT(rt->hasContexts());
   1.156 +    return rt->emptyString;
   1.157 +}
   1.158 +
   1.159 +namespace js {
   1.160 +
   1.161 +void
   1.162 +AssertHeapIsIdle(JSRuntime *rt)
   1.163 +{
   1.164 +    JS_ASSERT(rt->heapState == js::Idle);
   1.165 +}
   1.166 +
   1.167 +void
   1.168 +AssertHeapIsIdle(JSContext *cx)
   1.169 +{
   1.170 +    AssertHeapIsIdle(cx->runtime());
   1.171 +}
   1.172 +
   1.173 +}
   1.174 +
   1.175 +static void
   1.176 +AssertHeapIsIdleOrIterating(JSRuntime *rt)
   1.177 +{
   1.178 +    JS_ASSERT(!rt->isHeapCollecting());
   1.179 +}
   1.180 +
   1.181 +static void
   1.182 +AssertHeapIsIdleOrIterating(JSContext *cx)
   1.183 +{
   1.184 +    AssertHeapIsIdleOrIterating(cx->runtime());
   1.185 +}
   1.186 +
   1.187 +static void
   1.188 +AssertHeapIsIdleOrStringIsFlat(JSContext *cx, JSString *str)
   1.189 +{
   1.190 +    /*
   1.191 +     * We allow some functions to be called during a GC as long as the argument
   1.192 +     * is a flat string, since that will not cause allocation.
   1.193 +     */
   1.194 +    JS_ASSERT_IF(cx->runtime()->isHeapBusy(), str->isFlat());
   1.195 +}
   1.196 +
   1.197 +JS_PUBLIC_API(bool)
   1.198 +JS_ConvertArguments(JSContext *cx, const CallArgs &args, const char *format, ...)
   1.199 +{
   1.200 +    va_list ap;
   1.201 +    bool ok;
   1.202 +
   1.203 +    AssertHeapIsIdle(cx);
   1.204 +
   1.205 +    va_start(ap, format);
   1.206 +    ok = JS_ConvertArgumentsVA(cx, args, format, ap);
   1.207 +    va_end(ap);
   1.208 +    return ok;
   1.209 +}
   1.210 +
   1.211 +JS_PUBLIC_API(bool)
   1.212 +JS_ConvertArgumentsVA(JSContext *cx, const CallArgs &args, const char *format, va_list ap)
   1.213 +{
   1.214 +    unsigned index = 0;
   1.215 +    bool required;
   1.216 +    char c;
   1.217 +    double d;
   1.218 +    JSString *str;
   1.219 +    RootedObject obj(cx);
   1.220 +    RootedValue val(cx);
   1.221 +
   1.222 +    AssertHeapIsIdle(cx);
   1.223 +    CHECK_REQUEST(cx);
   1.224 +    assertSameCompartment(cx, args);
   1.225 +    required = true;
   1.226 +    while ((c = *format++) != '\0') {
   1.227 +        if (isspace(c))
   1.228 +            continue;
   1.229 +        if (c == '/') {
   1.230 +            required = false;
   1.231 +            continue;
   1.232 +        }
   1.233 +        if (index == args.length()) {
   1.234 +            if (required) {
   1.235 +                if (JSFunction *fun = ReportIfNotFunction(cx, args.calleev())) {
   1.236 +                    char numBuf[12];
   1.237 +                    JS_snprintf(numBuf, sizeof numBuf, "%u", args.length());
   1.238 +                    JSAutoByteString funNameBytes;
   1.239 +                    if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
   1.240 +                        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
   1.241 +                                             JSMSG_MORE_ARGS_NEEDED,
   1.242 +                                             name, numBuf, (args.length() == 1) ? "" : "s");
   1.243 +                    }
   1.244 +                }
   1.245 +                return false;
   1.246 +            }
   1.247 +            break;
   1.248 +        }
   1.249 +        MutableHandleValue arg = args[index++];
   1.250 +        switch (c) {
   1.251 +          case 'b':
   1.252 +            *va_arg(ap, bool *) = ToBoolean(arg);
   1.253 +            break;
   1.254 +          case 'c':
   1.255 +            if (!ToUint16(cx, arg, va_arg(ap, uint16_t *)))
   1.256 +                return false;
   1.257 +            break;
   1.258 +          case 'i':
   1.259 +          case 'j': // "j" was broken, you should not use it.
   1.260 +            if (!ToInt32(cx, arg, va_arg(ap, int32_t *)))
   1.261 +                return false;
   1.262 +            break;
   1.263 +          case 'u':
   1.264 +            if (!ToUint32(cx, arg, va_arg(ap, uint32_t *)))
   1.265 +                return false;
   1.266 +            break;
   1.267 +          case 'd':
   1.268 +            if (!ToNumber(cx, arg, va_arg(ap, double *)))
   1.269 +                return false;
   1.270 +            break;
   1.271 +          case 'I':
   1.272 +            if (!ToNumber(cx, arg, &d))
   1.273 +                return false;
   1.274 +            *va_arg(ap, double *) = ToInteger(d);
   1.275 +            break;
   1.276 +          case 'S':
   1.277 +          case 'W':
   1.278 +            str = ToString<CanGC>(cx, arg);
   1.279 +            if (!str)
   1.280 +                return false;
   1.281 +            arg.setString(str);
   1.282 +            if (c == 'W') {
   1.283 +                JSFlatString *flat = str->ensureFlat(cx);
   1.284 +                if (!flat)
   1.285 +                    return false;
   1.286 +                *va_arg(ap, const jschar **) = flat->chars();
   1.287 +            } else {
   1.288 +                *va_arg(ap, JSString **) = str;
   1.289 +            }
   1.290 +            break;
   1.291 +          case 'o':
   1.292 +            if (arg.isNullOrUndefined()) {
   1.293 +                obj = nullptr;
   1.294 +            } else {
   1.295 +                obj = ToObject(cx, arg);
   1.296 +                if (!obj)
   1.297 +                    return false;
   1.298 +            }
   1.299 +            arg.setObjectOrNull(obj);
   1.300 +            *va_arg(ap, JSObject **) = obj;
   1.301 +            break;
   1.302 +          case 'f':
   1.303 +            obj = ReportIfNotFunction(cx, arg);
   1.304 +            if (!obj)
   1.305 +                return false;
   1.306 +            arg.setObject(*obj);
   1.307 +            *va_arg(ap, JSFunction **) = &obj->as<JSFunction>();
   1.308 +            break;
   1.309 +          case 'v':
   1.310 +            *va_arg(ap, jsval *) = arg;
   1.311 +            break;
   1.312 +          case '*':
   1.313 +            break;
   1.314 +          default:
   1.315 +            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_CHAR, format);
   1.316 +            return false;
   1.317 +        }
   1.318 +    }
   1.319 +    return true;
   1.320 +}
   1.321 +
   1.322 +JS_PUBLIC_API(bool)
   1.323 +JS_ConvertValue(JSContext *cx, HandleValue value, JSType type, MutableHandleValue vp)
   1.324 +{
   1.325 +    bool ok;
   1.326 +    RootedObject obj(cx);
   1.327 +    JSString *str;
   1.328 +    double d;
   1.329 +
   1.330 +    AssertHeapIsIdle(cx);
   1.331 +    CHECK_REQUEST(cx);
   1.332 +    assertSameCompartment(cx, value);
   1.333 +    switch (type) {
   1.334 +      case JSTYPE_VOID:
   1.335 +        vp.setUndefined();
   1.336 +        ok = true;
   1.337 +        break;
   1.338 +      case JSTYPE_OBJECT:
   1.339 +        if (value.isNullOrUndefined()) {
   1.340 +            obj.set(nullptr);
   1.341 +        } else {
   1.342 +            obj = ToObject(cx, value);
   1.343 +            if (!obj)
   1.344 +                return false;
   1.345 +        }
   1.346 +        ok = true;
   1.347 +        break;
   1.348 +      case JSTYPE_FUNCTION:
   1.349 +        vp.set(value);
   1.350 +        obj = ReportIfNotFunction(cx, vp);
   1.351 +        ok = (obj != nullptr);
   1.352 +        break;
   1.353 +      case JSTYPE_STRING:
   1.354 +        str = ToString<CanGC>(cx, value);
   1.355 +        ok = (str != nullptr);
   1.356 +        if (ok)
   1.357 +            vp.setString(str);
   1.358 +        break;
   1.359 +      case JSTYPE_NUMBER:
   1.360 +        ok = ToNumber(cx, value, &d);
   1.361 +        if (ok)
   1.362 +            vp.setDouble(d);
   1.363 +        break;
   1.364 +      case JSTYPE_BOOLEAN:
   1.365 +        vp.setBoolean(ToBoolean(value));
   1.366 +        return true;
   1.367 +      default: {
   1.368 +        char numBuf[12];
   1.369 +        JS_snprintf(numBuf, sizeof numBuf, "%d", (int)type);
   1.370 +        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_TYPE, numBuf);
   1.371 +        ok = false;
   1.372 +        break;
   1.373 +      }
   1.374 +    }
   1.375 +    return ok;
   1.376 +}
   1.377 +
   1.378 +JS_PUBLIC_API(bool)
   1.379 +JS_ValueToObject(JSContext *cx, HandleValue value, MutableHandleObject objp)
   1.380 +{
   1.381 +    AssertHeapIsIdle(cx);
   1.382 +    CHECK_REQUEST(cx);
   1.383 +    assertSameCompartment(cx, value);
   1.384 +    if (value.isNullOrUndefined()) {
   1.385 +        objp.set(nullptr);
   1.386 +        return true;
   1.387 +    }
   1.388 +    JSObject *obj = ToObject(cx, value);
   1.389 +    if (!obj)
   1.390 +        return false;
   1.391 +    objp.set(obj);
   1.392 +    return true;
   1.393 +}
   1.394 +
   1.395 +JS_PUBLIC_API(JSFunction *)
   1.396 +JS_ValueToFunction(JSContext *cx, HandleValue value)
   1.397 +{
   1.398 +    AssertHeapIsIdle(cx);
   1.399 +    CHECK_REQUEST(cx);
   1.400 +    assertSameCompartment(cx, value);
   1.401 +    return ReportIfNotFunction(cx, value);
   1.402 +}
   1.403 +
   1.404 +JS_PUBLIC_API(JSFunction *)
   1.405 +JS_ValueToConstructor(JSContext *cx, HandleValue value)
   1.406 +{
   1.407 +    AssertHeapIsIdle(cx);
   1.408 +    CHECK_REQUEST(cx);
   1.409 +    assertSameCompartment(cx, value);
   1.410 +    return ReportIfNotFunction(cx, value);
   1.411 +}
   1.412 +
   1.413 +JS_PUBLIC_API(JSString *)
   1.414 +JS_ValueToSource(JSContext *cx, HandleValue value)
   1.415 +{
   1.416 +    AssertHeapIsIdle(cx);
   1.417 +    CHECK_REQUEST(cx);
   1.418 +    assertSameCompartment(cx, value);
   1.419 +    return ValueToSource(cx, value);
   1.420 +}
   1.421 +
   1.422 +JS_PUBLIC_API(bool)
   1.423 +JS_DoubleIsInt32(double d, int32_t *ip)
   1.424 +{
   1.425 +    return mozilla::NumberIsInt32(d, ip);
   1.426 +}
   1.427 +
   1.428 +JS_PUBLIC_API(int32_t)
   1.429 +JS_DoubleToInt32(double d)
   1.430 +{
   1.431 +    return ToInt32(d);
   1.432 +}
   1.433 +
   1.434 +JS_PUBLIC_API(uint32_t)
   1.435 +JS_DoubleToUint32(double d)
   1.436 +{
   1.437 +    return ToUint32(d);
   1.438 +}
   1.439 +
   1.440 +JS_PUBLIC_API(JSType)
   1.441 +JS_TypeOfValue(JSContext *cx, HandleValue value)
   1.442 +{
   1.443 +    AssertHeapIsIdle(cx);
   1.444 +    CHECK_REQUEST(cx);
   1.445 +    assertSameCompartment(cx, value);
   1.446 +    return TypeOfValue(value);
   1.447 +}
   1.448 +
   1.449 +JS_PUBLIC_API(const char *)
   1.450 +JS_GetTypeName(JSContext *cx, JSType type)
   1.451 +{
   1.452 +    if ((unsigned)type >= (unsigned)JSTYPE_LIMIT)
   1.453 +        return nullptr;
   1.454 +    return TypeStrings[type];
   1.455 +}
   1.456 +
   1.457 +JS_PUBLIC_API(bool)
   1.458 +JS_StrictlyEqual(JSContext *cx, jsval value1, jsval value2, bool *equal)
   1.459 +{
   1.460 +    AssertHeapIsIdle(cx);
   1.461 +    CHECK_REQUEST(cx);
   1.462 +    assertSameCompartment(cx, value1, value2);
   1.463 +    bool eq;
   1.464 +    if (!StrictlyEqual(cx, value1, value2, &eq))
   1.465 +        return false;
   1.466 +    *equal = eq;
   1.467 +    return true;
   1.468 +}
   1.469 +
   1.470 +JS_PUBLIC_API(bool)
   1.471 +JS_LooselyEqual(JSContext *cx, HandleValue value1, HandleValue value2, bool *equal)
   1.472 +{
   1.473 +    AssertHeapIsIdle(cx);
   1.474 +    CHECK_REQUEST(cx);
   1.475 +    assertSameCompartment(cx, value1, value2);
   1.476 +    JS_ASSERT(equal);
   1.477 +    return LooselyEqual(cx, value1, value2, equal);
   1.478 +}
   1.479 +
   1.480 +JS_PUBLIC_API(bool)
   1.481 +JS_SameValue(JSContext *cx, jsval value1, jsval value2, bool *same)
   1.482 +{
   1.483 +    AssertHeapIsIdle(cx);
   1.484 +    CHECK_REQUEST(cx);
   1.485 +    assertSameCompartment(cx, value1, value2);
   1.486 +    bool s;
   1.487 +    if (!SameValue(cx, value1, value2, &s))
   1.488 +        return false;
   1.489 +    *same = s;
   1.490 +    return true;
   1.491 +}
   1.492 +
   1.493 +JS_PUBLIC_API(bool)
   1.494 +JS_IsBuiltinEvalFunction(JSFunction *fun)
   1.495 +{
   1.496 +    return IsAnyBuiltinEval(fun);
   1.497 +}
   1.498 +
   1.499 +JS_PUBLIC_API(bool)
   1.500 +JS_IsBuiltinFunctionConstructor(JSFunction *fun)
   1.501 +{
   1.502 +    return fun->isBuiltinFunctionConstructor();
   1.503 +}
   1.504 +
   1.505 +/************************************************************************/
   1.506 +
   1.507 +/*
   1.508 + * SpiderMonkey's initialization status is tracked here, and it controls things
   1.509 + * that should happen only once across all runtimes.  It's an API requirement
   1.510 + * that JS_Init (and JS_ShutDown, if called) be called in a thread-aware
   1.511 + * manner, so this variable doesn't need to be atomic.
   1.512 + *
   1.513 + * The only reason at present for the restriction that you can't call
   1.514 + * JS_Init/stuff/JS_ShutDown multiple times is the Windows PRMJ NowInit
   1.515 + * initialization code, which uses PR_CallOnce to initialize the PRMJ_Now
   1.516 + * subsystem.  (For reinitialization to be permitted, we'd need to "reset" the
   1.517 + * called-once status -- doable, but more trouble than it's worth now.)
   1.518 + * Initializing that subsystem from JS_Init eliminates the problem, but
   1.519 + * initialization can take a comparatively long time (15ms or so), so we
   1.520 + * really don't want to do it in JS_Init, and we really do want to do it only
   1.521 + * when PRMJ_Now is eventually called.
   1.522 + */
   1.523 +enum InitState { Uninitialized, Running, ShutDown };
   1.524 +static InitState jsInitState = Uninitialized;
   1.525 +
   1.526 +#ifdef DEBUG
   1.527 +static void
   1.528 +CheckMessageNumbering()
   1.529 +{
   1.530 +    // Assert that the numbers associated with the error names in js.msg are
   1.531 +    // monotonically increasing.  It's not a compile-time check, but it's
   1.532 +    // better than nothing.
   1.533 +    int errorNumber = 0;
   1.534 +# define MSG_DEF(name, number, count, exception, format)                      \
   1.535 +    JS_ASSERT(name == errorNumber++);
   1.536 +# include "js.msg"
   1.537 +# undef MSG_DEF
   1.538 +}
   1.539 +
   1.540 +static unsigned
   1.541 +MessageParameterCount(const char *format)
   1.542 +{
   1.543 +    unsigned numfmtspecs = 0;
   1.544 +    for (const char *fmt = format; *fmt != '\0'; fmt++) {
   1.545 +        if (*fmt == '{' && isdigit(fmt[1]))
   1.546 +            ++numfmtspecs;
   1.547 +    }
   1.548 +    return numfmtspecs;
   1.549 +}
   1.550 +
   1.551 +static void
   1.552 +CheckMessageParameterCounts()
   1.553 +{
   1.554 +    // Assert that each message format has the correct number of braced
   1.555 +    // parameters.
   1.556 +# define MSG_DEF(name, number, count, exception, format)                      \
   1.557 +    JS_BEGIN_MACRO                                                            \
   1.558 +        JS_ASSERT(MessageParameterCount(format) == count);                    \
   1.559 +    JS_END_MACRO;
   1.560 +# include "js.msg"
   1.561 +# undef MSG_DEF
   1.562 +}
   1.563 +#endif /* DEBUG */
   1.564 +
   1.565 +JS_PUBLIC_API(bool)
   1.566 +JS_Init(void)
   1.567 +{
   1.568 +    MOZ_ASSERT(jsInitState == Uninitialized,
   1.569 +               "must call JS_Init once before any JSAPI operation except "
   1.570 +               "JS_SetICUMemoryFunctions");
   1.571 +    MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(),
   1.572 +               "how do we have live runtimes before JS_Init?");
   1.573 +
   1.574 +#ifdef DEBUG
   1.575 +    CheckMessageNumbering();
   1.576 +    CheckMessageParameterCounts();
   1.577 +#endif
   1.578 +
   1.579 +    using js::TlsPerThreadData;
   1.580 +    if (!TlsPerThreadData.initialized() && !TlsPerThreadData.init())
   1.581 +        return false;
   1.582 +
   1.583 +#if defined(JS_ION)
   1.584 +    if (!jit::InitializeIon())
   1.585 +        return false;
   1.586 +#endif
   1.587 +
   1.588 +    if (!ForkJoinContext::initialize())
   1.589 +        return false;
   1.590 +
   1.591 +#if EXPOSE_INTL_API
   1.592 +    UErrorCode err = U_ZERO_ERROR;
   1.593 +    u_init(&err);
   1.594 +    if (U_FAILURE(err))
   1.595 +        return false;
   1.596 +#endif // EXPOSE_INTL_API
   1.597 +
   1.598 +    jsInitState = Running;
   1.599 +    return true;
   1.600 +}
   1.601 +
   1.602 +JS_PUBLIC_API(void)
   1.603 +JS_ShutDown(void)
   1.604 +{
   1.605 +    MOZ_ASSERT(jsInitState == Running,
   1.606 +               "JS_ShutDown must only be called after JS_Init and can't race with it");
   1.607 +#ifdef DEBUG
   1.608 +    if (JSRuntime::hasLiveRuntimes()) {
   1.609 +        // Gecko is too buggy to assert this just yet.
   1.610 +        fprintf(stderr,
   1.611 +                "WARNING: YOU ARE LEAKING THE WORLD (at least one JSRuntime "
   1.612 +                "and everything alive inside it, that is) AT JS_ShutDown "
   1.613 +                "TIME.  FIX THIS!\n");
   1.614 +    }
   1.615 +#endif
   1.616 +
   1.617 +#ifdef JS_THREADSAFE
   1.618 +    WorkerThreadState().finish();
   1.619 +#endif
   1.620 +
   1.621 +    PRMJ_NowShutdown();
   1.622 +
   1.623 +#if EXPOSE_INTL_API
   1.624 +    u_cleanup();
   1.625 +#endif // EXPOSE_INTL_API
   1.626 +
   1.627 +    jsInitState = ShutDown;
   1.628 +}
   1.629 +
   1.630 +#ifdef DEBUG
   1.631 +JS_FRIEND_API(bool)
   1.632 +JS::isGCEnabled()
   1.633 +{
   1.634 +    return !TlsPerThreadData.get()->suppressGC;
   1.635 +}
   1.636 +#else
   1.637 +JS_FRIEND_API(bool) JS::isGCEnabled() { return true; }
   1.638 +#endif
   1.639 +
   1.640 +JS_PUBLIC_API(JSRuntime *)
   1.641 +JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads, JSRuntime *parentRuntime)
   1.642 +{
   1.643 +    MOZ_ASSERT(jsInitState == Running,
   1.644 +               "must call JS_Init prior to creating any JSRuntimes");
   1.645 +
   1.646 +    // Any parent runtime should be the topmost parent. This assert
   1.647 +    // isn't required for correctness, but ensuring that the parent
   1.648 +    // runtime is not destroyed before this one is more easily done
   1.649 +    // for the main runtime in the process.
   1.650 +    JS_ASSERT_IF(parentRuntime, !parentRuntime->parentRuntime);
   1.651 +
   1.652 +    JSRuntime *rt = js_new<JSRuntime>(parentRuntime, useHelperThreads);
   1.653 +    if (!rt)
   1.654 +        return nullptr;
   1.655 +
   1.656 +    if (!rt->init(maxbytes)) {
   1.657 +        JS_DestroyRuntime(rt);
   1.658 +        return nullptr;
   1.659 +    }
   1.660 +
   1.661 +    return rt;
   1.662 +}
   1.663 +
   1.664 +JS_PUBLIC_API(void)
   1.665 +JS_DestroyRuntime(JSRuntime *rt)
   1.666 +{
   1.667 +    js_delete(rt);
   1.668 +}
   1.669 +
   1.670 +JS_PUBLIC_API(bool)
   1.671 +JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn)
   1.672 +{
   1.673 +    MOZ_ASSERT(jsInitState == Uninitialized,
   1.674 +               "must call JS_SetICUMemoryFunctions before any other JSAPI "
   1.675 +               "operation (including JS_Init)");
   1.676 +
   1.677 +#if EXPOSE_INTL_API
   1.678 +    UErrorCode status = U_ZERO_ERROR;
   1.679 +    u_setMemoryFunctions(/* context = */ nullptr, allocFn, reallocFn, freeFn, &status);
   1.680 +    return U_SUCCESS(status);
   1.681 +#else
   1.682 +    return true;
   1.683 +#endif
   1.684 +}
   1.685 +
   1.686 +JS_PUBLIC_API(void *)
   1.687 +JS_GetRuntimePrivate(JSRuntime *rt)
   1.688 +{
   1.689 +    return rt->data;
   1.690 +}
   1.691 +
   1.692 +JS_PUBLIC_API(void)
   1.693 +JS_SetRuntimePrivate(JSRuntime *rt, void *data)
   1.694 +{
   1.695 +    rt->data = data;
   1.696 +}
   1.697 +
   1.698 +#ifdef JS_THREADSAFE
   1.699 +static void
   1.700 +StartRequest(JSContext *cx)
   1.701 +{
   1.702 +    JSRuntime *rt = cx->runtime();
   1.703 +    JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
   1.704 +
   1.705 +    if (rt->requestDepth) {
   1.706 +        rt->requestDepth++;
   1.707 +    } else {
   1.708 +        /* Indicate that a request is running. */
   1.709 +        rt->requestDepth = 1;
   1.710 +        rt->triggerActivityCallback(true);
   1.711 +    }
   1.712 +}
   1.713 +
   1.714 +static void
   1.715 +StopRequest(JSContext *cx)
   1.716 +{
   1.717 +    JSRuntime *rt = cx->runtime();
   1.718 +    JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
   1.719 +
   1.720 +    JS_ASSERT(rt->requestDepth != 0);
   1.721 +    if (rt->requestDepth != 1) {
   1.722 +        rt->requestDepth--;
   1.723 +    } else {
   1.724 +        rt->conservativeGC.updateForRequestEnd();
   1.725 +        rt->requestDepth = 0;
   1.726 +        rt->triggerActivityCallback(false);
   1.727 +    }
   1.728 +}
   1.729 +#endif /* JS_THREADSAFE */
   1.730 +
   1.731 +JS_PUBLIC_API(void)
   1.732 +JS_BeginRequest(JSContext *cx)
   1.733 +{
   1.734 +#ifdef JS_THREADSAFE
   1.735 +    cx->outstandingRequests++;
   1.736 +    StartRequest(cx);
   1.737 +#endif
   1.738 +}
   1.739 +
   1.740 +JS_PUBLIC_API(void)
   1.741 +JS_EndRequest(JSContext *cx)
   1.742 +{
   1.743 +#ifdef JS_THREADSAFE
   1.744 +    JS_ASSERT(cx->outstandingRequests != 0);
   1.745 +    cx->outstandingRequests--;
   1.746 +    StopRequest(cx);
   1.747 +#endif
   1.748 +}
   1.749 +
   1.750 +JS_PUBLIC_API(bool)
   1.751 +JS_IsInRequest(JSRuntime *rt)
   1.752 +{
   1.753 +#ifdef JS_THREADSAFE
   1.754 +    JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
   1.755 +    return rt->requestDepth != 0;
   1.756 +#else
   1.757 +    return false;
   1.758 +#endif
   1.759 +}
   1.760 +
   1.761 +JS_PUBLIC_API(void)
   1.762 +JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback, void *data)
   1.763 +{
   1.764 +    rt->cxCallback = cxCallback;
   1.765 +    rt->cxCallbackData = data;
   1.766 +}
   1.767 +
   1.768 +JS_PUBLIC_API(JSContext *)
   1.769 +JS_NewContext(JSRuntime *rt, size_t stackChunkSize)
   1.770 +{
   1.771 +    return NewContext(rt, stackChunkSize);
   1.772 +}
   1.773 +
   1.774 +JS_PUBLIC_API(void)
   1.775 +JS_DestroyContext(JSContext *cx)
   1.776 +{
   1.777 +    JS_ASSERT(!cx->compartment());
   1.778 +    DestroyContext(cx, DCM_FORCE_GC);
   1.779 +}
   1.780 +
   1.781 +JS_PUBLIC_API(void)
   1.782 +JS_DestroyContextNoGC(JSContext *cx)
   1.783 +{
   1.784 +    JS_ASSERT(!cx->compartment());
   1.785 +    DestroyContext(cx, DCM_NO_GC);
   1.786 +}
   1.787 +
   1.788 +JS_PUBLIC_API(void *)
   1.789 +JS_GetContextPrivate(JSContext *cx)
   1.790 +{
   1.791 +    return cx->data;
   1.792 +}
   1.793 +
   1.794 +JS_PUBLIC_API(void)
   1.795 +JS_SetContextPrivate(JSContext *cx, void *data)
   1.796 +{
   1.797 +    cx->data = data;
   1.798 +}
   1.799 +
   1.800 +JS_PUBLIC_API(void *)
   1.801 +JS_GetSecondContextPrivate(JSContext *cx)
   1.802 +{
   1.803 +    return cx->data2;
   1.804 +}
   1.805 +
   1.806 +JS_PUBLIC_API(void)
   1.807 +JS_SetSecondContextPrivate(JSContext *cx, void *data)
   1.808 +{
   1.809 +    cx->data2 = data;
   1.810 +}
   1.811 +
   1.812 +JS_PUBLIC_API(JSRuntime *)
   1.813 +JS_GetRuntime(JSContext *cx)
   1.814 +{
   1.815 +    return cx->runtime();
   1.816 +}
   1.817 +
   1.818 +JS_PUBLIC_API(JSRuntime *)
   1.819 +JS_GetParentRuntime(JSContext *cx)
   1.820 +{
   1.821 +    JSRuntime *rt = cx->runtime();
   1.822 +    return rt->parentRuntime ? rt->parentRuntime : rt;
   1.823 +}
   1.824 +
   1.825 +JS_PUBLIC_API(JSContext *)
   1.826 +JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
   1.827 +{
   1.828 +    JSContext *cx = *iterp;
   1.829 +    cx = cx ? cx->getNext() : rt->contextList.getFirst();
   1.830 +    *iterp = cx;
   1.831 +    return cx;
   1.832 +}
   1.833 +
   1.834 +JS_PUBLIC_API(JSVersion)
   1.835 +JS_GetVersion(JSContext *cx)
   1.836 +{
   1.837 +    return VersionNumber(cx->findVersion());
   1.838 +}
   1.839 +
   1.840 +JS_PUBLIC_API(void)
   1.841 +JS_SetVersionForCompartment(JSCompartment *compartment, JSVersion version)
   1.842 +{
   1.843 +    compartment->options().setVersion(version);
   1.844 +}
   1.845 +
   1.846 +static const struct v2smap {
   1.847 +    JSVersion   version;
   1.848 +    const char  *string;
   1.849 +} v2smap[] = {
   1.850 +    {JSVERSION_ECMA_3,  "ECMAv3"},
   1.851 +    {JSVERSION_1_6,     "1.6"},
   1.852 +    {JSVERSION_1_7,     "1.7"},
   1.853 +    {JSVERSION_1_8,     "1.8"},
   1.854 +    {JSVERSION_ECMA_5,  "ECMAv5"},
   1.855 +    {JSVERSION_DEFAULT, js_default_str},
   1.856 +    {JSVERSION_DEFAULT, "1.0"},
   1.857 +    {JSVERSION_DEFAULT, "1.1"},
   1.858 +    {JSVERSION_DEFAULT, "1.2"},
   1.859 +    {JSVERSION_DEFAULT, "1.3"},
   1.860 +    {JSVERSION_DEFAULT, "1.4"},
   1.861 +    {JSVERSION_DEFAULT, "1.5"},
   1.862 +    {JSVERSION_UNKNOWN, nullptr},          /* must be last, nullptr is sentinel */
   1.863 +};
   1.864 +
   1.865 +JS_PUBLIC_API(const char *)
   1.866 +JS_VersionToString(JSVersion version)
   1.867 +{
   1.868 +    int i;
   1.869 +
   1.870 +    for (i = 0; v2smap[i].string; i++)
   1.871 +        if (v2smap[i].version == version)
   1.872 +            return v2smap[i].string;
   1.873 +    return "unknown";
   1.874 +}
   1.875 +
   1.876 +JS_PUBLIC_API(JSVersion)
   1.877 +JS_StringToVersion(const char *string)
   1.878 +{
   1.879 +    int i;
   1.880 +
   1.881 +    for (i = 0; v2smap[i].string; i++)
   1.882 +        if (strcmp(v2smap[i].string, string) == 0)
   1.883 +            return v2smap[i].version;
   1.884 +    return JSVERSION_UNKNOWN;
   1.885 +}
   1.886 +
   1.887 +JS_PUBLIC_API(JS::RuntimeOptions &)
   1.888 +JS::RuntimeOptionsRef(JSRuntime *rt)
   1.889 +{
   1.890 +    return rt->options();
   1.891 +}
   1.892 +
   1.893 +JS_PUBLIC_API(JS::RuntimeOptions &)
   1.894 +JS::RuntimeOptionsRef(JSContext *cx)
   1.895 +{
   1.896 +    return cx->runtime()->options();
   1.897 +}
   1.898 +
   1.899 +JS_PUBLIC_API(JS::ContextOptions &)
   1.900 +JS::ContextOptionsRef(JSContext *cx)
   1.901 +{
   1.902 +    return cx->options();
   1.903 +}
   1.904 +
   1.905 +JS_PUBLIC_API(const char *)
   1.906 +JS_GetImplementationVersion(void)
   1.907 +{
   1.908 +    return "JavaScript-C" MOZILLA_VERSION;
   1.909 +}
   1.910 +
   1.911 +JS_PUBLIC_API(void)
   1.912 +JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback)
   1.913 +{
   1.914 +    rt->destroyCompartmentCallback = callback;
   1.915 +}
   1.916 +
   1.917 +JS_PUBLIC_API(void)
   1.918 +JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback)
   1.919 +{
   1.920 +    rt->destroyZoneCallback = callback;
   1.921 +}
   1.922 +
   1.923 +JS_PUBLIC_API(void)
   1.924 +JS_SetSweepZoneCallback(JSRuntime *rt, JSZoneCallback callback)
   1.925 +{
   1.926 +    rt->sweepZoneCallback = callback;
   1.927 +}
   1.928 +
   1.929 +JS_PUBLIC_API(void)
   1.930 +JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback)
   1.931 +{
   1.932 +    rt->compartmentNameCallback = callback;
   1.933 +}
   1.934 +
   1.935 +JS_PUBLIC_API(void)
   1.936 +JS_SetWrapObjectCallbacks(JSRuntime *rt, const JSWrapObjectCallbacks *callbacks)
   1.937 +{
   1.938 +    rt->wrapObjectCallbacks = callbacks;
   1.939 +}
   1.940 +
   1.941 +JS_PUBLIC_API(JSCompartment *)
   1.942 +JS_EnterCompartment(JSContext *cx, JSObject *target)
   1.943 +{
   1.944 +    AssertHeapIsIdle(cx);
   1.945 +    CHECK_REQUEST(cx);
   1.946 +
   1.947 +    JSCompartment *oldCompartment = cx->compartment();
   1.948 +    cx->enterCompartment(target->compartment());
   1.949 +    return oldCompartment;
   1.950 +}
   1.951 +
   1.952 +JS_PUBLIC_API(JSCompartment *)
   1.953 +JS_EnterCompartmentOfScript(JSContext *cx, JSScript *target)
   1.954 +{
   1.955 +    AssertHeapIsIdle(cx);
   1.956 +    CHECK_REQUEST(cx);
   1.957 +    GlobalObject &global = target->global();
   1.958 +    return JS_EnterCompartment(cx, &global);
   1.959 +}
   1.960 +
   1.961 +JS_PUBLIC_API(void)
   1.962 +JS_LeaveCompartment(JSContext *cx, JSCompartment *oldCompartment)
   1.963 +{
   1.964 +    AssertHeapIsIdle(cx);
   1.965 +    CHECK_REQUEST(cx);
   1.966 +    cx->leaveCompartment(oldCompartment);
   1.967 +}
   1.968 +
   1.969 +JSAutoCompartment::JSAutoCompartment(JSContext *cx, JSObject *target)
   1.970 +  : cx_(cx),
   1.971 +    oldCompartment_(cx->compartment())
   1.972 +{
   1.973 +    AssertHeapIsIdleOrIterating(cx_);
   1.974 +    cx_->enterCompartment(target->compartment());
   1.975 +}
   1.976 +
   1.977 +JSAutoCompartment::JSAutoCompartment(JSContext *cx, JSScript *target)
   1.978 +  : cx_(cx),
   1.979 +    oldCompartment_(cx->compartment())
   1.980 +{
   1.981 +    AssertHeapIsIdleOrIterating(cx_);
   1.982 +    cx_->enterCompartment(target->compartment());
   1.983 +}
   1.984 +
   1.985 +JSAutoCompartment::~JSAutoCompartment()
   1.986 +{
   1.987 +    cx_->leaveCompartment(oldCompartment_);
   1.988 +}
   1.989 +
   1.990 +JSAutoNullCompartment::JSAutoNullCompartment(JSContext *cx)
   1.991 +  : cx_(cx),
   1.992 +    oldCompartment_(cx->compartment())
   1.993 +{
   1.994 +    AssertHeapIsIdleOrIterating(cx_);
   1.995 +    cx_->enterNullCompartment();
   1.996 +}
   1.997 +
   1.998 +JSAutoNullCompartment::~JSAutoNullCompartment()
   1.999 +{
  1.1000 +    cx_->leaveCompartment(oldCompartment_);
  1.1001 +}
  1.1002 +
  1.1003 +JS_PUBLIC_API(void)
  1.1004 +JS_SetCompartmentPrivate(JSCompartment *compartment, void *data)
  1.1005 +{
  1.1006 +    compartment->data = data;
  1.1007 +}
  1.1008 +
  1.1009 +JS_PUBLIC_API(void *)
  1.1010 +JS_GetCompartmentPrivate(JSCompartment *compartment)
  1.1011 +{
  1.1012 +    return compartment->data;
  1.1013 +}
  1.1014 +
  1.1015 +JS_PUBLIC_API(void)
  1.1016 +JS_SetZoneUserData(JS::Zone *zone, void *data)
  1.1017 +{
  1.1018 +    zone->data = data;
  1.1019 +}
  1.1020 +
  1.1021 +JS_PUBLIC_API(void *)
  1.1022 +JS_GetZoneUserData(JS::Zone *zone)
  1.1023 +{
  1.1024 +    return zone->data;
  1.1025 +}
  1.1026 +
  1.1027 +JS_PUBLIC_API(bool)
  1.1028 +JS_WrapObject(JSContext *cx, MutableHandleObject objp)
  1.1029 +{
  1.1030 +    AssertHeapIsIdle(cx);
  1.1031 +    CHECK_REQUEST(cx);
  1.1032 +    if (objp)
  1.1033 +        JS::ExposeGCThingToActiveJS(objp, JSTRACE_OBJECT);
  1.1034 +    return cx->compartment()->wrap(cx, objp);
  1.1035 +}
  1.1036 +
  1.1037 +JS_PUBLIC_API(bool)
  1.1038 +JS_WrapValue(JSContext *cx, MutableHandleValue vp)
  1.1039 +{
  1.1040 +    AssertHeapIsIdle(cx);
  1.1041 +    CHECK_REQUEST(cx);
  1.1042 +    JS::ExposeValueToActiveJS(vp);
  1.1043 +    return cx->compartment()->wrap(cx, vp);
  1.1044 +}
  1.1045 +
  1.1046 +JS_PUBLIC_API(bool)
  1.1047 +JS_WrapId(JSContext *cx, JS::MutableHandleId idp)
  1.1048 +{
  1.1049 +  AssertHeapIsIdle(cx);
  1.1050 +  CHECK_REQUEST(cx);
  1.1051 +  jsid id = idp.get();
  1.1052 +  if (JSID_IS_STRING(id))
  1.1053 +      JS::ExposeGCThingToActiveJS(JSID_TO_STRING(id), JSTRACE_STRING);
  1.1054 +  else if (JSID_IS_OBJECT(id))
  1.1055 +      JS::ExposeGCThingToActiveJS(JSID_TO_OBJECT(id), JSTRACE_OBJECT);
  1.1056 +  return cx->compartment()->wrapId(cx, idp.address());
  1.1057 +}
  1.1058 +
  1.1059 +/*
  1.1060 + * Identity remapping. Not for casual consumers.
  1.1061 + *
  1.1062 + * Normally, an object's contents and its identity are inextricably linked.
  1.1063 + * Identity is determined by the address of the JSObject* in the heap, and
  1.1064 + * the contents are what is located at that address. Transplanting allows these
  1.1065 + * concepts to be separated through a combination of swapping (exchanging the
  1.1066 + * contents of two same-compartment objects) and remapping cross-compartment
  1.1067 + * identities by altering wrappers.
  1.1068 + *
  1.1069 + * The |origobj| argument should be the object whose identity needs to be
  1.1070 + * remapped, usually to another compartment. The contents of |origobj| are
  1.1071 + * destroyed.
  1.1072 + *
  1.1073 + * The |target| argument serves two purposes:
  1.1074 + *
  1.1075 + * First, |target| serves as a hint for the new identity of the object. The new
  1.1076 + * identity object will always be in the same compartment as |target|, but
  1.1077 + * if that compartment already had an object representing |origobj| (either a
  1.1078 + * cross-compartment wrapper for it, or |origobj| itself if the two arguments
  1.1079 + * are same-compartment), the existing object is used. Otherwise, |target|
  1.1080 + * itself is used. To avoid ambiguity, JS_TransplantObject always returns the
  1.1081 + * new identity.
  1.1082 + *
  1.1083 + * Second, the new identity object's contents will be those of |target|. A swap()
  1.1084 + * is used to make this happen if an object other than |target| is used.
  1.1085 + *
  1.1086 + * We don't have a good way to recover from failure in this function, so
  1.1087 + * we intentionally crash instead.
  1.1088 + */
  1.1089 +
  1.1090 +JS_PUBLIC_API(JSObject *)
  1.1091 +JS_TransplantObject(JSContext *cx, HandleObject origobj, HandleObject target)
  1.1092 +{
  1.1093 +    AssertHeapIsIdle(cx);
  1.1094 +    JS_ASSERT(origobj != target);
  1.1095 +    JS_ASSERT(!origobj->is<CrossCompartmentWrapperObject>());
  1.1096 +    JS_ASSERT(!target->is<CrossCompartmentWrapperObject>());
  1.1097 +
  1.1098 +    RootedValue origv(cx, ObjectValue(*origobj));
  1.1099 +    RootedObject newIdentity(cx);
  1.1100 +
  1.1101 +    {
  1.1102 +        // Scope to make ~AutoMaybeTouchDeadZones do its GC before the return value is on the stack.
  1.1103 +        AutoMaybeTouchDeadZones agc(cx);
  1.1104 +        AutoDisableProxyCheck adpc(cx->runtime());
  1.1105 +
  1.1106 +        JSCompartment *destination = target->compartment();
  1.1107 +
  1.1108 +        if (origobj->compartment() == destination) {
  1.1109 +            // If the original object is in the same compartment as the
  1.1110 +            // destination, then we know that we won't find a wrapper in the
  1.1111 +            // destination's cross compartment map and that the same
  1.1112 +            // object will continue to work.
  1.1113 +            if (!JSObject::swap(cx, origobj, target))
  1.1114 +                MOZ_CRASH();
  1.1115 +            newIdentity = origobj;
  1.1116 +        } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) {
  1.1117 +            // There might already be a wrapper for the original object in
  1.1118 +            // the new compartment. If there is, we use its identity and swap
  1.1119 +            // in the contents of |target|.
  1.1120 +        newIdentity = &p->value().toObject();
  1.1121 +
  1.1122 +            // When we remove origv from the wrapper map, its wrapper, newIdentity,
  1.1123 +            // must immediately cease to be a cross-compartment wrapper. Neuter it.
  1.1124 +            destination->removeWrapper(p);
  1.1125 +            NukeCrossCompartmentWrapper(cx, newIdentity);
  1.1126 +
  1.1127 +            if (!JSObject::swap(cx, newIdentity, target))
  1.1128 +                MOZ_CRASH();
  1.1129 +        } else {
  1.1130 +            // Otherwise, we use |target| for the new identity object.
  1.1131 +            newIdentity = target;
  1.1132 +        }
  1.1133 +
  1.1134 +        // Now, iterate through other scopes looking for references to the
  1.1135 +        // old object, and update the relevant cross-compartment wrappers.
  1.1136 +        if (!RemapAllWrappersForObject(cx, origobj, newIdentity))
  1.1137 +            MOZ_CRASH();
  1.1138 +
  1.1139 +        // Lastly, update the original object to point to the new one.
  1.1140 +        if (origobj->compartment() != destination) {
  1.1141 +            RootedObject newIdentityWrapper(cx, newIdentity);
  1.1142 +            AutoCompartment ac(cx, origobj);
  1.1143 +            if (!JS_WrapObject(cx, &newIdentityWrapper))
  1.1144 +                MOZ_CRASH();
  1.1145 +            JS_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity);
  1.1146 +            if (!JSObject::swap(cx, origobj, newIdentityWrapper))
  1.1147 +                MOZ_CRASH();
  1.1148 +        origobj->compartment()->putWrapper(cx, ObjectValue(*newIdentity), origv);
  1.1149 +        }
  1.1150 +    }
  1.1151 +
  1.1152 +    // The new identity object might be one of several things. Return it to avoid
  1.1153 +    // ambiguity.
  1.1154 +    return newIdentity;
  1.1155 +}
  1.1156 +
  1.1157 +/*
  1.1158 + * Recompute all cross-compartment wrappers for an object, resetting state.
  1.1159 + * Gecko uses this to clear Xray wrappers when doing a navigation that reuses
  1.1160 + * the inner window and global object.
  1.1161 + */
  1.1162 +JS_PUBLIC_API(bool)
  1.1163 +JS_RefreshCrossCompartmentWrappers(JSContext *cx, HandleObject obj)
  1.1164 +{
  1.1165 +    return RemapAllWrappersForObject(cx, obj, obj);
  1.1166 +}
  1.1167 +
  1.1168 +JS_PUBLIC_API(bool)
  1.1169 +JS_InitStandardClasses(JSContext *cx, HandleObject obj)
  1.1170 +{
  1.1171 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.1172 +    AssertHeapIsIdle(cx);
  1.1173 +    CHECK_REQUEST(cx);
  1.1174 +
  1.1175 +    cx->setDefaultCompartmentObjectIfUnset(obj);
  1.1176 +    assertSameCompartment(cx, obj);
  1.1177 +
  1.1178 +    Rooted<GlobalObject*> global(cx, &obj->global());
  1.1179 +    return GlobalObject::initStandardClasses(cx, global);
  1.1180 +}
  1.1181 +
  1.1182 +#define CLASP(name)                 (&name##Class)
  1.1183 +#define OCLASP(name)                (&name##Object::class_)
  1.1184 +#define TYPED_ARRAY_CLASP(type)     (&TypedArrayObject::classes[ScalarTypeDescr::type])
  1.1185 +#define EAGER_ATOM(name)            NAME_OFFSET(name)
  1.1186 +#define EAGER_CLASS_ATOM(name)      NAME_OFFSET(name)
  1.1187 +
  1.1188 +static js::Class DummyClass;
  1.1189 +static js::Class SentinelClass;
  1.1190 +
  1.1191 +typedef struct JSStdName {
  1.1192 +    size_t      atomOffset;     /* offset of atom pointer in JSAtomState */
  1.1193 +    const Class *clasp;
  1.1194 +    bool isDummy() const { return clasp == &DummyClass; };
  1.1195 +    bool isSentinel() const { return clasp == &SentinelClass; };
  1.1196 +} JSStdName;
  1.1197 +
  1.1198 +static const JSStdName*
  1.1199 +LookupStdName(JSRuntime *rt, HandleString name, const JSStdName *table)
  1.1200 +{
  1.1201 +    MOZ_ASSERT(name->isAtom());
  1.1202 +    for (unsigned i = 0; !table[i].isSentinel(); i++) {
  1.1203 +        if (table[i].isDummy())
  1.1204 +            continue;
  1.1205 +        JSAtom *atom = AtomStateOffsetToName(*rt->commonNames, table[i].atomOffset);
  1.1206 +        MOZ_ASSERT(atom);
  1.1207 +        if (name == atom)
  1.1208 +            return &table[i];
  1.1209 +    }
  1.1210 +
  1.1211 +    return nullptr;
  1.1212 +}
  1.1213 +
  1.1214 +/*
  1.1215 + * Table of standard classes, indexed by JSProtoKey. For entries where the
  1.1216 + * JSProtoKey does not correspond to a class with a meaningful constructor, we
  1.1217 + * insert a null entry into the table.
  1.1218 + */
  1.1219 +#define STD_NAME_ENTRY(name, code, init, clasp) { EAGER_CLASS_ATOM(name), clasp },
  1.1220 +#define STD_DUMMY_ENTRY(name, code, init, dummy) { 0, &DummyClass },
  1.1221 +static const JSStdName standard_class_names[] = {
  1.1222 +  JS_FOR_PROTOTYPES(STD_NAME_ENTRY, STD_DUMMY_ENTRY)
  1.1223 +  { 0, &SentinelClass }
  1.1224 +};
  1.1225 +
  1.1226 +/*
  1.1227 + * Table of top-level function and constant names and the init function of the
  1.1228 + * corresponding standard class that sets them up.
  1.1229 + */
  1.1230 +static const JSStdName builtin_property_names[] = {
  1.1231 +    { EAGER_ATOM(eval), &JSObject::class_ },
  1.1232 +
  1.1233 +    /* Global properties and functions defined by the Number class. */
  1.1234 +    { EAGER_ATOM(NaN), OCLASP(Number) },
  1.1235 +    { EAGER_ATOM(Infinity), OCLASP(Number) },
  1.1236 +    { EAGER_ATOM(isNaN), OCLASP(Number) },
  1.1237 +    { EAGER_ATOM(isFinite), OCLASP(Number) },
  1.1238 +    { EAGER_ATOM(parseFloat), OCLASP(Number) },
  1.1239 +    { EAGER_ATOM(parseInt), OCLASP(Number) },
  1.1240 +
  1.1241 +    /* String global functions. */
  1.1242 +    { EAGER_ATOM(escape), OCLASP(String) },
  1.1243 +    { EAGER_ATOM(unescape), OCLASP(String) },
  1.1244 +    { EAGER_ATOM(decodeURI), OCLASP(String) },
  1.1245 +    { EAGER_ATOM(encodeURI), OCLASP(String) },
  1.1246 +    { EAGER_ATOM(decodeURIComponent), OCLASP(String) },
  1.1247 +    { EAGER_ATOM(encodeURIComponent), OCLASP(String) },
  1.1248 +#if JS_HAS_UNEVAL
  1.1249 +    { EAGER_ATOM(uneval), OCLASP(String) },
  1.1250 +#endif
  1.1251 +#ifdef ENABLE_BINARYDATA
  1.1252 +    { EAGER_ATOM(SIMD), OCLASP(SIMD) },
  1.1253 +    { EAGER_ATOM(TypedObject), OCLASP(TypedObjectModule) },
  1.1254 +#endif
  1.1255 +
  1.1256 +    { 0, &SentinelClass }
  1.1257 +};
  1.1258 +
  1.1259 +#undef CLASP
  1.1260 +#undef TYPED_ARRAY_CLASP
  1.1261 +#undef EAGER_ATOM
  1.1262 +#undef EAGER_CLASS_ATOM
  1.1263 +#undef EAGER_ATOM_CLASP
  1.1264 +
  1.1265 +JS_PUBLIC_API(bool)
  1.1266 +JS_ResolveStandardClass(JSContext *cx, HandleObject obj, HandleId id, bool *resolved)
  1.1267 +{
  1.1268 +    JSRuntime *rt;
  1.1269 +    const JSStdName *stdnm;
  1.1270 +
  1.1271 +    AssertHeapIsIdle(cx);
  1.1272 +    CHECK_REQUEST(cx);
  1.1273 +    assertSameCompartment(cx, obj, id);
  1.1274 +
  1.1275 +    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
  1.1276 +    *resolved = false;
  1.1277 +
  1.1278 +    rt = cx->runtime();
  1.1279 +    if (!rt->hasContexts() || !JSID_IS_ATOM(id))
  1.1280 +        return true;
  1.1281 +
  1.1282 +    RootedString idstr(cx, JSID_TO_STRING(id));
  1.1283 +
  1.1284 +    /* Check whether we're resolving 'undefined', and define it if so. */
  1.1285 +    JSAtom *undefinedAtom = cx->names().undefined;
  1.1286 +    if (idstr == undefinedAtom) {
  1.1287 +        *resolved = true;
  1.1288 +        return JSObject::defineProperty(cx, obj, undefinedAtom->asPropertyName(),
  1.1289 +                                        UndefinedHandleValue,
  1.1290 +                                        JS_PropertyStub, JS_StrictPropertyStub,
  1.1291 +                                        JSPROP_PERMANENT | JSPROP_READONLY);
  1.1292 +    }
  1.1293 +
  1.1294 +    /* Try for class constructors/prototypes named by well-known atoms. */
  1.1295 +    stdnm = LookupStdName(rt, idstr, standard_class_names);
  1.1296 +
  1.1297 +    /* Try less frequently used top-level functions and constants. */
  1.1298 +    if (!stdnm)
  1.1299 +        stdnm = LookupStdName(rt, idstr, builtin_property_names);
  1.1300 +
  1.1301 +    // If this class is anonymous, then it doesn't exist as a global
  1.1302 +    // property, so we won't resolve anything.
  1.1303 +    if (stdnm && !(stdnm->clasp->flags & JSCLASS_IS_ANONYMOUS)) {
  1.1304 +        JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(stdnm->clasp);
  1.1305 +        if (!GlobalObject::ensureConstructor(cx, global, key))
  1.1306 +            return false;
  1.1307 +
  1.1308 +        *resolved = true;
  1.1309 +        return true;
  1.1310 +    }
  1.1311 +
  1.1312 +    // There is no such property to resolve. An ordinary resolve hook would
  1.1313 +    // just return true at this point. But the global object is special in one
  1.1314 +    // more way: its prototype chain is lazily initialized. That is,
  1.1315 +    // global->getProto() might be null right now because we haven't created
  1.1316 +    // Object.prototype yet. Force it now.
  1.1317 +    if (!global->getOrCreateObjectPrototype(cx))
  1.1318 +        return false;
  1.1319 +
  1.1320 +    return true;
  1.1321 +}
  1.1322 +
  1.1323 +JS_PUBLIC_API(bool)
  1.1324 +JS_EnumerateStandardClasses(JSContext *cx, HandleObject obj)
  1.1325 +{
  1.1326 +    AssertHeapIsIdle(cx);
  1.1327 +    CHECK_REQUEST(cx);
  1.1328 +    assertSameCompartment(cx, obj);
  1.1329 +    MOZ_ASSERT(obj->is<GlobalObject>());
  1.1330 +    Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>());
  1.1331 +    return GlobalObject::initStandardClasses(cx, global);
  1.1332 +}
  1.1333 +
  1.1334 +JS_PUBLIC_API(bool)
  1.1335 +JS_GetClassObject(JSContext *cx, JSProtoKey key, MutableHandleObject objp)
  1.1336 +{
  1.1337 +    AssertHeapIsIdle(cx);
  1.1338 +    CHECK_REQUEST(cx);
  1.1339 +    return GetBuiltinConstructor(cx, key, objp);
  1.1340 +}
  1.1341 +
  1.1342 +JS_PUBLIC_API(bool)
  1.1343 +JS_GetClassPrototype(JSContext *cx, JSProtoKey key, MutableHandleObject objp)
  1.1344 +{
  1.1345 +    AssertHeapIsIdle(cx);
  1.1346 +    CHECK_REQUEST(cx);
  1.1347 +    return GetBuiltinPrototype(cx, key, objp);
  1.1348 +}
  1.1349 +
  1.1350 +JS_PUBLIC_API(JSProtoKey)
  1.1351 +JS_IdToProtoKey(JSContext *cx, HandleId id)
  1.1352 +{
  1.1353 +    AssertHeapIsIdle(cx);
  1.1354 +    CHECK_REQUEST(cx);
  1.1355 +
  1.1356 +    if (!JSID_IS_ATOM(id))
  1.1357 +        return JSProto_Null;
  1.1358 +    RootedString idstr(cx, JSID_TO_STRING(id));
  1.1359 +    const JSStdName *stdnm = LookupStdName(cx->runtime(), idstr, standard_class_names);
  1.1360 +    if (!stdnm)
  1.1361 +        return JSProto_Null;
  1.1362 +
  1.1363 +    MOZ_ASSERT(MOZ_ARRAY_LENGTH(standard_class_names) == JSProto_LIMIT + 1);
  1.1364 +    return static_cast<JSProtoKey>(stdnm - standard_class_names);
  1.1365 +}
  1.1366 +
  1.1367 +JS_PUBLIC_API(JSObject *)
  1.1368 +JS_GetObjectPrototype(JSContext *cx, HandleObject forObj)
  1.1369 +{
  1.1370 +    CHECK_REQUEST(cx);
  1.1371 +    assertSameCompartment(cx, forObj);
  1.1372 +    return forObj->global().getOrCreateObjectPrototype(cx);
  1.1373 +}
  1.1374 +
  1.1375 +JS_PUBLIC_API(JSObject *)
  1.1376 +JS_GetFunctionPrototype(JSContext *cx, HandleObject forObj)
  1.1377 +{
  1.1378 +    CHECK_REQUEST(cx);
  1.1379 +    assertSameCompartment(cx, forObj);
  1.1380 +    return forObj->global().getOrCreateFunctionPrototype(cx);
  1.1381 +}
  1.1382 +
  1.1383 +JS_PUBLIC_API(JSObject *)
  1.1384 +JS_GetArrayPrototype(JSContext *cx, HandleObject forObj)
  1.1385 +{
  1.1386 +    CHECK_REQUEST(cx);
  1.1387 +    assertSameCompartment(cx, forObj);
  1.1388 +    Rooted<GlobalObject*> global(cx, &forObj->global());
  1.1389 +    return GlobalObject::getOrCreateArrayPrototype(cx, global);
  1.1390 +}
  1.1391 +
  1.1392 +JS_PUBLIC_API(JSObject *)
  1.1393 +JS_GetGlobalForObject(JSContext *cx, JSObject *obj)
  1.1394 +{
  1.1395 +    AssertHeapIsIdle(cx);
  1.1396 +    assertSameCompartment(cx, obj);
  1.1397 +    return &obj->global();
  1.1398 +}
  1.1399 +
  1.1400 +extern JS_PUBLIC_API(bool)
  1.1401 +JS_IsGlobalObject(JSObject *obj)
  1.1402 +{
  1.1403 +    return obj->is<GlobalObject>();
  1.1404 +}
  1.1405 +
  1.1406 +JS_PUBLIC_API(JSObject *)
  1.1407 +JS_GetGlobalForCompartmentOrNull(JSContext *cx, JSCompartment *c)
  1.1408 +{
  1.1409 +    AssertHeapIsIdleOrIterating(cx);
  1.1410 +    assertSameCompartment(cx, c);
  1.1411 +    return c->maybeGlobal();
  1.1412 +}
  1.1413 +
  1.1414 +JS_PUBLIC_API(JSObject *)
  1.1415 +JS::CurrentGlobalOrNull(JSContext *cx)
  1.1416 +{
  1.1417 +    AssertHeapIsIdleOrIterating(cx);
  1.1418 +    CHECK_REQUEST(cx);
  1.1419 +    if (!cx->compartment())
  1.1420 +        return nullptr;
  1.1421 +    return cx->global();
  1.1422 +}
  1.1423 +
  1.1424 +JS_PUBLIC_API(jsval)
  1.1425 +JS_ComputeThis(JSContext *cx, jsval *vp)
  1.1426 +{
  1.1427 +    AssertHeapIsIdle(cx);
  1.1428 +    assertSameCompartment(cx, JSValueArray(vp, 2));
  1.1429 +    CallReceiver call = CallReceiverFromVp(vp);
  1.1430 +    if (!BoxNonStrictThis(cx, call))
  1.1431 +        return JSVAL_NULL;
  1.1432 +    return call.thisv();
  1.1433 +}
  1.1434 +
  1.1435 +JS_PUBLIC_API(void *)
  1.1436 +JS_malloc(JSContext *cx, size_t nbytes)
  1.1437 +{
  1.1438 +    AssertHeapIsIdle(cx);
  1.1439 +    CHECK_REQUEST(cx);
  1.1440 +    return cx->malloc_(nbytes);
  1.1441 +}
  1.1442 +
  1.1443 +JS_PUBLIC_API(void *)
  1.1444 +JS_realloc(JSContext *cx, void *p, size_t nbytes)
  1.1445 +{
  1.1446 +    AssertHeapIsIdle(cx);
  1.1447 +    CHECK_REQUEST(cx);
  1.1448 +    return cx->realloc_(p, nbytes);
  1.1449 +}
  1.1450 +
  1.1451 +JS_PUBLIC_API(void)
  1.1452 +JS_free(JSContext *cx, void *p)
  1.1453 +{
  1.1454 +    return js_free(p);
  1.1455 +}
  1.1456 +
  1.1457 +JS_PUBLIC_API(void)
  1.1458 +JS_freeop(JSFreeOp *fop, void *p)
  1.1459 +{
  1.1460 +    return FreeOp::get(fop)->free_(p);
  1.1461 +}
  1.1462 +
  1.1463 +JS_PUBLIC_API(JSFreeOp *)
  1.1464 +JS_GetDefaultFreeOp(JSRuntime *rt)
  1.1465 +{
  1.1466 +    return rt->defaultFreeOp();
  1.1467 +}
  1.1468 +
  1.1469 +JS_PUBLIC_API(void)
  1.1470 +JS_updateMallocCounter(JSContext *cx, size_t nbytes)
  1.1471 +{
  1.1472 +    return cx->runtime()->updateMallocCounter(cx->zone(), nbytes);
  1.1473 +}
  1.1474 +
  1.1475 +JS_PUBLIC_API(char *)
  1.1476 +JS_strdup(JSContext *cx, const char *s)
  1.1477 +{
  1.1478 +    AssertHeapIsIdle(cx);
  1.1479 +    return js_strdup(cx, s);
  1.1480 +}
  1.1481 +
  1.1482 +JS_PUBLIC_API(char *)
  1.1483 +JS_strdup(JSRuntime *rt, const char *s)
  1.1484 +{
  1.1485 +    AssertHeapIsIdle(rt);
  1.1486 +    size_t n = strlen(s) + 1;
  1.1487 +    void *p = rt->malloc_(n);
  1.1488 +    if (!p)
  1.1489 +        return nullptr;
  1.1490 +    return static_cast<char*>(js_memcpy(p, s, n));
  1.1491 +}
  1.1492 +
  1.1493 +#undef JS_AddRoot
  1.1494 +
  1.1495 +JS_PUBLIC_API(bool)
  1.1496 +JS::AddValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
  1.1497 +{
  1.1498 +    AssertHeapIsIdle(cx);
  1.1499 +    CHECK_REQUEST(cx);
  1.1500 +    return AddValueRoot(cx, vp->unsafeGet(), nullptr);
  1.1501 +}
  1.1502 +
  1.1503 +JS_PUBLIC_API(bool)
  1.1504 +JS::AddStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
  1.1505 +{
  1.1506 +    AssertHeapIsIdle(cx);
  1.1507 +    CHECK_REQUEST(cx);
  1.1508 +    return AddStringRoot(cx, rp->unsafeGet(), nullptr);
  1.1509 +}
  1.1510 +
  1.1511 +JS_PUBLIC_API(bool)
  1.1512 +JS::AddObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
  1.1513 +{
  1.1514 +    AssertHeapIsIdle(cx);
  1.1515 +    CHECK_REQUEST(cx);
  1.1516 +    return AddObjectRoot(cx, rp->unsafeGet(), nullptr);
  1.1517 +}
  1.1518 +
  1.1519 +JS_PUBLIC_API(bool)
  1.1520 +JS::AddNamedValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp, const char *name)
  1.1521 +{
  1.1522 +    AssertHeapIsIdle(cx);
  1.1523 +    CHECK_REQUEST(cx);
  1.1524 +    return AddValueRoot(cx, vp->unsafeGet(), name);
  1.1525 +}
  1.1526 +
  1.1527 +JS_PUBLIC_API(bool)
  1.1528 +JS::AddNamedValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp, const char *name)
  1.1529 +{
  1.1530 +    return AddValueRootRT(rt, vp->unsafeGet(), name);
  1.1531 +}
  1.1532 +
  1.1533 +JS_PUBLIC_API(bool)
  1.1534 +JS::AddNamedStringRoot(JSContext *cx, JS::Heap<JSString *> *rp, const char *name)
  1.1535 +{
  1.1536 +    AssertHeapIsIdle(cx);
  1.1537 +    CHECK_REQUEST(cx);
  1.1538 +    return AddStringRoot(cx, rp->unsafeGet(), name);
  1.1539 +}
  1.1540 +
  1.1541 +JS_PUBLIC_API(bool)
  1.1542 +JS::AddNamedObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp, const char *name)
  1.1543 +{
  1.1544 +    AssertHeapIsIdle(cx);
  1.1545 +    CHECK_REQUEST(cx);
  1.1546 +    return AddObjectRoot(cx, rp->unsafeGet(), name);
  1.1547 +}
  1.1548 +
  1.1549 +JS_PUBLIC_API(bool)
  1.1550 +JS::AddNamedScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp, const char *name)
  1.1551 +{
  1.1552 +    AssertHeapIsIdle(cx);
  1.1553 +    CHECK_REQUEST(cx);
  1.1554 +    return AddScriptRoot(cx, rp->unsafeGet(), name);
  1.1555 +}
  1.1556 +
  1.1557 +/* We allow unrooting from finalizers within the GC */
  1.1558 +
  1.1559 +JS_PUBLIC_API(void)
  1.1560 +JS::RemoveValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
  1.1561 +{
  1.1562 +    CHECK_REQUEST(cx);
  1.1563 +    RemoveRoot(cx->runtime(), (void *)vp);
  1.1564 +    *vp = UndefinedValue();
  1.1565 +}
  1.1566 +
  1.1567 +JS_PUBLIC_API(void)
  1.1568 +JS::RemoveStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
  1.1569 +{
  1.1570 +    CHECK_REQUEST(cx);
  1.1571 +    RemoveRoot(cx->runtime(), (void *)rp);
  1.1572 +    *rp = nullptr;
  1.1573 +}
  1.1574 +
  1.1575 +JS_PUBLIC_API(void)
  1.1576 +JS::RemoveObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
  1.1577 +{
  1.1578 +    CHECK_REQUEST(cx);
  1.1579 +    RemoveRoot(cx->runtime(), (void *)rp);
  1.1580 +    *rp = nullptr;
  1.1581 +}
  1.1582 +
  1.1583 +JS_PUBLIC_API(void)
  1.1584 +JS::RemoveScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp)
  1.1585 +{
  1.1586 +    CHECK_REQUEST(cx);
  1.1587 +    RemoveRoot(cx->runtime(), (void *)rp);
  1.1588 +    *rp = nullptr;
  1.1589 +}
  1.1590 +
  1.1591 +JS_PUBLIC_API(void)
  1.1592 +JS::RemoveValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp)
  1.1593 +{
  1.1594 +    RemoveRoot(rt, (void *)vp);
  1.1595 +    *vp = UndefinedValue();
  1.1596 +}
  1.1597 +
  1.1598 +JS_PUBLIC_API(void)
  1.1599 +JS::RemoveStringRootRT(JSRuntime *rt, JS::Heap<JSString *> *rp)
  1.1600 +{
  1.1601 +    RemoveRoot(rt, (void *)rp);
  1.1602 +    *rp = nullptr;
  1.1603 +}
  1.1604 +
  1.1605 +JS_PUBLIC_API(void)
  1.1606 +JS::RemoveObjectRootRT(JSRuntime *rt, JS::Heap<JSObject *> *rp)
  1.1607 +{
  1.1608 +    RemoveRoot(rt, (void *)rp);
  1.1609 +    *rp = nullptr;
  1.1610 +}
  1.1611 +
  1.1612 +JS_PUBLIC_API(void)
  1.1613 +JS::RemoveScriptRootRT(JSRuntime *rt, JS::Heap<JSScript *> *rp)
  1.1614 +{
  1.1615 +    RemoveRoot(rt, (void *)rp);
  1.1616 +    *rp = nullptr;
  1.1617 +}
  1.1618 +
  1.1619 +JS_PUBLIC_API(bool)
  1.1620 +JS_AddExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
  1.1621 +{
  1.1622 +    AssertHeapIsIdle(rt);
  1.1623 +    return !!rt->gcBlackRootTracers.append(JSRuntime::ExtraTracer(traceOp, data));
  1.1624 +}
  1.1625 +
  1.1626 +JS_PUBLIC_API(void)
  1.1627 +JS_RemoveExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
  1.1628 +{
  1.1629 +    AssertHeapIsIdle(rt);
  1.1630 +    for (size_t i = 0; i < rt->gcBlackRootTracers.length(); i++) {
  1.1631 +        JSRuntime::ExtraTracer *e = &rt->gcBlackRootTracers[i];
  1.1632 +        if (e->op == traceOp && e->data == data) {
  1.1633 +            rt->gcBlackRootTracers.erase(e);
  1.1634 +            break;
  1.1635 +        }
  1.1636 +    }
  1.1637 +}
  1.1638 +
  1.1639 +#ifdef DEBUG
  1.1640 +
  1.1641 +typedef struct JSHeapDumpNode JSHeapDumpNode;
  1.1642 +
  1.1643 +struct JSHeapDumpNode {
  1.1644 +    void            *thing;
  1.1645 +    JSGCTraceKind   kind;
  1.1646 +    JSHeapDumpNode  *next;          /* next sibling */
  1.1647 +    JSHeapDumpNode  *parent;        /* node with the thing that refer to thing
  1.1648 +                                       from this node */
  1.1649 +    char            edgeName[1];    /* name of the edge from parent->thing
  1.1650 +                                       into thing */
  1.1651 +};
  1.1652 +
  1.1653 +typedef HashSet<void *, PointerHasher<void *, 3>, SystemAllocPolicy> VisitedSet;
  1.1654 +
  1.1655 +class DumpingTracer
  1.1656 +{
  1.1657 +  public:
  1.1658 +    DumpingTracer(JSRuntime *rt, JSTraceCallback callback)
  1.1659 +      : base(rt, callback)
  1.1660 +    {}
  1.1661 +
  1.1662 +    JSTracer            base;
  1.1663 +    VisitedSet          visited;
  1.1664 +    bool                ok;
  1.1665 +    void                *startThing;
  1.1666 +    void                *thingToFind;
  1.1667 +    void                *thingToIgnore;
  1.1668 +    JSHeapDumpNode      *parentNode;
  1.1669 +    JSHeapDumpNode      **lastNodep;
  1.1670 +    char                buffer[200];
  1.1671 +};
  1.1672 +
  1.1673 +static void
  1.1674 +DumpNotify(JSTracer *trc, void **thingp, JSGCTraceKind kind)
  1.1675 +{
  1.1676 +    JS_ASSERT(trc->callback == DumpNotify);
  1.1677 +
  1.1678 +    DumpingTracer *dtrc = (DumpingTracer *)trc;
  1.1679 +    void *thing = *thingp;
  1.1680 +
  1.1681 +    if (!dtrc->ok || thing == dtrc->thingToIgnore)
  1.1682 +        return;
  1.1683 +
  1.1684 +    /*
  1.1685 +     * Check if we have already seen thing unless it is thingToFind to include
  1.1686 +     * it to the graph each time we reach it and print all live things that
  1.1687 +     * refer to thingToFind.
  1.1688 +     *
  1.1689 +     * This does not print all possible paths leading to thingToFind since
  1.1690 +     * when a thing A refers directly or indirectly to thingToFind and A is
  1.1691 +     * present several times in the graph, we will print only the first path
  1.1692 +     * leading to A and thingToFind, other ways to reach A will be ignored.
  1.1693 +     */
  1.1694 +    if (dtrc->thingToFind != thing) {
  1.1695 +        /*
  1.1696 +         * The startThing check allows to avoid putting startThing into the
  1.1697 +         * hash table before tracing startThing in JS_DumpHeap.
  1.1698 +         */
  1.1699 +        if (thing == dtrc->startThing)
  1.1700 +            return;
  1.1701 +        VisitedSet::AddPtr p = dtrc->visited.lookupForAdd(thing);
  1.1702 +        if (p)
  1.1703 +            return;
  1.1704 +        if (!dtrc->visited.add(p, thing)) {
  1.1705 +            dtrc->ok = false;
  1.1706 +            return;
  1.1707 +        }
  1.1708 +    }
  1.1709 +
  1.1710 +    const char *edgeName = dtrc->base.getTracingEdgeName(dtrc->buffer, sizeof(dtrc->buffer));
  1.1711 +    size_t edgeNameSize = strlen(edgeName) + 1;
  1.1712 +    size_t bytes = offsetof(JSHeapDumpNode, edgeName) + edgeNameSize;
  1.1713 +    JSHeapDumpNode *node = (JSHeapDumpNode *) js_malloc(bytes);
  1.1714 +    if (!node) {
  1.1715 +        dtrc->ok = false;
  1.1716 +        return;
  1.1717 +    }
  1.1718 +
  1.1719 +    node->thing = thing;
  1.1720 +    node->kind = kind;
  1.1721 +    node->next = nullptr;
  1.1722 +    node->parent = dtrc->parentNode;
  1.1723 +    js_memcpy(node->edgeName, edgeName, edgeNameSize);
  1.1724 +
  1.1725 +    JS_ASSERT(!*dtrc->lastNodep);
  1.1726 +    *dtrc->lastNodep = node;
  1.1727 +    dtrc->lastNodep = &node->next;
  1.1728 +}
  1.1729 +
  1.1730 +/* Dump node and the chain that leads to thing it contains. */
  1.1731 +static bool
  1.1732 +DumpNode(DumpingTracer *dtrc, FILE* fp, JSHeapDumpNode *node)
  1.1733 +{
  1.1734 +    JSHeapDumpNode *prev, *following;
  1.1735 +    size_t chainLimit;
  1.1736 +    enum { MAX_PARENTS_TO_PRINT = 10 };
  1.1737 +
  1.1738 +    JS_GetTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
  1.1739 +                         &dtrc->base, node->thing, node->kind, true);
  1.1740 +    if (fprintf(fp, "%p %-22s via ", node->thing, dtrc->buffer) < 0)
  1.1741 +        return false;
  1.1742 +
  1.1743 +    /*
  1.1744 +     * We need to print the parent chain in the reverse order. To do it in
  1.1745 +     * O(N) time where N is the chain length we first reverse the chain while
  1.1746 +     * searching for the top and then print each node while restoring the
  1.1747 +     * chain order.
  1.1748 +     */
  1.1749 +    chainLimit = MAX_PARENTS_TO_PRINT;
  1.1750 +    prev = nullptr;
  1.1751 +    for (;;) {
  1.1752 +        following = node->parent;
  1.1753 +        node->parent = prev;
  1.1754 +        prev = node;
  1.1755 +        node = following;
  1.1756 +        if (!node)
  1.1757 +            break;
  1.1758 +        if (chainLimit == 0) {
  1.1759 +            if (fputs("...", fp) < 0)
  1.1760 +                return false;
  1.1761 +            break;
  1.1762 +        }
  1.1763 +        --chainLimit;
  1.1764 +    }
  1.1765 +
  1.1766 +    node = prev;
  1.1767 +    prev = following;
  1.1768 +    bool ok = true;
  1.1769 +    do {
  1.1770 +        /* Loop must continue even when !ok to restore the parent chain. */
  1.1771 +        if (ok) {
  1.1772 +            if (!prev) {
  1.1773 +                /* Print edge from some runtime root or startThing. */
  1.1774 +                if (fputs(node->edgeName, fp) < 0)
  1.1775 +                    ok = false;
  1.1776 +            } else {
  1.1777 +                JS_GetTraceThingInfo(dtrc->buffer, sizeof dtrc->buffer,
  1.1778 +                                     &dtrc->base, prev->thing, prev->kind,
  1.1779 +                                     false);
  1.1780 +                if (fprintf(fp, "(%p %s).%s",
  1.1781 +                           prev->thing, dtrc->buffer, node->edgeName) < 0) {
  1.1782 +                    ok = false;
  1.1783 +                }
  1.1784 +            }
  1.1785 +        }
  1.1786 +        following = node->parent;
  1.1787 +        node->parent = prev;
  1.1788 +        prev = node;
  1.1789 +        node = following;
  1.1790 +    } while (node);
  1.1791 +
  1.1792 +    return ok && putc('\n', fp) >= 0;
  1.1793 +}
  1.1794 +
  1.1795 +JS_PUBLIC_API(bool)
  1.1796 +JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind startKind,
  1.1797 +            void *thingToFind, size_t maxDepth, void *thingToIgnore)
  1.1798 +{
  1.1799 +    if (maxDepth == 0)
  1.1800 +        return true;
  1.1801 +
  1.1802 +    DumpingTracer dtrc(rt, DumpNotify);
  1.1803 +    if (!dtrc.visited.init())
  1.1804 +        return false;
  1.1805 +    dtrc.ok = true;
  1.1806 +    dtrc.startThing = startThing;
  1.1807 +    dtrc.thingToFind = thingToFind;
  1.1808 +    dtrc.thingToIgnore = thingToIgnore;
  1.1809 +    dtrc.parentNode = nullptr;
  1.1810 +    JSHeapDumpNode *node = nullptr;
  1.1811 +    dtrc.lastNodep = &node;
  1.1812 +    if (!startThing) {
  1.1813 +        JS_ASSERT(startKind == JSTRACE_OBJECT);
  1.1814 +        TraceRuntime(&dtrc.base);
  1.1815 +    } else {
  1.1816 +        JS_TraceChildren(&dtrc.base, startThing, startKind);
  1.1817 +    }
  1.1818 +
  1.1819 +    if (!node)
  1.1820 +        return dtrc.ok;
  1.1821 +
  1.1822 +    size_t depth = 1;
  1.1823 +    JSHeapDumpNode *children, *next, *parent;
  1.1824 +    bool thingToFindWasTraced = thingToFind && thingToFind == startThing;
  1.1825 +    for (;;) {
  1.1826 +        /*
  1.1827 +         * Loop must continue even when !dtrc.ok to free all nodes allocated
  1.1828 +         * so far.
  1.1829 +         */
  1.1830 +        if (dtrc.ok) {
  1.1831 +            if (thingToFind == nullptr || thingToFind == node->thing)
  1.1832 +                dtrc.ok = DumpNode(&dtrc, fp, node);
  1.1833 +
  1.1834 +            /* Descend into children. */
  1.1835 +            if (dtrc.ok &&
  1.1836 +                depth < maxDepth &&
  1.1837 +                (thingToFind != node->thing || !thingToFindWasTraced)) {
  1.1838 +                dtrc.parentNode = node;
  1.1839 +                children = nullptr;
  1.1840 +                dtrc.lastNodep = &children;
  1.1841 +                JS_TraceChildren(&dtrc.base, node->thing, node->kind);
  1.1842 +                if (thingToFind == node->thing)
  1.1843 +                    thingToFindWasTraced = true;
  1.1844 +                if (children != nullptr) {
  1.1845 +                    ++depth;
  1.1846 +                    node = children;
  1.1847 +                    continue;
  1.1848 +                }
  1.1849 +            }
  1.1850 +        }
  1.1851 +
  1.1852 +        /* Move to next or parents next and free the node. */
  1.1853 +        for (;;) {
  1.1854 +            next = node->next;
  1.1855 +            parent = node->parent;
  1.1856 +            js_free(node);
  1.1857 +            node = next;
  1.1858 +            if (node)
  1.1859 +                break;
  1.1860 +            if (!parent)
  1.1861 +                return dtrc.ok;
  1.1862 +            JS_ASSERT(depth > 1);
  1.1863 +            --depth;
  1.1864 +            node = parent;
  1.1865 +        }
  1.1866 +    }
  1.1867 +
  1.1868 +    JS_ASSERT(depth == 1);
  1.1869 +    return dtrc.ok;
  1.1870 +}
  1.1871 +
  1.1872 +#endif /* DEBUG */
  1.1873 +
  1.1874 +extern JS_PUBLIC_API(bool)
  1.1875 +JS_IsGCMarkingTracer(JSTracer *trc)
  1.1876 +{
  1.1877 +    return IS_GC_MARKING_TRACER(trc);
  1.1878 +}
  1.1879 +
  1.1880 +#ifdef DEBUG
  1.1881 +extern JS_PUBLIC_API(bool)
  1.1882 +JS_IsMarkingGray(JSTracer *trc)
  1.1883 +{
  1.1884 +    JS_ASSERT(JS_IsGCMarkingTracer(trc));
  1.1885 +    return trc->callback == GCMarker::GrayCallback;
  1.1886 +}
  1.1887 +#endif
  1.1888 +
  1.1889 +JS_PUBLIC_API(void)
  1.1890 +JS_GC(JSRuntime *rt)
  1.1891 +{
  1.1892 +    AssertHeapIsIdle(rt);
  1.1893 +    JS::PrepareForFullGC(rt);
  1.1894 +    GC(rt, GC_NORMAL, JS::gcreason::API);
  1.1895 +}
  1.1896 +
  1.1897 +JS_PUBLIC_API(void)
  1.1898 +JS_MaybeGC(JSContext *cx)
  1.1899 +{
  1.1900 +    MaybeGC(cx);
  1.1901 +}
  1.1902 +
  1.1903 +JS_PUBLIC_API(void)
  1.1904 +JS_SetGCCallback(JSRuntime *rt, JSGCCallback cb, void *data)
  1.1905 +{
  1.1906 +    AssertHeapIsIdle(rt);
  1.1907 +    rt->gcCallback = cb;
  1.1908 +    rt->gcCallbackData = data;
  1.1909 +}
  1.1910 +
  1.1911 +JS_PUBLIC_API(void)
  1.1912 +JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb)
  1.1913 +{
  1.1914 +    AssertHeapIsIdle(rt);
  1.1915 +    rt->gcFinalizeCallback = cb;
  1.1916 +}
  1.1917 +
  1.1918 +JS_PUBLIC_API(bool)
  1.1919 +JS_IsAboutToBeFinalized(JS::Heap<JSObject *> *objp)
  1.1920 +{
  1.1921 +    return IsObjectAboutToBeFinalized(objp->unsafeGet());
  1.1922 +}
  1.1923 +
  1.1924 +JS_PUBLIC_API(bool)
  1.1925 +JS_IsAboutToBeFinalizedUnbarriered(JSObject **objp)
  1.1926 +{
  1.1927 +    return IsObjectAboutToBeFinalized(objp);
  1.1928 +}
  1.1929 +
  1.1930 +JS_PUBLIC_API(void)
  1.1931 +JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value)
  1.1932 +{
  1.1933 +    switch (key) {
  1.1934 +      case JSGC_MAX_BYTES: {
  1.1935 +        JS_ASSERT(value >= rt->gcBytes);
  1.1936 +        rt->gcMaxBytes = value;
  1.1937 +        break;
  1.1938 +      }
  1.1939 +      case JSGC_MAX_MALLOC_BYTES:
  1.1940 +        rt->setGCMaxMallocBytes(value);
  1.1941 +        break;
  1.1942 +      case JSGC_SLICE_TIME_BUDGET:
  1.1943 +        rt->gcSliceBudget = SliceBudget::TimeBudget(value);
  1.1944 +        break;
  1.1945 +      case JSGC_MARK_STACK_LIMIT:
  1.1946 +        js::SetMarkStackLimit(rt, value);
  1.1947 +        break;
  1.1948 +      case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
  1.1949 +        rt->gcHighFrequencyTimeThreshold = value;
  1.1950 +        break;
  1.1951 +      case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
  1.1952 +        rt->gcHighFrequencyLowLimitBytes = value * 1024 * 1024;
  1.1953 +        break;
  1.1954 +      case JSGC_HIGH_FREQUENCY_HIGH_LIMIT:
  1.1955 +        rt->gcHighFrequencyHighLimitBytes = value * 1024 * 1024;
  1.1956 +        break;
  1.1957 +      case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX:
  1.1958 +        rt->gcHighFrequencyHeapGrowthMax = value / 100.0;
  1.1959 +        MOZ_ASSERT(rt->gcHighFrequencyHeapGrowthMax / 0.85 > 1.0);
  1.1960 +        break;
  1.1961 +      case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN:
  1.1962 +        rt->gcHighFrequencyHeapGrowthMin = value / 100.0;
  1.1963 +        MOZ_ASSERT(rt->gcHighFrequencyHeapGrowthMin / 0.85 > 1.0);
  1.1964 +        break;
  1.1965 +      case JSGC_LOW_FREQUENCY_HEAP_GROWTH:
  1.1966 +        rt->gcLowFrequencyHeapGrowth = value / 100.0;
  1.1967 +        MOZ_ASSERT(rt->gcLowFrequencyHeapGrowth / 0.9 > 1.0);
  1.1968 +        break;
  1.1969 +      case JSGC_DYNAMIC_HEAP_GROWTH:
  1.1970 +        rt->gcDynamicHeapGrowth = value;
  1.1971 +        break;
  1.1972 +      case JSGC_DYNAMIC_MARK_SLICE:
  1.1973 +        rt->gcDynamicMarkSlice = value;
  1.1974 +        break;
  1.1975 +      case JSGC_ALLOCATION_THRESHOLD:
  1.1976 +        rt->gcAllocationThreshold = value * 1024 * 1024;
  1.1977 +        break;
  1.1978 +      case JSGC_DECOMMIT_THRESHOLD:
  1.1979 +        rt->gcDecommitThreshold = value * 1024 * 1024;
  1.1980 +        break;
  1.1981 +      default:
  1.1982 +        JS_ASSERT(key == JSGC_MODE);
  1.1983 +        rt->setGCMode(JSGCMode(value));
  1.1984 +        JS_ASSERT(rt->gcMode() == JSGC_MODE_GLOBAL ||
  1.1985 +                  rt->gcMode() == JSGC_MODE_COMPARTMENT ||
  1.1986 +                  rt->gcMode() == JSGC_MODE_INCREMENTAL);
  1.1987 +        return;
  1.1988 +    }
  1.1989 +}
  1.1990 +
  1.1991 +JS_PUBLIC_API(uint32_t)
  1.1992 +JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
  1.1993 +{
  1.1994 +    switch (key) {
  1.1995 +      case JSGC_MAX_BYTES:
  1.1996 +        return uint32_t(rt->gcMaxBytes);
  1.1997 +      case JSGC_MAX_MALLOC_BYTES:
  1.1998 +        return rt->gcMaxMallocBytes;
  1.1999 +      case JSGC_BYTES:
  1.2000 +        return uint32_t(rt->gcBytes);
  1.2001 +      case JSGC_MODE:
  1.2002 +        return uint32_t(rt->gcMode());
  1.2003 +      case JSGC_UNUSED_CHUNKS:
  1.2004 +        return uint32_t(rt->gcChunkPool.getEmptyCount());
  1.2005 +      case JSGC_TOTAL_CHUNKS:
  1.2006 +        return uint32_t(rt->gcChunkSet.count() + rt->gcChunkPool.getEmptyCount());
  1.2007 +      case JSGC_SLICE_TIME_BUDGET:
  1.2008 +        return uint32_t(rt->gcSliceBudget > 0 ? rt->gcSliceBudget / PRMJ_USEC_PER_MSEC : 0);
  1.2009 +      case JSGC_MARK_STACK_LIMIT:
  1.2010 +        return rt->gcMarker.maxCapacity();
  1.2011 +      case JSGC_HIGH_FREQUENCY_TIME_LIMIT:
  1.2012 +        return rt->gcHighFrequencyTimeThreshold;
  1.2013 +      case JSGC_HIGH_FREQUENCY_LOW_LIMIT:
  1.2014 +        return rt->gcHighFrequencyLowLimitBytes / 1024 / 1024;
  1.2015 +      case JSGC_HIGH_FREQUENCY_HIGH_LIMIT:
  1.2016 +        return rt->gcHighFrequencyHighLimitBytes / 1024 / 1024;
  1.2017 +      case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX:
  1.2018 +        return uint32_t(rt->gcHighFrequencyHeapGrowthMax * 100);
  1.2019 +      case JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN:
  1.2020 +        return uint32_t(rt->gcHighFrequencyHeapGrowthMin * 100);
  1.2021 +      case JSGC_LOW_FREQUENCY_HEAP_GROWTH:
  1.2022 +        return uint32_t(rt->gcLowFrequencyHeapGrowth * 100);
  1.2023 +      case JSGC_DYNAMIC_HEAP_GROWTH:
  1.2024 +        return rt->gcDynamicHeapGrowth;
  1.2025 +      case JSGC_DYNAMIC_MARK_SLICE:
  1.2026 +        return rt->gcDynamicMarkSlice;
  1.2027 +      case JSGC_ALLOCATION_THRESHOLD:
  1.2028 +        return rt->gcAllocationThreshold / 1024 / 1024;
  1.2029 +      default:
  1.2030 +        JS_ASSERT(key == JSGC_NUMBER);
  1.2031 +        return uint32_t(rt->gcNumber);
  1.2032 +    }
  1.2033 +}
  1.2034 +
  1.2035 +JS_PUBLIC_API(void)
  1.2036 +JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value)
  1.2037 +{
  1.2038 +    JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
  1.2039 +}
  1.2040 +
  1.2041 +JS_PUBLIC_API(uint32_t)
  1.2042 +JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key)
  1.2043 +{
  1.2044 +    JS_ASSERT(key == JSGC_MAX_CODE_CACHE_BYTES);
  1.2045 +    return 0;
  1.2046 +}
  1.2047 +
  1.2048 +static const size_t NumGCConfigs = 14;
  1.2049 +struct JSGCConfig {
  1.2050 +    JSGCParamKey key;
  1.2051 +    uint32_t value;
  1.2052 +};
  1.2053 +
  1.2054 +JS_PUBLIC_API(void)
  1.2055 +JS_SetGCParametersBasedOnAvailableMemory(JSRuntime *rt, uint32_t availMem)
  1.2056 +{
  1.2057 +    static const JSGCConfig minimal[NumGCConfigs] = {
  1.2058 +        {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
  1.2059 +        {JSGC_SLICE_TIME_BUDGET, 30},
  1.2060 +        {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  1.2061 +        {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 40},
  1.2062 +        {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 0},
  1.2063 +        {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
  1.2064 +        {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 120},
  1.2065 +        {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 120},
  1.2066 +        {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  1.2067 +        {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  1.2068 +        {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  1.2069 +        {JSGC_ALLOCATION_THRESHOLD, 1},
  1.2070 +        {JSGC_DECOMMIT_THRESHOLD, 1},
  1.2071 +        {JSGC_MODE, JSGC_MODE_INCREMENTAL}
  1.2072 +    };
  1.2073 +
  1.2074 +    const JSGCConfig *config = minimal;
  1.2075 +    if (availMem > 512) {
  1.2076 +        static const JSGCConfig nominal[NumGCConfigs] = {
  1.2077 +            {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024},
  1.2078 +            {JSGC_SLICE_TIME_BUDGET, 30},
  1.2079 +            {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000},
  1.2080 +            {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500},
  1.2081 +            {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100},
  1.2082 +            {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300},
  1.2083 +            {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 150},
  1.2084 +            {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 150},
  1.2085 +            {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  1.2086 +            {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  1.2087 +            {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500},
  1.2088 +            {JSGC_ALLOCATION_THRESHOLD, 30},
  1.2089 +            {JSGC_DECOMMIT_THRESHOLD, 32},
  1.2090 +            {JSGC_MODE, JSGC_MODE_COMPARTMENT}
  1.2091 +        };
  1.2092 +
  1.2093 +        config = nominal;
  1.2094 +    }
  1.2095 +
  1.2096 +    for (size_t i = 0; i < NumGCConfigs; i++)
  1.2097 +        JS_SetGCParameter(rt, config[i].key, config[i].value);
  1.2098 +}
  1.2099 +
  1.2100 +
  1.2101 +JS_PUBLIC_API(JSString *)
  1.2102 +JS_NewExternalString(JSContext *cx, const jschar *chars, size_t length,
  1.2103 +                     const JSStringFinalizer *fin)
  1.2104 +{
  1.2105 +    AssertHeapIsIdle(cx);
  1.2106 +    CHECK_REQUEST(cx);
  1.2107 +    JSString *s = JSExternalString::new_(cx, chars, length, fin);
  1.2108 +    return s;
  1.2109 +}
  1.2110 +
  1.2111 +extern JS_PUBLIC_API(bool)
  1.2112 +JS_IsExternalString(JSString *str)
  1.2113 +{
  1.2114 +    return str->isExternal();
  1.2115 +}
  1.2116 +
  1.2117 +extern JS_PUBLIC_API(const JSStringFinalizer *)
  1.2118 +JS_GetExternalStringFinalizer(JSString *str)
  1.2119 +{
  1.2120 +    return str->asExternal().externalFinalizer();
  1.2121 +}
  1.2122 +
  1.2123 +static void
  1.2124 +SetNativeStackQuota(JSRuntime *rt, StackKind kind, size_t stackSize)
  1.2125 +{
  1.2126 +    rt->nativeStackQuota[kind] = stackSize;
  1.2127 +    if (rt->nativeStackBase)
  1.2128 +        RecomputeStackLimit(rt, kind);
  1.2129 +}
  1.2130 +
  1.2131 +void
  1.2132 +js::RecomputeStackLimit(JSRuntime *rt, StackKind kind)
  1.2133 +{
  1.2134 +    size_t stackSize = rt->nativeStackQuota[kind];
  1.2135 +#if JS_STACK_GROWTH_DIRECTION > 0
  1.2136 +    if (stackSize == 0) {
  1.2137 +        rt->mainThread.nativeStackLimit[kind] = UINTPTR_MAX;
  1.2138 +    } else {
  1.2139 +        JS_ASSERT(rt->nativeStackBase <= size_t(-1) - stackSize);
  1.2140 +        rt->mainThread.nativeStackLimit[kind] =
  1.2141 +          rt->nativeStackBase + stackSize - 1;
  1.2142 +    }
  1.2143 +#else
  1.2144 +    if (stackSize == 0) {
  1.2145 +        rt->mainThread.nativeStackLimit[kind] = 0;
  1.2146 +    } else {
  1.2147 +        JS_ASSERT(rt->nativeStackBase >= stackSize);
  1.2148 +        rt->mainThread.nativeStackLimit[kind] =
  1.2149 +          rt->nativeStackBase - (stackSize - 1);
  1.2150 +    }
  1.2151 +#endif
  1.2152 +
  1.2153 +    // If there's no pending interrupt request set on the runtime's main thread's
  1.2154 +    // jitStackLimit, then update it so that it reflects the new nativeStacklimit.
  1.2155 +    //
  1.2156 +    // Note that, for now, we use the untrusted limit for ion. This is fine,
  1.2157 +    // because it's the most conservative limit, and if we hit it, we'll bail
  1.2158 +    // out of ion into the interpeter, which will do a proper recursion check.
  1.2159 +#ifdef JS_ION
  1.2160 +    if (kind == StackForUntrustedScript) {
  1.2161 +        JSRuntime::AutoLockForInterrupt lock(rt);
  1.2162 +        if (rt->mainThread.jitStackLimit != uintptr_t(-1)) {
  1.2163 +            rt->mainThread.jitStackLimit = rt->mainThread.nativeStackLimit[kind];
  1.2164 +#ifdef JS_ARM_SIMULATOR
  1.2165 +            rt->mainThread.jitStackLimit = jit::Simulator::StackLimit();
  1.2166 +#endif
  1.2167 +        }
  1.2168 +    }
  1.2169 +#endif
  1.2170 +}
  1.2171 +
  1.2172 +JS_PUBLIC_API(void)
  1.2173 +JS_SetNativeStackQuota(JSRuntime *rt, size_t systemCodeStackSize,
  1.2174 +                       size_t trustedScriptStackSize,
  1.2175 +                       size_t untrustedScriptStackSize)
  1.2176 +{
  1.2177 +    JS_ASSERT_IF(trustedScriptStackSize,
  1.2178 +                 trustedScriptStackSize < systemCodeStackSize);
  1.2179 +    if (!trustedScriptStackSize)
  1.2180 +        trustedScriptStackSize = systemCodeStackSize;
  1.2181 +    JS_ASSERT_IF(untrustedScriptStackSize,
  1.2182 +                 untrustedScriptStackSize < trustedScriptStackSize);
  1.2183 +    if (!untrustedScriptStackSize)
  1.2184 +        untrustedScriptStackSize = trustedScriptStackSize;
  1.2185 +    SetNativeStackQuota(rt, StackForSystemCode, systemCodeStackSize);
  1.2186 +    SetNativeStackQuota(rt, StackForTrustedScript, trustedScriptStackSize);
  1.2187 +    SetNativeStackQuota(rt, StackForUntrustedScript, untrustedScriptStackSize);
  1.2188 +}
  1.2189 +
  1.2190 +/************************************************************************/
  1.2191 +
  1.2192 +JS_PUBLIC_API(int)
  1.2193 +JS_IdArrayLength(JSContext *cx, JSIdArray *ida)
  1.2194 +{
  1.2195 +    return ida->length;
  1.2196 +}
  1.2197 +
  1.2198 +JS_PUBLIC_API(jsid)
  1.2199 +JS_IdArrayGet(JSContext *cx, JSIdArray *ida, int index)
  1.2200 +{
  1.2201 +    JS_ASSERT(index >= 0 && index < ida->length);
  1.2202 +    return ida->vector[index];
  1.2203 +}
  1.2204 +
  1.2205 +JS_PUBLIC_API(void)
  1.2206 +JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
  1.2207 +{
  1.2208 +    cx->runtime()->defaultFreeOp()->free_(ida);
  1.2209 +}
  1.2210 +
  1.2211 +JS_PUBLIC_API(bool)
  1.2212 +JS_ValueToId(JSContext *cx, HandleValue value, MutableHandleId idp)
  1.2213 +{
  1.2214 +    AssertHeapIsIdle(cx);
  1.2215 +    CHECK_REQUEST(cx);
  1.2216 +    assertSameCompartment(cx, value);
  1.2217 +    return ValueToId<CanGC>(cx, value, idp);
  1.2218 +}
  1.2219 +
  1.2220 +JS_PUBLIC_API(bool)
  1.2221 +JS_StringToId(JSContext *cx, HandleString string, MutableHandleId idp)
  1.2222 +{
  1.2223 +    AssertHeapIsIdle(cx);
  1.2224 +    CHECK_REQUEST(cx);
  1.2225 +    assertSameCompartment(cx, string);
  1.2226 +    RootedValue value(cx, StringValue(string));
  1.2227 +    return ValueToId<CanGC>(cx, value, idp);
  1.2228 +}
  1.2229 +
  1.2230 +JS_PUBLIC_API(bool)
  1.2231 +JS_IdToValue(JSContext *cx, jsid id, MutableHandleValue vp)
  1.2232 +{
  1.2233 +    AssertHeapIsIdle(cx);
  1.2234 +    CHECK_REQUEST(cx);
  1.2235 +    vp.set(IdToValue(id));
  1.2236 +    assertSameCompartment(cx, vp);
  1.2237 +    return true;
  1.2238 +}
  1.2239 +
  1.2240 +JS_PUBLIC_API(bool)
  1.2241 +JS_DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp)
  1.2242 +{
  1.2243 +    AssertHeapIsIdle(cx);
  1.2244 +    CHECK_REQUEST(cx);
  1.2245 +    JS_ASSERT(obj != nullptr);
  1.2246 +    JS_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER);
  1.2247 +    return JSObject::defaultValue(cx, obj, hint, vp);
  1.2248 +}
  1.2249 +
  1.2250 +JS_PUBLIC_API(bool)
  1.2251 +JS_PropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
  1.2252 +{
  1.2253 +    return true;
  1.2254 +}
  1.2255 +
  1.2256 +JS_PUBLIC_API(bool)
  1.2257 +JS_StrictPropertyStub(JSContext *cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
  1.2258 +{
  1.2259 +    return true;
  1.2260 +}
  1.2261 +
  1.2262 +JS_PUBLIC_API(bool)
  1.2263 +JS_DeletePropertyStub(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
  1.2264 +{
  1.2265 +    *succeeded = true;
  1.2266 +    return true;
  1.2267 +}
  1.2268 +
  1.2269 +JS_PUBLIC_API(bool)
  1.2270 +JS_EnumerateStub(JSContext *cx, HandleObject obj)
  1.2271 +{
  1.2272 +    return true;
  1.2273 +}
  1.2274 +
  1.2275 +JS_PUBLIC_API(bool)
  1.2276 +JS_ResolveStub(JSContext *cx, HandleObject obj, HandleId id)
  1.2277 +{
  1.2278 +    return true;
  1.2279 +}
  1.2280 +
  1.2281 +JS_PUBLIC_API(bool)
  1.2282 +JS_ConvertStub(JSContext *cx, HandleObject obj, JSType type, MutableHandleValue vp)
  1.2283 +{
  1.2284 +    JS_ASSERT(type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION);
  1.2285 +    JS_ASSERT(obj);
  1.2286 +    return DefaultValue(cx, obj, type, vp);
  1.2287 +}
  1.2288 +
  1.2289 +JS_PUBLIC_API(JSObject *)
  1.2290 +JS_InitClass(JSContext *cx, HandleObject obj, HandleObject parent_proto,
  1.2291 +             const JSClass *clasp, JSNative constructor, unsigned nargs,
  1.2292 +             const JSPropertySpec *ps, const JSFunctionSpec *fs,
  1.2293 +             const JSPropertySpec *static_ps, const JSFunctionSpec *static_fs)
  1.2294 +{
  1.2295 +    AssertHeapIsIdle(cx);
  1.2296 +    CHECK_REQUEST(cx);
  1.2297 +    assertSameCompartment(cx, obj, parent_proto);
  1.2298 +    return js_InitClass(cx, obj, parent_proto, Valueify(clasp), constructor,
  1.2299 +                        nargs, ps, fs, static_ps, static_fs);
  1.2300 +}
  1.2301 +
  1.2302 +JS_PUBLIC_API(bool)
  1.2303 +JS_LinkConstructorAndPrototype(JSContext *cx, HandleObject ctor, HandleObject proto)
  1.2304 +{
  1.2305 +    return LinkConstructorAndPrototype(cx, ctor, proto);
  1.2306 +}
  1.2307 +
  1.2308 +JS_PUBLIC_API(const JSClass *)
  1.2309 +JS_GetClass(JSObject *obj)
  1.2310 +{
  1.2311 +    return obj->getJSClass();
  1.2312 +}
  1.2313 +
  1.2314 +JS_PUBLIC_API(bool)
  1.2315 +JS_InstanceOf(JSContext *cx, HandleObject obj, const JSClass *clasp, CallArgs *args)
  1.2316 +{
  1.2317 +    AssertHeapIsIdle(cx);
  1.2318 +    CHECK_REQUEST(cx);
  1.2319 +#ifdef DEBUG
  1.2320 +    if (args) {
  1.2321 +        assertSameCompartment(cx, obj);
  1.2322 +        assertSameCompartment(cx, args->thisv(), args->calleev());
  1.2323 +    }
  1.2324 +#endif
  1.2325 +    if (!obj || obj->getJSClass() != clasp) {
  1.2326 +        if (args)
  1.2327 +            ReportIncompatibleMethod(cx, *args, Valueify(clasp));
  1.2328 +        return false;
  1.2329 +    }
  1.2330 +    return true;
  1.2331 +}
  1.2332 +
  1.2333 +JS_PUBLIC_API(bool)
  1.2334 +JS_HasInstance(JSContext *cx, HandleObject obj, HandleValue value, bool *bp)
  1.2335 +{
  1.2336 +    AssertHeapIsIdle(cx);
  1.2337 +    assertSameCompartment(cx, obj, value);
  1.2338 +    return HasInstance(cx, obj, value, bp);
  1.2339 +}
  1.2340 +
  1.2341 +JS_PUBLIC_API(void *)
  1.2342 +JS_GetPrivate(JSObject *obj)
  1.2343 +{
  1.2344 +    /* This function can be called by a finalizer. */
  1.2345 +    return obj->getPrivate();
  1.2346 +}
  1.2347 +
  1.2348 +JS_PUBLIC_API(void)
  1.2349 +JS_SetPrivate(JSObject *obj, void *data)
  1.2350 +{
  1.2351 +    /* This function can be called by a finalizer. */
  1.2352 +    obj->setPrivate(data);
  1.2353 +}
  1.2354 +
  1.2355 +JS_PUBLIC_API(void *)
  1.2356 +JS_GetInstancePrivate(JSContext *cx, HandleObject obj, const JSClass *clasp, CallArgs *args)
  1.2357 +{
  1.2358 +    if (!JS_InstanceOf(cx, obj, clasp, args))
  1.2359 +        return nullptr;
  1.2360 +    return obj->getPrivate();
  1.2361 +}
  1.2362 +
  1.2363 +JS_PUBLIC_API(bool)
  1.2364 +JS_GetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JSObject*> protop)
  1.2365 +{
  1.2366 +    return JSObject::getProto(cx, obj, protop);
  1.2367 +}
  1.2368 +
  1.2369 +JS_PUBLIC_API(bool)
  1.2370 +JS_SetPrototype(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<JSObject*> proto)
  1.2371 +{
  1.2372 +    AssertHeapIsIdle(cx);
  1.2373 +    CHECK_REQUEST(cx);
  1.2374 +    assertSameCompartment(cx, obj, proto);
  1.2375 +
  1.2376 +    bool succeeded;
  1.2377 +    if (!JSObject::setProto(cx, obj, proto, &succeeded))
  1.2378 +        return false;
  1.2379 +
  1.2380 +    if (!succeeded) {
  1.2381 +        RootedValue val(cx, ObjectValue(*obj));
  1.2382 +        js_ReportValueError(cx, JSMSG_SETPROTOTYPEOF_FAIL, JSDVG_IGNORE_STACK, val, js::NullPtr());
  1.2383 +        return false;
  1.2384 +    }
  1.2385 +
  1.2386 +    return true;
  1.2387 +}
  1.2388 +
  1.2389 +JS_PUBLIC_API(JSObject *)
  1.2390 +JS_GetParent(JSObject *obj)
  1.2391 +{
  1.2392 +    JS_ASSERT(!obj->is<ScopeObject>());
  1.2393 +    return obj->getParent();
  1.2394 +}
  1.2395 +
  1.2396 +JS_PUBLIC_API(bool)
  1.2397 +JS_SetParent(JSContext *cx, HandleObject obj, HandleObject parent)
  1.2398 +{
  1.2399 +    AssertHeapIsIdle(cx);
  1.2400 +    CHECK_REQUEST(cx);
  1.2401 +    JS_ASSERT(!obj->is<ScopeObject>());
  1.2402 +    JS_ASSERT(parent || !obj->getParent());
  1.2403 +    assertSameCompartment(cx, obj, parent);
  1.2404 +
  1.2405 +    return JSObject::setParent(cx, obj, parent);
  1.2406 +}
  1.2407 +
  1.2408 +JS_PUBLIC_API(JSObject *)
  1.2409 +JS_GetConstructor(JSContext *cx, HandleObject proto)
  1.2410 +{
  1.2411 +    AssertHeapIsIdle(cx);
  1.2412 +    CHECK_REQUEST(cx);
  1.2413 +    assertSameCompartment(cx, proto);
  1.2414 +
  1.2415 +    RootedValue cval(cx);
  1.2416 +    if (!JSObject::getProperty(cx, proto, proto, cx->names().constructor, &cval))
  1.2417 +        return nullptr;
  1.2418 +    if (!IsFunctionObject(cval)) {
  1.2419 +        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
  1.2420 +                             proto->getClass()->name);
  1.2421 +        return nullptr;
  1.2422 +    }
  1.2423 +    return &cval.toObject();
  1.2424 +}
  1.2425 +
  1.2426 +namespace {
  1.2427 +
  1.2428 +class AutoCompartmentRooter : private JS::CustomAutoRooter
  1.2429 +{
  1.2430 +  public:
  1.2431 +    explicit AutoCompartmentRooter(JSContext *cx, JSCompartment *comp
  1.2432 +                                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  1.2433 +      : CustomAutoRooter(cx), compartment(comp)
  1.2434 +    {
  1.2435 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.2436 +    }
  1.2437 +
  1.2438 +    operator JSCompartment *() {
  1.2439 +        return compartment;
  1.2440 +    }
  1.2441 +
  1.2442 +    JSCompartment *operator->() {
  1.2443 +        return compartment;
  1.2444 +    }
  1.2445 +
  1.2446 +  protected:
  1.2447 +    virtual void trace(JSTracer *trc)
  1.2448 +    {
  1.2449 +        compartment->mark();
  1.2450 +    }
  1.2451 +
  1.2452 +  private:
  1.2453 +    JSCompartment *compartment;
  1.2454 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.2455 +};
  1.2456 +
  1.2457 +} /* anonymous namespace */
  1.2458 +
  1.2459 +bool
  1.2460 +JS::CompartmentOptions::cloneSingletons(JSContext *cx) const
  1.2461 +{
  1.2462 +    return cloneSingletonsOverride_.get(cx->options().cloneSingletons());
  1.2463 +}
  1.2464 +
  1.2465 +JS::CompartmentOptions &
  1.2466 +JS::CompartmentOptions::setZone(ZoneSpecifier spec)
  1.2467 +{
  1.2468 +    zone_.spec = spec;
  1.2469 +    return *this;
  1.2470 +}
  1.2471 +
  1.2472 +JS::CompartmentOptions &
  1.2473 +JS::CompartmentOptions::setSameZoneAs(JSObject *obj)
  1.2474 +{
  1.2475 +    zone_.pointer = static_cast<void *>(obj->zone());
  1.2476 +    return *this;
  1.2477 +}
  1.2478 +
  1.2479 +JS::CompartmentOptions &
  1.2480 +JS::CompartmentOptionsRef(JSCompartment *compartment)
  1.2481 +{
  1.2482 +    return compartment->options();
  1.2483 +}
  1.2484 +
  1.2485 +JS::CompartmentOptions &
  1.2486 +JS::CompartmentOptionsRef(JSObject *obj)
  1.2487 +{
  1.2488 +    return obj->compartment()->options();
  1.2489 +}
  1.2490 +
  1.2491 +JS::CompartmentOptions &
  1.2492 +JS::CompartmentOptionsRef(JSContext *cx)
  1.2493 +{
  1.2494 +    return cx->compartment()->options();
  1.2495 +}
  1.2496 +
  1.2497 +JS_PUBLIC_API(JSObject *)
  1.2498 +JS_NewGlobalObject(JSContext *cx, const JSClass *clasp, JSPrincipals *principals,
  1.2499 +                   JS::OnNewGlobalHookOption hookOption,
  1.2500 +                   const JS::CompartmentOptions &options /* = JS::CompartmentOptions() */)
  1.2501 +{
  1.2502 +    AssertHeapIsIdle(cx);
  1.2503 +    CHECK_REQUEST(cx);
  1.2504 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.2505 +    JS_ASSERT(!cx->isExceptionPending());
  1.2506 +
  1.2507 +    JSRuntime *rt = cx->runtime();
  1.2508 +
  1.2509 +    Zone *zone;
  1.2510 +    if (options.zoneSpecifier() == JS::SystemZone)
  1.2511 +        zone = rt->systemZone;
  1.2512 +    else if (options.zoneSpecifier() == JS::FreshZone)
  1.2513 +        zone = nullptr;
  1.2514 +    else
  1.2515 +        zone = static_cast<Zone *>(options.zonePointer());
  1.2516 +
  1.2517 +    AutoCompartmentRooter compartment(cx, NewCompartment(cx, zone, principals, options));
  1.2518 +    if (!compartment)
  1.2519 +        return nullptr;
  1.2520 +
  1.2521 +    // Lazily create the system zone.
  1.2522 +    if (!rt->systemZone && options.zoneSpecifier() == JS::SystemZone) {
  1.2523 +        rt->systemZone = compartment->zone();
  1.2524 +        rt->systemZone->isSystem = true;
  1.2525 +    }
  1.2526 +
  1.2527 +    Rooted<GlobalObject *> global(cx);
  1.2528 +    {
  1.2529 +        AutoCompartment ac(cx, compartment);
  1.2530 +        global = GlobalObject::create(cx, Valueify(clasp));
  1.2531 +    }
  1.2532 +
  1.2533 +    if (!global)
  1.2534 +        return nullptr;
  1.2535 +
  1.2536 +    if (hookOption == JS::FireOnNewGlobalHook)
  1.2537 +        JS_FireOnNewGlobalObject(cx, global);
  1.2538 +
  1.2539 +    return global;
  1.2540 +}
  1.2541 +
  1.2542 +JS_PUBLIC_API(void)
  1.2543 +JS_GlobalObjectTraceHook(JSTracer *trc, JSObject *global)
  1.2544 +{
  1.2545 +    JS_ASSERT(global->is<GlobalObject>());
  1.2546 +
  1.2547 +    // Off thread parsing and compilation tasks create a dummy global which is then
  1.2548 +    // merged back into the host compartment. Since it used to be a global, it will still
  1.2549 +    // have this trace hook, but it does not have a meaning relative to its new compartment.
  1.2550 +    // We can safely skip it.
  1.2551 +    if (!global->isOwnGlobal())
  1.2552 +        return;
  1.2553 +
  1.2554 +    // Trace the compartment for any GC things that should only stick around if we know the
  1.2555 +    // compartment is live.
  1.2556 +    global->compartment()->trace(trc);
  1.2557 +
  1.2558 +    JSTraceOp trace = global->compartment()->options().getTrace();
  1.2559 +    if (trace)
  1.2560 +        trace(trc, global);
  1.2561 +}
  1.2562 +
  1.2563 +JS_PUBLIC_API(void)
  1.2564 +JS_FireOnNewGlobalObject(JSContext *cx, JS::HandleObject global)
  1.2565 +{
  1.2566 +    // This hook is infallible, because we don't really want arbitrary script
  1.2567 +    // to be able to throw errors during delicate global creation routines.
  1.2568 +    // This infallibility will eat OOM and slow script, but if that happens
  1.2569 +    // we'll likely run up into them again soon in a fallible context.
  1.2570 +    Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>());
  1.2571 +    Debugger::onNewGlobalObject(cx, globalObject);
  1.2572 +}
  1.2573 +
  1.2574 +JS_PUBLIC_API(JSObject *)
  1.2575 +JS_NewObject(JSContext *cx, const JSClass *jsclasp, HandleObject proto, HandleObject parent)
  1.2576 +{
  1.2577 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.2578 +    AssertHeapIsIdle(cx);
  1.2579 +    CHECK_REQUEST(cx);
  1.2580 +    assertSameCompartment(cx, proto, parent);
  1.2581 +
  1.2582 +    const Class *clasp = Valueify(jsclasp);
  1.2583 +    if (!clasp)
  1.2584 +        clasp = &JSObject::class_;    /* default class is Object */
  1.2585 +
  1.2586 +    JS_ASSERT(clasp != &JSFunction::class_);
  1.2587 +    JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
  1.2588 +
  1.2589 +    JSObject *obj = NewObjectWithClassProto(cx, clasp, proto, parent);
  1.2590 +    JS_ASSERT_IF(obj, obj->getParent());
  1.2591 +    return obj;
  1.2592 +}
  1.2593 +
  1.2594 +JS_PUBLIC_API(JSObject *)
  1.2595 +JS_NewObjectWithGivenProto(JSContext *cx, const JSClass *jsclasp, HandleObject proto, HandleObject parent)
  1.2596 +{
  1.2597 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.2598 +    AssertHeapIsIdle(cx);
  1.2599 +    CHECK_REQUEST(cx);
  1.2600 +    assertSameCompartment(cx, proto, parent);
  1.2601 +
  1.2602 +    const Class *clasp = Valueify(jsclasp);
  1.2603 +    if (!clasp)
  1.2604 +        clasp = &JSObject::class_;    /* default class is Object */
  1.2605 +
  1.2606 +    JS_ASSERT(clasp != &JSFunction::class_);
  1.2607 +    JS_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL));
  1.2608 +
  1.2609 +    JSObject *obj = NewObjectWithGivenProto(cx, clasp, proto, parent);
  1.2610 +    if (obj)
  1.2611 +        MarkTypeObjectUnknownProperties(cx, obj->type());
  1.2612 +    return obj;
  1.2613 +}
  1.2614 +
  1.2615 +JS_PUBLIC_API(JSObject *)
  1.2616 +JS_NewObjectForConstructor(JSContext *cx, const JSClass *clasp, const CallArgs& args)
  1.2617 +{
  1.2618 +    AssertHeapIsIdle(cx);
  1.2619 +    CHECK_REQUEST(cx);
  1.2620 +
  1.2621 +    Value callee = args.calleev();
  1.2622 +    assertSameCompartment(cx, callee);
  1.2623 +    RootedObject obj(cx, &callee.toObject());
  1.2624 +    return CreateThis(cx, Valueify(clasp), obj);
  1.2625 +}
  1.2626 +
  1.2627 +JS_PUBLIC_API(bool)
  1.2628 +JS_IsExtensible(JSContext *cx, HandleObject obj, bool *extensible)
  1.2629 +{
  1.2630 +    return JSObject::isExtensible(cx, obj, extensible);
  1.2631 +}
  1.2632 +
  1.2633 +JS_PUBLIC_API(bool)
  1.2634 +JS_IsNative(JSObject *obj)
  1.2635 +{
  1.2636 +    return obj->isNative();
  1.2637 +}
  1.2638 +
  1.2639 +JS_PUBLIC_API(JSRuntime *)
  1.2640 +JS_GetObjectRuntime(JSObject *obj)
  1.2641 +{
  1.2642 +    return obj->compartment()->runtimeFromMainThread();
  1.2643 +}
  1.2644 +
  1.2645 +JS_PUBLIC_API(bool)
  1.2646 +JS_FreezeObject(JSContext *cx, HandleObject obj)
  1.2647 +{
  1.2648 +    AssertHeapIsIdle(cx);
  1.2649 +    CHECK_REQUEST(cx);
  1.2650 +    assertSameCompartment(cx, obj);
  1.2651 +    return JSObject::freeze(cx, obj);
  1.2652 +}
  1.2653 +
  1.2654 +JS_PUBLIC_API(bool)
  1.2655 +JS_DeepFreezeObject(JSContext *cx, HandleObject obj)
  1.2656 +{
  1.2657 +    AssertHeapIsIdle(cx);
  1.2658 +    CHECK_REQUEST(cx);
  1.2659 +    assertSameCompartment(cx, obj);
  1.2660 +
  1.2661 +    /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
  1.2662 +    bool extensible;
  1.2663 +    if (!JSObject::isExtensible(cx, obj, &extensible))
  1.2664 +        return false;
  1.2665 +    if (!extensible)
  1.2666 +        return true;
  1.2667 +
  1.2668 +    if (!JSObject::freeze(cx, obj))
  1.2669 +        return false;
  1.2670 +
  1.2671 +    /* Walk slots in obj and if any value is a non-null object, seal it. */
  1.2672 +    for (uint32_t i = 0, n = obj->slotSpan(); i < n; ++i) {
  1.2673 +        const Value &v = obj->getSlot(i);
  1.2674 +        if (v.isPrimitive())
  1.2675 +            continue;
  1.2676 +        RootedObject obj(cx, &v.toObject());
  1.2677 +        if (!JS_DeepFreezeObject(cx, obj))
  1.2678 +            return false;
  1.2679 +    }
  1.2680 +
  1.2681 +    return true;
  1.2682 +}
  1.2683 +
  1.2684 +static bool
  1.2685 +LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id,
  1.2686 +                   MutableHandleObject objp, MutableHandleShape propp)
  1.2687 +{
  1.2688 +    AssertHeapIsIdle(cx);
  1.2689 +    CHECK_REQUEST(cx);
  1.2690 +    assertSameCompartment(cx, obj, id);
  1.2691 +
  1.2692 +    return JSObject::lookupGeneric(cx, obj, id, objp, propp);
  1.2693 +}
  1.2694 +
  1.2695 +#define AUTO_NAMELEN(s,n)   (((n) == (size_t)-1) ? js_strlen(s) : (n))
  1.2696 +
  1.2697 +static bool
  1.2698 +LookupResult(JSContext *cx, HandleObject obj, HandleObject obj2, HandleId id,
  1.2699 +             HandleShape shape, MutableHandleValue vp)
  1.2700 +{
  1.2701 +    if (!shape) {
  1.2702 +        /* XXX bad API: no way to tell "not defined" from "void value" */
  1.2703 +        vp.setUndefined();
  1.2704 +        return true;
  1.2705 +    }
  1.2706 +
  1.2707 +    if (!obj2->isNative()) {
  1.2708 +        if (obj2->is<ProxyObject>()) {
  1.2709 +            Rooted<PropertyDescriptor> desc(cx);
  1.2710 +            if (!Proxy::getPropertyDescriptor(cx, obj2, id, &desc))
  1.2711 +                return false;
  1.2712 +            if (!desc.isShared()) {
  1.2713 +                vp.set(desc.value());
  1.2714 +                return true;
  1.2715 +            }
  1.2716 +        }
  1.2717 +    } else if (IsImplicitDenseOrTypedArrayElement(shape)) {
  1.2718 +        vp.set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
  1.2719 +        return true;
  1.2720 +    } else {
  1.2721 +        /* Peek at the native property's slot value, without doing a Get. */
  1.2722 +        if (shape->hasSlot()) {
  1.2723 +            vp.set(obj2->nativeGetSlot(shape->slot()));
  1.2724 +            return true;
  1.2725 +        }
  1.2726 +    }
  1.2727 +
  1.2728 +    /* XXX bad API: no way to return "defined but value unknown" */
  1.2729 +    vp.setBoolean(true);
  1.2730 +    return true;
  1.2731 +}
  1.2732 +
  1.2733 +JS_PUBLIC_API(bool)
  1.2734 +JS_LookupPropertyById(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
  1.2735 +{
  1.2736 +    RootedObject obj2(cx);
  1.2737 +    RootedShape prop(cx);
  1.2738 +
  1.2739 +    return LookupPropertyById(cx, obj, id, &obj2, &prop) &&
  1.2740 +           LookupResult(cx, obj, obj2, id, prop, vp);
  1.2741 +}
  1.2742 +
  1.2743 +JS_PUBLIC_API(bool)
  1.2744 +JS_LookupElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
  1.2745 +{
  1.2746 +    CHECK_REQUEST(cx);
  1.2747 +    RootedId id(cx);
  1.2748 +    if (!IndexToId(cx, index, &id))
  1.2749 +        return false;
  1.2750 +    return JS_LookupPropertyById(cx, obj, id, vp);
  1.2751 +}
  1.2752 +
  1.2753 +JS_PUBLIC_API(bool)
  1.2754 +JS_LookupProperty(JSContext *cx, HandleObject objArg, const char *name, MutableHandleValue vp)
  1.2755 +{
  1.2756 +    RootedObject obj(cx, objArg);
  1.2757 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.2758 +    if (!atom)
  1.2759 +        return false;
  1.2760 +
  1.2761 +    RootedId id(cx, AtomToId(atom));
  1.2762 +    return JS_LookupPropertyById(cx, obj, id, vp);
  1.2763 +}
  1.2764 +
  1.2765 +JS_PUBLIC_API(bool)
  1.2766 +JS_LookupUCProperty(JSContext *cx, HandleObject objArg, const jschar *name, size_t namelen,
  1.2767 +                    MutableHandleValue vp)
  1.2768 +{
  1.2769 +    RootedObject obj(cx, objArg);
  1.2770 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.2771 +    if (!atom)
  1.2772 +        return false;
  1.2773 +
  1.2774 +    RootedId id(cx, AtomToId(atom));
  1.2775 +    return JS_LookupPropertyById(cx, obj, id, vp);
  1.2776 +}
  1.2777 +
  1.2778 +JS_PUBLIC_API(bool)
  1.2779 +JS_HasPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool *foundp)
  1.2780 +{
  1.2781 +    RootedObject obj2(cx);
  1.2782 +    RootedShape prop(cx);
  1.2783 +    bool ok = LookupPropertyById(cx, obj, id, &obj2, &prop);
  1.2784 +    *foundp = (prop != nullptr);
  1.2785 +    return ok;
  1.2786 +}
  1.2787 +
  1.2788 +JS_PUBLIC_API(bool)
  1.2789 +JS_HasElement(JSContext *cx, HandleObject obj, uint32_t index, bool *foundp)
  1.2790 +{
  1.2791 +    AssertHeapIsIdle(cx);
  1.2792 +    CHECK_REQUEST(cx);
  1.2793 +    RootedId id(cx);
  1.2794 +    if (!IndexToId(cx, index, &id))
  1.2795 +        return false;
  1.2796 +    return JS_HasPropertyById(cx, obj, id, foundp);
  1.2797 +}
  1.2798 +
  1.2799 +JS_PUBLIC_API(bool)
  1.2800 +JS_HasProperty(JSContext *cx, HandleObject obj, const char *name, bool *foundp)
  1.2801 +{
  1.2802 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.2803 +    if (!atom)
  1.2804 +        return false;
  1.2805 +    RootedId id(cx, AtomToId(atom));
  1.2806 +    return JS_HasPropertyById(cx, obj, id, foundp);
  1.2807 +}
  1.2808 +
  1.2809 +JS_PUBLIC_API(bool)
  1.2810 +JS_HasUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen, bool *foundp)
  1.2811 +{
  1.2812 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.2813 +    if (!atom)
  1.2814 +        return false;
  1.2815 +    RootedId id(cx, AtomToId(atom));
  1.2816 +    return JS_HasPropertyById(cx, obj, id, foundp);
  1.2817 +}
  1.2818 +
  1.2819 +JS_PUBLIC_API(bool)
  1.2820 +JS_AlreadyHasOwnPropertyById(JSContext *cx, HandleObject obj, HandleId id, bool *foundp)
  1.2821 +{
  1.2822 +    AssertHeapIsIdle(cx);
  1.2823 +    CHECK_REQUEST(cx);
  1.2824 +    assertSameCompartment(cx, obj, id);
  1.2825 +
  1.2826 +    if (!obj->isNative()) {
  1.2827 +        RootedObject obj2(cx);
  1.2828 +        RootedShape prop(cx);
  1.2829 +
  1.2830 +        if (!LookupPropertyById(cx, obj, id, &obj2, &prop))
  1.2831 +            return false;
  1.2832 +        *foundp = (obj == obj2);
  1.2833 +        return true;
  1.2834 +    }
  1.2835 +
  1.2836 +    // Check for an existing native property on the objct. Be careful not to
  1.2837 +    // call any lookup or resolve hooks.
  1.2838 +
  1.2839 +    if (JSID_IS_INT(id)) {
  1.2840 +        uint32_t index = JSID_TO_INT(id);
  1.2841 +
  1.2842 +        if (obj->containsDenseElement(index)) {
  1.2843 +            *foundp = true;
  1.2844 +            return true;
  1.2845 +        }
  1.2846 +
  1.2847 +        if (obj->is<TypedArrayObject>() && index < obj->as<TypedArrayObject>().length()) {
  1.2848 +            *foundp = true;
  1.2849 +            return true;
  1.2850 +        }
  1.2851 +    }
  1.2852 +
  1.2853 +    *foundp = obj->nativeContains(cx, id);
  1.2854 +    return true;
  1.2855 +}
  1.2856 +
  1.2857 +JS_PUBLIC_API(bool)
  1.2858 +JS_AlreadyHasOwnElement(JSContext *cx, HandleObject obj, uint32_t index, bool *foundp)
  1.2859 +{
  1.2860 +    AssertHeapIsIdle(cx);
  1.2861 +    CHECK_REQUEST(cx);
  1.2862 +    RootedId id(cx);
  1.2863 +    if (!IndexToId(cx, index, &id))
  1.2864 +        return false;
  1.2865 +    return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
  1.2866 +}
  1.2867 +
  1.2868 +JS_PUBLIC_API(bool)
  1.2869 +JS_AlreadyHasOwnProperty(JSContext *cx, HandleObject obj, const char *name, bool *foundp)
  1.2870 +{
  1.2871 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.2872 +    if (!atom)
  1.2873 +        return false;
  1.2874 +    RootedId id(cx, AtomToId(atom));
  1.2875 +    return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
  1.2876 +}
  1.2877 +
  1.2878 +JS_PUBLIC_API(bool)
  1.2879 +JS_AlreadyHasOwnUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  1.2880 +                           bool *foundp)
  1.2881 +{
  1.2882 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.2883 +    if (!atom)
  1.2884 +        return false;
  1.2885 +    RootedId id(cx, AtomToId(atom));
  1.2886 +    return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
  1.2887 +}
  1.2888 +
  1.2889 +/* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
  1.2890 + * function arguments.
  1.2891 + */
  1.2892 +static JSPropertyOpWrapper
  1.2893 +GetterWrapper(JSPropertyOp getter)
  1.2894 +{
  1.2895 +    JSPropertyOpWrapper ret;
  1.2896 +    ret.op = getter;
  1.2897 +    ret.info = nullptr;
  1.2898 +    return ret;
  1.2899 +}
  1.2900 +
  1.2901 +static JSStrictPropertyOpWrapper
  1.2902 +SetterWrapper(JSStrictPropertyOp setter)
  1.2903 +{
  1.2904 +    JSStrictPropertyOpWrapper ret;
  1.2905 +    ret.op = setter;
  1.2906 +    ret.info = nullptr;
  1.2907 +    return ret;
  1.2908 +}
  1.2909 +
  1.2910 +static bool
  1.2911 +DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
  1.2912 +                   const JSPropertyOpWrapper &get, const JSStrictPropertyOpWrapper &set,
  1.2913 +                   unsigned attrs, unsigned flags)
  1.2914 +{
  1.2915 +    PropertyOp getter = get.op;
  1.2916 +    StrictPropertyOp setter = set.op;
  1.2917 +    /*
  1.2918 +     * JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd
  1.2919 +     * throw if this happens, but we've accepted it for long enough that it's
  1.2920 +     * not worth trying to make callers change their ways. Just flip it off on
  1.2921 +     * its way through the API layer so that we can enforce this internally.
  1.2922 +     */
  1.2923 +    if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
  1.2924 +        attrs &= ~JSPROP_READONLY;
  1.2925 +
  1.2926 +    /*
  1.2927 +     * When we use DefineProperty, we need full scriptable Function objects rather
  1.2928 +     * than JSNatives. However, we might be pulling this property descriptor off
  1.2929 +     * of something with JSNative property descriptors. If we are, wrap them in
  1.2930 +     * JS Function objects.
  1.2931 +     */
  1.2932 +    if (attrs & JSPROP_NATIVE_ACCESSORS) {
  1.2933 +        JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
  1.2934 +        JSFunction::Flags zeroFlags = JSAPIToJSFunctionFlags(0);
  1.2935 +        // We can't just use JS_NewFunctionById here because it
  1.2936 +        // assumes a string id.
  1.2937 +        RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : nullptr);
  1.2938 +        attrs &= ~JSPROP_NATIVE_ACCESSORS;
  1.2939 +        if (getter) {
  1.2940 +            RootedObject global(cx, (JSObject*) &obj->global());
  1.2941 +            JSFunction *getobj = NewFunction(cx, NullPtr(), (Native) getter, 0,
  1.2942 +                                             zeroFlags, global, atom);
  1.2943 +            if (!getobj)
  1.2944 +                return false;
  1.2945 +
  1.2946 +            if (get.info)
  1.2947 +                getobj->setJitInfo(get.info);
  1.2948 +
  1.2949 +            getter = JS_DATA_TO_FUNC_PTR(PropertyOp, getobj);
  1.2950 +            attrs |= JSPROP_GETTER;
  1.2951 +        }
  1.2952 +        if (setter) {
  1.2953 +            // Root just the getter, since the setter is not yet a JSObject.
  1.2954 +            AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, nullptr);
  1.2955 +            RootedObject global(cx, (JSObject*) &obj->global());
  1.2956 +            JSFunction *setobj = NewFunction(cx, NullPtr(), (Native) setter, 1,
  1.2957 +                                             zeroFlags, global, atom);
  1.2958 +            if (!setobj)
  1.2959 +                return false;
  1.2960 +
  1.2961 +            if (set.info)
  1.2962 +                setobj->setJitInfo(set.info);
  1.2963 +
  1.2964 +            setter = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setobj);
  1.2965 +            attrs |= JSPROP_SETTER;
  1.2966 +        }
  1.2967 +    }
  1.2968 +
  1.2969 +
  1.2970 +    AssertHeapIsIdle(cx);
  1.2971 +    CHECK_REQUEST(cx);
  1.2972 +    assertSameCompartment(cx, obj, id, value,
  1.2973 +                            (attrs & JSPROP_GETTER)
  1.2974 +                            ? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
  1.2975 +                            : nullptr,
  1.2976 +                            (attrs & JSPROP_SETTER)
  1.2977 +                            ? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
  1.2978 +                            : nullptr);
  1.2979 +
  1.2980 +    return JSObject::defineGeneric(cx, obj, id, value, getter, setter, attrs);
  1.2981 +}
  1.2982 +
  1.2983 +JS_PUBLIC_API(bool)
  1.2984 +JS_DefinePropertyById(JSContext *cx, JSObject *objArg, jsid idArg, jsval valueArg,
  1.2985 +                      JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
  1.2986 +{
  1.2987 +    RootedObject obj(cx, objArg);
  1.2988 +    RootedId id(cx, idArg);
  1.2989 +    RootedValue value(cx, valueArg);
  1.2990 +    return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), SetterWrapper(setter),
  1.2991 +                              attrs, 0);
  1.2992 +}
  1.2993 +
  1.2994 +JS_PUBLIC_API(bool)
  1.2995 +JS_DefineElement(JSContext *cx, JSObject *objArg, uint32_t index, jsval valueArg,
  1.2996 +                 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
  1.2997 +{
  1.2998 +    RootedObject obj(cx, objArg);
  1.2999 +    RootedValue value(cx, valueArg);
  1.3000 +    AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
  1.3001 +    AssertHeapIsIdle(cx);
  1.3002 +    CHECK_REQUEST(cx);
  1.3003 +    RootedId id(cx);
  1.3004 +    if (!IndexToId(cx, index, &id))
  1.3005 +        return false;
  1.3006 +    return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), SetterWrapper(setter),
  1.3007 +                              attrs, 0);
  1.3008 +}
  1.3009 +
  1.3010 +static bool
  1.3011 +DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleValue value,
  1.3012 +               const JSPropertyOpWrapper &getter, const JSStrictPropertyOpWrapper &setter,
  1.3013 +               unsigned attrs, unsigned flags)
  1.3014 +{
  1.3015 +    AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSPropertyOp *>(&getter.op),
  1.3016 +                                  const_cast<JSStrictPropertyOp *>(&setter.op));
  1.3017 +
  1.3018 +    RootedId id(cx);
  1.3019 +    if (attrs & JSPROP_INDEX) {
  1.3020 +        id.set(INT_TO_JSID(intptr_t(name)));
  1.3021 +        attrs &= ~JSPROP_INDEX;
  1.3022 +    } else {
  1.3023 +        JSAtom *atom = Atomize(cx, name, strlen(name));
  1.3024 +        if (!atom)
  1.3025 +            return false;
  1.3026 +        id = AtomToId(atom);
  1.3027 +    }
  1.3028 +
  1.3029 +    return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags);
  1.3030 +}
  1.3031 +
  1.3032 +
  1.3033 +static bool
  1.3034 +DefineSelfHostedProperty(JSContext *cx,
  1.3035 +                         HandleObject obj,
  1.3036 +                         const char *name,
  1.3037 +                         const char *getterName,
  1.3038 +                         const char *setterName,
  1.3039 +                         unsigned attrs,
  1.3040 +                         unsigned flags)
  1.3041 +{
  1.3042 +    RootedAtom nameAtom(cx, Atomize(cx, name, strlen(name)));
  1.3043 +    if (!nameAtom)
  1.3044 +        return false;
  1.3045 +
  1.3046 +    RootedAtom getterNameAtom(cx, Atomize(cx, getterName, strlen(getterName)));
  1.3047 +    if (!getterNameAtom)
  1.3048 +        return false;
  1.3049 +
  1.3050 +    RootedValue getterValue(cx);
  1.3051 +    if (!cx->global()->getSelfHostedFunction(cx, getterNameAtom, nameAtom,
  1.3052 +                                             0, &getterValue))
  1.3053 +    {
  1.3054 +        return false;
  1.3055 +    }
  1.3056 +    JS_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
  1.3057 +    RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
  1.3058 +    JSPropertyOp getterOp = JS_DATA_TO_FUNC_PTR(PropertyOp, getterFunc.get());
  1.3059 +
  1.3060 +    RootedFunction setterFunc(cx);
  1.3061 +    if (setterName) {
  1.3062 +        RootedAtom setterNameAtom(cx, Atomize(cx, setterName, strlen(setterName)));
  1.3063 +        if (!setterNameAtom)
  1.3064 +            return false;
  1.3065 +
  1.3066 +        RootedValue setterValue(cx);
  1.3067 +        if (!cx->global()->getSelfHostedFunction(cx, setterNameAtom, nameAtom,
  1.3068 +                                                 0, &setterValue))
  1.3069 +        {
  1.3070 +            return false;
  1.3071 +        }
  1.3072 +        JS_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
  1.3073 +        setterFunc = &getterValue.toObject().as<JSFunction>();
  1.3074 +    }
  1.3075 +    JSStrictPropertyOp setterOp = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setterFunc.get());
  1.3076 +
  1.3077 +    return DefineProperty(cx, obj, name, JS::UndefinedHandleValue,
  1.3078 +                          GetterWrapper(getterOp), SetterWrapper(setterOp),
  1.3079 +                          attrs, flags);
  1.3080 +}
  1.3081 +
  1.3082 +JS_PUBLIC_API(bool)
  1.3083 +JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleValue value,
  1.3084 +                  unsigned attrs,
  1.3085 +                  PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  1.3086 +{
  1.3087 +    return DefineProperty(cx, obj, name, value, GetterWrapper(getter), SetterWrapper(setter),
  1.3088 +                          attrs, 0);
  1.3089 +}
  1.3090 +
  1.3091 +JS_PUBLIC_API(bool)
  1.3092 +JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleObject valueArg,
  1.3093 +                  unsigned attrs,
  1.3094 +                  PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  1.3095 +{
  1.3096 +    RootedValue value(cx, ObjectValue(*valueArg));
  1.3097 +    return DefineProperty(cx, obj, name, value, GetterWrapper(getter), SetterWrapper(setter),
  1.3098 +                          attrs, 0);
  1.3099 +}
  1.3100 +
  1.3101 +JS_PUBLIC_API(bool)
  1.3102 +JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleString valueArg,
  1.3103 +                  unsigned attrs,
  1.3104 +                  PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  1.3105 +{
  1.3106 +    RootedValue value(cx, StringValue(valueArg));
  1.3107 +    return DefineProperty(cx, obj, name, value, GetterWrapper(getter), SetterWrapper(setter),
  1.3108 +                          attrs, 0);
  1.3109 +}
  1.3110 +
  1.3111 +JS_PUBLIC_API(bool)
  1.3112 +JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, int32_t valueArg,
  1.3113 +                  unsigned attrs,
  1.3114 +                  PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  1.3115 +{
  1.3116 +    Value value = Int32Value(valueArg);
  1.3117 +    return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
  1.3118 +                          GetterWrapper(getter), SetterWrapper(setter), attrs, 0);
  1.3119 +}
  1.3120 +
  1.3121 +JS_PUBLIC_API(bool)
  1.3122 +JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, uint32_t valueArg,
  1.3123 +                  unsigned attrs,
  1.3124 +                  PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  1.3125 +{
  1.3126 +    Value value = UINT_TO_JSVAL(valueArg);
  1.3127 +    return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
  1.3128 +                          GetterWrapper(getter), SetterWrapper(setter), attrs, 0);
  1.3129 +}
  1.3130 +
  1.3131 +JS_PUBLIC_API(bool)
  1.3132 +JS_DefineProperty(JSContext *cx, HandleObject obj, const char *name, double valueArg,
  1.3133 +                  unsigned attrs,
  1.3134 +                  PropertyOp getter /* = nullptr */, JSStrictPropertyOp setter /* = nullptr */)
  1.3135 +{
  1.3136 +    Value value = NumberValue(valueArg);
  1.3137 +    return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value),
  1.3138 +                          GetterWrapper(getter), SetterWrapper(setter), attrs, 0);
  1.3139 +}
  1.3140 +
  1.3141 +static bool
  1.3142 +DefineUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  1.3143 +                 const Value &value_, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
  1.3144 +                 unsigned flags)
  1.3145 +{
  1.3146 +    RootedValue value(cx, value_);
  1.3147 +    AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
  1.3148 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.3149 +    if (!atom)
  1.3150 +        return false;
  1.3151 +    RootedId id(cx, AtomToId(atom));
  1.3152 +    return DefinePropertyById(cx, obj, id, value, GetterWrapper(getter), SetterWrapper(setter),
  1.3153 +                              attrs, flags);
  1.3154 +}
  1.3155 +
  1.3156 +JS_PUBLIC_API(bool)
  1.3157 +JS_DefineUCProperty(JSContext *cx, JSObject *objArg, const jschar *name, size_t namelen,
  1.3158 +                    jsval valueArg, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
  1.3159 +{
  1.3160 +    RootedObject obj(cx, objArg);
  1.3161 +    RootedValue value(cx, valueArg);
  1.3162 +    return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0);
  1.3163 +}
  1.3164 +
  1.3165 +JS_PUBLIC_API(bool)
  1.3166 +JS_DefineOwnProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue descriptor, bool *bp)
  1.3167 +{
  1.3168 +    AssertHeapIsIdle(cx);
  1.3169 +    CHECK_REQUEST(cx);
  1.3170 +    assertSameCompartment(cx, obj, id, descriptor);
  1.3171 +
  1.3172 +    return DefineOwnProperty(cx, obj, id, descriptor, bp);
  1.3173 +}
  1.3174 +
  1.3175 +JS_PUBLIC_API(JSObject *)
  1.3176 +JS_DefineObject(JSContext *cx, JSObject *objArg, const char *name, const JSClass *jsclasp,
  1.3177 +                JSObject *protoArg, unsigned attrs)
  1.3178 +{
  1.3179 +    RootedObject obj(cx, objArg);
  1.3180 +    RootedObject proto(cx, protoArg);
  1.3181 +    AssertHeapIsIdle(cx);
  1.3182 +    CHECK_REQUEST(cx);
  1.3183 +    assertSameCompartment(cx, obj, proto);
  1.3184 +
  1.3185 +    const Class *clasp = Valueify(jsclasp);
  1.3186 +    if (!clasp)
  1.3187 +        clasp = &JSObject::class_;    /* default class is Object */
  1.3188 +
  1.3189 +    RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, proto, obj));
  1.3190 +    if (!nobj)
  1.3191 +        return nullptr;
  1.3192 +
  1.3193 +    RootedValue nobjValue(cx, ObjectValue(*nobj));
  1.3194 +    if (!DefineProperty(cx, obj, name, nobjValue, GetterWrapper(nullptr), SetterWrapper(nullptr),
  1.3195 +                        attrs, 0)) {
  1.3196 +        return nullptr;
  1.3197 +    }
  1.3198 +
  1.3199 +    return nobj;
  1.3200 +}
  1.3201 +
  1.3202 +JS_PUBLIC_API(bool)
  1.3203 +JS_DefineConstDoubles(JSContext *cx, HandleObject obj, const JSConstDoubleSpec *cds)
  1.3204 +{
  1.3205 +    bool ok;
  1.3206 +    unsigned attrs;
  1.3207 +
  1.3208 +    AssertHeapIsIdle(cx);
  1.3209 +    CHECK_REQUEST(cx);
  1.3210 +    JSPropertyOpWrapper noget = GetterWrapper(nullptr);
  1.3211 +    JSStrictPropertyOpWrapper noset = SetterWrapper(nullptr);
  1.3212 +    for (ok = true; cds->name; cds++) {
  1.3213 +        RootedValue value(cx, DoubleValue(cds->dval));
  1.3214 +        attrs = cds->flags;
  1.3215 +        if (!attrs)
  1.3216 +            attrs = JSPROP_READONLY | JSPROP_PERMANENT;
  1.3217 +        ok = DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0);
  1.3218 +        if (!ok)
  1.3219 +            break;
  1.3220 +    }
  1.3221 +    return ok;
  1.3222 +}
  1.3223 +
  1.3224 +JS_PUBLIC_API(bool)
  1.3225 +JS_DefineProperties(JSContext *cx, HandleObject obj, const JSPropertySpec *ps)
  1.3226 +{
  1.3227 +    bool ok;
  1.3228 +    for (ok = true; ps->name; ps++) {
  1.3229 +        if (ps->flags & JSPROP_NATIVE_ACCESSORS) {
  1.3230 +            // If you declare native accessors, then you should have a native
  1.3231 +            // getter.
  1.3232 +            JS_ASSERT(ps->getter.propertyOp.op);
  1.3233 +            // If you do not have a self-hosted getter, you should not have a
  1.3234 +            // self-hosted setter. This is the closest approximation to that
  1.3235 +            // assertion we can have with our setup.
  1.3236 +            JS_ASSERT_IF(ps->setter.propertyOp.info, ps->setter.propertyOp.op);
  1.3237 +
  1.3238 +            ok = DefineProperty(cx, obj, ps->name, JS::UndefinedHandleValue,
  1.3239 +                                ps->getter.propertyOp, ps->setter.propertyOp, ps->flags, 0);
  1.3240 +        } else {
  1.3241 +            // If you have self-hosted getter/setter, you can't have a
  1.3242 +            // native one.
  1.3243 +            JS_ASSERT(!ps->getter.propertyOp.op && !ps->setter.propertyOp.op);
  1.3244 +            JS_ASSERT(ps->flags & JSPROP_GETTER);
  1.3245 +            /*
  1.3246 +             * During creation of the self-hosting global, we ignore all
  1.3247 +             * self-hosted properties, as that means we're currently setting up
  1.3248 +             * the global object that the self-hosted code is then compiled
  1.3249 +             * in. That means that Self-hosted properties can't be used in the
  1.3250 +             * self-hosting global itself, right now.
  1.3251 +             */
  1.3252 +            if (cx->runtime()->isSelfHostingGlobal(cx->global()))
  1.3253 +                continue;
  1.3254 +
  1.3255 +            ok = DefineSelfHostedProperty(cx, obj, ps->name,
  1.3256 +                                          ps->getter.selfHosted.funname,
  1.3257 +                                          ps->setter.selfHosted.funname,
  1.3258 +                                          ps->flags, 0);
  1.3259 +        }
  1.3260 +        if (!ok)
  1.3261 +            break;
  1.3262 +    }
  1.3263 +    return ok;
  1.3264 +}
  1.3265 +
  1.3266 +static bool
  1.3267 +GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id,
  1.3268 +                          MutableHandle<PropertyDescriptor> desc)
  1.3269 +{
  1.3270 +    RootedObject obj2(cx);
  1.3271 +    RootedShape shape(cx);
  1.3272 +
  1.3273 +    if (!LookupPropertyById(cx, obj, id, &obj2, &shape))
  1.3274 +        return false;
  1.3275 +
  1.3276 +    desc.clear();
  1.3277 +    if (!shape)
  1.3278 +        return true;
  1.3279 +
  1.3280 +    desc.object().set(obj2);
  1.3281 +    if (obj2->isNative()) {
  1.3282 +        if (IsImplicitDenseOrTypedArrayElement(shape)) {
  1.3283 +            desc.setEnumerable();
  1.3284 +            desc.value().set(obj2->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
  1.3285 +        } else {
  1.3286 +            desc.setAttributes(shape->attributes());
  1.3287 +            desc.setGetter(shape->getter());
  1.3288 +            desc.setSetter(shape->setter());
  1.3289 +            JS_ASSERT(desc.value().isUndefined());
  1.3290 +            if (shape->hasSlot())
  1.3291 +                desc.value().set(obj2->nativeGetSlot(shape->slot()));
  1.3292 +        }
  1.3293 +    } else {
  1.3294 +        if (obj2->is<ProxyObject>())
  1.3295 +            return Proxy::getPropertyDescriptor(cx, obj2, id, desc);
  1.3296 +        if (!JSObject::getGenericAttributes(cx, obj2, id, &desc.attributesRef()))
  1.3297 +            return false;
  1.3298 +        JS_ASSERT(desc.getter() == nullptr);
  1.3299 +        JS_ASSERT(desc.setter() == nullptr);
  1.3300 +        JS_ASSERT(desc.value().isUndefined());
  1.3301 +    }
  1.3302 +    return true;
  1.3303 +}
  1.3304 +
  1.3305 +JS_PUBLIC_API(bool)
  1.3306 +JS_GetOwnPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id,
  1.3307 +                                MutableHandle<JSPropertyDescriptor> desc)
  1.3308 +{
  1.3309 +    AssertHeapIsIdle(cx);
  1.3310 +    CHECK_REQUEST(cx);
  1.3311 +
  1.3312 +    return GetOwnPropertyDescriptor(cx, obj, id, desc);
  1.3313 +}
  1.3314 +
  1.3315 +JS_PUBLIC_API(bool)
  1.3316 +JS_GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, const char *name,
  1.3317 +                            MutableHandle<JSPropertyDescriptor> desc)
  1.3318 +{
  1.3319 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.3320 +    if (!atom)
  1.3321 +        return false;
  1.3322 +    RootedId id(cx, AtomToId(atom));
  1.3323 +    return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc);
  1.3324 +}
  1.3325 +
  1.3326 +JS_PUBLIC_API(bool)
  1.3327 +JS_GetPropertyDescriptorById(JSContext *cx, HandleObject obj, HandleId id,
  1.3328 +                             MutableHandle<JSPropertyDescriptor> desc)
  1.3329 +{
  1.3330 +    return GetPropertyDescriptorById(cx, obj, id, desc);
  1.3331 +}
  1.3332 +
  1.3333 +JS_PUBLIC_API(bool)
  1.3334 +JS_GetPropertyDescriptor(JSContext *cx, HandleObject obj, const char *name,
  1.3335 +                         MutableHandle<JSPropertyDescriptor> desc)
  1.3336 +{
  1.3337 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.3338 +    if (!atom)
  1.3339 +        return false;
  1.3340 +    RootedId id(cx, AtomToId(atom));
  1.3341 +    return atom && JS_GetPropertyDescriptorById(cx, obj, id, desc);
  1.3342 +}
  1.3343 +
  1.3344 +JS_PUBLIC_API(bool)
  1.3345 +JS_GetPropertyById(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp)
  1.3346 +{
  1.3347 +    return JS_ForwardGetPropertyTo(cx, obj, id, obj, vp);
  1.3348 +}
  1.3349 +
  1.3350 +JS_PUBLIC_API(bool)
  1.3351 +JS_ForwardGetPropertyTo(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject onBehalfOf,
  1.3352 +                        JS::MutableHandleValue vp)
  1.3353 +{
  1.3354 +    AssertHeapIsIdle(cx);
  1.3355 +    CHECK_REQUEST(cx);
  1.3356 +    assertSameCompartment(cx, obj, id);
  1.3357 +    assertSameCompartment(cx, onBehalfOf);
  1.3358 +
  1.3359 +    return JSObject::getGeneric(cx, obj, onBehalfOf, id, vp);
  1.3360 +}
  1.3361 +
  1.3362 +JS_PUBLIC_API(bool)
  1.3363 +JS_GetElement(JSContext *cx, HandleObject objArg, uint32_t index, MutableHandleValue vp)
  1.3364 +{
  1.3365 +    return JS_ForwardGetElementTo(cx, objArg, index, objArg, vp);
  1.3366 +}
  1.3367 +
  1.3368 +JS_PUBLIC_API(bool)
  1.3369 +JS_ForwardGetElementTo(JSContext *cx, HandleObject obj, uint32_t index, HandleObject onBehalfOf,
  1.3370 +                       MutableHandleValue vp)
  1.3371 +{
  1.3372 +    AssertHeapIsIdle(cx);
  1.3373 +    CHECK_REQUEST(cx);
  1.3374 +    assertSameCompartment(cx, obj);
  1.3375 +
  1.3376 +    return JSObject::getElement(cx, obj, onBehalfOf, index, vp);
  1.3377 +}
  1.3378 +
  1.3379 +JS_PUBLIC_API(bool)
  1.3380 +JS_GetProperty(JSContext *cx, HandleObject obj, const char *name, MutableHandleValue vp)
  1.3381 +{
  1.3382 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.3383 +    if (!atom)
  1.3384 +        return false;
  1.3385 +    RootedId id(cx, AtomToId(atom));
  1.3386 +    return JS_GetPropertyById(cx, obj, id, vp);
  1.3387 +}
  1.3388 +
  1.3389 +JS_PUBLIC_API(bool)
  1.3390 +JS_GetUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  1.3391 +                 MutableHandleValue vp)
  1.3392 +{
  1.3393 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.3394 +    if (!atom)
  1.3395 +        return false;
  1.3396 +    RootedId id(cx, AtomToId(atom));
  1.3397 +    return JS_GetPropertyById(cx, obj, id, vp);
  1.3398 +}
  1.3399 +
  1.3400 +JS_PUBLIC_API(bool)
  1.3401 +JS_SetPropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue v)
  1.3402 +{
  1.3403 +    RootedValue value(cx, v);
  1.3404 +    AssertHeapIsIdle(cx);
  1.3405 +    CHECK_REQUEST(cx);
  1.3406 +    assertSameCompartment(cx, obj, id);
  1.3407 +
  1.3408 +    return JSObject::setGeneric(cx, obj, obj, id, &value, false);
  1.3409 +}
  1.3410 +
  1.3411 +static bool
  1.3412 +SetElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
  1.3413 +{
  1.3414 +    AssertHeapIsIdle(cx);
  1.3415 +    CHECK_REQUEST(cx);
  1.3416 +    assertSameCompartment(cx, obj, vp);
  1.3417 +
  1.3418 +    return JSObject::setElement(cx, obj, obj, index, vp, false);
  1.3419 +}
  1.3420 +
  1.3421 +JS_PUBLIC_API(bool)
  1.3422 +JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v)
  1.3423 +{
  1.3424 +    RootedValue value(cx, v);
  1.3425 +    return SetElement(cx, obj, index, &value);
  1.3426 +}
  1.3427 +
  1.3428 +JS_PUBLIC_API(bool)
  1.3429 +JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleObject v)
  1.3430 +{
  1.3431 +    RootedValue value(cx, ObjectOrNullValue(v));
  1.3432 +    return SetElement(cx, obj, index, &value);
  1.3433 +}
  1.3434 +
  1.3435 +JS_PUBLIC_API(bool)
  1.3436 +JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleString v)
  1.3437 +{
  1.3438 +    RootedValue value(cx, StringValue(v));
  1.3439 +    return SetElement(cx, obj, index, &value);
  1.3440 +}
  1.3441 +
  1.3442 +JS_PUBLIC_API(bool)
  1.3443 +JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, int32_t v)
  1.3444 +{
  1.3445 +    RootedValue value(cx, NumberValue(v));
  1.3446 +    return SetElement(cx, obj, index, &value);
  1.3447 +}
  1.3448 +
  1.3449 +JS_PUBLIC_API(bool)
  1.3450 +JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, uint32_t v)
  1.3451 +{
  1.3452 +    RootedValue value(cx, NumberValue(v));
  1.3453 +    return SetElement(cx, obj, index, &value);
  1.3454 +}
  1.3455 +
  1.3456 +JS_PUBLIC_API(bool)
  1.3457 +JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, double v)
  1.3458 +{
  1.3459 +    RootedValue value(cx, NumberValue(v));
  1.3460 +    return SetElement(cx, obj, index, &value);
  1.3461 +}
  1.3462 +
  1.3463 +JS_PUBLIC_API(bool)
  1.3464 +JS_SetProperty(JSContext *cx, HandleObject obj, const char *name, HandleValue v)
  1.3465 +{
  1.3466 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.3467 +    if (!atom)
  1.3468 +        return false;
  1.3469 +    RootedId id(cx, AtomToId(atom));
  1.3470 +    return JS_SetPropertyById(cx, obj, id, v);
  1.3471 +}
  1.3472 +
  1.3473 +JS_PUBLIC_API(bool)
  1.3474 +JS_SetUCProperty(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  1.3475 +                 HandleValue v)
  1.3476 +{
  1.3477 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.3478 +    if (!atom)
  1.3479 +        return false;
  1.3480 +    RootedId id(cx, AtomToId(atom));
  1.3481 +    return JS_SetPropertyById(cx, obj, id, v);
  1.3482 +}
  1.3483 +
  1.3484 +JS_PUBLIC_API(bool)
  1.3485 +JS_DeletePropertyById2(JSContext *cx, HandleObject obj, HandleId id, bool *result)
  1.3486 +{
  1.3487 +    AssertHeapIsIdle(cx);
  1.3488 +    CHECK_REQUEST(cx);
  1.3489 +    assertSameCompartment(cx, obj, id);
  1.3490 +
  1.3491 +    return JSObject::deleteByValue(cx, obj, IdToValue(id), result);
  1.3492 +}
  1.3493 +
  1.3494 +JS_PUBLIC_API(bool)
  1.3495 +JS_DeleteElement2(JSContext *cx, HandleObject obj, uint32_t index, bool *result)
  1.3496 +{
  1.3497 +    AssertHeapIsIdle(cx);
  1.3498 +    CHECK_REQUEST(cx);
  1.3499 +    assertSameCompartment(cx, obj);
  1.3500 +
  1.3501 +    return JSObject::deleteElement(cx, obj, index, result);
  1.3502 +}
  1.3503 +
  1.3504 +JS_PUBLIC_API(bool)
  1.3505 +JS_DeleteProperty2(JSContext *cx, HandleObject obj, const char *name, bool *result)
  1.3506 +{
  1.3507 +    CHECK_REQUEST(cx);
  1.3508 +    assertSameCompartment(cx, obj);
  1.3509 +
  1.3510 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.3511 +    if (!atom)
  1.3512 +        return false;
  1.3513 +    return JSObject::deleteByValue(cx, obj, StringValue(atom), result);
  1.3514 +}
  1.3515 +
  1.3516 +JS_PUBLIC_API(bool)
  1.3517 +JS_DeleteUCProperty2(JSContext *cx, HandleObject obj, const jschar *name, size_t namelen,
  1.3518 +                     bool *result)
  1.3519 +{
  1.3520 +    CHECK_REQUEST(cx);
  1.3521 +    assertSameCompartment(cx, obj);
  1.3522 +
  1.3523 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.3524 +    if (!atom)
  1.3525 +        return false;
  1.3526 +    return JSObject::deleteByValue(cx, obj, StringValue(atom), result);
  1.3527 +}
  1.3528 +
  1.3529 +JS_PUBLIC_API(bool)
  1.3530 +JS_DeletePropertyById(JSContext *cx, HandleObject obj, HandleId id)
  1.3531 +{
  1.3532 +    bool junk;
  1.3533 +    return JS_DeletePropertyById2(cx, obj, id, &junk);
  1.3534 +}
  1.3535 +
  1.3536 +JS_PUBLIC_API(bool)
  1.3537 +JS_DeleteElement(JSContext *cx, HandleObject obj, uint32_t index)
  1.3538 +{
  1.3539 +    bool junk;
  1.3540 +    return JS_DeleteElement2(cx, obj, index, &junk);
  1.3541 +}
  1.3542 +
  1.3543 +JS_PUBLIC_API(bool)
  1.3544 +JS_DeleteProperty(JSContext *cx, HandleObject obj, const char *name)
  1.3545 +{
  1.3546 +    bool junk;
  1.3547 +    return JS_DeleteProperty2(cx, obj, name, &junk);
  1.3548 +}
  1.3549 +
  1.3550 +static Shape *
  1.3551 +LastConfigurableShape(JSObject *obj)
  1.3552 +{
  1.3553 +    for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront()) {
  1.3554 +        Shape *shape = &r.front();
  1.3555 +        if (shape->configurable())
  1.3556 +            return shape;
  1.3557 +    }
  1.3558 +    return nullptr;
  1.3559 +}
  1.3560 +
  1.3561 +JS_PUBLIC_API(void)
  1.3562 +JS_ClearNonGlobalObject(JSContext *cx, HandleObject obj)
  1.3563 +{
  1.3564 +    AssertHeapIsIdle(cx);
  1.3565 +    CHECK_REQUEST(cx);
  1.3566 +    assertSameCompartment(cx, obj);
  1.3567 +
  1.3568 +    JS_ASSERT(!obj->is<GlobalObject>());
  1.3569 +
  1.3570 +    if (!obj->isNative())
  1.3571 +        return;
  1.3572 +
  1.3573 +    /* Remove all configurable properties from obj. */
  1.3574 +    RootedShape shape(cx);
  1.3575 +    while ((shape = LastConfigurableShape(obj))) {
  1.3576 +        if (!obj->removeProperty(cx, shape->propid()))
  1.3577 +            return;
  1.3578 +    }
  1.3579 +
  1.3580 +    /* Set all remaining writable plain data properties to undefined. */
  1.3581 +    for (Shape::Range<NoGC> r(obj->lastProperty()); !r.empty(); r.popFront()) {
  1.3582 +        Shape *shape = &r.front();
  1.3583 +        if (shape->isDataDescriptor() &&
  1.3584 +            shape->writable() &&
  1.3585 +            shape->hasDefaultSetter() &&
  1.3586 +            shape->hasSlot())
  1.3587 +        {
  1.3588 +            obj->nativeSetSlot(shape->slot(), UndefinedValue());
  1.3589 +        }
  1.3590 +    }
  1.3591 +}
  1.3592 +
  1.3593 +JS_PUBLIC_API(void)
  1.3594 +JS_SetAllNonReservedSlotsToUndefined(JSContext *cx, JSObject *objArg)
  1.3595 +{
  1.3596 +    RootedObject obj(cx, objArg);
  1.3597 +    AssertHeapIsIdle(cx);
  1.3598 +    CHECK_REQUEST(cx);
  1.3599 +    assertSameCompartment(cx, obj);
  1.3600 +
  1.3601 +    if (!obj->isNative())
  1.3602 +        return;
  1.3603 +
  1.3604 +    const Class *clasp = obj->getClass();
  1.3605 +    unsigned numReserved = JSCLASS_RESERVED_SLOTS(clasp);
  1.3606 +    unsigned numSlots = obj->slotSpan();
  1.3607 +    for (unsigned i = numReserved; i < numSlots; i++)
  1.3608 +        obj->setSlot(i, UndefinedValue());
  1.3609 +}
  1.3610 +
  1.3611 +JS_PUBLIC_API(JSIdArray *)
  1.3612 +JS_Enumerate(JSContext *cx, HandleObject obj)
  1.3613 +{
  1.3614 +    AssertHeapIsIdle(cx);
  1.3615 +    CHECK_REQUEST(cx);
  1.3616 +    assertSameCompartment(cx, obj);
  1.3617 +
  1.3618 +    AutoIdVector props(cx);
  1.3619 +    JSIdArray *ida;
  1.3620 +    if (!GetPropertyNames(cx, obj, JSITER_OWNONLY, &props) || !VectorToIdArray(cx, props, &ida))
  1.3621 +        return nullptr;
  1.3622 +    return ida;
  1.3623 +}
  1.3624 +
  1.3625 +/*
  1.3626 + * XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
  1.3627 + *     prop_iterator_class somehow...
  1.3628 + * + preserve the obj->enumerate API while optimizing the native object case
  1.3629 + * + native case here uses a JSShape *, but that iterates in reverse!
  1.3630 + * + so we make non-native match, by reverse-iterating after JS_Enumerating
  1.3631 + */
  1.3632 +static const uint32_t JSSLOT_ITER_INDEX = 0;
  1.3633 +
  1.3634 +static void
  1.3635 +prop_iter_finalize(FreeOp *fop, JSObject *obj)
  1.3636 +{
  1.3637 +    void *pdata = obj->getPrivate();
  1.3638 +    if (!pdata)
  1.3639 +        return;
  1.3640 +
  1.3641 +    if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
  1.3642 +        /* Non-native case: destroy the ida enumerated when obj was created. */
  1.3643 +        JSIdArray *ida = (JSIdArray *) pdata;
  1.3644 +        fop->free_(ida);
  1.3645 +    }
  1.3646 +}
  1.3647 +
  1.3648 +static void
  1.3649 +prop_iter_trace(JSTracer *trc, JSObject *obj)
  1.3650 +{
  1.3651 +    void *pdata = obj->getPrivate();
  1.3652 +    if (!pdata)
  1.3653 +        return;
  1.3654 +
  1.3655 +    if (obj->getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
  1.3656 +        /*
  1.3657 +         * Native case: just mark the next property to visit. We don't need a
  1.3658 +         * barrier here because the pointer is updated via setPrivate, which
  1.3659 +         * always takes a barrier.
  1.3660 +         */
  1.3661 +        Shape *tmp = static_cast<Shape *>(pdata);
  1.3662 +        MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
  1.3663 +        obj->setPrivateUnbarriered(tmp);
  1.3664 +    } else {
  1.3665 +        /* Non-native case: mark each id in the JSIdArray private. */
  1.3666 +        JSIdArray *ida = (JSIdArray *) pdata;
  1.3667 +        MarkIdRange(trc, ida->length, ida->vector, "prop iter");
  1.3668 +    }
  1.3669 +}
  1.3670 +
  1.3671 +static const Class prop_iter_class = {
  1.3672 +    "PropertyIterator",
  1.3673 +    JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
  1.3674 +    JS_PropertyStub,         /* addProperty */
  1.3675 +    JS_DeletePropertyStub,   /* delProperty */
  1.3676 +    JS_PropertyStub,         /* getProperty */
  1.3677 +    JS_StrictPropertyStub,   /* setProperty */
  1.3678 +    JS_EnumerateStub,
  1.3679 +    JS_ResolveStub,
  1.3680 +    JS_ConvertStub,
  1.3681 +    prop_iter_finalize,
  1.3682 +    nullptr,        /* call        */
  1.3683 +    nullptr,        /* hasInstance */
  1.3684 +    nullptr,        /* construct   */
  1.3685 +    prop_iter_trace
  1.3686 +};
  1.3687 +
  1.3688 +JS_PUBLIC_API(JSObject *)
  1.3689 +JS_NewPropertyIterator(JSContext *cx, HandleObject obj)
  1.3690 +{
  1.3691 +    AssertHeapIsIdle(cx);
  1.3692 +    CHECK_REQUEST(cx);
  1.3693 +    assertSameCompartment(cx, obj);
  1.3694 +
  1.3695 +    RootedObject iterobj(cx, NewObjectWithClassProto(cx, &prop_iter_class, nullptr, obj));
  1.3696 +    if (!iterobj)
  1.3697 +        return nullptr;
  1.3698 +
  1.3699 +    int index;
  1.3700 +    if (obj->isNative()) {
  1.3701 +        /* Native case: start with the last property in obj. */
  1.3702 +        iterobj->setPrivateGCThing(obj->lastProperty());
  1.3703 +        index = -1;
  1.3704 +    } else {
  1.3705 +        /* Non-native case: enumerate a JSIdArray and keep it via private. */
  1.3706 +        JSIdArray *ida = JS_Enumerate(cx, obj);
  1.3707 +        if (!ida)
  1.3708 +            return nullptr;
  1.3709 +        iterobj->setPrivate((void *)ida);
  1.3710 +        index = ida->length;
  1.3711 +    }
  1.3712 +
  1.3713 +    /* iterobj cannot escape to other threads here. */
  1.3714 +    iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
  1.3715 +    return iterobj;
  1.3716 +}
  1.3717 +
  1.3718 +JS_PUBLIC_API(bool)
  1.3719 +JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp)
  1.3720 +{
  1.3721 +    AssertHeapIsIdle(cx);
  1.3722 +    CHECK_REQUEST(cx);
  1.3723 +    assertSameCompartment(cx, iterobj);
  1.3724 +    int32_t i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
  1.3725 +    if (i < 0) {
  1.3726 +        /* Native case: private data is a property tree node pointer. */
  1.3727 +        JS_ASSERT(iterobj->getParent()->isNative());
  1.3728 +        Shape *shape = static_cast<Shape *>(iterobj->getPrivate());
  1.3729 +
  1.3730 +        while (shape->previous() && !shape->enumerable())
  1.3731 +            shape = shape->previous();
  1.3732 +
  1.3733 +        if (!shape->previous()) {
  1.3734 +            JS_ASSERT(shape->isEmptyShape());
  1.3735 +            *idp = JSID_VOID;
  1.3736 +        } else {
  1.3737 +            iterobj->setPrivateGCThing(const_cast<Shape *>(shape->previous().get()));
  1.3738 +            *idp = shape->propid();
  1.3739 +        }
  1.3740 +    } else {
  1.3741 +        /* Non-native case: use the ida enumerated when iterobj was created. */
  1.3742 +        JSIdArray *ida = (JSIdArray *) iterobj->getPrivate();
  1.3743 +        JS_ASSERT(i <= ida->length);
  1.3744 +        STATIC_ASSUME(i <= ida->length);
  1.3745 +        if (i == 0) {
  1.3746 +            *idp = JSID_VOID;
  1.3747 +        } else {
  1.3748 +            *idp = ida->vector[--i];
  1.3749 +            iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
  1.3750 +        }
  1.3751 +    }
  1.3752 +    return true;
  1.3753 +}
  1.3754 +
  1.3755 +JS_PUBLIC_API(jsval)
  1.3756 +JS_GetReservedSlot(JSObject *obj, uint32_t index)
  1.3757 +{
  1.3758 +    return obj->getReservedSlot(index);
  1.3759 +}
  1.3760 +
  1.3761 +JS_PUBLIC_API(void)
  1.3762 +JS_SetReservedSlot(JSObject *obj, uint32_t index, Value value)
  1.3763 +{
  1.3764 +    obj->setReservedSlot(index, value);
  1.3765 +}
  1.3766 +
  1.3767 +JS_PUBLIC_API(JSObject *)
  1.3768 +JS_NewArrayObject(JSContext *cx, const JS::HandleValueArray& contents)
  1.3769 +{
  1.3770 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.3771 +    AssertHeapIsIdle(cx);
  1.3772 +    CHECK_REQUEST(cx);
  1.3773 +
  1.3774 +    assertSameCompartment(cx, contents);
  1.3775 +    return NewDenseCopiedArray(cx, contents.length(), contents.begin());
  1.3776 +}
  1.3777 +
  1.3778 +JS_PUBLIC_API(JSObject *)
  1.3779 +JS_NewArrayObject(JSContext *cx, size_t length)
  1.3780 +{
  1.3781 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.3782 +    AssertHeapIsIdle(cx);
  1.3783 +    CHECK_REQUEST(cx);
  1.3784 +
  1.3785 +    return NewDenseAllocatedArray(cx, length);
  1.3786 +}
  1.3787 +
  1.3788 +JS_PUBLIC_API(bool)
  1.3789 +JS_IsArrayObject(JSContext *cx, JS::HandleObject obj)
  1.3790 +{
  1.3791 +    assertSameCompartment(cx, obj);
  1.3792 +    return ObjectClassIs(obj, ESClass_Array, cx);
  1.3793 +}
  1.3794 +
  1.3795 +JS_PUBLIC_API(bool)
  1.3796 +JS_IsArrayObject(JSContext *cx, JS::HandleValue value)
  1.3797 +{
  1.3798 +    if (!value.isObject())
  1.3799 +        return false;
  1.3800 +    RootedObject obj(cx, &value.toObject());
  1.3801 +    return JS_IsArrayObject(cx, obj);
  1.3802 +}
  1.3803 +
  1.3804 +JS_PUBLIC_API(bool)
  1.3805 +JS_GetArrayLength(JSContext *cx, HandleObject obj, uint32_t *lengthp)
  1.3806 +{
  1.3807 +    AssertHeapIsIdle(cx);
  1.3808 +    CHECK_REQUEST(cx);
  1.3809 +    assertSameCompartment(cx, obj);
  1.3810 +    return GetLengthProperty(cx, obj, lengthp);
  1.3811 +}
  1.3812 +
  1.3813 +JS_PUBLIC_API(bool)
  1.3814 +JS_SetArrayLength(JSContext *cx, HandleObject obj, uint32_t length)
  1.3815 +{
  1.3816 +    AssertHeapIsIdle(cx);
  1.3817 +    CHECK_REQUEST(cx);
  1.3818 +    assertSameCompartment(cx, obj);
  1.3819 +    return SetLengthProperty(cx, obj, length);
  1.3820 +}
  1.3821 +
  1.3822 +JS_PUBLIC_API(void)
  1.3823 +JS_HoldPrincipals(JSPrincipals *principals)
  1.3824 +{
  1.3825 +    ++principals->refcount;
  1.3826 +}
  1.3827 +
  1.3828 +JS_PUBLIC_API(void)
  1.3829 +JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals)
  1.3830 +{
  1.3831 +    int rc = --principals->refcount;
  1.3832 +    if (rc == 0)
  1.3833 +        rt->destroyPrincipals(principals);
  1.3834 +}
  1.3835 +
  1.3836 +JS_PUBLIC_API(void)
  1.3837 +JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *scb)
  1.3838 +{
  1.3839 +    JS_ASSERT(scb != &NullSecurityCallbacks);
  1.3840 +    rt->securityCallbacks = scb ? scb : &NullSecurityCallbacks;
  1.3841 +}
  1.3842 +
  1.3843 +JS_PUBLIC_API(const JSSecurityCallbacks *)
  1.3844 +JS_GetSecurityCallbacks(JSRuntime *rt)
  1.3845 +{
  1.3846 +    return (rt->securityCallbacks != &NullSecurityCallbacks) ? rt->securityCallbacks : nullptr;
  1.3847 +}
  1.3848 +
  1.3849 +JS_PUBLIC_API(void)
  1.3850 +JS_SetTrustedPrincipals(JSRuntime *rt, const JSPrincipals *prin)
  1.3851 +{
  1.3852 +    rt->setTrustedPrincipals(prin);
  1.3853 +}
  1.3854 +
  1.3855 +extern JS_PUBLIC_API(void)
  1.3856 +JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals)
  1.3857 +{
  1.3858 +    JS_ASSERT(destroyPrincipals);
  1.3859 +    JS_ASSERT(!rt->destroyPrincipals);
  1.3860 +    rt->destroyPrincipals = destroyPrincipals;
  1.3861 +}
  1.3862 +
  1.3863 +JS_PUBLIC_API(JSFunction *)
  1.3864 +JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
  1.3865 +               HandleObject parent, const char *name)
  1.3866 +{
  1.3867 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.3868 +
  1.3869 +    AssertHeapIsIdle(cx);
  1.3870 +    CHECK_REQUEST(cx);
  1.3871 +    assertSameCompartment(cx, parent);
  1.3872 +
  1.3873 +    RootedAtom atom(cx);
  1.3874 +    if (name) {
  1.3875 +        atom = Atomize(cx, name, strlen(name));
  1.3876 +        if (!atom)
  1.3877 +            return nullptr;
  1.3878 +    }
  1.3879 +
  1.3880 +    JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
  1.3881 +    return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
  1.3882 +}
  1.3883 +
  1.3884 +JS_PUBLIC_API(JSFunction *)
  1.3885 +JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
  1.3886 +                   HandleObject parent, HandleId id)
  1.3887 +{
  1.3888 +    JS_ASSERT(JSID_IS_STRING(id));
  1.3889 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.3890 +    JS_ASSERT(native);
  1.3891 +    AssertHeapIsIdle(cx);
  1.3892 +    CHECK_REQUEST(cx);
  1.3893 +    assertSameCompartment(cx, parent);
  1.3894 +
  1.3895 +    RootedAtom name(cx, JSID_TO_ATOM(id));
  1.3896 +    JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
  1.3897 +    return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, name);
  1.3898 +}
  1.3899 +
  1.3900 +JS_PUBLIC_API(JSFunction *)
  1.3901 +JS::GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, HandleId id, unsigned nargs)
  1.3902 +{
  1.3903 +    JS_ASSERT(JSID_IS_STRING(id));
  1.3904 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.3905 +    AssertHeapIsIdle(cx);
  1.3906 +    CHECK_REQUEST(cx);
  1.3907 +
  1.3908 +    RootedAtom name(cx, JSID_TO_ATOM(id));
  1.3909 +    RootedAtom shName(cx, Atomize(cx, selfHostedName, strlen(selfHostedName)));
  1.3910 +    if (!shName)
  1.3911 +        return nullptr;
  1.3912 +    RootedValue funVal(cx);
  1.3913 +    if (!cx->global()->getSelfHostedFunction(cx, shName, name, nargs, &funVal))
  1.3914 +        return nullptr;
  1.3915 +    return &funVal.toObject().as<JSFunction>();
  1.3916 +}
  1.3917 +
  1.3918 +JS_PUBLIC_API(JSObject *)
  1.3919 +JS_CloneFunctionObject(JSContext *cx, HandleObject funobj, HandleObject parentArg)
  1.3920 +{
  1.3921 +    RootedObject parent(cx, parentArg);
  1.3922 +
  1.3923 +    AssertHeapIsIdle(cx);
  1.3924 +    CHECK_REQUEST(cx);
  1.3925 +    assertSameCompartment(cx, parent);
  1.3926 +    // Note that funobj can be in a different compartment.
  1.3927 +
  1.3928 +    if (!parent)
  1.3929 +        parent = cx->global();
  1.3930 +
  1.3931 +    if (!funobj->is<JSFunction>()) {
  1.3932 +        AutoCompartment ac(cx, funobj);
  1.3933 +        RootedValue v(cx, ObjectValue(*funobj));
  1.3934 +        ReportIsNotFunction(cx, v);
  1.3935 +        return nullptr;
  1.3936 +    }
  1.3937 +
  1.3938 +    RootedFunction fun(cx, &funobj->as<JSFunction>());
  1.3939 +    if (fun->isInterpretedLazy()) {
  1.3940 +        AutoCompartment ac(cx, funobj);
  1.3941 +        if (!fun->getOrCreateScript(cx))
  1.3942 +            return nullptr;
  1.3943 +    }
  1.3944 +    /*
  1.3945 +     * If a function was compiled to be lexically nested inside some other
  1.3946 +     * script, we cannot clone it without breaking the compiler's assumptions.
  1.3947 +     */
  1.3948 +    if (fun->isInterpreted() && (fun->nonLazyScript()->enclosingStaticScope() ||
  1.3949 +        (fun->nonLazyScript()->compileAndGo() && !parent->is<GlobalObject>())))
  1.3950 +    {
  1.3951 +        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
  1.3952 +        return nullptr;
  1.3953 +    }
  1.3954 +
  1.3955 +    if (fun->isBoundFunction()) {
  1.3956 +        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
  1.3957 +        return nullptr;
  1.3958 +    }
  1.3959 +
  1.3960 +    if (fun->isNative() && IsAsmJSModuleNative(fun->native())) {
  1.3961 +        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT);
  1.3962 +        return nullptr;
  1.3963 +    }
  1.3964 +
  1.3965 +    return CloneFunctionObject(cx, fun, parent, fun->getAllocKind());
  1.3966 +}
  1.3967 +
  1.3968 +JS_PUBLIC_API(JSObject *)
  1.3969 +JS_GetFunctionObject(JSFunction *fun)
  1.3970 +{
  1.3971 +    return fun;
  1.3972 +}
  1.3973 +
  1.3974 +JS_PUBLIC_API(JSString *)
  1.3975 +JS_GetFunctionId(JSFunction *fun)
  1.3976 +{
  1.3977 +    return fun->atom();
  1.3978 +}
  1.3979 +
  1.3980 +JS_PUBLIC_API(JSString *)
  1.3981 +JS_GetFunctionDisplayId(JSFunction *fun)
  1.3982 +{
  1.3983 +    return fun->displayAtom();
  1.3984 +}
  1.3985 +
  1.3986 +JS_PUBLIC_API(uint16_t)
  1.3987 +JS_GetFunctionArity(JSFunction *fun)
  1.3988 +{
  1.3989 +    return fun->nargs();
  1.3990 +}
  1.3991 +
  1.3992 +JS_PUBLIC_API(bool)
  1.3993 +JS_ObjectIsFunction(JSContext *cx, JSObject *obj)
  1.3994 +{
  1.3995 +    return obj->is<JSFunction>();
  1.3996 +}
  1.3997 +
  1.3998 +JS_PUBLIC_API(bool)
  1.3999 +JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
  1.4000 +{
  1.4001 +    return obj->isCallable();
  1.4002 +}
  1.4003 +
  1.4004 +JS_PUBLIC_API(bool)
  1.4005 +JS_IsNativeFunction(JSObject *funobj, JSNative call)
  1.4006 +{
  1.4007 +    if (!funobj->is<JSFunction>())
  1.4008 +        return false;
  1.4009 +    JSFunction *fun = &funobj->as<JSFunction>();
  1.4010 +    return fun->isNative() && fun->native() == call;
  1.4011 +}
  1.4012 +
  1.4013 +extern JS_PUBLIC_API(bool)
  1.4014 +JS_IsConstructor(JSFunction *fun)
  1.4015 +{
  1.4016 +    return fun->isNativeConstructor() || fun->isInterpretedConstructor();
  1.4017 +}
  1.4018 +
  1.4019 +JS_PUBLIC_API(JSObject*)
  1.4020 +JS_BindCallable(JSContext *cx, HandleObject target, HandleObject newThis)
  1.4021 +{
  1.4022 +    RootedValue thisArg(cx, ObjectValue(*newThis));
  1.4023 +    return js_fun_bind(cx, target, thisArg, nullptr, 0);
  1.4024 +}
  1.4025 +
  1.4026 +static bool
  1.4027 +js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp)
  1.4028 +{
  1.4029 +    CallArgs args = CallArgsFromVp(argc, vp);
  1.4030 +
  1.4031 +    const JSFunctionSpec *fs = (JSFunctionSpec *)
  1.4032 +        args.callee().as<JSFunction>().getExtendedSlot(0).toPrivate();
  1.4033 +    JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
  1.4034 +
  1.4035 +    if (argc < 1) {
  1.4036 +        js_ReportMissingArg(cx, args.calleev(), 0);
  1.4037 +        return false;
  1.4038 +    }
  1.4039 +
  1.4040 +    /*
  1.4041 +     * Copy all actual (argc) arguments down over our |this| parameter, vp[1],
  1.4042 +     * which is almost always the class constructor object, e.g. Array.  Then
  1.4043 +     * call the corresponding prototype native method with our first argument
  1.4044 +     * passed as |this|.
  1.4045 +     */
  1.4046 +    memmove(vp + 1, vp + 2, argc * sizeof(jsval));
  1.4047 +
  1.4048 +    /* Clear the last parameter in case too few arguments were passed. */
  1.4049 +    vp[2 + --argc].setUndefined();
  1.4050 +
  1.4051 +    return fs->call.op(cx, argc, vp);
  1.4052 +}
  1.4053 +
  1.4054 +JS_PUBLIC_API(bool)
  1.4055 +JS_DefineFunctions(JSContext *cx, HandleObject obj, const JSFunctionSpec *fs)
  1.4056 +{
  1.4057 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4058 +    AssertHeapIsIdle(cx);
  1.4059 +    CHECK_REQUEST(cx);
  1.4060 +    assertSameCompartment(cx, obj);
  1.4061 +
  1.4062 +    RootedObject ctor(cx);
  1.4063 +
  1.4064 +    for (; fs->name; fs++) {
  1.4065 +        RootedAtom atom(cx);
  1.4066 +        // If the name starts with "@@", it must be a well-known symbol.
  1.4067 +        if (fs->name[0] != '@' || fs->name[1] != '@')
  1.4068 +            atom = Atomize(cx, fs->name, strlen(fs->name));
  1.4069 +        else if (strcmp(fs->name, "@@iterator") == 0)
  1.4070 +            // FIXME: This atom should be a symbol: bug 918828.
  1.4071 +            atom = cx->names().std_iterator;
  1.4072 +        else
  1.4073 +            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_SYMBOL, fs->name);
  1.4074 +        if (!atom)
  1.4075 +            return false;
  1.4076 +
  1.4077 +        Rooted<jsid> id(cx, AtomToId(atom));
  1.4078 +
  1.4079 +        /*
  1.4080 +         * Define a generic arity N+1 static method for the arity N prototype
  1.4081 +         * method if flags contains JSFUN_GENERIC_NATIVE.
  1.4082 +         */
  1.4083 +        unsigned flags = fs->flags;
  1.4084 +        if (flags & JSFUN_GENERIC_NATIVE) {
  1.4085 +            if (!ctor) {
  1.4086 +                ctor = JS_GetConstructor(cx, obj);
  1.4087 +                if (!ctor)
  1.4088 +                    return false;
  1.4089 +            }
  1.4090 +
  1.4091 +            flags &= ~JSFUN_GENERIC_NATIVE;
  1.4092 +            JSFunction *fun = DefineFunction(cx, ctor, id,
  1.4093 +                                             js_generic_native_method_dispatcher,
  1.4094 +                                             fs->nargs + 1, flags,
  1.4095 +                                             JSFunction::ExtendedFinalizeKind);
  1.4096 +            if (!fun)
  1.4097 +                return false;
  1.4098 +
  1.4099 +            /*
  1.4100 +             * As jsapi.h notes, fs must point to storage that lives as long
  1.4101 +             * as fun->object lives.
  1.4102 +             */
  1.4103 +            fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
  1.4104 +        }
  1.4105 +
  1.4106 +        /*
  1.4107 +         * Delay cloning self-hosted functions until they are called. This is
  1.4108 +         * achieved by passing DefineFunction a nullptr JSNative which
  1.4109 +         * produces an interpreted JSFunction where !hasScript. Interpreted
  1.4110 +         * call paths then call InitializeLazyFunctionScript if !hasScript.
  1.4111 +         */
  1.4112 +        if (fs->selfHostedName) {
  1.4113 +            JS_ASSERT(!fs->call.op);
  1.4114 +            JS_ASSERT(!fs->call.info);
  1.4115 +            /*
  1.4116 +             * During creation of the self-hosting global, we ignore all
  1.4117 +             * self-hosted functions, as that means we're currently setting up
  1.4118 +             * the global object that the self-hosted code is then compiled
  1.4119 +             * in. Self-hosted functions can access each other via their names,
  1.4120 +             * but not via the builtin classes they get installed into.
  1.4121 +             */
  1.4122 +            if (cx->runtime()->isSelfHostingGlobal(cx->global()))
  1.4123 +                continue;
  1.4124 +
  1.4125 +            RootedAtom shName(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
  1.4126 +            if (!shName)
  1.4127 +                return false;
  1.4128 +            RootedValue funVal(cx);
  1.4129 +            if (!cx->global()->getSelfHostedFunction(cx, shName, atom, fs->nargs, &funVal))
  1.4130 +                return false;
  1.4131 +            if (!JSObject::defineGeneric(cx, obj, id, funVal, nullptr, nullptr, flags))
  1.4132 +                return false;
  1.4133 +        } else {
  1.4134 +            JSFunction *fun = DefineFunction(cx, obj, id, fs->call.op, fs->nargs, flags);
  1.4135 +            if (!fun)
  1.4136 +                return false;
  1.4137 +            if (fs->call.info)
  1.4138 +                fun->setJitInfo(fs->call.info);
  1.4139 +        }
  1.4140 +    }
  1.4141 +    return true;
  1.4142 +}
  1.4143 +
  1.4144 +JS_PUBLIC_API(JSFunction *)
  1.4145 +JS_DefineFunction(JSContext *cx, HandleObject obj, const char *name, JSNative call,
  1.4146 +                  unsigned nargs, unsigned attrs)
  1.4147 +{
  1.4148 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4149 +    AssertHeapIsIdle(cx);
  1.4150 +    CHECK_REQUEST(cx);
  1.4151 +    assertSameCompartment(cx, obj);
  1.4152 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.4153 +    if (!atom)
  1.4154 +        return nullptr;
  1.4155 +    Rooted<jsid> id(cx, AtomToId(atom));
  1.4156 +    return DefineFunction(cx, obj, id, call, nargs, attrs);
  1.4157 +}
  1.4158 +
  1.4159 +JS_PUBLIC_API(JSFunction *)
  1.4160 +JS_DefineUCFunction(JSContext *cx, HandleObject obj,
  1.4161 +                    const jschar *name, size_t namelen, JSNative call,
  1.4162 +                    unsigned nargs, unsigned attrs)
  1.4163 +{
  1.4164 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4165 +    AssertHeapIsIdle(cx);
  1.4166 +    CHECK_REQUEST(cx);
  1.4167 +    assertSameCompartment(cx, obj);
  1.4168 +    JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
  1.4169 +    if (!atom)
  1.4170 +        return nullptr;
  1.4171 +    Rooted<jsid> id(cx, AtomToId(atom));
  1.4172 +    return DefineFunction(cx, obj, id, call, nargs, attrs);
  1.4173 +}
  1.4174 +
  1.4175 +extern JS_PUBLIC_API(JSFunction *)
  1.4176 +JS_DefineFunctionById(JSContext *cx, HandleObject obj, HandleId id, JSNative call,
  1.4177 +                      unsigned nargs, unsigned attrs)
  1.4178 +{
  1.4179 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4180 +    AssertHeapIsIdle(cx);
  1.4181 +    CHECK_REQUEST(cx);
  1.4182 +    assertSameCompartment(cx, obj);
  1.4183 +    return DefineFunction(cx, obj, id, call, nargs, attrs);
  1.4184 +}
  1.4185 +
  1.4186 +struct AutoLastFrameCheck
  1.4187 +{
  1.4188 +    AutoLastFrameCheck(JSContext *cx
  1.4189 +                       MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  1.4190 +      : cx(cx)
  1.4191 +    {
  1.4192 +        JS_ASSERT(cx);
  1.4193 +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  1.4194 +    }
  1.4195 +
  1.4196 +    ~AutoLastFrameCheck() {
  1.4197 +        if (cx->isExceptionPending() &&
  1.4198 +            !JS_IsRunning(cx) &&
  1.4199 +            !cx->options().dontReportUncaught()) {
  1.4200 +            js_ReportUncaughtException(cx);
  1.4201 +        }
  1.4202 +    }
  1.4203 +
  1.4204 +  private:
  1.4205 +    JSContext *cx;
  1.4206 +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  1.4207 +};
  1.4208 +
  1.4209 +/* Use the fastest available getc. */
  1.4210 +#if defined(HAVE_GETC_UNLOCKED)
  1.4211 +# define fast_getc getc_unlocked
  1.4212 +#elif defined(HAVE__GETC_NOLOCK)
  1.4213 +# define fast_getc _getc_nolock
  1.4214 +#else
  1.4215 +# define fast_getc getc
  1.4216 +#endif
  1.4217 +
  1.4218 +typedef js::Vector<char, 8, TempAllocPolicy> FileContents;
  1.4219 +
  1.4220 +static bool
  1.4221 +ReadCompleteFile(JSContext *cx, FILE *fp, FileContents &buffer)
  1.4222 +{
  1.4223 +    /* Get the complete length of the file, if possible. */
  1.4224 +    struct stat st;
  1.4225 +    int ok = fstat(fileno(fp), &st);
  1.4226 +    if (ok != 0)
  1.4227 +        return false;
  1.4228 +    if (st.st_size > 0) {
  1.4229 +        if (!buffer.reserve(st.st_size))
  1.4230 +            return false;
  1.4231 +    }
  1.4232 +
  1.4233 +    // Read in the whole file. Note that we can't assume the data's length
  1.4234 +    // is actually st.st_size, because 1) some files lie about their size
  1.4235 +    // (/dev/zero and /dev/random), and 2) reading files in text mode on
  1.4236 +    // Windows collapses "\r\n" pairs to single \n characters.
  1.4237 +    for (;;) {
  1.4238 +        int c = fast_getc(fp);
  1.4239 +        if (c == EOF)
  1.4240 +            break;
  1.4241 +        if (!buffer.append(c))
  1.4242 +            return false;
  1.4243 +    }
  1.4244 +
  1.4245 +    return true;
  1.4246 +}
  1.4247 +
  1.4248 +namespace {
  1.4249 +
  1.4250 +class AutoFile
  1.4251 +{
  1.4252 +    FILE *fp_;
  1.4253 +  public:
  1.4254 +    AutoFile()
  1.4255 +      : fp_(nullptr)
  1.4256 +    {}
  1.4257 +    ~AutoFile()
  1.4258 +    {
  1.4259 +        if (fp_ && fp_ != stdin)
  1.4260 +            fclose(fp_);
  1.4261 +    }
  1.4262 +    FILE *fp() const { return fp_; }
  1.4263 +    bool open(JSContext *cx, const char *filename);
  1.4264 +    bool readAll(JSContext *cx, FileContents &buffer)
  1.4265 +    {
  1.4266 +        JS_ASSERT(fp_);
  1.4267 +        return ReadCompleteFile(cx, fp_, buffer);
  1.4268 +    }
  1.4269 +};
  1.4270 +
  1.4271 +} /* anonymous namespace */
  1.4272 +
  1.4273 +/*
  1.4274 + * Open a source file for reading. Supports "-" and nullptr to mean stdin. The
  1.4275 + * return value must be fclosed unless it is stdin.
  1.4276 + */
  1.4277 +bool
  1.4278 +AutoFile::open(JSContext *cx, const char *filename)
  1.4279 +{
  1.4280 +    if (!filename || strcmp(filename, "-") == 0) {
  1.4281 +        fp_ = stdin;
  1.4282 +    } else {
  1.4283 +        fp_ = fopen(filename, "r");
  1.4284 +        if (!fp_) {
  1.4285 +            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
  1.4286 +                                 filename, "No such file or directory");
  1.4287 +            return false;
  1.4288 +        }
  1.4289 +    }
  1.4290 +    return true;
  1.4291 +}
  1.4292 +
  1.4293 +JSObject * const JS::ReadOnlyCompileOptions::nullObjectPtr = nullptr;
  1.4294 +
  1.4295 +void
  1.4296 +JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions &rhs)
  1.4297 +{
  1.4298 +    version = rhs.version;
  1.4299 +    versionSet = rhs.versionSet;
  1.4300 +    utf8 = rhs.utf8;
  1.4301 +    lineno = rhs.lineno;
  1.4302 +    column = rhs.column;
  1.4303 +    compileAndGo = rhs.compileAndGo;
  1.4304 +    forEval = rhs.forEval;
  1.4305 +    noScriptRval = rhs.noScriptRval;
  1.4306 +    selfHostingMode = rhs.selfHostingMode;
  1.4307 +    canLazilyParse = rhs.canLazilyParse;
  1.4308 +    strictOption = rhs.strictOption;
  1.4309 +    extraWarningsOption = rhs.extraWarningsOption;
  1.4310 +    werrorOption = rhs.werrorOption;
  1.4311 +    asmJSOption = rhs.asmJSOption;
  1.4312 +    forceAsync = rhs.forceAsync;
  1.4313 +    installedFile = rhs.installedFile;
  1.4314 +    sourceIsLazy = rhs.sourceIsLazy;
  1.4315 +    introductionType = rhs.introductionType;
  1.4316 +    introductionLineno = rhs.introductionLineno;
  1.4317 +    introductionOffset = rhs.introductionOffset;
  1.4318 +    hasIntroductionInfo = rhs.hasIntroductionInfo;
  1.4319 +}
  1.4320 +
  1.4321 +JSPrincipals *
  1.4322 +JS::ReadOnlyCompileOptions::originPrincipals(ExclusiveContext *cx) const
  1.4323 +{
  1.4324 +    return NormalizeOriginPrincipals(cx->compartment()->principals, originPrincipals_);
  1.4325 +}
  1.4326 +
  1.4327 +JS::OwningCompileOptions::OwningCompileOptions(JSContext *cx)
  1.4328 +    : ReadOnlyCompileOptions(),
  1.4329 +      runtime(GetRuntime(cx)),
  1.4330 +      elementRoot(cx),
  1.4331 +      elementAttributeNameRoot(cx),
  1.4332 +      introductionScriptRoot(cx)
  1.4333 +{
  1.4334 +}
  1.4335 +
  1.4336 +JS::OwningCompileOptions::~OwningCompileOptions()
  1.4337 +{
  1.4338 +    if (originPrincipals_)
  1.4339 +        JS_DropPrincipals(runtime, originPrincipals_);
  1.4340 +
  1.4341 +    // OwningCompileOptions always owns these, so these casts are okay.
  1.4342 +    js_free(const_cast<char *>(filename_));
  1.4343 +    js_free(const_cast<jschar *>(sourceMapURL_));
  1.4344 +    js_free(const_cast<char *>(introducerFilename_));
  1.4345 +}
  1.4346 +
  1.4347 +bool
  1.4348 +JS::OwningCompileOptions::copy(JSContext *cx, const ReadOnlyCompileOptions &rhs)
  1.4349 +{
  1.4350 +    copyPODOptions(rhs);
  1.4351 +
  1.4352 +    setOriginPrincipals(rhs.originPrincipals(cx));
  1.4353 +    setElement(rhs.element());
  1.4354 +    setElementAttributeName(rhs.elementAttributeName());
  1.4355 +    setIntroductionScript(rhs.introductionScript());
  1.4356 +
  1.4357 +    return (setFileAndLine(cx, rhs.filename(), rhs.lineno) &&
  1.4358 +            setSourceMapURL(cx, rhs.sourceMapURL()) &&
  1.4359 +            setIntroducerFilename(cx, rhs.introducerFilename()));
  1.4360 +}
  1.4361 +
  1.4362 +bool
  1.4363 +JS::OwningCompileOptions::setFile(JSContext *cx, const char *f)
  1.4364 +{
  1.4365 +    char *copy = nullptr;
  1.4366 +    if (f) {
  1.4367 +        copy = JS_strdup(cx, f);
  1.4368 +        if (!copy)
  1.4369 +            return false;
  1.4370 +    }
  1.4371 +
  1.4372 +    // OwningCompileOptions always owns filename_, so this cast is okay.
  1.4373 +    js_free(const_cast<char *>(filename_));
  1.4374 +
  1.4375 +    filename_ = copy;
  1.4376 +    return true;
  1.4377 +}
  1.4378 +
  1.4379 +bool
  1.4380 +JS::OwningCompileOptions::setFileAndLine(JSContext *cx, const char *f, unsigned l)
  1.4381 +{
  1.4382 +    if (!setFile(cx, f))
  1.4383 +        return false;
  1.4384 +
  1.4385 +    lineno = l;
  1.4386 +    return true;
  1.4387 +}
  1.4388 +
  1.4389 +bool
  1.4390 +JS::OwningCompileOptions::setSourceMapURL(JSContext *cx, const jschar *s)
  1.4391 +{
  1.4392 +    jschar *copy = nullptr;
  1.4393 +    if (s) {
  1.4394 +        copy = js_strdup(cx, s);
  1.4395 +        if (!copy)
  1.4396 +            return false;
  1.4397 +    }
  1.4398 +
  1.4399 +    // OwningCompileOptions always owns sourceMapURL_, so this cast is okay.
  1.4400 +    js_free(const_cast<jschar *>(sourceMapURL_));
  1.4401 +
  1.4402 +    sourceMapURL_ = copy;
  1.4403 +    return true;
  1.4404 +}
  1.4405 +
  1.4406 +bool
  1.4407 +JS::OwningCompileOptions::setIntroducerFilename(JSContext *cx, const char *s)
  1.4408 +{
  1.4409 +    char *copy = nullptr;
  1.4410 +    if (s) {
  1.4411 +        copy = JS_strdup(cx, s);
  1.4412 +        if (!copy)
  1.4413 +            return false;
  1.4414 +    }
  1.4415 +
  1.4416 +    // OwningCompileOptions always owns introducerFilename_, so this cast is okay.
  1.4417 +    js_free(const_cast<char *>(introducerFilename_));
  1.4418 +
  1.4419 +    introducerFilename_ = copy;
  1.4420 +    return true;
  1.4421 +}
  1.4422 +
  1.4423 +bool
  1.4424 +JS::OwningCompileOptions::wrap(JSContext *cx, JSCompartment *compartment)
  1.4425 +{
  1.4426 +    if (!compartment->wrap(cx, &elementRoot))
  1.4427 +        return false;
  1.4428 +    if (elementAttributeNameRoot) {
  1.4429 +        if (!compartment->wrap(cx, elementAttributeNameRoot.address()))
  1.4430 +            return false;
  1.4431 +    }
  1.4432 +
  1.4433 +    // There is no equivalent of cross-compartment wrappers for scripts. If
  1.4434 +    // the introduction script would be in a different compartment from the
  1.4435 +    // compiled code, we would be creating a cross-compartment script
  1.4436 +    // reference, which would be bogus. In that case, just don't bother to
  1.4437 +    // retain the introduction script.
  1.4438 +    if (introductionScriptRoot) {
  1.4439 +        if (introductionScriptRoot->compartment() != compartment)
  1.4440 +            introductionScriptRoot = nullptr;
  1.4441 +    }
  1.4442 +
  1.4443 +    return true;
  1.4444 +}
  1.4445 +
  1.4446 +JS::CompileOptions::CompileOptions(JSContext *cx, JSVersion version)
  1.4447 +    : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
  1.4448 +      introductionScriptRoot(cx)
  1.4449 +{
  1.4450 +    this->version = (version != JSVERSION_UNKNOWN) ? version : cx->findVersion();
  1.4451 +
  1.4452 +    compileAndGo = false;
  1.4453 +    noScriptRval = cx->options().noScriptRval();
  1.4454 +    strictOption = cx->options().strictMode();
  1.4455 +    extraWarningsOption = cx->options().extraWarnings();
  1.4456 +    werrorOption = cx->options().werror();
  1.4457 +    asmJSOption = cx->runtime()->options().asmJS();
  1.4458 +}
  1.4459 +
  1.4460 +bool
  1.4461 +JS::CompileOptions::wrap(JSContext *cx, JSCompartment *compartment)
  1.4462 +{
  1.4463 +    if (!compartment->wrap(cx, &elementRoot))
  1.4464 +        return false;
  1.4465 +    if (elementAttributeNameRoot) {
  1.4466 +        if (!compartment->wrap(cx, elementAttributeNameRoot.address()))
  1.4467 +            return false;
  1.4468 +    }
  1.4469 +
  1.4470 +    // There is no equivalent of cross-compartment wrappers for scripts. If
  1.4471 +    // the introduction script would be in a different compartment from the
  1.4472 +    // compiled code, we would be creating a cross-compartment script
  1.4473 +    // reference, which would be bogus. In that case, just don't bother to
  1.4474 +    // retain the introduction script.
  1.4475 +    if (introductionScriptRoot) {
  1.4476 +        if (introductionScriptRoot->compartment() != compartment)
  1.4477 +            introductionScriptRoot = nullptr;
  1.4478 +    }
  1.4479 +
  1.4480 +    return true;
  1.4481 +}
  1.4482 +
  1.4483 +bool
  1.4484 +JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4485 +            SourceBufferHolder &srcBuf, MutableHandleScript script)
  1.4486 +{
  1.4487 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4488 +    AssertHeapIsIdle(cx);
  1.4489 +    CHECK_REQUEST(cx);
  1.4490 +    assertSameCompartment(cx, obj);
  1.4491 +    AutoLastFrameCheck lfc(cx);
  1.4492 +
  1.4493 +    script.set(frontend::CompileScript(cx, &cx->tempLifoAlloc(), obj, NullPtr(), options, srcBuf));
  1.4494 +    return !!script;
  1.4495 +}
  1.4496 +
  1.4497 +JSScript *
  1.4498 +JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4499 +            const jschar *chars, size_t length)
  1.4500 +{
  1.4501 +    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
  1.4502 +    RootedScript script(cx);
  1.4503 +    if (!Compile(cx, obj, options, srcBuf, &script))
  1.4504 +        return nullptr;
  1.4505 +    return script;
  1.4506 +}
  1.4507 +
  1.4508 +JSScript *
  1.4509 +JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4510 +            const char *bytes, size_t length)
  1.4511 +{
  1.4512 +    jschar *chars;
  1.4513 +    if (options.utf8)
  1.4514 +        chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
  1.4515 +    else
  1.4516 +        chars = InflateString(cx, bytes, &length);
  1.4517 +    if (!chars)
  1.4518 +        return nullptr;
  1.4519 +
  1.4520 +    JSScript *script = Compile(cx, obj, options, chars, length);
  1.4521 +    js_free(chars);
  1.4522 +    return script;
  1.4523 +}
  1.4524 +
  1.4525 +JSScript *
  1.4526 +JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options, FILE *fp)
  1.4527 +{
  1.4528 +    FileContents buffer(cx);
  1.4529 +    if (!ReadCompleteFile(cx, fp, buffer))
  1.4530 +        return nullptr;
  1.4531 +
  1.4532 +    JSScript *script = Compile(cx, obj, options, buffer.begin(), buffer.length());
  1.4533 +    return script;
  1.4534 +}
  1.4535 +
  1.4536 +JSScript *
  1.4537 +JS::Compile(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg, const char *filename)
  1.4538 +{
  1.4539 +    AutoFile file;
  1.4540 +    if (!file.open(cx, filename))
  1.4541 +        return nullptr;
  1.4542 +    CompileOptions options(cx, optionsArg);
  1.4543 +    options.setFileAndLine(filename, 1);
  1.4544 +    return Compile(cx, obj, options, file.fp());
  1.4545 +}
  1.4546 +
  1.4547 +JS_PUBLIC_API(bool)
  1.4548 +JS::CanCompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options, size_t length)
  1.4549 +{
  1.4550 +    static const size_t TINY_LENGTH = 1000;
  1.4551 +    static const size_t HUGE_LENGTH = 100 * 1000;
  1.4552 +
  1.4553 +    // These are heuristics which the caller may choose to ignore (e.g., for
  1.4554 +    // testing purposes).
  1.4555 +    if (!options.forceAsync) {
  1.4556 +        // Compiling off the main thread inolves creating a new Zone and other
  1.4557 +        // significant overheads.  Don't bother if the script is tiny.
  1.4558 +        if (length < TINY_LENGTH)
  1.4559 +            return false;
  1.4560 +
  1.4561 +#ifdef JS_THREADSAFE
  1.4562 +        // If the parsing task would have to wait for GC to complete, it'll probably
  1.4563 +        // be faster to just start it synchronously on the main thread unless the
  1.4564 +        // script is huge.
  1.4565 +        if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH)
  1.4566 +            return false;
  1.4567 +#endif // JS_THREADSAFE
  1.4568 +    }
  1.4569 +
  1.4570 +    return cx->runtime()->canUseParallelParsing();
  1.4571 +}
  1.4572 +
  1.4573 +JS_PUBLIC_API(bool)
  1.4574 +JS::CompileOffThread(JSContext *cx, const ReadOnlyCompileOptions &options,
  1.4575 +                     const jschar *chars, size_t length,
  1.4576 +                     OffThreadCompileCallback callback, void *callbackData)
  1.4577 +{
  1.4578 +    JS_ASSERT(CanCompileOffThread(cx, options, length));
  1.4579 +    return StartOffThreadParseScript(cx, options, chars, length, callback, callbackData);
  1.4580 +}
  1.4581 +
  1.4582 +JS_PUBLIC_API(JSScript *)
  1.4583 +JS::FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token)
  1.4584 +{
  1.4585 +#ifdef JS_THREADSAFE
  1.4586 +    JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
  1.4587 +
  1.4588 +    if (maybecx) {
  1.4589 +        RootedScript script(maybecx);
  1.4590 +        {
  1.4591 +            AutoLastFrameCheck lfc(maybecx);
  1.4592 +            script = WorkerThreadState().finishParseTask(maybecx, rt, token);
  1.4593 +        }
  1.4594 +        return script;
  1.4595 +    } else {
  1.4596 +        return WorkerThreadState().finishParseTask(maybecx, rt, token);
  1.4597 +    }
  1.4598 +#else
  1.4599 +    MOZ_ASSUME_UNREACHABLE("Off thread compilation is not available.");
  1.4600 +#endif
  1.4601 +}
  1.4602 +
  1.4603 +JS_PUBLIC_API(JSScript *)
  1.4604 +JS_CompileScript(JSContext *cx, JS::HandleObject obj, const char *ascii,
  1.4605 +                 size_t length, const JS::CompileOptions &options)
  1.4606 +{
  1.4607 +    return Compile(cx, obj, options, ascii, length);
  1.4608 +}
  1.4609 +
  1.4610 +JS_PUBLIC_API(JSScript *)
  1.4611 +JS_CompileUCScript(JSContext *cx, JS::HandleObject obj, const jschar *chars,
  1.4612 +                   size_t length, const JS::CompileOptions &options)
  1.4613 +{
  1.4614 +    return Compile(cx, obj, options, chars, length);
  1.4615 +}
  1.4616 +
  1.4617 +JS_PUBLIC_API(bool)
  1.4618 +JS_BufferIsCompilableUnit(JSContext *cx, HandleObject obj, const char *utf8, size_t length)
  1.4619 +{
  1.4620 +    AssertHeapIsIdle(cx);
  1.4621 +    CHECK_REQUEST(cx);
  1.4622 +    assertSameCompartment(cx, obj);
  1.4623 +
  1.4624 +    cx->clearPendingException();
  1.4625 +
  1.4626 +    jschar *chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get();
  1.4627 +    if (!chars)
  1.4628 +        return true;
  1.4629 +
  1.4630 +    // Return true on any out-of-memory error or non-EOF-related syntax error, so our
  1.4631 +    // caller doesn't try to collect more buffered source.
  1.4632 +    bool result = true;
  1.4633 +
  1.4634 +    CompileOptions options(cx);
  1.4635 +    options.setCompileAndGo(false);
  1.4636 +    Parser<frontend::FullParseHandler> parser(cx, &cx->tempLifoAlloc(),
  1.4637 +                                              options, chars, length,
  1.4638 +                                              /* foldConstants = */ true, nullptr, nullptr);
  1.4639 +    JSErrorReporter older = JS_SetErrorReporter(cx, nullptr);
  1.4640 +    if (!parser.parse(obj)) {
  1.4641 +        // We ran into an error. If it was because we ran out of source, we
  1.4642 +        // return false so our caller knows to try to collect more buffered
  1.4643 +        // source.
  1.4644 +        if (parser.isUnexpectedEOF())
  1.4645 +            result = false;
  1.4646 +
  1.4647 +        cx->clearPendingException();
  1.4648 +    }
  1.4649 +    JS_SetErrorReporter(cx, older);
  1.4650 +
  1.4651 +    js_free(chars);
  1.4652 +    return result;
  1.4653 +}
  1.4654 +
  1.4655 +JS_PUBLIC_API(JSObject *)
  1.4656 +JS_GetGlobalFromScript(JSScript *script)
  1.4657 +{
  1.4658 +    JS_ASSERT(!script->isCachedEval());
  1.4659 +    return &script->global();
  1.4660 +}
  1.4661 +
  1.4662 +JS_PUBLIC_API(bool)
  1.4663 +JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4664 +                    const char *name, unsigned nargs, const char *const *argnames,
  1.4665 +                    SourceBufferHolder &srcBuf, MutableHandleFunction fun)
  1.4666 +{
  1.4667 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4668 +    AssertHeapIsIdle(cx);
  1.4669 +    CHECK_REQUEST(cx);
  1.4670 +    assertSameCompartment(cx, obj);
  1.4671 +    RootedAtom funAtom(cx);
  1.4672 +    AutoLastFrameCheck lfc(cx);
  1.4673 +
  1.4674 +    if (name) {
  1.4675 +        funAtom = Atomize(cx, name, strlen(name));
  1.4676 +        if (!funAtom)
  1.4677 +            return false;
  1.4678 +    }
  1.4679 +
  1.4680 +    AutoNameVector formals(cx);
  1.4681 +    for (unsigned i = 0; i < nargs; i++) {
  1.4682 +        RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
  1.4683 +        if (!argAtom || !formals.append(argAtom->asPropertyName()))
  1.4684 +            return false;
  1.4685 +    }
  1.4686 +
  1.4687 +    fun.set(NewFunction(cx, NullPtr(), nullptr, 0, JSFunction::INTERPRETED, obj,
  1.4688 +                        funAtom, JSFunction::FinalizeKind, TenuredObject));
  1.4689 +    if (!fun)
  1.4690 +        return false;
  1.4691 +
  1.4692 +    if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf))
  1.4693 +        return false;
  1.4694 +
  1.4695 +    if (obj && funAtom && options.defineOnScope) {
  1.4696 +        Rooted<jsid> id(cx, AtomToId(funAtom));
  1.4697 +        RootedValue value(cx, ObjectValue(*fun));
  1.4698 +        if (!JSObject::defineGeneric(cx, obj, id, value, nullptr, nullptr, JSPROP_ENUMERATE))
  1.4699 +            return false;
  1.4700 +    }
  1.4701 +
  1.4702 +    return true;
  1.4703 +}
  1.4704 +
  1.4705 +JS_PUBLIC_API(JSFunction *)
  1.4706 +JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4707 +                    const char *name, unsigned nargs, const char *const *argnames,
  1.4708 +                    const jschar *chars, size_t length)
  1.4709 +{
  1.4710 +    RootedFunction fun(cx);
  1.4711 +    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
  1.4712 +    if (!JS::CompileFunction(cx, obj, options, name, nargs, argnames, srcBuf, &fun))
  1.4713 +        return nullptr;
  1.4714 +    return fun;
  1.4715 +}
  1.4716 +
  1.4717 +JS_PUBLIC_API(JSFunction *)
  1.4718 +JS::CompileFunction(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4719 +                    const char *name, unsigned nargs, const char *const *argnames,
  1.4720 +                    const char *bytes, size_t length)
  1.4721 +{
  1.4722 +    jschar *chars;
  1.4723 +    if (options.utf8)
  1.4724 +        chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
  1.4725 +    else
  1.4726 +        chars = InflateString(cx, bytes, &length);
  1.4727 +    if (!chars)
  1.4728 +        return nullptr;
  1.4729 +
  1.4730 +    JSFunction *fun = CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
  1.4731 +    js_free(chars);
  1.4732 +    return fun;
  1.4733 +}
  1.4734 +
  1.4735 +JS_PUBLIC_API(JSFunction *)
  1.4736 +JS_CompileUCFunction(JSContext *cx, JS::HandleObject obj, const char *name,
  1.4737 +                     unsigned nargs, const char *const *argnames,
  1.4738 +                     const jschar *chars, size_t length,
  1.4739 +                     const CompileOptions &options)
  1.4740 +{
  1.4741 +    return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
  1.4742 +}
  1.4743 +
  1.4744 +JS_PUBLIC_API(JSFunction *)
  1.4745 +JS_CompileFunction(JSContext *cx, JS::HandleObject obj, const char *name,
  1.4746 +                   unsigned nargs, const char *const *argnames,
  1.4747 +                   const char *ascii, size_t length,
  1.4748 +                   const JS::CompileOptions &options)
  1.4749 +{
  1.4750 +    return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
  1.4751 +}
  1.4752 +
  1.4753 +JS_PUBLIC_API(JSString *)
  1.4754 +JS_DecompileScript(JSContext *cx, HandleScript script, const char *name, unsigned indent)
  1.4755 +{
  1.4756 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4757 +
  1.4758 +    AssertHeapIsIdle(cx);
  1.4759 +    CHECK_REQUEST(cx);
  1.4760 +    script->ensureNonLazyCanonicalFunction(cx);
  1.4761 +    RootedFunction fun(cx, script->functionNonDelazifying());
  1.4762 +    if (fun)
  1.4763 +        return JS_DecompileFunction(cx, fun, indent);
  1.4764 +    bool haveSource = script->scriptSource()->hasSourceData();
  1.4765 +    if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
  1.4766 +        return nullptr;
  1.4767 +    return haveSource ? script->sourceData(cx) : js_NewStringCopyZ<CanGC>(cx, "[no source]");
  1.4768 +}
  1.4769 +
  1.4770 +JS_PUBLIC_API(JSString *)
  1.4771 +JS_DecompileFunction(JSContext *cx, HandleFunction fun, unsigned indent)
  1.4772 +{
  1.4773 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4774 +    AssertHeapIsIdle(cx);
  1.4775 +    CHECK_REQUEST(cx);
  1.4776 +    assertSameCompartment(cx, fun);
  1.4777 +    return FunctionToString(cx, fun, false, !(indent & JS_DONT_PRETTY_PRINT));
  1.4778 +}
  1.4779 +
  1.4780 +JS_PUBLIC_API(JSString *)
  1.4781 +JS_DecompileFunctionBody(JSContext *cx, HandleFunction fun, unsigned indent)
  1.4782 +{
  1.4783 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4784 +    AssertHeapIsIdle(cx);
  1.4785 +    CHECK_REQUEST(cx);
  1.4786 +    assertSameCompartment(cx, fun);
  1.4787 +    return FunctionToString(cx, fun, true, !(indent & JS_DONT_PRETTY_PRINT));
  1.4788 +}
  1.4789 +
  1.4790 +MOZ_NEVER_INLINE static bool
  1.4791 +ExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg, jsval *rval)
  1.4792 +{
  1.4793 +    RootedScript script(cx, scriptArg);
  1.4794 +
  1.4795 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4796 +    AssertHeapIsIdle(cx);
  1.4797 +    CHECK_REQUEST(cx);
  1.4798 +    assertSameCompartment(cx, obj, scriptArg);
  1.4799 +    AutoLastFrameCheck lfc(cx);
  1.4800 +    return Execute(cx, script, *obj, rval);
  1.4801 +}
  1.4802 +
  1.4803 +MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
  1.4804 +JS_ExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg, MutableHandleValue rval)
  1.4805 +{
  1.4806 +    return ExecuteScript(cx, obj, scriptArg, rval.address());
  1.4807 +}
  1.4808 +
  1.4809 +MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
  1.4810 +JS_ExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg)
  1.4811 +{
  1.4812 +    return ExecuteScript(cx, obj, scriptArg, nullptr);
  1.4813 +}
  1.4814 +
  1.4815 +JS_PUBLIC_API(bool)
  1.4816 +JS::CloneAndExecuteScript(JSContext *cx, HandleObject obj, HandleScript scriptArg)
  1.4817 +{
  1.4818 +    CHECK_REQUEST(cx);
  1.4819 +    assertSameCompartment(cx, obj);
  1.4820 +    RootedScript script(cx, scriptArg);
  1.4821 +    if (script->compartment() != cx->compartment()) {
  1.4822 +        script = CloneScript(cx, NullPtr(), NullPtr(), script);
  1.4823 +        if (!script)
  1.4824 +            return false;
  1.4825 +    }
  1.4826 +    return ExecuteScript(cx, obj, script, nullptr);
  1.4827 +}
  1.4828 +
  1.4829 +JS_PUBLIC_API(bool)
  1.4830 +JS_ExecuteScriptVersion(JSContext *cx, HandleObject obj, HandleScript script,
  1.4831 +                        MutableHandleValue rval, JSVersion version)
  1.4832 +{
  1.4833 +    return ExecuteScript(cx, obj, script, rval.address());
  1.4834 +}
  1.4835 +
  1.4836 +JS_PUBLIC_API(bool)
  1.4837 +JS_ExecuteScriptVersion(JSContext *cx, HandleObject obj, HandleScript script, JSVersion version)
  1.4838 +{
  1.4839 +    return ExecuteScript(cx, obj, script, nullptr);
  1.4840 +}
  1.4841 +
  1.4842 +static const unsigned LARGE_SCRIPT_LENGTH = 500*1024;
  1.4843 +
  1.4844 +static bool
  1.4845 +Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4846 +         SourceBufferHolder &srcBuf, JS::Value *rval)
  1.4847 +{
  1.4848 +    CompileOptions options(cx, optionsArg);
  1.4849 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.4850 +    AssertHeapIsIdle(cx);
  1.4851 +    CHECK_REQUEST(cx);
  1.4852 +    assertSameCompartment(cx, obj);
  1.4853 +
  1.4854 +    AutoLastFrameCheck lfc(cx);
  1.4855 +
  1.4856 +    options.setCompileAndGo(obj->is<GlobalObject>());
  1.4857 +    options.setNoScriptRval(!rval);
  1.4858 +    SourceCompressionTask sct(cx);
  1.4859 +    RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(),
  1.4860 +                                                    obj, NullPtr(), options,
  1.4861 +                                                    srcBuf, nullptr, 0, &sct));
  1.4862 +    if (!script)
  1.4863 +        return false;
  1.4864 +
  1.4865 +    JS_ASSERT(script->getVersion() == options.version);
  1.4866 +
  1.4867 +    bool result = Execute(cx, script, *obj, rval);
  1.4868 +    if (!sct.complete())
  1.4869 +        result = false;
  1.4870 +
  1.4871 +    // After evaluation, the compiled script will not be run again.
  1.4872 +    // script->ensureRanAnalysis allocated 1 analyze::Bytecode for every opcode
  1.4873 +    // which for large scripts means significant memory. Perform a GC eagerly
  1.4874 +    // to clear out this analysis data before anything happens to inhibit the
  1.4875 +    // flushing of this memory (such as setting requestAnimationFrame).
  1.4876 +    if (script->length() > LARGE_SCRIPT_LENGTH) {
  1.4877 +        script = nullptr;
  1.4878 +        PrepareZoneForGC(cx->zone());
  1.4879 +        GC(cx->runtime(), GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUTE);
  1.4880 +    }
  1.4881 +
  1.4882 +    return result;
  1.4883 +}
  1.4884 +
  1.4885 +static bool
  1.4886 +Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4887 +         const jschar *chars, size_t length, JS::Value *rval)
  1.4888 +{
  1.4889 +  SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
  1.4890 +  return ::Evaluate(cx, obj, optionsArg, srcBuf, rval);
  1.4891 +}
  1.4892 +
  1.4893 +static bool
  1.4894 +Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4895 +         const char *bytes, size_t length, JS::Value *rval)
  1.4896 +{
  1.4897 +    jschar *chars;
  1.4898 +    if (options.utf8)
  1.4899 +        chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
  1.4900 +    else
  1.4901 +        chars = InflateString(cx, bytes, &length);
  1.4902 +    if (!chars)
  1.4903 +        return false;
  1.4904 +
  1.4905 +    SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
  1.4906 +    bool ok = ::Evaluate(cx, obj, options, srcBuf, rval);
  1.4907 +    return ok;
  1.4908 +}
  1.4909 +
  1.4910 +static bool
  1.4911 +Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4912 +         const char *filename, JS::Value *rval)
  1.4913 +{
  1.4914 +    FileContents buffer(cx);
  1.4915 +    {
  1.4916 +        AutoFile file;
  1.4917 +        if (!file.open(cx, filename) || !file.readAll(cx, buffer))
  1.4918 +            return false;
  1.4919 +    }
  1.4920 +
  1.4921 +    CompileOptions options(cx, optionsArg);
  1.4922 +    options.setFileAndLine(filename, 1);
  1.4923 +    return Evaluate(cx, obj, options, buffer.begin(), buffer.length(), rval);
  1.4924 +}
  1.4925 +
  1.4926 +extern JS_PUBLIC_API(bool)
  1.4927 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4928 +             SourceBufferHolder &srcBuf, MutableHandleValue rval)
  1.4929 +{
  1.4930 +    return ::Evaluate(cx, obj, optionsArg, srcBuf, rval.address());
  1.4931 +}
  1.4932 +
  1.4933 +extern JS_PUBLIC_API(bool)
  1.4934 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4935 +             const jschar *chars, size_t length, MutableHandleValue rval)
  1.4936 +{
  1.4937 +    return ::Evaluate(cx, obj, optionsArg, chars, length, rval.address());
  1.4938 +}
  1.4939 +
  1.4940 +extern JS_PUBLIC_API(bool)
  1.4941 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4942 +             const char *bytes, size_t length, MutableHandleValue rval)
  1.4943 +{
  1.4944 +    return ::Evaluate(cx, obj, options, bytes, length, rval.address());
  1.4945 +}
  1.4946 +
  1.4947 +extern JS_PUBLIC_API(bool)
  1.4948 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4949 +             const char *filename, MutableHandleValue rval)
  1.4950 +{
  1.4951 +    return ::Evaluate(cx, obj, optionsArg, filename, rval.address());
  1.4952 +}
  1.4953 +
  1.4954 +extern JS_PUBLIC_API(bool)
  1.4955 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4956 +             SourceBufferHolder &srcBuf)
  1.4957 +{
  1.4958 +    return ::Evaluate(cx, obj, optionsArg, srcBuf, nullptr);
  1.4959 +}
  1.4960 +
  1.4961 +extern JS_PUBLIC_API(bool)
  1.4962 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4963 +             const jschar *chars, size_t length)
  1.4964 +{
  1.4965 +    return ::Evaluate(cx, obj, optionsArg, chars, length, nullptr);
  1.4966 +}
  1.4967 +
  1.4968 +extern JS_PUBLIC_API(bool)
  1.4969 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &options,
  1.4970 +             const char *bytes, size_t length)
  1.4971 +{
  1.4972 +    return ::Evaluate(cx, obj, options, bytes, length, nullptr);
  1.4973 +}
  1.4974 +
  1.4975 +extern JS_PUBLIC_API(bool)
  1.4976 +JS::Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsArg,
  1.4977 +             const char *filename)
  1.4978 +{
  1.4979 +    return ::Evaluate(cx, obj, optionsArg, filename, nullptr);
  1.4980 +}
  1.4981 +
  1.4982 +JS_PUBLIC_API(bool)
  1.4983 +JS_EvaluateUCScript(JSContext *cx, HandleObject obj, const jschar *chars, unsigned length,
  1.4984 +                    const char *filename, unsigned lineno, MutableHandleValue rval)
  1.4985 +{
  1.4986 +    CompileOptions options(cx);
  1.4987 +    options.setFileAndLine(filename, lineno);
  1.4988 +
  1.4989 +    return ::Evaluate(cx, obj, options, chars, length, rval.address());
  1.4990 +}
  1.4991 +
  1.4992 +JS_PUBLIC_API(bool)
  1.4993 +JS_EvaluateUCScript(JSContext *cx, HandleObject obj, SourceBufferHolder &srcBuf,
  1.4994 +                    const char *filename, unsigned lineno, MutableHandleValue rval)
  1.4995 +{
  1.4996 +    CompileOptions options(cx);
  1.4997 +    options.setFileAndLine(filename, lineno);
  1.4998 +
  1.4999 +    return ::Evaluate(cx, obj, options, srcBuf, rval.address());
  1.5000 +}
  1.5001 +
  1.5002 +JS_PUBLIC_API(bool)
  1.5003 +JS_EvaluateScript(JSContext *cx, HandleObject obj, const char *bytes, unsigned nbytes,
  1.5004 +                  const char *filename, unsigned lineno, MutableHandleValue rval)
  1.5005 +{
  1.5006 +    CompileOptions options(cx);
  1.5007 +    options.setFileAndLine(filename, lineno);
  1.5008 +
  1.5009 +    return ::Evaluate(cx, obj, options, bytes, nbytes, rval.address());
  1.5010 +}
  1.5011 +
  1.5012 +JS_PUBLIC_API(bool)
  1.5013 +JS_EvaluateScript(JSContext *cx, HandleObject obj, const char *bytes, unsigned nbytes,
  1.5014 +                  const char *filename, unsigned lineno)
  1.5015 +{
  1.5016 +    CompileOptions options(cx);
  1.5017 +    options.setFileAndLine(filename, lineno);
  1.5018 +
  1.5019 +    return ::Evaluate(cx, obj, options, bytes, nbytes, nullptr);
  1.5020 +}
  1.5021 +
  1.5022 +JS_PUBLIC_API(bool)
  1.5023 +JS_CallFunction(JSContext *cx, HandleObject obj, HandleFunction fun, const HandleValueArray& args,
  1.5024 +                MutableHandleValue rval)
  1.5025 +{
  1.5026 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.5027 +    AssertHeapIsIdle(cx);
  1.5028 +    CHECK_REQUEST(cx);
  1.5029 +    assertSameCompartment(cx, obj, fun, args);
  1.5030 +    AutoLastFrameCheck lfc(cx);
  1.5031 +
  1.5032 +    return Invoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), args.length(), args.begin(), rval);
  1.5033 +}
  1.5034 +
  1.5035 +JS_PUBLIC_API(bool)
  1.5036 +JS_CallFunctionName(JSContext *cx, HandleObject obj, const char *name, const HandleValueArray& args,
  1.5037 +                    MutableHandleValue rval)
  1.5038 +{
  1.5039 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.5040 +    AssertHeapIsIdle(cx);
  1.5041 +    CHECK_REQUEST(cx);
  1.5042 +    assertSameCompartment(cx, obj, args);
  1.5043 +    AutoLastFrameCheck lfc(cx);
  1.5044 +
  1.5045 +    JSAtom *atom = Atomize(cx, name, strlen(name));
  1.5046 +    if (!atom)
  1.5047 +        return false;
  1.5048 +
  1.5049 +    RootedValue v(cx);
  1.5050 +    RootedId id(cx, AtomToId(atom));
  1.5051 +    if (!JSObject::getGeneric(cx, obj, obj, id, &v))
  1.5052 +        return false;
  1.5053 +
  1.5054 +    return Invoke(cx, ObjectOrNullValue(obj), v, args.length(), args.begin(), rval);
  1.5055 +}
  1.5056 +
  1.5057 +JS_PUBLIC_API(bool)
  1.5058 +JS_CallFunctionValue(JSContext *cx, HandleObject obj, HandleValue fval, const HandleValueArray& args,
  1.5059 +                     MutableHandleValue rval)
  1.5060 +{
  1.5061 +    JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
  1.5062 +    AssertHeapIsIdle(cx);
  1.5063 +    CHECK_REQUEST(cx);
  1.5064 +    assertSameCompartment(cx, obj, fval, args);
  1.5065 +    AutoLastFrameCheck lfc(cx);
  1.5066 +
  1.5067 +    return Invoke(cx, ObjectOrNullValue(obj), fval, args.length(), args.begin(), rval);
  1.5068 +}
  1.5069 +
  1.5070 +JS_PUBLIC_API(bool)
  1.5071 +JS::Call(JSContext *cx, HandleValue thisv, HandleValue fval, const JS::HandleValueArray& args,
  1.5072 +         MutableHandleValue rval)
  1.5073 +{
  1.5074 +    AssertHeapIsIdle(cx);
  1.5075 +    CHECK_REQUEST(cx);
  1.5076 +    assertSameCompartment(cx, thisv, fval, args);
  1.5077 +    AutoLastFrameCheck lfc(cx);
  1.5078 +
  1.5079 +    return Invoke(cx, thisv, fval, args.length(), args.begin(), rval);
  1.5080 +}
  1.5081 +
  1.5082 +static JSObject *
  1.5083 +JS_NewHelper(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
  1.5084 +{
  1.5085 +    AssertHeapIsIdle(cx);
  1.5086 +    CHECK_REQUEST(cx);
  1.5087 +    assertSameCompartment(cx, ctor, inputArgs);
  1.5088 +
  1.5089 +    // This is not a simple variation of JS_CallFunctionValue because JSOP_NEW
  1.5090 +    // is not a simple variation of JSOP_CALL. We have to determine what class
  1.5091 +    // of object to create, create it, and clamp the return value to an object,
  1.5092 +    // among other details. InvokeConstructor does the hard work.
  1.5093 +    InvokeArgs args(cx);
  1.5094 +    if (!args.init(inputArgs.length()))
  1.5095 +        return nullptr;
  1.5096 +
  1.5097 +    args.setCallee(ObjectValue(*ctor));
  1.5098 +    args.setThis(NullValue());
  1.5099 +    PodCopy(args.array(), inputArgs.begin(), inputArgs.length());
  1.5100 +
  1.5101 +    if (!InvokeConstructor(cx, args))
  1.5102 +        return nullptr;
  1.5103 +
  1.5104 +    if (!args.rval().isObject()) {
  1.5105 +        /*
  1.5106 +         * Although constructors may return primitives (via proxies), this
  1.5107 +         * API is asking for an object, so we report an error.
  1.5108 +         */
  1.5109 +        JSAutoByteString bytes;
  1.5110 +        if (js_ValueToPrintable(cx, args.rval(), &bytes)) {
  1.5111 +            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_NEW_RESULT,
  1.5112 +                                 bytes.ptr());
  1.5113 +        }
  1.5114 +        return nullptr;
  1.5115 +    }
  1.5116 +
  1.5117 +    return &args.rval().toObject();
  1.5118 +}
  1.5119 +
  1.5120 +JS_PUBLIC_API(JSObject *)
  1.5121 +JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
  1.5122 +{
  1.5123 +    RootedObject obj(cx);
  1.5124 +    {
  1.5125 +        AutoLastFrameCheck lfc(cx);
  1.5126 +        obj = JS_NewHelper(cx, ctor, inputArgs);
  1.5127 +    }
  1.5128 +    return obj;
  1.5129 +}
  1.5130 +
  1.5131 +JS_PUBLIC_API(JSInterruptCallback)
  1.5132 +JS_SetInterruptCallback(JSRuntime *rt, JSInterruptCallback callback)
  1.5133 +{
  1.5134 +    JSInterruptCallback old = rt->interruptCallback;
  1.5135 +    rt->interruptCallback = callback;
  1.5136 +    return old;
  1.5137 +}
  1.5138 +
  1.5139 +JS_PUBLIC_API(JSInterruptCallback)
  1.5140 +JS_GetInterruptCallback(JSRuntime *rt)
  1.5141 +{
  1.5142 +    return rt->interruptCallback;
  1.5143 +}
  1.5144 +
  1.5145 +JS_PUBLIC_API(void)
  1.5146 +JS_RequestInterruptCallback(JSRuntime *rt)
  1.5147 +{
  1.5148 +    rt->requestInterrupt(JSRuntime::RequestInterruptAnyThread);
  1.5149 +}
  1.5150 +
  1.5151 +JS_PUBLIC_API(bool)
  1.5152 +JS_IsRunning(JSContext *cx)
  1.5153 +{
  1.5154 +    return cx->currentlyRunning();
  1.5155 +}
  1.5156 +
  1.5157 +JS_PUBLIC_API(bool)
  1.5158 +JS_SaveFrameChain(JSContext *cx)
  1.5159 +{
  1.5160 +    AssertHeapIsIdleOrIterating(cx);
  1.5161 +    CHECK_REQUEST(cx);
  1.5162 +    return cx->saveFrameChain();
  1.5163 +}
  1.5164 +
  1.5165 +JS_PUBLIC_API(void)
  1.5166 +JS_RestoreFrameChain(JSContext *cx)
  1.5167 +{
  1.5168 +    AssertHeapIsIdleOrIterating(cx);
  1.5169 +    CHECK_REQUEST(cx);
  1.5170 +    cx->restoreFrameChain();
  1.5171 +}
  1.5172 +
  1.5173 +#ifdef MOZ_TRACE_JSCALLS
  1.5174 +JS_PUBLIC_API(void)
  1.5175 +JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb)
  1.5176 +{
  1.5177 +    cx->functionCallback = fcb;
  1.5178 +}
  1.5179 +
  1.5180 +JS_PUBLIC_API(JSFunctionCallback)
  1.5181 +JS_GetFunctionCallback(JSContext *cx)
  1.5182 +{
  1.5183 +    return cx->functionCallback;
  1.5184 +}
  1.5185 +#endif
  1.5186 +
  1.5187 +/************************************************************************/
  1.5188 +JS_PUBLIC_API(JSString *)
  1.5189 +JS_NewStringCopyN(JSContext *cx, const char *s, size_t n)
  1.5190 +{
  1.5191 +    AssertHeapIsIdle(cx);
  1.5192 +    CHECK_REQUEST(cx);
  1.5193 +    if (!n)
  1.5194 +        return cx->names().empty;
  1.5195 +    return js_NewStringCopyN<CanGC>(cx, s, n);
  1.5196 +}
  1.5197 +
  1.5198 +JS_PUBLIC_API(JSString *)
  1.5199 +JS_NewStringCopyZ(JSContext *cx, const char *s)
  1.5200 +{
  1.5201 +    size_t n;
  1.5202 +    jschar *js;
  1.5203 +    JSString *str;
  1.5204 +
  1.5205 +    AssertHeapIsIdle(cx);
  1.5206 +    CHECK_REQUEST(cx);
  1.5207 +    if (!s || !*s)
  1.5208 +        return cx->runtime()->emptyString;
  1.5209 +    n = strlen(s);
  1.5210 +    js = InflateString(cx, s, &n);
  1.5211 +    if (!js)
  1.5212 +        return nullptr;
  1.5213 +    str = js_NewString<CanGC>(cx, js, n);
  1.5214 +    if (!str)
  1.5215 +        js_free(js);
  1.5216 +    return str;
  1.5217 +}
  1.5218 +
  1.5219 +JS_PUBLIC_API(bool)
  1.5220 +JS_StringHasBeenInterned(JSContext *cx, JSString *str)
  1.5221 +{
  1.5222 +    AssertHeapIsIdle(cx);
  1.5223 +    CHECK_REQUEST(cx);
  1.5224 +
  1.5225 +    if (!str->isAtom())
  1.5226 +        return false;
  1.5227 +
  1.5228 +    return AtomIsInterned(cx, &str->asAtom());
  1.5229 +}
  1.5230 +
  1.5231 +JS_PUBLIC_API(jsid)
  1.5232 +INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str)
  1.5233 +{
  1.5234 +    JS_ASSERT(str);
  1.5235 +    JS_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0);
  1.5236 +    JS_ASSERT_IF(cx, JS_StringHasBeenInterned(cx, str));
  1.5237 +    return AtomToId(&str->asAtom());
  1.5238 +}
  1.5239 +
  1.5240 +JS_PUBLIC_API(JSString *)
  1.5241 +JS_InternJSString(JSContext *cx, HandleString str)
  1.5242 +{
  1.5243 +    AssertHeapIsIdle(cx);
  1.5244 +    CHECK_REQUEST(cx);
  1.5245 +    JSAtom *atom = AtomizeString(cx, str, InternAtom);
  1.5246 +    JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
  1.5247 +    return atom;
  1.5248 +}
  1.5249 +
  1.5250 +JS_PUBLIC_API(JSString *)
  1.5251 +JS_InternString(JSContext *cx, const char *s)
  1.5252 +{
  1.5253 +    return JS_InternStringN(cx, s, strlen(s));
  1.5254 +}
  1.5255 +
  1.5256 +JS_PUBLIC_API(JSString *)
  1.5257 +JS_InternStringN(JSContext *cx, const char *s, size_t length)
  1.5258 +{
  1.5259 +    AssertHeapIsIdle(cx);
  1.5260 +    CHECK_REQUEST(cx);
  1.5261 +    JSAtom *atom = Atomize(cx, s, length, InternAtom);
  1.5262 +    JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
  1.5263 +    return atom;
  1.5264 +}
  1.5265 +
  1.5266 +JS_PUBLIC_API(JSString *)
  1.5267 +JS_NewUCString(JSContext *cx, jschar *chars, size_t length)
  1.5268 +{
  1.5269 +    AssertHeapIsIdle(cx);
  1.5270 +    CHECK_REQUEST(cx);
  1.5271 +    return js_NewString<CanGC>(cx, chars, length);
  1.5272 +}
  1.5273 +
  1.5274 +JS_PUBLIC_API(JSString *)
  1.5275 +JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n)
  1.5276 +{
  1.5277 +    AssertHeapIsIdle(cx);
  1.5278 +    CHECK_REQUEST(cx);
  1.5279 +    if (!n)
  1.5280 +        return cx->names().empty;
  1.5281 +    return js_NewStringCopyN<CanGC>(cx, s, n);
  1.5282 +}
  1.5283 +
  1.5284 +JS_PUBLIC_API(JSString *)
  1.5285 +JS_NewUCStringCopyZ(JSContext *cx, const jschar *s)
  1.5286 +{
  1.5287 +    AssertHeapIsIdle(cx);
  1.5288 +    CHECK_REQUEST(cx);
  1.5289 +    if (!s)
  1.5290 +        return cx->runtime()->emptyString;
  1.5291 +    return js_NewStringCopyZ<CanGC>(cx, s);
  1.5292 +}
  1.5293 +
  1.5294 +JS_PUBLIC_API(JSString *)
  1.5295 +JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
  1.5296 +{
  1.5297 +    AssertHeapIsIdle(cx);
  1.5298 +    CHECK_REQUEST(cx);
  1.5299 +    JSAtom *atom = AtomizeChars(cx, s, length, InternAtom);
  1.5300 +    JS_ASSERT_IF(atom, JS_StringHasBeenInterned(cx, atom));
  1.5301 +    return atom;
  1.5302 +}
  1.5303 +
  1.5304 +JS_PUBLIC_API(JSString *)
  1.5305 +JS_InternUCString(JSContext *cx, const jschar *s)
  1.5306 +{
  1.5307 +    return JS_InternUCStringN(cx, s, js_strlen(s));
  1.5308 +}
  1.5309 +
  1.5310 +JS_PUBLIC_API(size_t)
  1.5311 +JS_GetStringLength(JSString *str)
  1.5312 +{
  1.5313 +    return str->length();
  1.5314 +}
  1.5315 +
  1.5316 +JS_PUBLIC_API(const jschar *)
  1.5317 +JS_GetStringCharsZ(JSContext *cx, JSString *str)
  1.5318 +{
  1.5319 +    size_t dummy;
  1.5320 +    return JS_GetStringCharsZAndLength(cx, str, &dummy);
  1.5321 +}
  1.5322 +
  1.5323 +JS_PUBLIC_API(const jschar *)
  1.5324 +JS_GetStringCharsZAndLength(JSContext *cx, JSString *str, size_t *plength)
  1.5325 +{
  1.5326 +    /*
  1.5327 +     * Don't require |cx->compartment()| to be |str|'s compartment. We don't need
  1.5328 +     * it, and it's annoying for callers.
  1.5329 +     */
  1.5330 +    JS_ASSERT(plength);
  1.5331 +    AssertHeapIsIdleOrStringIsFlat(cx, str);
  1.5332 +    CHECK_REQUEST(cx);
  1.5333 +    JSFlatString *flat = str->ensureFlat(cx);
  1.5334 +    if (!flat)
  1.5335 +        return nullptr;
  1.5336 +    *plength = flat->length();
  1.5337 +    return flat->chars();
  1.5338 +}
  1.5339 +
  1.5340 +JS_PUBLIC_API(const jschar *)
  1.5341 +JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *plength)
  1.5342 +{
  1.5343 +    JS_ASSERT(plength);
  1.5344 +    AssertHeapIsIdleOrStringIsFlat(cx, str);
  1.5345 +    CHECK_REQUEST(cx);
  1.5346 +    assertSameCompartment(cx, str);
  1.5347 +    JSLinearString *linear = str->ensureLinear(cx);
  1.5348 +    if (!linear)
  1.5349 +        return nullptr;
  1.5350 +    *plength = linear->length();
  1.5351 +    return linear->chars();
  1.5352 +}
  1.5353 +
  1.5354 +JS_PUBLIC_API(const jschar *)
  1.5355 +JS_GetInternedStringChars(JSString *str)
  1.5356 +{
  1.5357 +    JS_ASSERT(str->isAtom());
  1.5358 +    JSFlatString *flat = str->ensureFlat(nullptr);
  1.5359 +    if (!flat)
  1.5360 +        return nullptr;
  1.5361 +    return flat->chars();
  1.5362 +}
  1.5363 +
  1.5364 +JS_PUBLIC_API(const jschar *)
  1.5365 +JS_GetInternedStringCharsAndLength(JSString *str, size_t *plength)
  1.5366 +{
  1.5367 +    JS_ASSERT(str->isAtom());
  1.5368 +    JS_ASSERT(plength);
  1.5369 +    JSFlatString *flat = str->ensureFlat(nullptr);
  1.5370 +    if (!flat)
  1.5371 +        return nullptr;
  1.5372 +    *plength = flat->length();
  1.5373 +    return flat->chars();
  1.5374 +}
  1.5375 +
  1.5376 +extern JS_PUBLIC_API(JSFlatString *)
  1.5377 +JS_FlattenString(JSContext *cx, JSString *str)
  1.5378 +{
  1.5379 +    AssertHeapIsIdle(cx);
  1.5380 +    CHECK_REQUEST(cx);
  1.5381 +    assertSameCompartment(cx, str);
  1.5382 +    JSFlatString *flat = str->ensureFlat(cx);
  1.5383 +    if (!flat)
  1.5384 +        return nullptr;
  1.5385 +    return flat;
  1.5386 +}
  1.5387 +
  1.5388 +extern JS_PUBLIC_API(const jschar *)
  1.5389 +JS_GetFlatStringChars(JSFlatString *str)
  1.5390 +{
  1.5391 +    return str->chars();
  1.5392 +}
  1.5393 +
  1.5394 +JS_PUBLIC_API(bool)
  1.5395 +JS_CompareStrings(JSContext *cx, JSString *str1, JSString *str2, int32_t *result)
  1.5396 +{
  1.5397 +    AssertHeapIsIdle(cx);
  1.5398 +    CHECK_REQUEST(cx);
  1.5399 +
  1.5400 +    return CompareStrings(cx, str1, str2, result);
  1.5401 +}
  1.5402 +
  1.5403 +JS_PUBLIC_API(bool)
  1.5404 +JS_StringEqualsAscii(JSContext *cx, JSString *str, const char *asciiBytes, bool *match)
  1.5405 +{
  1.5406 +    AssertHeapIsIdle(cx);
  1.5407 +    CHECK_REQUEST(cx);
  1.5408 +
  1.5409 +    JSLinearString *linearStr = str->ensureLinear(cx);
  1.5410 +    if (!linearStr)
  1.5411 +        return false;
  1.5412 +    *match = StringEqualsAscii(linearStr, asciiBytes);
  1.5413 +    return true;
  1.5414 +}
  1.5415 +
  1.5416 +JS_PUBLIC_API(bool)
  1.5417 +JS_FlatStringEqualsAscii(JSFlatString *str, const char *asciiBytes)
  1.5418 +{
  1.5419 +    return StringEqualsAscii(str, asciiBytes);
  1.5420 +}
  1.5421 +
  1.5422 +JS_PUBLIC_API(size_t)
  1.5423 +JS_PutEscapedFlatString(char *buffer, size_t size, JSFlatString *str, char quote)
  1.5424 +{
  1.5425 +    return PutEscapedString(buffer, size, str, quote);
  1.5426 +}
  1.5427 +
  1.5428 +JS_PUBLIC_API(size_t)
  1.5429 +JS_PutEscapedString(JSContext *cx, char *buffer, size_t size, JSString *str, char quote)
  1.5430 +{
  1.5431 +    AssertHeapIsIdle(cx);
  1.5432 +    JSLinearString *linearStr = str->ensureLinear(cx);
  1.5433 +    if (!linearStr)
  1.5434 +        return size_t(-1);
  1.5435 +    return PutEscapedString(buffer, size, linearStr, quote);
  1.5436 +}
  1.5437 +
  1.5438 +JS_PUBLIC_API(bool)
  1.5439 +JS_FileEscapedString(FILE *fp, JSString *str, char quote)
  1.5440 +{
  1.5441 +    JSLinearString *linearStr = str->ensureLinear(nullptr);
  1.5442 +    return linearStr && FileEscapedString(fp, linearStr, quote);
  1.5443 +}
  1.5444 +
  1.5445 +JS_PUBLIC_API(JSString *)
  1.5446 +JS_NewDependentString(JSContext *cx, HandleString str, size_t start, size_t length)
  1.5447 +{
  1.5448 +    AssertHeapIsIdle(cx);
  1.5449 +    CHECK_REQUEST(cx);
  1.5450 +    return js_NewDependentString(cx, str, start, length);
  1.5451 +}
  1.5452 +
  1.5453 +JS_PUBLIC_API(JSString *)
  1.5454 +JS_ConcatStrings(JSContext *cx, HandleString left, HandleString right)
  1.5455 +{
  1.5456 +    AssertHeapIsIdle(cx);
  1.5457 +    CHECK_REQUEST(cx);
  1.5458 +    return ConcatStrings<CanGC>(cx, left, right);
  1.5459 +}
  1.5460 +
  1.5461 +JS_PUBLIC_API(bool)
  1.5462 +JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
  1.5463 +{
  1.5464 +    AssertHeapIsIdle(cx);
  1.5465 +    CHECK_REQUEST(cx);
  1.5466 +
  1.5467 +    if (!dst) {
  1.5468 +        *dstlenp = srclen;
  1.5469 +        return true;
  1.5470 +    }
  1.5471 +
  1.5472 +    size_t dstlen = *dstlenp;
  1.5473 +
  1.5474 +    if (srclen > dstlen) {
  1.5475 +        InflateStringToBuffer(src, dstlen, dst);
  1.5476 +
  1.5477 +        AutoSuppressGC suppress(cx);
  1.5478 +        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BUFFER_TOO_SMALL);
  1.5479 +        return false;
  1.5480 +    }
  1.5481 +
  1.5482 +    InflateStringToBuffer(src, srclen, dst);
  1.5483 +    *dstlenp = srclen;
  1.5484 +    return true;
  1.5485 +}
  1.5486 +
  1.5487 +JS_PUBLIC_API(char *)
  1.5488 +JS_EncodeString(JSContext *cx, JSString *str)
  1.5489 +{
  1.5490 +    AssertHeapIsIdle(cx);
  1.5491 +    CHECK_REQUEST(cx);
  1.5492 +
  1.5493 +    JSLinearString *linear = str->ensureLinear(cx);
  1.5494 +    if (!linear)
  1.5495 +        return nullptr;
  1.5496 +
  1.5497 +    return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
  1.5498 +}
  1.5499 +
  1.5500 +JS_PUBLIC_API(char *)
  1.5501 +JS_EncodeStringToUTF8(JSContext *cx, HandleString str)
  1.5502 +{
  1.5503 +    AssertHeapIsIdle(cx);
  1.5504 +    CHECK_REQUEST(cx);
  1.5505 +
  1.5506 +    JSLinearString *linear = str->ensureLinear(cx);
  1.5507 +    if (!linear)
  1.5508 +        return nullptr;
  1.5509 +
  1.5510 +    return TwoByteCharsToNewUTF8CharsZ(cx, linear->range()).c_str();
  1.5511 +}
  1.5512 +
  1.5513 +JS_PUBLIC_API(size_t)
  1.5514 +JS_GetStringEncodingLength(JSContext *cx, JSString *str)
  1.5515 +{
  1.5516 +    AssertHeapIsIdle(cx);
  1.5517 +    CHECK_REQUEST(cx);
  1.5518 +
  1.5519 +    const jschar *chars = str->getChars(cx);
  1.5520 +    if (!chars)
  1.5521 +        return size_t(-1);
  1.5522 +    return str->length();
  1.5523 +}
  1.5524 +
  1.5525 +JS_PUBLIC_API(size_t)
  1.5526 +JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length)
  1.5527 +{
  1.5528 +    AssertHeapIsIdle(cx);
  1.5529 +    CHECK_REQUEST(cx);
  1.5530 +
  1.5531 +    /*
  1.5532 +     * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
  1.5533 +     * would allow to distinguish between insufficient buffer and encoding
  1.5534 +     * error.
  1.5535 +     */
  1.5536 +    size_t writtenLength = length;
  1.5537 +    const jschar *chars = str->getChars(nullptr);
  1.5538 +    if (!chars)
  1.5539 +        return size_t(-1);
  1.5540 +    if (DeflateStringToBuffer(nullptr, chars, str->length(), buffer, &writtenLength)) {
  1.5541 +        JS_ASSERT(writtenLength <= length);
  1.5542 +        return writtenLength;
  1.5543 +    }
  1.5544 +    JS_ASSERT(writtenLength <= length);
  1.5545 +    size_t necessaryLength = str->length();
  1.5546 +    if (necessaryLength == size_t(-1))
  1.5547 +        return size_t(-1);
  1.5548 +    JS_ASSERT(writtenLength == length); // C strings are NOT encoded.
  1.5549 +    return necessaryLength;
  1.5550 +}
  1.5551 +
  1.5552 +JS_PUBLIC_API(bool)
  1.5553 +JS_Stringify(JSContext *cx, MutableHandleValue vp, HandleObject replacer,
  1.5554 +             HandleValue space, JSONWriteCallback callback, void *data)
  1.5555 +{
  1.5556 +    AssertHeapIsIdle(cx);
  1.5557 +    CHECK_REQUEST(cx);
  1.5558 +    assertSameCompartment(cx, replacer, space);
  1.5559 +    StringBuffer sb(cx);
  1.5560 +    if (!js_Stringify(cx, vp, replacer, space, sb))
  1.5561 +        return false;
  1.5562 +    if (sb.empty()) {
  1.5563 +        HandlePropertyName null = cx->names().null;
  1.5564 +        return callback(null->chars(), null->length(), data);
  1.5565 +    }
  1.5566 +    return callback(sb.begin(), sb.length(), data);
  1.5567 +}
  1.5568 +
  1.5569 +JS_PUBLIC_API(bool)
  1.5570 +JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, JS::MutableHandleValue vp)
  1.5571 +{
  1.5572 +    AssertHeapIsIdle(cx);
  1.5573 +    CHECK_REQUEST(cx);
  1.5574 +
  1.5575 +    RootedValue reviver(cx, NullValue());
  1.5576 +    return ParseJSONWithReviver(cx, ConstTwoByteChars(chars, len), len, reviver, vp);
  1.5577 +}
  1.5578 +
  1.5579 +JS_PUBLIC_API(bool)
  1.5580 +JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, HandleValue reviver, MutableHandleValue vp)
  1.5581 +{
  1.5582 +    AssertHeapIsIdle(cx);
  1.5583 +    CHECK_REQUEST(cx);
  1.5584 +    return ParseJSONWithReviver(cx, ConstTwoByteChars(chars, len), len, reviver, vp);
  1.5585 +}
  1.5586 +
  1.5587 +/************************************************************************/
  1.5588 +
  1.5589 +JS_PUBLIC_API(void)
  1.5590 +JS_ReportError(JSContext *cx, const char *format, ...)
  1.5591 +{
  1.5592 +    va_list ap;
  1.5593 +
  1.5594 +    AssertHeapIsIdle(cx);
  1.5595 +    va_start(ap, format);
  1.5596 +    js_ReportErrorVA(cx, JSREPORT_ERROR, format, ap);
  1.5597 +    va_end(ap);
  1.5598 +}
  1.5599 +
  1.5600 +JS_PUBLIC_API(void)
  1.5601 +JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback,
  1.5602 +                     void *userRef, const unsigned errorNumber, ...)
  1.5603 +{
  1.5604 +    va_list ap;
  1.5605 +    va_start(ap, errorNumber);
  1.5606 +    JS_ReportErrorNumberVA(cx, errorCallback, userRef, errorNumber, ap);
  1.5607 +    va_end(ap);
  1.5608 +}
  1.5609 +
  1.5610 +JS_PUBLIC_API(void)
  1.5611 +JS_ReportErrorNumberVA(JSContext *cx, JSErrorCallback errorCallback,
  1.5612 +                       void *userRef, const unsigned errorNumber,
  1.5613 +                       va_list ap)
  1.5614 +{
  1.5615 +    AssertHeapIsIdle(cx);
  1.5616 +    js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
  1.5617 +                           errorNumber, ArgumentsAreASCII, ap);
  1.5618 +}
  1.5619 +
  1.5620 +JS_PUBLIC_API(void)
  1.5621 +JS_ReportErrorNumberUC(JSContext *cx, JSErrorCallback errorCallback,
  1.5622 +                       void *userRef, const unsigned errorNumber, ...)
  1.5623 +{
  1.5624 +    va_list ap;
  1.5625 +
  1.5626 +    AssertHeapIsIdle(cx);
  1.5627 +    va_start(ap, errorNumber);
  1.5628 +    js_ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef,
  1.5629 +                           errorNumber, ArgumentsAreUnicode, ap);
  1.5630 +    va_end(ap);
  1.5631 +}
  1.5632 +
  1.5633 +JS_PUBLIC_API(void)
  1.5634 +JS_ReportErrorNumberUCArray(JSContext *cx, JSErrorCallback errorCallback,
  1.5635 +                            void *userRef, const unsigned errorNumber,
  1.5636 +                            const jschar **args)
  1.5637 +{
  1.5638 +    AssertHeapIsIdle(cx);
  1.5639 +    js_ReportErrorNumberUCArray(cx, JSREPORT_ERROR, errorCallback, userRef,
  1.5640 +                                errorNumber, args);
  1.5641 +}
  1.5642 +
  1.5643 +JS_PUBLIC_API(bool)
  1.5644 +JS_ReportWarning(JSContext *cx, const char *format, ...)
  1.5645 +{
  1.5646 +    va_list ap;
  1.5647 +    bool ok;
  1.5648 +
  1.5649 +    AssertHeapIsIdle(cx);
  1.5650 +    va_start(ap, format);
  1.5651 +    ok = js_ReportErrorVA(cx, JSREPORT_WARNING, format, ap);
  1.5652 +    va_end(ap);
  1.5653 +    return ok;
  1.5654 +}
  1.5655 +
  1.5656 +JS_PUBLIC_API(bool)
  1.5657 +JS_ReportErrorFlagsAndNumber(JSContext *cx, unsigned flags,
  1.5658 +                             JSErrorCallback errorCallback, void *userRef,
  1.5659 +                             const unsigned errorNumber, ...)
  1.5660 +{
  1.5661 +    va_list ap;
  1.5662 +    bool ok;
  1.5663 +
  1.5664 +    AssertHeapIsIdle(cx);
  1.5665 +    va_start(ap, errorNumber);
  1.5666 +    ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
  1.5667 +                                errorNumber, ArgumentsAreASCII, ap);
  1.5668 +    va_end(ap);
  1.5669 +    return ok;
  1.5670 +}
  1.5671 +
  1.5672 +JS_PUBLIC_API(bool)
  1.5673 +JS_ReportErrorFlagsAndNumberUC(JSContext *cx, unsigned flags,
  1.5674 +                               JSErrorCallback errorCallback, void *userRef,
  1.5675 +                               const unsigned errorNumber, ...)
  1.5676 +{
  1.5677 +    va_list ap;
  1.5678 +    bool ok;
  1.5679 +
  1.5680 +    AssertHeapIsIdle(cx);
  1.5681 +    va_start(ap, errorNumber);
  1.5682 +    ok = js_ReportErrorNumberVA(cx, flags, errorCallback, userRef,
  1.5683 +                                errorNumber, ArgumentsAreUnicode, ap);
  1.5684 +    va_end(ap);
  1.5685 +    return ok;
  1.5686 +}
  1.5687 +
  1.5688 +JS_PUBLIC_API(void)
  1.5689 +JS_ReportOutOfMemory(JSContext *cx)
  1.5690 +{
  1.5691 +    js_ReportOutOfMemory(cx);
  1.5692 +}
  1.5693 +
  1.5694 +JS_PUBLIC_API(void)
  1.5695 +JS_ReportAllocationOverflow(JSContext *cx)
  1.5696 +{
  1.5697 +    js_ReportAllocationOverflow(cx);
  1.5698 +}
  1.5699 +
  1.5700 +JS_PUBLIC_API(JSErrorReporter)
  1.5701 +JS_GetErrorReporter(JSContext *cx)
  1.5702 +{
  1.5703 +    return cx->errorReporter;
  1.5704 +}
  1.5705 +
  1.5706 +JS_PUBLIC_API(JSErrorReporter)
  1.5707 +JS_SetErrorReporter(JSContext *cx, JSErrorReporter er)
  1.5708 +{
  1.5709 +    JSErrorReporter older;
  1.5710 +
  1.5711 +    older = cx->errorReporter;
  1.5712 +    cx->errorReporter = er;
  1.5713 +    return older;
  1.5714 +}
  1.5715 +
  1.5716 +/************************************************************************/
  1.5717 +
  1.5718 +/*
  1.5719 + * Dates.
  1.5720 + */
  1.5721 +JS_PUBLIC_API(JSObject *)
  1.5722 +JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec)
  1.5723 +{
  1.5724 +    AssertHeapIsIdle(cx);
  1.5725 +    CHECK_REQUEST(cx);
  1.5726 +    return js_NewDateObject(cx, year, mon, mday, hour, min, sec);
  1.5727 +}
  1.5728 +
  1.5729 +JS_PUBLIC_API(JSObject *)
  1.5730 +JS_NewDateObjectMsec(JSContext *cx, double msec)
  1.5731 +{
  1.5732 +    AssertHeapIsIdle(cx);
  1.5733 +    CHECK_REQUEST(cx);
  1.5734 +    return js_NewDateObjectMsec(cx, msec);
  1.5735 +}
  1.5736 +
  1.5737 +JS_PUBLIC_API(bool)
  1.5738 +JS_ObjectIsDate(JSContext *cx, HandleObject obj)
  1.5739 +{
  1.5740 +    assertSameCompartment(cx, obj);
  1.5741 +    return ObjectClassIs(obj, ESClass_Date, cx);
  1.5742 +}
  1.5743 +
  1.5744 +JS_PUBLIC_API(void)
  1.5745 +JS_ClearDateCaches(JSContext *cx)
  1.5746 +{
  1.5747 +    AssertHeapIsIdle(cx);
  1.5748 +    CHECK_REQUEST(cx);
  1.5749 +    cx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
  1.5750 +}
  1.5751 +
  1.5752 +/************************************************************************/
  1.5753 +
  1.5754 +/*
  1.5755 + * Regular Expressions.
  1.5756 + */
  1.5757 +JS_PUBLIC_API(JSObject *)
  1.5758 +JS_NewRegExpObject(JSContext *cx, HandleObject obj, char *bytes, size_t length, unsigned flags)
  1.5759 +{
  1.5760 +    AssertHeapIsIdle(cx);
  1.5761 +    CHECK_REQUEST(cx);
  1.5762 +    jschar *chars = InflateString(cx, bytes, &length);
  1.5763 +    if (!chars)
  1.5764 +        return nullptr;
  1.5765 +
  1.5766 +    RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
  1.5767 +    RegExpObject *reobj = RegExpObject::create(cx, res, chars, length,
  1.5768 +                                               RegExpFlag(flags), nullptr);
  1.5769 +    js_free(chars);
  1.5770 +    return reobj;
  1.5771 +}
  1.5772 +
  1.5773 +JS_PUBLIC_API(JSObject *)
  1.5774 +JS_NewUCRegExpObject(JSContext *cx, HandleObject obj, jschar *chars, size_t length,
  1.5775 +                     unsigned flags)
  1.5776 +{
  1.5777 +    AssertHeapIsIdle(cx);
  1.5778 +    CHECK_REQUEST(cx);
  1.5779 +    RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
  1.5780 +    return RegExpObject::create(cx, res, chars, length,
  1.5781 +                                RegExpFlag(flags), nullptr);
  1.5782 +}
  1.5783 +
  1.5784 +JS_PUBLIC_API(void)
  1.5785 +JS_SetRegExpInput(JSContext *cx, HandleObject obj, HandleString input, bool multiline)
  1.5786 +{
  1.5787 +    AssertHeapIsIdle(cx);
  1.5788 +    CHECK_REQUEST(cx);
  1.5789 +    assertSameCompartment(cx, input);
  1.5790 +
  1.5791 +    obj->as<GlobalObject>().getRegExpStatics()->reset(cx, input, !!multiline);
  1.5792 +}
  1.5793 +
  1.5794 +JS_PUBLIC_API(void)
  1.5795 +JS_ClearRegExpStatics(JSContext *cx, HandleObject obj)
  1.5796 +{
  1.5797 +    AssertHeapIsIdle(cx);
  1.5798 +    CHECK_REQUEST(cx);
  1.5799 +    JS_ASSERT(obj);
  1.5800 +
  1.5801 +    obj->as<GlobalObject>().getRegExpStatics()->clear();
  1.5802 +}
  1.5803 +
  1.5804 +JS_PUBLIC_API(bool)
  1.5805 +JS_ExecuteRegExp(JSContext *cx, HandleObject obj, HandleObject reobj, jschar *chars,
  1.5806 +                 size_t length, size_t *indexp, bool test, MutableHandleValue rval)
  1.5807 +{
  1.5808 +    AssertHeapIsIdle(cx);
  1.5809 +    CHECK_REQUEST(cx);
  1.5810 +
  1.5811 +    RegExpStatics *res = obj->as<GlobalObject>().getRegExpStatics();
  1.5812 +
  1.5813 +    return ExecuteRegExpLegacy(cx, res, reobj->as<RegExpObject>(), NullPtr(), chars, length, indexp,
  1.5814 +                               test, rval);
  1.5815 +}
  1.5816 +
  1.5817 +JS_PUBLIC_API(JSObject *)
  1.5818 +JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, unsigned flags)
  1.5819 +{
  1.5820 +    AssertHeapIsIdle(cx);
  1.5821 +    CHECK_REQUEST(cx);
  1.5822 +    jschar *chars = InflateString(cx, bytes, &length);
  1.5823 +    if (!chars)
  1.5824 +        return nullptr;
  1.5825 +    RegExpObject *reobj = RegExpObject::createNoStatics(cx, chars, length,
  1.5826 +                                                        RegExpFlag(flags), nullptr);
  1.5827 +    js_free(chars);
  1.5828 +    return reobj;
  1.5829 +}
  1.5830 +
  1.5831 +JS_PUBLIC_API(JSObject *)
  1.5832 +JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, unsigned flags)
  1.5833 +{
  1.5834 +    AssertHeapIsIdle(cx);
  1.5835 +    CHECK_REQUEST(cx);
  1.5836 +    return RegExpObject::createNoStatics(cx, chars, length,
  1.5837 +                                         RegExpFlag(flags), nullptr);
  1.5838 +}
  1.5839 +
  1.5840 +JS_PUBLIC_API(bool)
  1.5841 +JS_ExecuteRegExpNoStatics(JSContext *cx, HandleObject obj, jschar *chars, size_t length,
  1.5842 +                          size_t *indexp, bool test, MutableHandleValue rval)
  1.5843 +{
  1.5844 +    AssertHeapIsIdle(cx);
  1.5845 +    CHECK_REQUEST(cx);
  1.5846 +
  1.5847 +    return ExecuteRegExpLegacy(cx, nullptr, obj->as<RegExpObject>(), NullPtr(), chars, length,
  1.5848 +                               indexp, test, rval);
  1.5849 +}
  1.5850 +
  1.5851 +JS_PUBLIC_API(bool)
  1.5852 +JS_ObjectIsRegExp(JSContext *cx, HandleObject obj)
  1.5853 +{
  1.5854 +    assertSameCompartment(cx, obj);
  1.5855 +    return ObjectClassIs(obj, ESClass_RegExp, cx);
  1.5856 +}
  1.5857 +
  1.5858 +JS_PUBLIC_API(unsigned)
  1.5859 +JS_GetRegExpFlags(JSContext *cx, HandleObject obj)
  1.5860 +{
  1.5861 +    AssertHeapIsIdle(cx);
  1.5862 +    CHECK_REQUEST(cx);
  1.5863 +
  1.5864 +    return obj->as<RegExpObject>().getFlags();
  1.5865 +}
  1.5866 +
  1.5867 +JS_PUBLIC_API(JSString *)
  1.5868 +JS_GetRegExpSource(JSContext *cx, HandleObject obj)
  1.5869 +{
  1.5870 +    AssertHeapIsIdle(cx);
  1.5871 +    CHECK_REQUEST(cx);
  1.5872 +
  1.5873 +    return obj->as<RegExpObject>().getSource();
  1.5874 +}
  1.5875 +
  1.5876 +/************************************************************************/
  1.5877 +
  1.5878 +JS_PUBLIC_API(bool)
  1.5879 +JS_SetDefaultLocale(JSRuntime *rt, const char *locale)
  1.5880 +{
  1.5881 +    AssertHeapIsIdle(rt);
  1.5882 +    return rt->setDefaultLocale(locale);
  1.5883 +}
  1.5884 +
  1.5885 +JS_PUBLIC_API(const char*)
  1.5886 +JS_GetDefaultLocale(JSRuntime *rt)
  1.5887 +{
  1.5888 +    AssertHeapIsIdle(rt);
  1.5889 +    return rt->getDefaultLocale();
  1.5890 +}
  1.5891 +
  1.5892 +JS_PUBLIC_API(void)
  1.5893 +JS_ResetDefaultLocale(JSRuntime *rt)
  1.5894 +{
  1.5895 +    AssertHeapIsIdle(rt);
  1.5896 +    rt->resetDefaultLocale();
  1.5897 +}
  1.5898 +
  1.5899 +JS_PUBLIC_API(void)
  1.5900 +JS_SetLocaleCallbacks(JSRuntime *rt, JSLocaleCallbacks *callbacks)
  1.5901 +{
  1.5902 +    AssertHeapIsIdle(rt);
  1.5903 +    rt->localeCallbacks = callbacks;
  1.5904 +}
  1.5905 +
  1.5906 +JS_PUBLIC_API(JSLocaleCallbacks *)
  1.5907 +JS_GetLocaleCallbacks(JSRuntime *rt)
  1.5908 +{
  1.5909 +    /* This function can be called by a finalizer. */
  1.5910 +    return rt->localeCallbacks;
  1.5911 +}
  1.5912 +
  1.5913 +/************************************************************************/
  1.5914 +
  1.5915 +JS_PUBLIC_API(bool)
  1.5916 +JS_IsExceptionPending(JSContext *cx)
  1.5917 +{
  1.5918 +    /* This function can be called by a finalizer. */
  1.5919 +    return (bool) cx->isExceptionPending();
  1.5920 +}
  1.5921 +
  1.5922 +JS_PUBLIC_API(bool)
  1.5923 +JS_GetPendingException(JSContext *cx, MutableHandleValue vp)
  1.5924 +{
  1.5925 +    AssertHeapIsIdle(cx);
  1.5926 +    CHECK_REQUEST(cx);
  1.5927 +    if (!cx->isExceptionPending())
  1.5928 +        return false;
  1.5929 +    return cx->getPendingException(vp);
  1.5930 +}
  1.5931 +
  1.5932 +JS_PUBLIC_API(void)
  1.5933 +JS_SetPendingException(JSContext *cx, HandleValue value)
  1.5934 +{
  1.5935 +    AssertHeapIsIdle(cx);
  1.5936 +    CHECK_REQUEST(cx);
  1.5937 +    assertSameCompartment(cx, value);
  1.5938 +    cx->setPendingException(value);
  1.5939 +}
  1.5940 +
  1.5941 +JS_PUBLIC_API(void)
  1.5942 +JS_ClearPendingException(JSContext *cx)
  1.5943 +{
  1.5944 +    AssertHeapIsIdle(cx);
  1.5945 +    cx->clearPendingException();
  1.5946 +}
  1.5947 +
  1.5948 +JS_PUBLIC_API(bool)
  1.5949 +JS_ReportPendingException(JSContext *cx)
  1.5950 +{
  1.5951 +    AssertHeapIsIdle(cx);
  1.5952 +    CHECK_REQUEST(cx);
  1.5953 +
  1.5954 +    // This can only fail due to oom.
  1.5955 +    bool ok = js_ReportUncaughtException(cx);
  1.5956 +    JS_ASSERT(!cx->isExceptionPending());
  1.5957 +    return ok;
  1.5958 +}
  1.5959 +
  1.5960 +JS::AutoSaveExceptionState::AutoSaveExceptionState(JSContext *cx)
  1.5961 +    : context(cx), wasThrowing(cx->throwing), exceptionValue(cx)
  1.5962 +{
  1.5963 +    AssertHeapIsIdle(cx);
  1.5964 +    CHECK_REQUEST(cx);
  1.5965 +    if (wasThrowing) {
  1.5966 +        exceptionValue = cx->unwrappedException_;
  1.5967 +        cx->clearPendingException();
  1.5968 +    }
  1.5969 +}
  1.5970 +
  1.5971 +void
  1.5972 +JS::AutoSaveExceptionState::restore()
  1.5973 +{
  1.5974 +    context->throwing = wasThrowing;
  1.5975 +    context->unwrappedException_ = exceptionValue;
  1.5976 +    drop();
  1.5977 +}
  1.5978 +
  1.5979 +JS::AutoSaveExceptionState::~AutoSaveExceptionState()
  1.5980 +{
  1.5981 +    if (wasThrowing && !context->isExceptionPending()) {
  1.5982 +        context->throwing = true;
  1.5983 +        context->unwrappedException_ = exceptionValue;
  1.5984 +    }
  1.5985 +}
  1.5986 +
  1.5987 +struct JSExceptionState {
  1.5988 +    bool throwing;
  1.5989 +    jsval exception;
  1.5990 +};
  1.5991 +
  1.5992 +JS_PUBLIC_API(JSExceptionState *)
  1.5993 +JS_SaveExceptionState(JSContext *cx)
  1.5994 +{
  1.5995 +    JSExceptionState *state;
  1.5996 +
  1.5997 +    AssertHeapIsIdle(cx);
  1.5998 +    CHECK_REQUEST(cx);
  1.5999 +    state = cx->pod_malloc<JSExceptionState>();
  1.6000 +    if (state) {
  1.6001 +        state->throwing =
  1.6002 +            JS_GetPendingException(cx, MutableHandleValue::fromMarkedLocation(&state->exception));
  1.6003 +        if (state->throwing && JSVAL_IS_GCTHING(state->exception))
  1.6004 +            AddValueRoot(cx, &state->exception, "JSExceptionState.exception");
  1.6005 +    }
  1.6006 +    return state;
  1.6007 +}
  1.6008 +
  1.6009 +JS_PUBLIC_API(void)
  1.6010 +JS_RestoreExceptionState(JSContext *cx, JSExceptionState *state)
  1.6011 +{
  1.6012 +    AssertHeapIsIdle(cx);
  1.6013 +    CHECK_REQUEST(cx);
  1.6014 +    if (state) {
  1.6015 +        if (state->throwing)
  1.6016 +            JS_SetPendingException(cx, HandleValue::fromMarkedLocation(&state->exception));
  1.6017 +        else
  1.6018 +            JS_ClearPendingException(cx);
  1.6019 +        JS_DropExceptionState(cx, state);
  1.6020 +    }
  1.6021 +}
  1.6022 +
  1.6023 +JS_PUBLIC_API(void)
  1.6024 +JS_DropExceptionState(JSContext *cx, JSExceptionState *state)
  1.6025 +{
  1.6026 +    AssertHeapIsIdle(cx);
  1.6027 +    CHECK_REQUEST(cx);
  1.6028 +    if (state) {
  1.6029 +        if (state->throwing && JSVAL_IS_GCTHING(state->exception)) {
  1.6030 +            assertSameCompartment(cx, state->exception);
  1.6031 +            RemoveRoot(cx->runtime(), &state->exception);
  1.6032 +        }
  1.6033 +        js_free(state);
  1.6034 +    }
  1.6035 +}
  1.6036 +
  1.6037 +JS_PUBLIC_API(JSErrorReport *)
  1.6038 +JS_ErrorFromException(JSContext *cx, HandleObject obj)
  1.6039 +{
  1.6040 +    AssertHeapIsIdle(cx);
  1.6041 +    CHECK_REQUEST(cx);
  1.6042 +    assertSameCompartment(cx, obj);
  1.6043 +    return js_ErrorFromException(cx, obj);
  1.6044 +}
  1.6045 +
  1.6046 +JS_PUBLIC_API(bool)
  1.6047 +JS_ThrowStopIteration(JSContext *cx)
  1.6048 +{
  1.6049 +    AssertHeapIsIdle(cx);
  1.6050 +    return js_ThrowStopIteration(cx);
  1.6051 +}
  1.6052 +
  1.6053 +JS_PUBLIC_API(bool)
  1.6054 +JS_IsStopIteration(jsval v)
  1.6055 +{
  1.6056 +    return v.isObject() && v.toObject().is<StopIterationObject>();
  1.6057 +}
  1.6058 +
  1.6059 +JS_PUBLIC_API(intptr_t)
  1.6060 +JS_GetCurrentThread()
  1.6061 +{
  1.6062 +#ifdef JS_THREADSAFE
  1.6063 +    return reinterpret_cast<intptr_t>(PR_GetCurrentThread());
  1.6064 +#else
  1.6065 +    return 0;
  1.6066 +#endif
  1.6067 +}
  1.6068 +
  1.6069 +extern MOZ_NEVER_INLINE JS_PUBLIC_API(void)
  1.6070 +JS_AbortIfWrongThread(JSRuntime *rt)
  1.6071 +{
  1.6072 +    if (!CurrentThreadCanAccessRuntime(rt))
  1.6073 +        MOZ_CRASH();
  1.6074 +    if (!js::TlsPerThreadData.get()->associatedWith(rt))
  1.6075 +        MOZ_CRASH();
  1.6076 +}
  1.6077 +
  1.6078 +#ifdef JS_GC_ZEAL
  1.6079 +JS_PUBLIC_API(void)
  1.6080 +JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
  1.6081 +{
  1.6082 +    SetGCZeal(cx->runtime(), zeal, frequency);
  1.6083 +}
  1.6084 +
  1.6085 +JS_PUBLIC_API(void)
  1.6086 +JS_ScheduleGC(JSContext *cx, uint32_t count)
  1.6087 +{
  1.6088 +    cx->runtime()->gcNextScheduled = count;
  1.6089 +}
  1.6090 +#endif
  1.6091 +
  1.6092 +JS_PUBLIC_API(void)
  1.6093 +JS_SetParallelParsingEnabled(JSRuntime *rt, bool enabled)
  1.6094 +{
  1.6095 +#ifdef JS_ION
  1.6096 +    rt->setParallelParsingEnabled(enabled);
  1.6097 +#endif
  1.6098 +}
  1.6099 +
  1.6100 +JS_PUBLIC_API(void)
  1.6101 +JS_SetParallelIonCompilationEnabled(JSRuntime *rt, bool enabled)
  1.6102 +{
  1.6103 +#ifdef JS_ION
  1.6104 +    rt->setParallelIonCompilationEnabled(enabled);
  1.6105 +#endif
  1.6106 +}
  1.6107 +
  1.6108 +JS_PUBLIC_API(void)
  1.6109 +JS_SetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt, uint32_t value)
  1.6110 +{
  1.6111 +#ifdef JS_ION
  1.6112 +
  1.6113 +    switch (opt) {
  1.6114 +      case JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER:
  1.6115 +        if (value == uint32_t(-1)) {
  1.6116 +            jit::JitOptions defaultValues;
  1.6117 +            value = defaultValues.baselineUsesBeforeCompile;
  1.6118 +        }
  1.6119 +        jit::js_JitOptions.baselineUsesBeforeCompile = value;
  1.6120 +        break;
  1.6121 +      case JSJITCOMPILER_ION_USECOUNT_TRIGGER:
  1.6122 +        if (value == uint32_t(-1)) {
  1.6123 +            jit::js_JitOptions.resetUsesBeforeCompile();
  1.6124 +            break;
  1.6125 +        }
  1.6126 +        jit::js_JitOptions.setUsesBeforeCompile(value);
  1.6127 +        if (value == 0)
  1.6128 +            jit::js_JitOptions.setEagerCompilation();
  1.6129 +        break;
  1.6130 +      case JSJITCOMPILER_ION_ENABLE:
  1.6131 +        if (value == 1) {
  1.6132 +            JS::RuntimeOptionsRef(rt).setIon(true);
  1.6133 +            IonSpew(js::jit::IonSpew_Scripts, "Enable ion");
  1.6134 +        } else if (value == 0) {
  1.6135 +            JS::RuntimeOptionsRef(rt).setIon(false);
  1.6136 +            IonSpew(js::jit::IonSpew_Scripts, "Disable ion");
  1.6137 +        }
  1.6138 +        break;
  1.6139 +      case JSJITCOMPILER_BASELINE_ENABLE:
  1.6140 +        if (value == 1) {
  1.6141 +            JS::RuntimeOptionsRef(rt).setBaseline(true);
  1.6142 +            IonSpew(js::jit::IonSpew_BaselineScripts, "Enable baseline");
  1.6143 +        } else if (value == 0) {
  1.6144 +            JS::RuntimeOptionsRef(rt).setBaseline(false);
  1.6145 +            IonSpew(js::jit::IonSpew_BaselineScripts, "Disable baseline");
  1.6146 +        }
  1.6147 +        break;
  1.6148 +      case JSJITCOMPILER_PARALLEL_COMPILATION_ENABLE:
  1.6149 +        if (value == 1) {
  1.6150 +            rt->setParallelIonCompilationEnabled(true);
  1.6151 +            IonSpew(js::jit::IonSpew_Scripts, "Enable parallel compilation");
  1.6152 +        } else if (value == 0) {
  1.6153 +            rt->setParallelIonCompilationEnabled(false);
  1.6154 +            IonSpew(js::jit::IonSpew_Scripts, "Disable parallel compilation");
  1.6155 +        }
  1.6156 +        break;
  1.6157 +      default:
  1.6158 +        break;
  1.6159 +    }
  1.6160 +#endif
  1.6161 +}
  1.6162 +
  1.6163 +JS_PUBLIC_API(int)
  1.6164 +JS_GetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt)
  1.6165 +{
  1.6166 +#ifdef JS_ION
  1.6167 +    switch (opt) {
  1.6168 +      case JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER:
  1.6169 +        return jit::js_JitOptions.baselineUsesBeforeCompile;
  1.6170 +      case JSJITCOMPILER_ION_USECOUNT_TRIGGER:
  1.6171 +        return jit::js_JitOptions.forcedDefaultIonUsesBeforeCompile;
  1.6172 +      case JSJITCOMPILER_ION_ENABLE:
  1.6173 +        return JS::RuntimeOptionsRef(rt).ion();
  1.6174 +      case JSJITCOMPILER_BASELINE_ENABLE:
  1.6175 +        return JS::RuntimeOptionsRef(rt).baseline();
  1.6176 +      case JSJITCOMPILER_PARALLEL_COMPILATION_ENABLE:
  1.6177 +        return rt->canUseParallelIonCompilation();
  1.6178 +      default:
  1.6179 +        break;
  1.6180 +    }
  1.6181 +#endif
  1.6182 +    return 0;
  1.6183 +}
  1.6184 +
  1.6185 +/************************************************************************/
  1.6186 +
  1.6187 +#if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
  1.6188 +
  1.6189 +#include "jswin.h"
  1.6190 +
  1.6191 +/*
  1.6192 + * Initialization routine for the JS DLL.
  1.6193 + */
  1.6194 +BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved)
  1.6195 +{
  1.6196 +    return TRUE;
  1.6197 +}
  1.6198 +
  1.6199 +#endif
  1.6200 +
  1.6201 +JS_PUBLIC_API(bool)
  1.6202 +JS_IndexToId(JSContext *cx, uint32_t index, MutableHandleId id)
  1.6203 +{
  1.6204 +    return IndexToId(cx, index, id);
  1.6205 +}
  1.6206 +
  1.6207 +JS_PUBLIC_API(bool)
  1.6208 +JS_CharsToId(JSContext* cx, JS::TwoByteChars chars, MutableHandleId idp)
  1.6209 +{
  1.6210 +    RootedAtom atom(cx, AtomizeChars(cx, chars.start().get(), chars.length()));
  1.6211 +    if (!atom)
  1.6212 +        return false;
  1.6213 +#ifdef DEBUG
  1.6214 +    uint32_t dummy;
  1.6215 +    MOZ_ASSERT(!atom->isIndex(&dummy), "API misuse: |chars| must not encode an index");
  1.6216 +#endif
  1.6217 +    idp.set(AtomToId(atom));
  1.6218 +    return true;
  1.6219 +}
  1.6220 +
  1.6221 +JS_PUBLIC_API(bool)
  1.6222 +JS_IsIdentifier(JSContext *cx, HandleString str, bool *isIdentifier)
  1.6223 +{
  1.6224 +    assertSameCompartment(cx, str);
  1.6225 +
  1.6226 +    JSLinearString* linearStr = str->ensureLinear(cx);
  1.6227 +    if (!linearStr)
  1.6228 +        return false;
  1.6229 +
  1.6230 +    *isIdentifier = js::frontend::IsIdentifier(linearStr);
  1.6231 +    return true;
  1.6232 +}
  1.6233 +
  1.6234 +namespace JS {
  1.6235 +
  1.6236 +void
  1.6237 +AutoFilename::reset(void *newScriptSource)
  1.6238 +{
  1.6239 +    if (newScriptSource)
  1.6240 +        reinterpret_cast<ScriptSource*>(newScriptSource)->incref();
  1.6241 +    if (scriptSource_)
  1.6242 +        reinterpret_cast<ScriptSource*>(scriptSource_)->decref();
  1.6243 +    scriptSource_ = newScriptSource;
  1.6244 +}
  1.6245 +
  1.6246 +const char *
  1.6247 +AutoFilename::get() const
  1.6248 +{
  1.6249 +    JS_ASSERT(scriptSource_);
  1.6250 +    return reinterpret_cast<ScriptSource*>(scriptSource_)->filename();
  1.6251 +}
  1.6252 +
  1.6253 +JS_PUBLIC_API(bool)
  1.6254 +DescribeScriptedCaller(JSContext *cx, AutoFilename *filename, unsigned *lineno)
  1.6255 +{
  1.6256 +    if (lineno)
  1.6257 +        *lineno = 0;
  1.6258 +
  1.6259 +    NonBuiltinFrameIter i(cx);
  1.6260 +    if (i.done())
  1.6261 +        return false;
  1.6262 +
  1.6263 +    // If the caller is hidden, the embedding wants us to return false here so
  1.6264 +    // that it can check its own stack (see HideScriptedCaller).
  1.6265 +    if (i.activation()->scriptedCallerIsHidden())
  1.6266 +        return false;
  1.6267 +
  1.6268 +    if (filename)
  1.6269 +        filename->reset(i.scriptSource());
  1.6270 +    if (lineno)
  1.6271 +        *lineno = i.computeLine();
  1.6272 +    return true;
  1.6273 +}
  1.6274 +
  1.6275 +JS_PUBLIC_API(JSObject *)
  1.6276 +GetScriptedCallerGlobal(JSContext *cx)
  1.6277 +{
  1.6278 +    NonBuiltinFrameIter i(cx);
  1.6279 +    if (i.done())
  1.6280 +        return nullptr;
  1.6281 +
  1.6282 +    // If the caller is hidden, the embedding wants us to return null here so
  1.6283 +    // that it can check its own stack (see HideScriptedCaller).
  1.6284 +    if (i.activation()->scriptedCallerIsHidden())
  1.6285 +        return nullptr;
  1.6286 +
  1.6287 +    GlobalObject *global = i.activation()->compartment()->maybeGlobal();
  1.6288 +
  1.6289 +    // Noone should be running code in the atoms compartment or running code in
  1.6290 +    // a compartment without any live objects, so there should definitely be a
  1.6291 +    // live global.
  1.6292 +    JS_ASSERT(global);
  1.6293 +
  1.6294 +    return global;
  1.6295 +}
  1.6296 +
  1.6297 +JS_PUBLIC_API(void)
  1.6298 +HideScriptedCaller(JSContext *cx)
  1.6299 +{
  1.6300 +    MOZ_ASSERT(cx);
  1.6301 +
  1.6302 +    // If there's no accessible activation on the stack, we'll return null from
  1.6303 +    // DescribeScriptedCaller anyway, so there's no need to annotate anything.
  1.6304 +    Activation *act = cx->runtime()->mainThread.activation();
  1.6305 +    if (!act)
  1.6306 +        return;
  1.6307 +    act->hideScriptedCaller();
  1.6308 +}
  1.6309 +
  1.6310 +JS_PUBLIC_API(void)
  1.6311 +UnhideScriptedCaller(JSContext *cx)
  1.6312 +{
  1.6313 +    Activation *act = cx->runtime()->mainThread.activation();
  1.6314 +    if (!act)
  1.6315 +        return;
  1.6316 +    act->unhideScriptedCaller();
  1.6317 +}
  1.6318 +
  1.6319 +} /* namespace JS */
  1.6320 +
  1.6321 +#ifdef JS_THREADSAFE
  1.6322 +static PRStatus
  1.6323 +CallOnce(void *func)
  1.6324 +{
  1.6325 +    JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
  1.6326 +    return init() ? PR_SUCCESS : PR_FAILURE;
  1.6327 +}
  1.6328 +#endif
  1.6329 +
  1.6330 +JS_PUBLIC_API(bool)
  1.6331 +JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
  1.6332 +{
  1.6333 +#ifdef JS_THREADSAFE
  1.6334 +    return PR_CallOnceWithArg(once, CallOnce, JS_FUNC_TO_DATA_PTR(void *, func)) == PR_SUCCESS;
  1.6335 +#else
  1.6336 +    if (!*once) {
  1.6337 +        *once = true;
  1.6338 +        return func();
  1.6339 +    } else {
  1.6340 +        return true;
  1.6341 +    }
  1.6342 +#endif
  1.6343 +}
  1.6344 +
  1.6345 +AutoGCRooter::AutoGCRooter(JSContext *cx, ptrdiff_t tag)
  1.6346 +  : down(ContextFriendFields::get(cx)->autoGCRooters),
  1.6347 +    tag_(tag),
  1.6348 +    stackTop(&ContextFriendFields::get(cx)->autoGCRooters)
  1.6349 +{
  1.6350 +    JS_ASSERT(this != *stackTop);
  1.6351 +    *stackTop = this;
  1.6352 +}
  1.6353 +
  1.6354 +AutoGCRooter::AutoGCRooter(ContextFriendFields *cx, ptrdiff_t tag)
  1.6355 +  : down(cx->autoGCRooters),
  1.6356 +    tag_(tag),
  1.6357 +    stackTop(&cx->autoGCRooters)
  1.6358 +{
  1.6359 +    JS_ASSERT(this != *stackTop);
  1.6360 +    *stackTop = this;
  1.6361 +}
  1.6362 +
  1.6363 +#ifdef DEBUG
  1.6364 +JS_PUBLIC_API(void)
  1.6365 +JS::AssertArgumentsAreSane(JSContext *cx, HandleValue value)
  1.6366 +{
  1.6367 +    AssertHeapIsIdle(cx);
  1.6368 +    CHECK_REQUEST(cx);
  1.6369 +    assertSameCompartment(cx, value);
  1.6370 +}
  1.6371 +#endif /* DEBUG */
  1.6372 +
  1.6373 +JS_PUBLIC_API(void *)
  1.6374 +JS_EncodeScript(JSContext *cx, HandleScript scriptArg, uint32_t *lengthp)
  1.6375 +{
  1.6376 +    XDREncoder encoder(cx);
  1.6377 +    RootedScript script(cx, scriptArg);
  1.6378 +    if (!encoder.codeScript(&script))
  1.6379 +        return nullptr;
  1.6380 +    return encoder.forgetData(lengthp);
  1.6381 +}
  1.6382 +
  1.6383 +JS_PUBLIC_API(void *)
  1.6384 +JS_EncodeInterpretedFunction(JSContext *cx, HandleObject funobjArg, uint32_t *lengthp)
  1.6385 +{
  1.6386 +    XDREncoder encoder(cx);
  1.6387 +    RootedObject funobj(cx, funobjArg);
  1.6388 +    if (!encoder.codeFunction(&funobj))
  1.6389 +        return nullptr;
  1.6390 +    return encoder.forgetData(lengthp);
  1.6391 +}
  1.6392 +
  1.6393 +JS_PUBLIC_API(JSScript *)
  1.6394 +JS_DecodeScript(JSContext *cx, const void *data, uint32_t length,
  1.6395 +                JSPrincipals *originPrincipals)
  1.6396 +{
  1.6397 +    XDRDecoder decoder(cx, data, length, originPrincipals);
  1.6398 +    RootedScript script(cx);
  1.6399 +    if (!decoder.codeScript(&script))
  1.6400 +        return nullptr;
  1.6401 +    return script;
  1.6402 +}
  1.6403 +
  1.6404 +JS_PUBLIC_API(JSObject *)
  1.6405 +JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length,
  1.6406 +                             JSPrincipals *originPrincipals)
  1.6407 +{
  1.6408 +    XDRDecoder decoder(cx, data, length, originPrincipals);
  1.6409 +    RootedObject funobj(cx);
  1.6410 +    if (!decoder.codeFunction(&funobj))
  1.6411 +        return nullptr;
  1.6412 +    return funobj;
  1.6413 +}
  1.6414 +
  1.6415 +JS_PUBLIC_API(bool)
  1.6416 +JS_PreventExtensions(JSContext *cx, JS::HandleObject obj)
  1.6417 +{
  1.6418 +    bool extensible;
  1.6419 +    if (!JSObject::isExtensible(cx, obj, &extensible))
  1.6420 +        return false;
  1.6421 +    if (!extensible)
  1.6422 +        return true;
  1.6423 +    return JSObject::preventExtensions(cx, obj);
  1.6424 +}
  1.6425 +
  1.6426 +JS_PUBLIC_API(void)
  1.6427 +JS::SetAsmJSCacheOps(JSRuntime *rt, const JS::AsmJSCacheOps *ops)
  1.6428 +{
  1.6429 +    rt->asmJSCacheOps = *ops;
  1.6430 +}
  1.6431 +
  1.6432 +char *
  1.6433 +JSAutoByteString::encodeLatin1(ExclusiveContext *cx, JSString *str)
  1.6434 +{
  1.6435 +    JSLinearString *linear = str->ensureLinear(cx);
  1.6436 +    if (!linear)
  1.6437 +        return nullptr;
  1.6438 +
  1.6439 +    mBytes = LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
  1.6440 +    return mBytes;
  1.6441 +}
  1.6442 +
  1.6443 +JS_PUBLIC_API(void)
  1.6444 +JS::SetLargeAllocationFailureCallback(JSRuntime *rt, JS::LargeAllocationFailureCallback lafc)
  1.6445 +{
  1.6446 +    rt->largeAllocationFailureCallback = lafc;
  1.6447 +}
  1.6448 +
  1.6449 +JS_PUBLIC_API(void)
  1.6450 +JS::SetOutOfMemoryCallback(JSRuntime *rt, OutOfMemoryCallback cb)
  1.6451 +{
  1.6452 +    rt->oomCallback = cb;
  1.6453 +}
  1.6454 +

mercurial