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 +