1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * vim: set ts=8 sts=4 et sw=4 tw=99: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* 8 * JavaScript API. 9 */ 10 11 #include "jsapi.h" 12 13 #include "mozilla/FloatingPoint.h" 14 #include "mozilla/PodOperations.h" 15 #include "mozilla/Sprintf.h" 16 17 #include <ctype.h> 18 #include <stdarg.h> 19 #include <string.h> 20 #include <sys/stat.h> 21 22 #include "jsarray.h" 23 #include "jsatom.h" 24 #include "jsbool.h" 25 #include "jscntxt.h" 26 #include "jsdate.h" 27 #include "jsexn.h" 28 #include "jsfriendapi.h" 29 #include "jsfun.h" 30 #include "jsgc.h" 31 #include "jsiter.h" 32 #include "jsmath.h" 33 #include "jsnum.h" 34 #include "jsobj.h" 35 #include "json.h" 36 #include "jsprf.h" 37 #include "jsscript.h" 38 #include "jsstr.h" 39 #include "jstypes.h" 40 #include "jsutil.h" 41 #include "jswatchpoint.h" 42 #include "jsweakmap.h" 43 #include "jswrapper.h" 44 45 #include "builtin/AtomicsObject.h" 46 #include "builtin/Eval.h" 47 #include "builtin/Intl.h" 48 #include "builtin/MapObject.h" 49 #include "builtin/Promise.h" 50 #include "builtin/RegExp.h" 51 #include "builtin/SymbolObject.h" 52 #ifdef ENABLE_SIMD 53 # include "builtin/SIMD.h" 54 #endif 55 #ifdef ENABLE_BINARYDATA 56 # include "builtin/TypedObject.h" 57 #endif 58 #include "frontend/BytecodeCompiler.h" 59 #include "frontend/FullParseHandler.h" // for JS_BufferIsCompileableUnit 60 #include "frontend/Parser.h" // for JS_BufferIsCompileableUnit 61 #include "gc/Marking.h" 62 #include "gc/Policy.h" 63 #include "jit/JitCommon.h" 64 #include "js/CharacterEncoding.h" 65 #include "js/Conversions.h" 66 #include "js/Date.h" 67 #include "js/Initialization.h" 68 #include "js/Proxy.h" 69 #include "js/SliceBudget.h" 70 #include "js/StructuredClone.h" 71 #include "js/UniquePtr.h" 72 #include "js/Utility.h" 73 #include "vm/AsyncFunction.h" 74 #include "vm/DateObject.h" 75 #include "vm/Debugger.h" 76 #include "vm/EnvironmentObject.h" 77 #include "vm/ErrorObject.h" 78 #include "vm/HelperThreads.h" 79 #include "vm/Interpreter.h" 80 #include "vm/RegExpStatics.h" 81 #include "vm/Runtime.h" 82 #include "vm/SavedStacks.h" 83 #include "vm/SelfHosting.h" 84 #include "vm/Shape.h" 85 #include "vm/StopIterationObject.h" 86 #include "vm/String.h" 87 #include "vm/StringBuffer.h" 88 #include "vm/Symbol.h" 89 #include "vm/TypedArrayCommon.h" 90 #include "vm/WrapperObject.h" 91 #include "vm/Xdr.h" 92 #include "wasm/AsmJS.h" 93 #include "wasm/WasmModule.h" 94 95 #include "jsatominlines.h" 96 #include "jsfuninlines.h" 97 #include "jsscriptinlines.h" 98 99 #include "vm/Interpreter-inl.h" 100 #include "vm/NativeObject-inl.h" 101 #include "vm/SavedStacks-inl.h" 102 #include "vm/String-inl.h" 103 104 using namespace js; 105 using namespace js::gc; 106 107 using mozilla::Maybe; 108 using mozilla::PodCopy; 109 using mozilla::PodZero; 110 111 using JS::AutoGCRooter; 112 using JS::ToInt32; 113 using JS::ToInteger; 114 using JS::ToUint32; 115 116 #ifdef HAVE_VA_LIST_AS_ARRAY 117 #define JS_ADDRESSOF_VA_LIST(ap) ((va_list*)(ap)) 118 #else 119 #define JS_ADDRESSOF_VA_LIST(ap) (&(ap)) 120 #endif 121 122 JS_PUBLIC_API(bool) 123 JS::CallArgs::requireAtLeast(JSContext* cx, const char* fnname, unsigned required) const 124 { 125 if (length() < required) { 126 char numArgsStr[40]; 127 SprintfLiteral(numArgsStr, "%u", required - 1); 128 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED, 129 fnname, numArgsStr, required == 2 ? "" : "s"); 130 return false; 131 } 132 133 return true; 134 } 135 136 static bool 137 ErrorTakesArguments(unsigned msg) 138 { 139 MOZ_ASSERT(msg < JSErr_Limit); 140 unsigned argCount = js_ErrorFormatString[msg].argCount; 141 MOZ_ASSERT(argCount <= 2); 142 return argCount == 1 || argCount == 2; 143 } 144 145 static bool 146 ErrorTakesObjectArgument(unsigned msg) 147 { 148 MOZ_ASSERT(msg < JSErr_Limit); 149 unsigned argCount = js_ErrorFormatString[msg].argCount; 150 MOZ_ASSERT(argCount <= 2); 151 return argCount == 2; 152 } 153 154 JS_PUBLIC_API(bool) 155 JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, HandleId id, 156 bool strict) 157 { 158 static_assert(unsigned(OkCode) == unsigned(JSMSG_NOT_AN_ERROR), 159 "unsigned value of OkCode must not be an error code"); 160 MOZ_ASSERT(code_ != Uninitialized); 161 MOZ_ASSERT(!ok()); 162 163 unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT); 164 if (code_ == JSMSG_OBJECT_NOT_EXTENSIBLE || code_ == JSMSG_SET_NON_OBJECT_RECEIVER) { 165 RootedValue val(cx, ObjectValue(*obj)); 166 return ReportValueErrorFlags(cx, flags, code_, JSDVG_IGNORE_STACK, val, 167 nullptr, nullptr, nullptr); 168 } 169 if (ErrorTakesArguments(code_)) { 170 RootedValue idv(cx, IdToValue(id)); 171 RootedString str(cx, ValueToSource(cx, idv)); 172 if (!str) 173 return false; 174 175 JSAutoByteString propName; 176 if (!propName.encodeUtf8(cx, str)) 177 return false; 178 179 if (ErrorTakesObjectArgument(code_)) { 180 return JS_ReportErrorFlagsAndNumberUTF8(cx, flags, GetErrorMessage, nullptr, code_, 181 obj->getClass()->name, propName.ptr()); 182 } 183 184 return JS_ReportErrorFlagsAndNumberUTF8(cx, flags, GetErrorMessage, nullptr, code_, 185 propName.ptr()); 186 } 187 return JS_ReportErrorFlagsAndNumberASCII(cx, flags, GetErrorMessage, nullptr, code_); 188 } 189 190 JS_PUBLIC_API(bool) 191 JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext* cx, HandleObject obj, bool strict) 192 { 193 MOZ_ASSERT(code_ != Uninitialized); 194 MOZ_ASSERT(!ok()); 195 MOZ_ASSERT(!ErrorTakesArguments(code_)); 196 197 unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT); 198 return JS_ReportErrorFlagsAndNumberASCII(cx, flags, GetErrorMessage, nullptr, code_); 199 } 200 201 JS_PUBLIC_API(bool) 202 JS::ObjectOpResult::failCantRedefineProp() 203 { 204 return fail(JSMSG_CANT_REDEFINE_PROP); 205 } 206 207 JS_PUBLIC_API(bool) 208 JS::ObjectOpResult::failReadOnly() 209 { 210 return fail(JSMSG_READ_ONLY); 211 } 212 213 JS_PUBLIC_API(bool) 214 JS::ObjectOpResult::failGetterOnly() 215 { 216 return fail(JSMSG_GETTER_ONLY); 217 } 218 219 JS_PUBLIC_API(bool) 220 JS::ObjectOpResult::failCantDelete() 221 { 222 return fail(JSMSG_CANT_DELETE); 223 } 224 225 JS_PUBLIC_API(bool) 226 JS::ObjectOpResult::failCantSetInterposed() 227 { 228 return fail(JSMSG_CANT_SET_INTERPOSED); 229 } 230 231 JS_PUBLIC_API(bool) 232 JS::ObjectOpResult::failCantDefineWindowElement() 233 { 234 return fail(JSMSG_CANT_DEFINE_WINDOW_ELEMENT); 235 } 236 237 JS_PUBLIC_API(bool) 238 JS::ObjectOpResult::failCantDeleteWindowElement() 239 { 240 return fail(JSMSG_CANT_DELETE_WINDOW_ELEMENT); 241 } 242 243 JS_PUBLIC_API(bool) 244 JS::ObjectOpResult::failCantDeleteWindowNamedProperty() 245 { 246 return fail(JSMSG_CANT_DELETE_WINDOW_NAMED_PROPERTY); 247 } 248 249 JS_PUBLIC_API(bool) 250 JS::ObjectOpResult::failCantPreventExtensions() 251 { 252 return fail(JSMSG_CANT_PREVENT_EXTENSIONS); 253 } 254 255 JS_PUBLIC_API(bool) 256 JS::ObjectOpResult::failCantSetProto() 257 { 258 return fail(JSMSG_CANT_SET_PROTO); 259 } 260 261 JS_PUBLIC_API(bool) 262 JS::ObjectOpResult::failNoNamedSetter() 263 { 264 return fail(JSMSG_NO_NAMED_SETTER); 265 } 266 267 JS_PUBLIC_API(bool) 268 JS::ObjectOpResult::failNoIndexedSetter() 269 { 270 return fail(JSMSG_NO_INDEXED_SETTER); 271 } 272 273 JS_PUBLIC_API(int64_t) 274 JS_Now() 275 { 276 return PRMJ_Now(); 277 } 278 279 JS_PUBLIC_API(Value) 280 JS_GetNaNValue(JSContext* cx) 281 { 282 return cx->runtime()->NaNValue; 283 } 284 285 JS_PUBLIC_API(Value) 286 JS_GetNegativeInfinityValue(JSContext* cx) 287 { 288 return cx->runtime()->negativeInfinityValue; 289 } 290 291 JS_PUBLIC_API(Value) 292 JS_GetPositiveInfinityValue(JSContext* cx) 293 { 294 return cx->runtime()->positiveInfinityValue; 295 } 296 297 JS_PUBLIC_API(Value) 298 JS_GetEmptyStringValue(JSContext* cx) 299 { 300 return StringValue(cx->runtime()->emptyString); 301 } 302 303 JS_PUBLIC_API(JSString*) 304 JS_GetEmptyString(JSContext* cx) 305 { 306 MOZ_ASSERT(cx->emptyString()); 307 return cx->emptyString(); 308 } 309 310 namespace js { 311 312 void 313 AssertHeapIsIdle(JSRuntime* rt) 314 { 315 MOZ_ASSERT(!rt->isHeapBusy()); 316 } 317 318 } // namespace js 319 320 static void 321 AssertHeapIsIdleOrIterating(JSRuntime* rt) 322 { 323 MOZ_ASSERT(!rt->isHeapCollecting()); 324 } 325 326 static void 327 AssertHeapIsIdleOrStringIsFlat(JSContext* cx, JSString* str) 328 { 329 /* 330 * We allow some functions to be called during a GC as long as the argument 331 * is a flat string, since that will not cause allocation. 332 */ 333 MOZ_ASSERT_IF(cx->runtime()->isHeapBusy(), str->isFlat()); 334 } 335 336 JS_PUBLIC_API(bool) 337 JS_ValueToObject(JSContext* cx, HandleValue value, MutableHandleObject objp) 338 { 339 AssertHeapIsIdle(cx); 340 CHECK_REQUEST(cx); 341 assertSameCompartment(cx, value); 342 if (value.isNullOrUndefined()) { 343 objp.set(nullptr); 344 return true; 345 } 346 JSObject* obj = ToObject(cx, value); 347 if (!obj) 348 return false; 349 objp.set(obj); 350 return true; 351 } 352 353 JS_PUBLIC_API(JSFunction*) 354 JS_ValueToFunction(JSContext* cx, HandleValue value) 355 { 356 AssertHeapIsIdle(cx); 357 CHECK_REQUEST(cx); 358 assertSameCompartment(cx, value); 359 return ReportIfNotFunction(cx, value); 360 } 361 362 JS_PUBLIC_API(JSFunction*) 363 JS_ValueToConstructor(JSContext* cx, HandleValue value) 364 { 365 AssertHeapIsIdle(cx); 366 CHECK_REQUEST(cx); 367 assertSameCompartment(cx, value); 368 return ReportIfNotFunction(cx, value); 369 } 370 371 JS_PUBLIC_API(JSString*) 372 JS_ValueToSource(JSContext* cx, HandleValue value) 373 { 374 AssertHeapIsIdle(cx); 375 CHECK_REQUEST(cx); 376 assertSameCompartment(cx, value); 377 return ValueToSource(cx, value); 378 } 379 380 JS_PUBLIC_API(bool) 381 JS_DoubleIsInt32(double d, int32_t* ip) 382 { 383 return mozilla::NumberIsInt32(d, ip); 384 } 385 386 JS_PUBLIC_API(JSType) 387 JS_TypeOfValue(JSContext* cx, HandleValue value) 388 { 389 AssertHeapIsIdle(cx); 390 CHECK_REQUEST(cx); 391 assertSameCompartment(cx, value); 392 return TypeOfValue(value); 393 } 394 395 JS_PUBLIC_API(bool) 396 JS_StrictlyEqual(JSContext* cx, HandleValue value1, HandleValue value2, bool* equal) 397 { 398 AssertHeapIsIdle(cx); 399 CHECK_REQUEST(cx); 400 assertSameCompartment(cx, value1, value2); 401 MOZ_ASSERT(equal); 402 return StrictlyEqual(cx, value1, value2, equal); 403 } 404 405 JS_PUBLIC_API(bool) 406 JS_LooselyEqual(JSContext* cx, HandleValue value1, HandleValue value2, bool* equal) 407 { 408 AssertHeapIsIdle(cx); 409 CHECK_REQUEST(cx); 410 assertSameCompartment(cx, value1, value2); 411 MOZ_ASSERT(equal); 412 return LooselyEqual(cx, value1, value2, equal); 413 } 414 415 JS_PUBLIC_API(bool) 416 JS_SameValue(JSContext* cx, HandleValue value1, HandleValue value2, bool* same) 417 { 418 AssertHeapIsIdle(cx); 419 CHECK_REQUEST(cx); 420 assertSameCompartment(cx, value1, value2); 421 MOZ_ASSERT(same); 422 return SameValue(cx, value1, value2, same); 423 } 424 425 JS_PUBLIC_API(bool) 426 JS_IsBuiltinEvalFunction(JSFunction* fun) 427 { 428 return IsAnyBuiltinEval(fun); 429 } 430 431 JS_PUBLIC_API(bool) 432 JS_IsBuiltinFunctionConstructor(JSFunction* fun) 433 { 434 return fun->isBuiltinFunctionConstructor(); 435 } 436 437 JS_PUBLIC_API(bool) 438 JS_IsFunctionBound(JSFunction* fun) 439 { 440 return fun->isBoundFunction(); 441 } 442 443 JS_PUBLIC_API(JSObject*) 444 JS_GetBoundFunctionTarget(JSFunction* fun) 445 { 446 return fun->isBoundFunction() ? 447 fun->getBoundFunctionTarget() : nullptr; 448 } 449 450 /************************************************************************/ 451 452 #ifdef DEBUG 453 JS_FRIEND_API(bool) 454 JS::isGCEnabled() 455 { 456 return !TlsPerThreadData.get()->suppressGC; 457 } 458 #else 459 JS_FRIEND_API(bool) JS::isGCEnabled() { return true; } 460 #endif 461 462 JS_PUBLIC_API(JSContext*) 463 JS_NewContext(uint32_t maxbytes, uint32_t maxNurseryBytes, JSContext* parentContext) 464 { 465 MOZ_ASSERT(JS::detail::libraryInitState == JS::detail::InitState::Running, 466 "must call JS_Init prior to creating any JSContexts"); 467 468 // Make sure that all parent runtimes are the topmost parent. 469 JSRuntime* parentRuntime = nullptr; 470 if (parentContext) { 471 parentRuntime = parentContext->runtime(); 472 while (parentRuntime && parentRuntime->parentRuntime) 473 parentRuntime = parentRuntime->parentRuntime; 474 } 475 476 return NewContext(maxbytes, maxNurseryBytes, parentRuntime); 477 } 478 479 JS_PUBLIC_API(void) 480 JS_DestroyContext(JSContext* cx) 481 { 482 DestroyContext(cx); 483 } 484 485 static JS_CurrentEmbedderTimeFunction currentEmbedderTimeFunction; 486 487 JS_PUBLIC_API(void) 488 JS_SetCurrentEmbedderTimeFunction(JS_CurrentEmbedderTimeFunction timeFn) 489 { 490 currentEmbedderTimeFunction = timeFn; 491 } 492 493 JS_PUBLIC_API(double) 494 JS_GetCurrentEmbedderTime() 495 { 496 if (currentEmbedderTimeFunction) 497 return currentEmbedderTimeFunction(); 498 return PRMJ_Now() / static_cast<double>(PRMJ_USEC_PER_MSEC); 499 } 500 501 JS_PUBLIC_API(void*) 502 JS_GetContextPrivate(JSContext* cx) 503 { 504 return cx->data; 505 } 506 507 JS_PUBLIC_API(void) 508 JS_SetContextPrivate(JSContext* cx, void* data) 509 { 510 cx->data = data; 511 } 512 513 JS_PUBLIC_API(void) 514 JS_SetFutexCanWait(JSContext* cx) 515 { 516 cx->fx.setCanWait(true); 517 } 518 519 static void 520 StartRequest(JSContext* cx) 521 { 522 JSRuntime* rt = cx->runtime(); 523 MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt)); 524 525 if (rt->requestDepth) { 526 rt->requestDepth++; 527 } else { 528 /* Indicate that a request is running. */ 529 rt->requestDepth = 1; 530 rt->triggerActivityCallback(true); 531 } 532 } 533 534 static void 535 StopRequest(JSContext* cx) 536 { 537 JSRuntime* rt = cx->runtime(); 538 MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt)); 539 540 MOZ_ASSERT(rt->requestDepth != 0); 541 if (rt->requestDepth != 1) { 542 rt->requestDepth--; 543 } else { 544 rt->requestDepth = 0; 545 rt->triggerActivityCallback(false); 546 } 547 } 548 549 JS_PUBLIC_API(void) 550 JS_BeginRequest(JSContext* cx) 551 { 552 cx->outstandingRequests++; 553 StartRequest(cx); 554 } 555 556 JS_PUBLIC_API(void) 557 JS_EndRequest(JSContext* cx) 558 { 559 MOZ_ASSERT(cx->outstandingRequests != 0); 560 cx->outstandingRequests--; 561 StopRequest(cx); 562 } 563 564 JS_PUBLIC_API(JSContext*) 565 JS_GetParentContext(JSContext* cx) 566 { 567 return cx->parentRuntime ? cx->parentRuntime->unsafeContextFromAnyThread() : cx; 568 } 569 570 JS_PUBLIC_API(JSVersion) 571 JS_GetVersion(JSContext* cx) 572 { 573 return VersionNumber(cx->findVersion()); 574 } 575 576 JS_PUBLIC_API(void) 577 JS_SetVersionForCompartment(JSCompartment* compartment, JSVersion version) 578 { 579 compartment->behaviors().setVersion(version); 580 } 581 582 static const struct v2smap { 583 JSVersion version; 584 const char* string; 585 } v2smap[] = { 586 {JSVERSION_ECMA_3, "ECMAv3"}, 587 {JSVERSION_1_6, "1.6"}, 588 {JSVERSION_1_7, "1.7"}, 589 {JSVERSION_1_8, "1.8"}, 590 {JSVERSION_ECMA_5, "ECMAv5"}, 591 {JSVERSION_DEFAULT, js_default_str}, 592 {JSVERSION_DEFAULT, "1.0"}, 593 {JSVERSION_DEFAULT, "1.1"}, 594 {JSVERSION_DEFAULT, "1.2"}, 595 {JSVERSION_DEFAULT, "1.3"}, 596 {JSVERSION_DEFAULT, "1.4"}, 597 {JSVERSION_DEFAULT, "1.5"}, 598 {JSVERSION_UNKNOWN, nullptr}, /* must be last, nullptr is sentinel */ 599 }; 600 601 JS_PUBLIC_API(const char*) 602 JS_VersionToString(JSVersion version) 603 { 604 int i; 605 606 for (i = 0; v2smap[i].string; i++) 607 if (v2smap[i].version == version) 608 return v2smap[i].string; 609 return "unknown"; 610 } 611 612 JS_PUBLIC_API(JSVersion) 613 JS_StringToVersion(const char* string) 614 { 615 int i; 616 617 for (i = 0; v2smap[i].string; i++) 618 if (strcmp(v2smap[i].string, string) == 0) 619 return v2smap[i].version; 620 return JSVERSION_UNKNOWN; 621 } 622 623 JS_PUBLIC_API(JS::ContextOptions&) 624 JS::ContextOptionsRef(JSContext* cx) 625 { 626 return cx->options(); 627 } 628 629 JS_PUBLIC_API(bool) 630 JS::InitSelfHostedCode(JSContext* cx) 631 { 632 MOZ_RELEASE_ASSERT(!cx->runtime()->hasInitializedSelfHosting(), 633 "JS::InitSelfHostedCode() called more than once"); 634 635 JSRuntime* rt = cx->runtime(); 636 637 JSAutoRequest ar(cx); 638 if (!rt->initializeAtoms(cx)) 639 return false; 640 641 if (!cx->cycleDetectorSet.init()) 642 return false; 643 644 if (!rt->initSelfHosting(cx)) 645 return false; 646 647 if (!rt->parentRuntime && !rt->transformToPermanentAtoms(cx)) 648 return false; 649 650 return true; 651 } 652 653 JS_PUBLIC_API(const char*) 654 JS_GetImplementationVersion(void) 655 { 656 return "JavaScript-C" MOZILLA_VERSION; 657 } 658 659 JS_PUBLIC_API(void) 660 JS_SetDestroyCompartmentCallback(JSContext* cx, JSDestroyCompartmentCallback callback) 661 { 662 cx->destroyCompartmentCallback = callback; 663 } 664 665 JS_PUBLIC_API(void) 666 JS_SetSizeOfIncludingThisCompartmentCallback(JSContext* cx, 667 JSSizeOfIncludingThisCompartmentCallback callback) 668 { 669 cx->sizeOfIncludingThisCompartmentCallback = callback; 670 } 671 672 JS_PUBLIC_API(void) 673 JS_SetDestroyZoneCallback(JSContext* cx, JSZoneCallback callback) 674 { 675 cx->destroyZoneCallback = callback; 676 } 677 678 JS_PUBLIC_API(void) 679 JS_SetSweepZoneCallback(JSContext* cx, JSZoneCallback callback) 680 { 681 cx->sweepZoneCallback = callback; 682 } 683 684 JS_PUBLIC_API(void) 685 JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback) 686 { 687 cx->compartmentNameCallback = callback; 688 } 689 690 JS_PUBLIC_API(void) 691 JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks) 692 { 693 cx->wrapObjectCallbacks = callbacks; 694 } 695 696 JS_PUBLIC_API(JSCompartment*) 697 JS_EnterCompartment(JSContext* cx, JSObject* target) 698 { 699 AssertHeapIsIdle(cx); 700 CHECK_REQUEST(cx); 701 MOZ_ASSERT(!JS::ObjectIsMarkedGray(target)); 702 703 JSCompartment* oldCompartment = cx->compartment(); 704 cx->enterCompartment(target->compartment()); 705 return oldCompartment; 706 } 707 708 JS_PUBLIC_API(void) 709 JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment) 710 { 711 AssertHeapIsIdle(cx); 712 CHECK_REQUEST(cx); 713 cx->leaveCompartment(oldCompartment); 714 } 715 716 JSAutoCompartment::JSAutoCompartment(JSContext* cx, JSObject* target 717 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) 718 : cx_(cx), 719 oldCompartment_(cx->compartment()) 720 { 721 AssertHeapIsIdleOrIterating(cx_); 722 MOZ_GUARD_OBJECT_NOTIFIER_INIT; 723 MOZ_ASSERT(!JS::ObjectIsMarkedGray(target)); 724 cx_->enterCompartment(target->compartment()); 725 } 726 727 JSAutoCompartment::JSAutoCompartment(JSContext* cx, JSScript* target 728 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) 729 : cx_(cx), 730 oldCompartment_(cx->compartment()) 731 { 732 AssertHeapIsIdleOrIterating(cx_); 733 MOZ_GUARD_OBJECT_NOTIFIER_INIT; 734 MOZ_ASSERT(!JS::ScriptIsMarkedGray(target)); 735 cx_->enterCompartment(target->compartment()); 736 } 737 738 JSAutoCompartment::~JSAutoCompartment() 739 { 740 cx_->leaveCompartment(oldCompartment_); 741 } 742 743 JSAutoNullableCompartment::JSAutoNullableCompartment(JSContext* cx, 744 JSObject* targetOrNull 745 MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) 746 : cx_(cx), 747 oldCompartment_(cx->compartment()) 748 { 749 AssertHeapIsIdleOrIterating(cx_); 750 MOZ_GUARD_OBJECT_NOTIFIER_INIT; 751 if (targetOrNull) { 752 MOZ_ASSERT(!JS::ObjectIsMarkedGray(targetOrNull)); 753 cx_->enterCompartment(targetOrNull->compartment()); 754 } else { 755 cx_->enterNullCompartment(); 756 } 757 } 758 759 JSAutoNullableCompartment::~JSAutoNullableCompartment() 760 { 761 cx_->leaveCompartment(oldCompartment_); 762 } 763 764 JS_PUBLIC_API(void) 765 JS_SetCompartmentPrivate(JSCompartment* compartment, void* data) 766 { 767 compartment->data = data; 768 } 769 770 JS_PUBLIC_API(void*) 771 JS_GetCompartmentPrivate(JSCompartment* compartment) 772 { 773 return compartment->data; 774 } 775 776 JS_PUBLIC_API(JSAddonId*) 777 JS::NewAddonId(JSContext* cx, HandleString str) 778 { 779 return static_cast<JSAddonId*>(JS_AtomizeAndPinJSString(cx, str)); 780 } 781 782 JS_PUBLIC_API(JSString*) 783 JS::StringOfAddonId(JSAddonId* id) 784 { 785 return id; 786 } 787 788 JS_PUBLIC_API(JSAddonId*) 789 JS::AddonIdOfObject(JSObject* obj) 790 { 791 return obj->compartment()->creationOptions().addonIdOrNull(); 792 } 793 794 JS_PUBLIC_API(void) 795 JS_SetZoneUserData(JS::Zone* zone, void* data) 796 { 797 zone->data = data; 798 } 799 800 JS_PUBLIC_API(void*) 801 JS_GetZoneUserData(JS::Zone* zone) 802 { 803 return zone->data; 804 } 805 806 JS_PUBLIC_API(bool) 807 JS_WrapObject(JSContext* cx, MutableHandleObject objp) 808 { 809 AssertHeapIsIdle(cx); 810 CHECK_REQUEST(cx); 811 if (objp) 812 JS::ExposeObjectToActiveJS(objp); 813 return cx->compartment()->wrap(cx, objp); 814 } 815 816 JS_PUBLIC_API(bool) 817 JS_WrapValue(JSContext* cx, MutableHandleValue vp) 818 { 819 AssertHeapIsIdle(cx); 820 CHECK_REQUEST(cx); 821 JS::ExposeValueToActiveJS(vp); 822 return cx->compartment()->wrap(cx, vp); 823 } 824 825 /* 826 * Identity remapping. Not for casual consumers. 827 * 828 * Normally, an object's contents and its identity are inextricably linked. 829 * Identity is determined by the address of the JSObject* in the heap, and 830 * the contents are what is located at that address. Transplanting allows these 831 * concepts to be separated through a combination of swapping (exchanging the 832 * contents of two same-compartment objects) and remapping cross-compartment 833 * identities by altering wrappers. 834 * 835 * The |origobj| argument should be the object whose identity needs to be 836 * remapped, usually to another compartment. The contents of |origobj| are 837 * destroyed. 838 * 839 * The |target| argument serves two purposes: 840 * 841 * First, |target| serves as a hint for the new identity of the object. The new 842 * identity object will always be in the same compartment as |target|, but 843 * if that compartment already had an object representing |origobj| (either a 844 * cross-compartment wrapper for it, or |origobj| itself if the two arguments 845 * are same-compartment), the existing object is used. Otherwise, |target| 846 * itself is used. To avoid ambiguity, JS_TransplantObject always returns the 847 * new identity. 848 * 849 * Second, the new identity object's contents will be those of |target|. A swap() 850 * is used to make this happen if an object other than |target| is used. 851 * 852 * We don't have a good way to recover from failure in this function, so 853 * we intentionally crash instead. 854 */ 855 856 JS_PUBLIC_API(JSObject*) 857 JS_TransplantObject(JSContext* cx, HandleObject origobj, HandleObject target) 858 { 859 AssertHeapIsIdle(cx); 860 MOZ_ASSERT(origobj != target); 861 MOZ_ASSERT(!origobj->is<CrossCompartmentWrapperObject>()); 862 MOZ_ASSERT(!target->is<CrossCompartmentWrapperObject>()); 863 864 RootedValue origv(cx, ObjectValue(*origobj)); 865 RootedObject newIdentity(cx); 866 867 // Don't allow a compacting GC to observe any intermediate state. 868 AutoDisableCompactingGC nocgc(cx); 869 870 AutoDisableProxyCheck adpc(cx->runtime()); 871 872 JSCompartment* destination = target->compartment(); 873 874 if (origobj->compartment() == destination) { 875 // If the original object is in the same compartment as the 876 // destination, then we know that we won't find a wrapper in the 877 // destination's cross compartment map and that the same 878 // object will continue to work. 879 if (!JSObject::swap(cx, origobj, target)) 880 MOZ_CRASH(); 881 newIdentity = origobj; 882 } else if (WrapperMap::Ptr p = destination->lookupWrapper(origv)) { 883 // There might already be a wrapper for the original object in 884 // the new compartment. If there is, we use its identity and swap 885 // in the contents of |target|. 886 newIdentity = &p->value().get().toObject(); 887 888 // When we remove origv from the wrapper map, its wrapper, newIdentity, 889 // must immediately cease to be a cross-compartment wrapper. Nuke it. 890 destination->removeWrapper(p); 891 NukeCrossCompartmentWrapper(cx, newIdentity); 892 893 if (!JSObject::swap(cx, newIdentity, target)) 894 MOZ_CRASH(); 895 } else { 896 // Otherwise, we use |target| for the new identity object. 897 newIdentity = target; 898 } 899 900 // Now, iterate through other scopes looking for references to the 901 // old object, and update the relevant cross-compartment wrappers. 902 if (!RemapAllWrappersForObject(cx, origobj, newIdentity)) 903 MOZ_CRASH(); 904 905 // Lastly, update the original object to point to the new one. 906 if (origobj->compartment() != destination) { 907 RootedObject newIdentityWrapper(cx, newIdentity); 908 AutoCompartment ac(cx, origobj); 909 if (!JS_WrapObject(cx, &newIdentityWrapper)) 910 MOZ_CRASH(); 911 MOZ_ASSERT(Wrapper::wrappedObject(newIdentityWrapper) == newIdentity); 912 if (!JSObject::swap(cx, origobj, newIdentityWrapper)) 913 MOZ_CRASH(); 914 if (!origobj->compartment()->putWrapper(cx, CrossCompartmentKey(newIdentity), origv)) 915 MOZ_CRASH(); 916 } 917 918 // The new identity object might be one of several things. Return it to avoid 919 // ambiguity. 920 return newIdentity; 921 } 922 923 /* 924 * Recompute all cross-compartment wrappers for an object, resetting state. 925 * Gecko uses this to clear Xray wrappers when doing a navigation that reuses 926 * the inner window and global object. 927 */ 928 JS_PUBLIC_API(bool) 929 JS_RefreshCrossCompartmentWrappers(JSContext* cx, HandleObject obj) 930 { 931 return RemapAllWrappersForObject(cx, obj, obj); 932 } 933 934 JS_PUBLIC_API(bool) 935 JS_InitStandardClasses(JSContext* cx, HandleObject obj) 936 { 937 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 938 AssertHeapIsIdle(cx); 939 CHECK_REQUEST(cx); 940 941 assertSameCompartment(cx, obj); 942 943 Rooted<GlobalObject*> global(cx, &obj->global()); 944 return GlobalObject::initStandardClasses(cx, global); 945 } 946 947 #define EAGER_ATOM(name) NAME_OFFSET(name) 948 949 typedef struct JSStdName { 950 size_t atomOffset; /* offset of atom pointer in JSAtomState */ 951 JSProtoKey key; 952 bool isDummy() const { return key == JSProto_Null; } 953 bool isSentinel() const { return key == JSProto_LIMIT; } 954 } JSStdName; 955 956 static const JSStdName* 957 LookupStdName(const JSAtomState& names, JSAtom* name, const JSStdName* table) 958 { 959 for (unsigned i = 0; !table[i].isSentinel(); i++) { 960 if (table[i].isDummy()) 961 continue; 962 JSAtom* atom = AtomStateOffsetToName(names, table[i].atomOffset); 963 MOZ_ASSERT(atom); 964 if (name == atom) 965 return &table[i]; 966 } 967 968 return nullptr; 969 } 970 971 /* 972 * Table of standard classes, indexed by JSProtoKey. For entries where the 973 * JSProtoKey does not correspond to a class with a meaningful constructor, we 974 * insert a null entry into the table. 975 */ 976 #define STD_NAME_ENTRY(name, code, init, clasp) { EAGER_ATOM(name), static_cast<JSProtoKey>(code) }, 977 #define STD_DUMMY_ENTRY(name, code, init, dummy) { 0, JSProto_Null }, 978 static const JSStdName standard_class_names[] = { 979 JS_FOR_PROTOTYPES(STD_NAME_ENTRY, STD_DUMMY_ENTRY) 980 { 0, JSProto_LIMIT } 981 }; 982 983 /* 984 * Table of top-level function and constant names and the JSProtoKey of the 985 * standard class that initializes them. 986 */ 987 static const JSStdName builtin_property_names[] = { 988 { EAGER_ATOM(eval), JSProto_Object }, 989 990 /* Global properties and functions defined by the Number class. */ 991 { EAGER_ATOM(NaN), JSProto_Number }, 992 { EAGER_ATOM(Infinity), JSProto_Number }, 993 { EAGER_ATOM(isNaN), JSProto_Number }, 994 { EAGER_ATOM(isFinite), JSProto_Number }, 995 { EAGER_ATOM(parseFloat), JSProto_Number }, 996 { EAGER_ATOM(parseInt), JSProto_Number }, 997 998 /* String global functions. */ 999 { EAGER_ATOM(escape), JSProto_String }, 1000 { EAGER_ATOM(unescape), JSProto_String }, 1001 { EAGER_ATOM(decodeURI), JSProto_String }, 1002 { EAGER_ATOM(encodeURI), JSProto_String }, 1003 { EAGER_ATOM(decodeURIComponent), JSProto_String }, 1004 { EAGER_ATOM(encodeURIComponent), JSProto_String }, 1005 #if JS_HAS_UNEVAL 1006 { EAGER_ATOM(uneval), JSProto_String }, 1007 #endif 1008 1009 { 0, JSProto_LIMIT } 1010 }; 1011 1012 #undef EAGER_ATOM 1013 1014 JS_PUBLIC_API(bool) 1015 JS_ResolveStandardClass(JSContext* cx, HandleObject obj, HandleId id, bool* resolved) 1016 { 1017 const JSStdName* stdnm; 1018 1019 AssertHeapIsIdle(cx); 1020 CHECK_REQUEST(cx); 1021 assertSameCompartment(cx, obj, id); 1022 1023 Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); 1024 *resolved = false; 1025 1026 if (!JSID_IS_ATOM(id)) 1027 return true; 1028 1029 /* Check whether we're resolving 'undefined', and define it if so. */ 1030 JSAtom* idAtom = JSID_TO_ATOM(id); 1031 JSAtom* undefinedAtom = cx->names().undefined; 1032 if (idAtom == undefinedAtom) { 1033 *resolved = true; 1034 return DefineProperty(cx, global, id, UndefinedHandleValue, nullptr, nullptr, 1035 JSPROP_PERMANENT | JSPROP_READONLY | JSPROP_RESOLVING); 1036 } 1037 1038 /* Try for class constructors/prototypes named by well-known atoms. */ 1039 stdnm = LookupStdName(cx->names(), idAtom, standard_class_names); 1040 1041 /* Try less frequently used top-level functions and constants. */ 1042 if (!stdnm) 1043 stdnm = LookupStdName(cx->names(), idAtom, builtin_property_names); 1044 1045 if (stdnm && GlobalObject::skipDeselectedConstructor(cx, stdnm->key)) 1046 stdnm = nullptr; 1047 1048 // If this class is anonymous, then it doesn't exist as a global 1049 // property, so we won't resolve anything. 1050 JSProtoKey key = stdnm ? stdnm->key : JSProto_Null; 1051 if (key != JSProto_Null) { 1052 const Class* clasp = ProtoKeyToClass(key); 1053 if (!clasp || !(clasp->flags & JSCLASS_IS_ANONYMOUS)) { 1054 if (!GlobalObject::ensureConstructor(cx, global, key)) 1055 return false; 1056 1057 *resolved = true; 1058 return true; 1059 } 1060 } 1061 1062 // There is no such property to resolve. An ordinary resolve hook would 1063 // just return true at this point. But the global object is special in one 1064 // more way: its prototype chain is lazily initialized. That is, 1065 // global->getProto() might be null right now because we haven't created 1066 // Object.prototype yet. Force it now. 1067 if (!global->getOrCreateObjectPrototype(cx)) 1068 return false; 1069 1070 return true; 1071 } 1072 1073 JS_PUBLIC_API(bool) 1074 JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj) 1075 { 1076 MOZ_ASSERT_IF(maybeObj, maybeObj->is<GlobalObject>()); 1077 1078 // The global object's resolve hook is special: JS_ResolveStandardClass 1079 // initializes the prototype chain lazily. Only attempt to optimize here 1080 // if we know the prototype chain has been initialized. 1081 if (!maybeObj || !maybeObj->staticPrototype()) 1082 return true; 1083 1084 if (!JSID_IS_ATOM(id)) 1085 return false; 1086 1087 JSAtom* atom = JSID_TO_ATOM(id); 1088 1089 // This will return true even for deselected constructors. (To do 1090 // better, we need a JSContext here; it's fine as it is.) 1091 1092 return atom == names.undefined || 1093 LookupStdName(names, atom, standard_class_names) || 1094 LookupStdName(names, atom, builtin_property_names); 1095 } 1096 1097 JS_PUBLIC_API(bool) 1098 JS_EnumerateStandardClasses(JSContext* cx, HandleObject obj) 1099 { 1100 AssertHeapIsIdle(cx); 1101 CHECK_REQUEST(cx); 1102 assertSameCompartment(cx, obj); 1103 MOZ_ASSERT(obj->is<GlobalObject>()); 1104 Rooted<GlobalObject*> global(cx, &obj->as<GlobalObject>()); 1105 return GlobalObject::initStandardClasses(cx, global); 1106 } 1107 1108 JS_PUBLIC_API(bool) 1109 JS_GetClassObject(JSContext* cx, JSProtoKey key, MutableHandleObject objp) 1110 { 1111 AssertHeapIsIdle(cx); 1112 CHECK_REQUEST(cx); 1113 return GetBuiltinConstructor(cx, key, objp); 1114 } 1115 1116 JS_PUBLIC_API(bool) 1117 JS_GetClassPrototype(JSContext* cx, JSProtoKey key, MutableHandleObject objp) 1118 { 1119 AssertHeapIsIdle(cx); 1120 CHECK_REQUEST(cx); 1121 return GetBuiltinPrototype(cx, key, objp); 1122 } 1123 1124 namespace JS { 1125 1126 JS_PUBLIC_API(void) 1127 ProtoKeyToId(JSContext* cx, JSProtoKey key, MutableHandleId idp) 1128 { 1129 idp.set(NameToId(ClassName(key, cx))); 1130 } 1131 1132 } /* namespace JS */ 1133 1134 JS_PUBLIC_API(JSProtoKey) 1135 JS_IdToProtoKey(JSContext* cx, HandleId id) 1136 { 1137 AssertHeapIsIdle(cx); 1138 CHECK_REQUEST(cx); 1139 1140 if (!JSID_IS_ATOM(id)) 1141 return JSProto_Null; 1142 1143 JSAtom* atom = JSID_TO_ATOM(id); 1144 const JSStdName* stdnm = LookupStdName(cx->names(), atom, standard_class_names); 1145 if (!stdnm) 1146 return JSProto_Null; 1147 1148 if (GlobalObject::skipDeselectedConstructor(cx, stdnm->key)) 1149 return JSProto_Null; 1150 1151 MOZ_ASSERT(MOZ_ARRAY_LENGTH(standard_class_names) == JSProto_LIMIT + 1); 1152 return static_cast<JSProtoKey>(stdnm - standard_class_names); 1153 } 1154 1155 JS_PUBLIC_API(JSObject*) 1156 JS_GetObjectPrototype(JSContext* cx, HandleObject forObj) 1157 { 1158 CHECK_REQUEST(cx); 1159 assertSameCompartment(cx, forObj); 1160 return forObj->global().getOrCreateObjectPrototype(cx); 1161 } 1162 1163 JS_PUBLIC_API(JSObject*) 1164 JS_GetFunctionPrototype(JSContext* cx, HandleObject forObj) 1165 { 1166 CHECK_REQUEST(cx); 1167 assertSameCompartment(cx, forObj); 1168 return forObj->global().getOrCreateFunctionPrototype(cx); 1169 } 1170 1171 JS_PUBLIC_API(JSObject*) 1172 JS_GetArrayPrototype(JSContext* cx, HandleObject forObj) 1173 { 1174 CHECK_REQUEST(cx); 1175 assertSameCompartment(cx, forObj); 1176 Rooted<GlobalObject*> global(cx, &forObj->global()); 1177 return GlobalObject::getOrCreateArrayPrototype(cx, global); 1178 } 1179 1180 JS_PUBLIC_API(JSObject*) 1181 JS_GetErrorPrototype(JSContext* cx) 1182 { 1183 CHECK_REQUEST(cx); 1184 Rooted<GlobalObject*> global(cx, cx->global()); 1185 return GlobalObject::getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR); 1186 } 1187 1188 JS_PUBLIC_API(JSObject*) 1189 JS_GetIteratorPrototype(JSContext* cx) 1190 { 1191 CHECK_REQUEST(cx); 1192 Rooted<GlobalObject*> global(cx, cx->global()); 1193 return GlobalObject::getOrCreateIteratorPrototype(cx, global); 1194 } 1195 1196 JS_PUBLIC_API(JSObject*) 1197 JS_GetGlobalForObject(JSContext* cx, JSObject* obj) 1198 { 1199 AssertHeapIsIdle(cx); 1200 assertSameCompartment(cx, obj); 1201 return &obj->global(); 1202 } 1203 1204 extern JS_PUBLIC_API(bool) 1205 JS_IsGlobalObject(JSObject* obj) 1206 { 1207 return obj->is<GlobalObject>(); 1208 } 1209 1210 extern JS_PUBLIC_API(JSObject*) 1211 JS_GlobalLexicalEnvironment(JSObject* obj) 1212 { 1213 return &obj->as<GlobalObject>().lexicalEnvironment(); 1214 } 1215 1216 extern JS_PUBLIC_API(bool) 1217 JS_HasExtensibleLexicalEnvironment(JSObject* obj) 1218 { 1219 return obj->is<GlobalObject>() || obj->compartment()->getNonSyntacticLexicalEnvironment(obj); 1220 } 1221 1222 extern JS_PUBLIC_API(JSObject*) 1223 JS_ExtensibleLexicalEnvironment(JSObject* obj) 1224 { 1225 JSObject* lexical = nullptr; 1226 if (obj->is<GlobalObject>()) 1227 lexical = JS_GlobalLexicalEnvironment(obj); 1228 else 1229 lexical = obj->compartment()->getNonSyntacticLexicalEnvironment(obj); 1230 MOZ_ASSERT(lexical); 1231 return lexical; 1232 } 1233 1234 JS_PUBLIC_API(JSObject*) 1235 JS_GetGlobalForCompartmentOrNull(JSContext* cx, JSCompartment* c) 1236 { 1237 AssertHeapIsIdleOrIterating(cx); 1238 assertSameCompartment(cx, c); 1239 return c->maybeGlobal(); 1240 } 1241 1242 JS_PUBLIC_API(JSObject*) 1243 JS::CurrentGlobalOrNull(JSContext* cx) 1244 { 1245 AssertHeapIsIdleOrIterating(cx); 1246 CHECK_REQUEST(cx); 1247 if (!cx->compartment()) 1248 return nullptr; 1249 return cx->global(); 1250 } 1251 1252 JS_PUBLIC_API(Value) 1253 JS::detail::ComputeThis(JSContext* cx, Value* vp) 1254 { 1255 AssertHeapIsIdle(cx); 1256 assertSameCompartment(cx, JSValueArray(vp, 2)); 1257 1258 MutableHandleValue thisv = MutableHandleValue::fromMarkedLocation(&vp[1]); 1259 if (!BoxNonStrictThis(cx, thisv, thisv)) 1260 return NullValue(); 1261 1262 return thisv; 1263 } 1264 1265 JS_PUBLIC_API(void*) 1266 JS_malloc(JSContext* cx, size_t nbytes) 1267 { 1268 AssertHeapIsIdle(cx); 1269 CHECK_REQUEST(cx); 1270 return static_cast<void*>(cx->runtime()->pod_malloc<uint8_t>(nbytes)); 1271 } 1272 1273 JS_PUBLIC_API(void*) 1274 JS_realloc(JSContext* cx, void* p, size_t oldBytes, size_t newBytes) 1275 { 1276 AssertHeapIsIdle(cx); 1277 CHECK_REQUEST(cx); 1278 return static_cast<void*>(cx->zone()->pod_realloc<uint8_t>(static_cast<uint8_t*>(p), oldBytes, 1279 newBytes)); 1280 } 1281 1282 JS_PUBLIC_API(void) 1283 JS_free(JSContext* cx, void* p) 1284 { 1285 return js_free(p); 1286 } 1287 1288 JS_PUBLIC_API(void) 1289 JS_freeop(JSFreeOp* fop, void* p) 1290 { 1291 return FreeOp::get(fop)->free_(p); 1292 } 1293 1294 JS_PUBLIC_API(void) 1295 JS_updateMallocCounter(JSContext* cx, size_t nbytes) 1296 { 1297 return cx->updateMallocCounter(nbytes); 1298 } 1299 1300 JS_PUBLIC_API(char*) 1301 JS_strdup(JSContext* cx, const char* s) 1302 { 1303 AssertHeapIsIdle(cx); 1304 return DuplicateString(cx, s).release(); 1305 } 1306 1307 #undef JS_AddRoot 1308 1309 JS_PUBLIC_API(bool) 1310 JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data) 1311 { 1312 return cx->gc.addBlackRootsTracer(traceOp, data); 1313 } 1314 1315 JS_PUBLIC_API(void) 1316 JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data) 1317 { 1318 return cx->gc.removeBlackRootsTracer(traceOp, data); 1319 } 1320 1321 JS_PUBLIC_API(void) 1322 JS_GC(JSContext* cx) 1323 { 1324 AssertHeapIsIdle(cx); 1325 JS::PrepareForFullGC(cx); 1326 cx->gc.gc(GC_NORMAL, JS::gcreason::API); 1327 } 1328 1329 JS_PUBLIC_API(void) 1330 JS_MaybeGC(JSContext* cx) 1331 { 1332 GCRuntime& gc = cx->runtime()->gc; 1333 gc.maybeGC(cx->zone()); 1334 } 1335 1336 JS_PUBLIC_API(void) 1337 JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data) 1338 { 1339 AssertHeapIsIdle(cx); 1340 cx->gc.setGCCallback(cb, data); 1341 } 1342 1343 JS_PUBLIC_API(void) 1344 JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb, 1345 void* data) 1346 { 1347 AssertHeapIsIdle(cx); 1348 cx->gc.setObjectsTenuredCallback(cb, data); 1349 } 1350 1351 JS_PUBLIC_API(bool) 1352 JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data) 1353 { 1354 AssertHeapIsIdle(cx); 1355 return cx->gc.addFinalizeCallback(cb, data); 1356 } 1357 1358 JS_PUBLIC_API(void) 1359 JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb) 1360 { 1361 cx->gc.removeFinalizeCallback(cb); 1362 } 1363 1364 JS_PUBLIC_API(bool) 1365 JS_AddWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb, void* data) 1366 { 1367 AssertHeapIsIdle(cx); 1368 return cx->gc.addWeakPointerZoneGroupCallback(cb, data); 1369 } 1370 1371 JS_PUBLIC_API(void) 1372 JS_RemoveWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb) 1373 { 1374 cx->gc.removeWeakPointerZoneGroupCallback(cb); 1375 } 1376 1377 JS_PUBLIC_API(bool) 1378 JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb, 1379 void* data) 1380 { 1381 AssertHeapIsIdle(cx); 1382 return cx->gc.addWeakPointerCompartmentCallback(cb, data); 1383 } 1384 1385 JS_PUBLIC_API(void) 1386 JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb) 1387 { 1388 cx->gc.removeWeakPointerCompartmentCallback(cb); 1389 } 1390 1391 1392 JS_PUBLIC_API(void) 1393 JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp) 1394 { 1395 JS_UpdateWeakPointerAfterGCUnbarriered(objp->unsafeGet()); 1396 } 1397 1398 JS_PUBLIC_API(void) 1399 JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp) 1400 { 1401 if (IsAboutToBeFinalizedUnbarriered(objp)) 1402 *objp = nullptr; 1403 } 1404 1405 JS_PUBLIC_API(void) 1406 JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value) 1407 { 1408 cx->gc.waitBackgroundSweepEnd(); 1409 AutoLockGC lock(cx); 1410 MOZ_ALWAYS_TRUE(cx->gc.setParameter(key, value, lock)); 1411 } 1412 1413 JS_PUBLIC_API(uint32_t) 1414 JS_GetGCParameter(JSContext* cx, JSGCParamKey key) 1415 { 1416 AutoLockGC lock(cx); 1417 return cx->gc.getParameter(key, lock); 1418 } 1419 1420 static const size_t NumGCConfigs = 14; 1421 struct JSGCConfig { 1422 JSGCParamKey key; 1423 uint32_t value; 1424 }; 1425 1426 JS_PUBLIC_API(void) 1427 JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem) 1428 { 1429 static const JSGCConfig minimal[NumGCConfigs] = { 1430 {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024}, 1431 {JSGC_SLICE_TIME_BUDGET, 30}, 1432 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500}, 1433 {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 40}, 1434 {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 0}, 1435 {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300}, 1436 {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 120}, 1437 {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 120}, 1438 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500}, 1439 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500}, 1440 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500}, 1441 {JSGC_ALLOCATION_THRESHOLD, 1}, 1442 {JSGC_MODE, JSGC_MODE_INCREMENTAL} 1443 }; 1444 1445 const JSGCConfig* config = minimal; 1446 if (availMem > 512) { 1447 static const JSGCConfig nominal[NumGCConfigs] = { 1448 {JSGC_MAX_MALLOC_BYTES, 6 * 1024 * 1024}, 1449 {JSGC_SLICE_TIME_BUDGET, 30}, 1450 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1000}, 1451 {JSGC_HIGH_FREQUENCY_HIGH_LIMIT, 500}, 1452 {JSGC_HIGH_FREQUENCY_LOW_LIMIT, 100}, 1453 {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, 300}, 1454 {JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, 150}, 1455 {JSGC_LOW_FREQUENCY_HEAP_GROWTH, 150}, 1456 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500}, 1457 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500}, 1458 {JSGC_HIGH_FREQUENCY_TIME_LIMIT, 1500}, 1459 {JSGC_ALLOCATION_THRESHOLD, 30}, 1460 {JSGC_MODE, JSGC_MODE_ZONE} 1461 }; 1462 1463 config = nominal; 1464 } 1465 1466 for (size_t i = 0; i < NumGCConfigs; i++) 1467 JS_SetGCParameter(cx, config[i].key, config[i].value); 1468 } 1469 1470 1471 JS_PUBLIC_API(JSString*) 1472 JS_NewExternalString(JSContext* cx, const char16_t* chars, size_t length, 1473 const JSStringFinalizer* fin) 1474 { 1475 AssertHeapIsIdle(cx); 1476 CHECK_REQUEST(cx); 1477 JSString* s = JSExternalString::new_(cx, chars, length, fin); 1478 return s; 1479 } 1480 1481 extern JS_PUBLIC_API(bool) 1482 JS_IsExternalString(JSString* str) 1483 { 1484 return str->isExternal(); 1485 } 1486 1487 extern JS_PUBLIC_API(const JSStringFinalizer*) 1488 JS_GetExternalStringFinalizer(JSString* str) 1489 { 1490 return str->asExternal().externalFinalizer(); 1491 } 1492 1493 static void 1494 SetNativeStackQuotaAndLimit(JSContext* cx, StackKind kind, size_t stackSize) 1495 { 1496 cx->nativeStackQuota[kind] = stackSize; 1497 1498 #if JS_STACK_GROWTH_DIRECTION > 0 1499 if (stackSize == 0) { 1500 cx->nativeStackLimit[kind] = UINTPTR_MAX; 1501 } else { 1502 MOZ_ASSERT(cx->nativeStackBase <= size_t(-1) - stackSize); 1503 cx->nativeStackLimit[kind] = cx->nativeStackBase + stackSize - 1; 1504 } 1505 #else 1506 if (stackSize == 0) { 1507 cx->nativeStackLimit[kind] = 0; 1508 } else { 1509 MOZ_ASSERT(cx->nativeStackBase >= stackSize); 1510 cx->nativeStackLimit[kind] = cx->nativeStackBase - (stackSize - 1); 1511 } 1512 #endif 1513 } 1514 1515 JS_PUBLIC_API(void) 1516 JS_SetNativeStackQuota(JSContext* cx, size_t systemCodeStackSize, size_t trustedScriptStackSize, 1517 size_t untrustedScriptStackSize) 1518 { 1519 MOZ_ASSERT(cx->requestDepth == 0); 1520 1521 if (!trustedScriptStackSize) 1522 trustedScriptStackSize = systemCodeStackSize; 1523 else 1524 MOZ_ASSERT(trustedScriptStackSize < systemCodeStackSize); 1525 1526 if (!untrustedScriptStackSize) 1527 untrustedScriptStackSize = trustedScriptStackSize; 1528 else 1529 MOZ_ASSERT(untrustedScriptStackSize < trustedScriptStackSize); 1530 1531 SetNativeStackQuotaAndLimit(cx, StackForSystemCode, systemCodeStackSize); 1532 SetNativeStackQuotaAndLimit(cx, StackForTrustedScript, trustedScriptStackSize); 1533 SetNativeStackQuotaAndLimit(cx, StackForUntrustedScript, untrustedScriptStackSize); 1534 1535 cx->initJitStackLimit(); 1536 } 1537 1538 /************************************************************************/ 1539 1540 JS_PUBLIC_API(bool) 1541 JS_ValueToId(JSContext* cx, HandleValue value, MutableHandleId idp) 1542 { 1543 AssertHeapIsIdle(cx); 1544 CHECK_REQUEST(cx); 1545 assertSameCompartment(cx, value); 1546 return ValueToId<CanGC>(cx, value, idp); 1547 } 1548 1549 JS_PUBLIC_API(bool) 1550 JS_StringToId(JSContext* cx, HandleString string, MutableHandleId idp) 1551 { 1552 AssertHeapIsIdle(cx); 1553 CHECK_REQUEST(cx); 1554 assertSameCompartment(cx, string); 1555 RootedValue value(cx, StringValue(string)); 1556 return ValueToId<CanGC>(cx, value, idp); 1557 } 1558 1559 JS_PUBLIC_API(bool) 1560 JS_IdToValue(JSContext* cx, jsid id, MutableHandleValue vp) 1561 { 1562 AssertHeapIsIdle(cx); 1563 CHECK_REQUEST(cx); 1564 vp.set(IdToValue(id)); 1565 assertSameCompartment(cx, vp); 1566 return true; 1567 } 1568 1569 JS_PUBLIC_API(bool) 1570 JS::ToPrimitive(JSContext* cx, HandleObject obj, JSType hint, MutableHandleValue vp) 1571 { 1572 AssertHeapIsIdle(cx); 1573 CHECK_REQUEST(cx); 1574 MOZ_ASSERT(obj != nullptr); 1575 MOZ_ASSERT(hint == JSTYPE_VOID || hint == JSTYPE_STRING || hint == JSTYPE_NUMBER); 1576 vp.setObject(*obj); 1577 return ToPrimitiveSlow(cx, hint, vp); 1578 } 1579 1580 JS_PUBLIC_API(bool) 1581 JS::GetFirstArgumentAsTypeHint(JSContext* cx, CallArgs args, JSType *result) 1582 { 1583 if (!args.get(0).isString()) { 1584 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE, 1585 "Symbol.toPrimitive", 1586 "\"string\", \"number\", or \"default\"", 1587 InformalValueTypeName(args.get(0))); 1588 return false; 1589 } 1590 1591 RootedString str(cx, args.get(0).toString()); 1592 bool match; 1593 1594 if (!EqualStrings(cx, str, cx->names().default_, &match)) 1595 return false; 1596 if (match) { 1597 *result = JSTYPE_VOID; 1598 return true; 1599 } 1600 1601 if (!EqualStrings(cx, str, cx->names().string, &match)) 1602 return false; 1603 if (match) { 1604 *result = JSTYPE_STRING; 1605 return true; 1606 } 1607 1608 if (!EqualStrings(cx, str, cx->names().number, &match)) 1609 return false; 1610 if (match) { 1611 *result = JSTYPE_NUMBER; 1612 return true; 1613 } 1614 1615 JSAutoByteString bytes; 1616 const char* source = ValueToSourceForError(cx, args.get(0), bytes); 1617 if (!source) { 1618 ReportOutOfMemory(cx); 1619 return false; 1620 } 1621 1622 JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE, 1623 "Symbol.toPrimitive", 1624 "\"string\", \"number\", or \"default\"", source); 1625 return false; 1626 } 1627 1628 JS_PUBLIC_API(bool) 1629 JS_PropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp) 1630 { 1631 return true; 1632 } 1633 1634 JS_PUBLIC_API(bool) 1635 JS_StrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp, 1636 ObjectOpResult& result) 1637 { 1638 return result.succeed(); 1639 } 1640 1641 JS_PUBLIC_API(JSObject*) 1642 JS_InitClass(JSContext* cx, HandleObject obj, HandleObject parent_proto, 1643 const JSClass* clasp, JSNative constructor, unsigned nargs, 1644 const JSPropertySpec* ps, const JSFunctionSpec* fs, 1645 const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs) 1646 { 1647 AssertHeapIsIdle(cx); 1648 CHECK_REQUEST(cx); 1649 assertSameCompartment(cx, obj, parent_proto); 1650 return InitClass(cx, obj, parent_proto, Valueify(clasp), constructor, 1651 nargs, ps, fs, static_ps, static_fs); 1652 } 1653 1654 JS_PUBLIC_API(bool) 1655 JS_LinkConstructorAndPrototype(JSContext* cx, HandleObject ctor, HandleObject proto) 1656 { 1657 return LinkConstructorAndPrototype(cx, ctor, proto); 1658 } 1659 1660 JS_PUBLIC_API(const JSClass*) 1661 JS_GetClass(JSObject* obj) 1662 { 1663 return obj->getJSClass(); 1664 } 1665 1666 JS_PUBLIC_API(bool) 1667 JS_InstanceOf(JSContext* cx, HandleObject obj, const JSClass* clasp, CallArgs* args) 1668 { 1669 AssertHeapIsIdle(cx); 1670 CHECK_REQUEST(cx); 1671 #ifdef DEBUG 1672 if (args) { 1673 assertSameCompartment(cx, obj); 1674 assertSameCompartment(cx, args->thisv(), args->calleev()); 1675 } 1676 #endif 1677 if (!obj || obj->getJSClass() != clasp) { 1678 if (args) 1679 ReportIncompatibleMethod(cx, *args, Valueify(clasp)); 1680 return false; 1681 } 1682 return true; 1683 } 1684 1685 JS_PUBLIC_API(bool) 1686 JS_HasInstance(JSContext* cx, HandleObject obj, HandleValue value, bool* bp) 1687 { 1688 AssertHeapIsIdle(cx); 1689 assertSameCompartment(cx, obj, value); 1690 return HasInstance(cx, obj, value, bp); 1691 } 1692 1693 JS_PUBLIC_API(void*) 1694 JS_GetPrivate(JSObject* obj) 1695 { 1696 /* This function can be called by a finalizer. */ 1697 return obj->as<NativeObject>().getPrivate(); 1698 } 1699 1700 JS_PUBLIC_API(void) 1701 JS_SetPrivate(JSObject* obj, void* data) 1702 { 1703 /* This function can be called by a finalizer. */ 1704 obj->as<NativeObject>().setPrivate(data); 1705 } 1706 1707 JS_PUBLIC_API(void*) 1708 JS_GetInstancePrivate(JSContext* cx, HandleObject obj, const JSClass* clasp, CallArgs* args) 1709 { 1710 if (!JS_InstanceOf(cx, obj, clasp, args)) 1711 return nullptr; 1712 return obj->as<NativeObject>().getPrivate(); 1713 } 1714 1715 JS_PUBLIC_API(JSObject*) 1716 JS_GetConstructor(JSContext* cx, HandleObject proto) 1717 { 1718 AssertHeapIsIdle(cx); 1719 CHECK_REQUEST(cx); 1720 assertSameCompartment(cx, proto); 1721 1722 RootedValue cval(cx); 1723 if (!GetProperty(cx, proto, proto, cx->names().constructor, &cval)) 1724 return nullptr; 1725 if (!IsFunctionObject(cval)) { 1726 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR, 1727 proto->getClass()->name); 1728 return nullptr; 1729 } 1730 return &cval.toObject(); 1731 } 1732 1733 bool 1734 JS::CompartmentBehaviors::extraWarnings(JSContext* cx) const 1735 { 1736 return extraWarningsOverride_.get(cx->options().extraWarnings()); 1737 } 1738 1739 JS::CompartmentCreationOptions& 1740 JS::CompartmentCreationOptions::setZone(ZoneSpecifier spec) 1741 { 1742 zone_.spec = spec; 1743 return *this; 1744 } 1745 1746 JS::CompartmentCreationOptions& 1747 JS::CompartmentCreationOptions::setSameZoneAs(JSObject* obj) 1748 { 1749 zone_.pointer = static_cast<void*>(obj->zone()); 1750 return *this; 1751 } 1752 1753 const JS::CompartmentCreationOptions& 1754 JS::CompartmentCreationOptionsRef(JSCompartment* compartment) 1755 { 1756 return compartment->creationOptions(); 1757 } 1758 1759 const JS::CompartmentCreationOptions& 1760 JS::CompartmentCreationOptionsRef(JSObject* obj) 1761 { 1762 return obj->compartment()->creationOptions(); 1763 } 1764 1765 const JS::CompartmentCreationOptions& 1766 JS::CompartmentCreationOptionsRef(JSContext* cx) 1767 { 1768 return cx->compartment()->creationOptions(); 1769 } 1770 1771 bool 1772 JS::CompartmentCreationOptions::getSharedMemoryAndAtomicsEnabled() const 1773 { 1774 #if defined(ENABLE_SHARED_ARRAY_BUFFER) 1775 return sharedMemoryAndAtomics_; 1776 #else 1777 return false; 1778 #endif 1779 } 1780 1781 JS::CompartmentCreationOptions& 1782 JS::CompartmentCreationOptions::setSharedMemoryAndAtomicsEnabled(bool flag) 1783 { 1784 #if defined(ENABLE_SHARED_ARRAY_BUFFER) 1785 sharedMemoryAndAtomics_ = flag; 1786 #endif 1787 return *this; 1788 } 1789 1790 JS::CompartmentBehaviors& 1791 JS::CompartmentBehaviorsRef(JSCompartment* compartment) 1792 { 1793 return compartment->behaviors(); 1794 } 1795 1796 JS::CompartmentBehaviors& 1797 JS::CompartmentBehaviorsRef(JSObject* obj) 1798 { 1799 return obj->compartment()->behaviors(); 1800 } 1801 1802 JS::CompartmentBehaviors& 1803 JS::CompartmentBehaviorsRef(JSContext* cx) 1804 { 1805 return cx->compartment()->behaviors(); 1806 } 1807 1808 JS_PUBLIC_API(JSObject*) 1809 JS_NewGlobalObject(JSContext* cx, const JSClass* clasp, JSPrincipals* principals, 1810 JS::OnNewGlobalHookOption hookOption, 1811 const JS::CompartmentOptions& options) 1812 { 1813 MOZ_RELEASE_ASSERT(cx->runtime()->hasInitializedSelfHosting(), 1814 "Must call JS::InitSelfHostedCode() before creating a global"); 1815 1816 AssertHeapIsIdle(cx); 1817 CHECK_REQUEST(cx); 1818 1819 return GlobalObject::new_(cx, Valueify(clasp), principals, hookOption, options); 1820 } 1821 1822 JS_PUBLIC_API(void) 1823 JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global) 1824 { 1825 MOZ_ASSERT(global->is<GlobalObject>()); 1826 1827 // Off thread parsing and compilation tasks create a dummy global which is 1828 // then merged back into the host compartment. Since it used to be a 1829 // global, it will still have this trace hook, but it does not have a 1830 // meaning relative to its new compartment. We can safely skip it. 1831 // 1832 // Similarly, if we GC when creating the global, we may not have set that 1833 // global's compartment's global pointer yet. In this case, the compartment 1834 // will not yet contain anything that needs to be traced. 1835 if (!global->isOwnGlobal(trc)) 1836 return; 1837 1838 // Trace the compartment for any GC things that should only stick around if 1839 // we know the compartment is live. 1840 global->compartment()->trace(trc); 1841 1842 if (JSTraceOp trace = global->compartment()->creationOptions().getTrace()) 1843 trace(trc, global); 1844 } 1845 1846 JS_PUBLIC_API(void) 1847 JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global) 1848 { 1849 // This hook is infallible, because we don't really want arbitrary script 1850 // to be able to throw errors during delicate global creation routines. 1851 // This infallibility will eat OOM and slow script, but if that happens 1852 // we'll likely run up into them again soon in a fallible context. 1853 Rooted<js::GlobalObject*> globalObject(cx, &global->as<GlobalObject>()); 1854 Debugger::onNewGlobalObject(cx, globalObject); 1855 } 1856 1857 JS_PUBLIC_API(JSObject*) 1858 JS_NewObject(JSContext* cx, const JSClass* jsclasp) 1859 { 1860 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 1861 AssertHeapIsIdle(cx); 1862 CHECK_REQUEST(cx); 1863 1864 const Class* clasp = Valueify(jsclasp); 1865 if (!clasp) 1866 clasp = &PlainObject::class_; /* default class is Object */ 1867 1868 MOZ_ASSERT(clasp != &JSFunction::class_); 1869 MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL)); 1870 1871 return NewObjectWithClassProto(cx, clasp, nullptr); 1872 } 1873 1874 JS_PUBLIC_API(JSObject*) 1875 JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* jsclasp, HandleObject proto) 1876 { 1877 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 1878 AssertHeapIsIdle(cx); 1879 CHECK_REQUEST(cx); 1880 assertSameCompartment(cx, proto); 1881 1882 const Class* clasp = Valueify(jsclasp); 1883 if (!clasp) 1884 clasp = &PlainObject::class_; /* default class is Object */ 1885 1886 MOZ_ASSERT(clasp != &JSFunction::class_); 1887 MOZ_ASSERT(!(clasp->flags & JSCLASS_IS_GLOBAL)); 1888 1889 return NewObjectWithGivenProto(cx, clasp, proto); 1890 } 1891 1892 JS_PUBLIC_API(JSObject*) 1893 JS_NewPlainObject(JSContext* cx) 1894 { 1895 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 1896 AssertHeapIsIdle(cx); 1897 CHECK_REQUEST(cx); 1898 1899 return NewBuiltinClassInstance<PlainObject>(cx); 1900 } 1901 1902 JS_PUBLIC_API(JSObject*) 1903 JS_NewObjectForConstructor(JSContext* cx, const JSClass* clasp, const CallArgs& args) 1904 { 1905 AssertHeapIsIdle(cx); 1906 CHECK_REQUEST(cx); 1907 1908 Value callee = args.calleev(); 1909 assertSameCompartment(cx, callee); 1910 RootedObject obj(cx, &callee.toObject()); 1911 return CreateThis(cx, Valueify(clasp), obj); 1912 } 1913 1914 JS_PUBLIC_API(bool) 1915 JS_IsNative(JSObject* obj) 1916 { 1917 return obj->isNative(); 1918 } 1919 1920 JS_PUBLIC_API(void) 1921 JS::AssertObjectBelongsToCurrentThread(JSObject* obj) 1922 { 1923 JSRuntime* rt = obj->compartment()->runtimeFromAnyThread(); 1924 MOZ_RELEASE_ASSERT(CurrentThreadCanAccessRuntime(rt)); 1925 } 1926 1927 1928 /*** Standard internal methods *******************************************************************/ 1929 1930 JS_PUBLIC_API(bool) 1931 JS_GetPrototype(JSContext* cx, HandleObject obj, MutableHandleObject result) 1932 { 1933 return GetPrototype(cx, obj, result); 1934 } 1935 1936 JS_PUBLIC_API(bool) 1937 JS_SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto) 1938 { 1939 AssertHeapIsIdle(cx); 1940 CHECK_REQUEST(cx); 1941 assertSameCompartment(cx, obj, proto); 1942 1943 return SetPrototype(cx, obj, proto); 1944 } 1945 1946 JS_PUBLIC_API(bool) 1947 JS_GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary, 1948 MutableHandleObject result) 1949 { 1950 return GetPrototypeIfOrdinary(cx, obj, isOrdinary, result); 1951 } 1952 1953 JS_PUBLIC_API(bool) 1954 JS_IsExtensible(JSContext* cx, HandleObject obj, bool* extensible) 1955 { 1956 return IsExtensible(cx, obj, extensible); 1957 } 1958 1959 JS_PUBLIC_API(bool) 1960 JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, ObjectOpResult& result) 1961 { 1962 return PreventExtensions(cx, obj, result); 1963 } 1964 1965 JS_PUBLIC_API(bool) 1966 JS_SetImmutablePrototype(JSContext *cx, JS::HandleObject obj, bool *succeeded) 1967 { 1968 return SetImmutablePrototype(cx, obj, succeeded); 1969 } 1970 1971 JS_PUBLIC_API(bool) 1972 JS_GetOwnPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id, 1973 MutableHandle<PropertyDescriptor> desc) 1974 { 1975 AssertHeapIsIdle(cx); 1976 CHECK_REQUEST(cx); 1977 1978 return GetOwnPropertyDescriptor(cx, obj, id, desc); 1979 } 1980 1981 JS_PUBLIC_API(bool) 1982 JS_GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name, 1983 MutableHandle<PropertyDescriptor> desc) 1984 { 1985 JSAtom* atom = Atomize(cx, name, strlen(name)); 1986 if (!atom) 1987 return false; 1988 RootedId id(cx, AtomToId(atom)); 1989 return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc); 1990 } 1991 1992 JS_PUBLIC_API(bool) 1993 JS_GetOwnUCPropertyDescriptor(JSContext* cx, HandleObject obj, const char16_t* name, 1994 MutableHandle<PropertyDescriptor> desc) 1995 { 1996 JSAtom* atom = AtomizeChars(cx, name, js_strlen(name)); 1997 if (!atom) 1998 return false; 1999 RootedId id(cx, AtomToId(atom)); 2000 return JS_GetOwnPropertyDescriptorById(cx, obj, id, desc); 2001 } 2002 2003 JS_PUBLIC_API(bool) 2004 JS_GetPropertyDescriptorById(JSContext* cx, HandleObject obj, HandleId id, 2005 MutableHandle<PropertyDescriptor> desc) 2006 { 2007 return GetPropertyDescriptor(cx, obj, id, desc); 2008 } 2009 2010 JS_PUBLIC_API(bool) 2011 JS_GetPropertyDescriptor(JSContext* cx, HandleObject obj, const char* name, 2012 MutableHandle<PropertyDescriptor> desc) 2013 { 2014 JSAtom* atom = Atomize(cx, name, strlen(name)); 2015 if (!atom) 2016 return false; 2017 RootedId id(cx, AtomToId(atom)); 2018 return atom && JS_GetPropertyDescriptorById(cx, obj, id, desc); 2019 } 2020 2021 static bool 2022 DefinePropertyByDescriptor(JSContext* cx, HandleObject obj, HandleId id, 2023 Handle<PropertyDescriptor> desc, ObjectOpResult& result) 2024 { 2025 AssertHeapIsIdle(cx); 2026 CHECK_REQUEST(cx); 2027 assertSameCompartment(cx, obj, id, desc); 2028 return DefineProperty(cx, obj, id, desc.value(), desc.getter(), desc.setter(), 2029 desc.attributes(), result); 2030 } 2031 2032 JS_PUBLIC_API(bool) 2033 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, 2034 Handle<PropertyDescriptor> desc, ObjectOpResult& result) 2035 { 2036 return DefinePropertyByDescriptor(cx, obj, id, desc, result); 2037 } 2038 2039 JS_PUBLIC_API(bool) 2040 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, 2041 Handle<PropertyDescriptor> desc) 2042 { 2043 ObjectOpResult result; 2044 return DefinePropertyByDescriptor(cx, obj, id, desc, result) && 2045 result.checkStrict(cx, obj, id); 2046 } 2047 2048 static bool 2049 DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue value, 2050 const JSNativeWrapper& get, const JSNativeWrapper& set, 2051 unsigned attrs, unsigned flags) 2052 { 2053 JSGetterOp getter = JS_CAST_NATIVE_TO(get.op, JSGetterOp); 2054 JSSetterOp setter = JS_CAST_NATIVE_TO(set.op, JSSetterOp); 2055 2056 // JSPROP_READONLY has no meaning when accessors are involved. Ideally we'd 2057 // throw if this happens, but we've accepted it for long enough that it's 2058 // not worth trying to make callers change their ways. Just flip it off on 2059 // its way through the API layer so that we can enforce this internally. 2060 if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) 2061 attrs &= ~JSPROP_READONLY; 2062 2063 // When we use DefineProperty, we need full scriptable Function objects rather 2064 // than JSNatives. However, we might be pulling this property descriptor off 2065 // of something with JSNative property descriptors. If we are, wrap them in 2066 // JS Function objects. 2067 // 2068 // But skip doing this if our accessors are the well-known stub 2069 // accessors, since those are known to be JSGetterOps. Assert 2070 // some sanity about it, though. 2071 MOZ_ASSERT_IF(getter == JS_PropertyStub, 2072 setter == JS_StrictPropertyStub || (attrs & JSPROP_PROPOP_ACCESSORS)); 2073 MOZ_ASSERT_IF(setter == JS_StrictPropertyStub, 2074 getter == JS_PropertyStub || (attrs & JSPROP_PROPOP_ACCESSORS)); 2075 2076 // If !(attrs & JSPROP_PROPOP_ACCESSORS), then either getter/setter are both 2077 // possibly-null JSNatives (or possibly-null JSFunction* if JSPROP_GETTER or 2078 // JSPROP_SETTER is appropriately set), or both are the well-known property 2079 // stubs. The subsequent block must handle only the first of these cases, 2080 // so carefully exclude the latter case. 2081 if (!(attrs & JSPROP_PROPOP_ACCESSORS) && 2082 getter != JS_PropertyStub && setter != JS_StrictPropertyStub) 2083 { 2084 if (getter && !(attrs & JSPROP_GETTER)) { 2085 RootedAtom atom(cx, IdToFunctionName(cx, id, "get")); 2086 if (!atom) 2087 return false; 2088 JSFunction* getobj = NewNativeFunction(cx, (Native) getter, 0, atom); 2089 if (!getobj) 2090 return false; 2091 2092 if (get.info) 2093 getobj->setJitInfo(get.info); 2094 2095 getter = JS_DATA_TO_FUNC_PTR(GetterOp, getobj); 2096 attrs |= JSPROP_GETTER; 2097 } 2098 if (setter && !(attrs & JSPROP_SETTER)) { 2099 // Root just the getter, since the setter is not yet a JSObject. 2100 AutoRooterGetterSetter getRoot(cx, JSPROP_GETTER, &getter, nullptr); 2101 RootedAtom atom(cx, IdToFunctionName(cx, id, "set")); 2102 if (!atom) 2103 return false; 2104 JSFunction* setobj = NewNativeFunction(cx, (Native) setter, 1, atom); 2105 if (!setobj) 2106 return false; 2107 2108 if (set.info) 2109 setobj->setJitInfo(set.info); 2110 2111 setter = JS_DATA_TO_FUNC_PTR(SetterOp, setobj); 2112 attrs |= JSPROP_SETTER; 2113 } 2114 } else { 2115 attrs &= ~JSPROP_PROPOP_ACCESSORS; 2116 } 2117 2118 AssertHeapIsIdle(cx); 2119 CHECK_REQUEST(cx); 2120 assertSameCompartment(cx, obj, id, value, 2121 (attrs & JSPROP_GETTER) 2122 ? JS_FUNC_TO_DATA_PTR(JSObject*, getter) 2123 : nullptr, 2124 (attrs & JSPROP_SETTER) 2125 ? JS_FUNC_TO_DATA_PTR(JSObject*, setter) 2126 : nullptr); 2127 2128 // In most places throughout the engine, a property with null getter and 2129 // not JSPROP_GETTER/SETTER/SHARED has no getter, and the same for setters: 2130 // it's just a plain old data property. However the JS_Define* APIs use 2131 // null getter and setter to mean "default to the Class getProperty and 2132 // setProperty ops". 2133 if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER))) { 2134 if (!getter) 2135 getter = obj->getClass()->getGetProperty(); 2136 if (!setter) 2137 setter = obj->getClass()->getSetProperty(); 2138 } 2139 if (getter == JS_PropertyStub) 2140 getter = nullptr; 2141 if (setter == JS_StrictPropertyStub) 2142 setter = nullptr; 2143 return DefineProperty(cx, obj, id, value, getter, setter, attrs); 2144 } 2145 2146 /* 2147 * Wrapper functions to create wrappers with no corresponding JSJitInfo from API 2148 * function arguments. 2149 */ 2150 static JSNativeWrapper 2151 NativeOpWrapper(Native native) 2152 { 2153 JSNativeWrapper ret; 2154 ret.op = native; 2155 ret.info = nullptr; 2156 return ret; 2157 } 2158 2159 JS_PUBLIC_API(bool) 2160 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue value, 2161 unsigned attrs, Native getter, Native setter) 2162 { 2163 return DefinePropertyById(cx, obj, id, value, 2164 NativeOpWrapper(getter), NativeOpWrapper(setter), 2165 attrs, 0); 2166 } 2167 2168 JS_PUBLIC_API(bool) 2169 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleObject valueArg, 2170 unsigned attrs, Native getter, Native setter) 2171 { 2172 RootedValue value(cx, ObjectValue(*valueArg)); 2173 return DefinePropertyById(cx, obj, id, value, 2174 NativeOpWrapper(getter), NativeOpWrapper(setter), 2175 attrs, 0); 2176 } 2177 2178 JS_PUBLIC_API(bool) 2179 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleString valueArg, 2180 unsigned attrs, Native getter, Native setter) 2181 { 2182 RootedValue value(cx, StringValue(valueArg)); 2183 return DefinePropertyById(cx, obj, id, value, 2184 NativeOpWrapper(getter), NativeOpWrapper(setter), 2185 attrs, 0); 2186 } 2187 2188 JS_PUBLIC_API(bool) 2189 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, int32_t valueArg, 2190 unsigned attrs, Native getter, Native setter) 2191 { 2192 Value value = Int32Value(valueArg); 2193 return DefinePropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value), 2194 NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0); 2195 } 2196 2197 JS_PUBLIC_API(bool) 2198 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, uint32_t valueArg, 2199 unsigned attrs, Native getter, Native setter) 2200 { 2201 Value value = NumberValue(valueArg); 2202 return DefinePropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value), 2203 NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0); 2204 } 2205 2206 JS_PUBLIC_API(bool) 2207 JS_DefinePropertyById(JSContext* cx, HandleObject obj, HandleId id, double valueArg, 2208 unsigned attrs, Native getter, Native setter) 2209 { 2210 Value value = NumberValue(valueArg); 2211 return DefinePropertyById(cx, obj, id, HandleValue::fromMarkedLocation(&value), 2212 NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0); 2213 } 2214 2215 static bool 2216 DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue value, 2217 const JSNativeWrapper& getter, const JSNativeWrapper& setter, 2218 unsigned attrs, unsigned flags) 2219 { 2220 AutoRooterGetterSetter gsRoot(cx, attrs, const_cast<JSNative*>(&getter.op), 2221 const_cast<JSNative*>(&setter.op)); 2222 2223 JSAtom* atom = Atomize(cx, name, strlen(name)); 2224 if (!atom) 2225 return false; 2226 RootedId id(cx, AtomToId(atom)); 2227 2228 return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags); 2229 } 2230 2231 JS_PUBLIC_API(bool) 2232 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue value, 2233 unsigned attrs, 2234 Native getter /* = nullptr */, Native setter /* = nullptr */) 2235 { 2236 return DefineProperty(cx, obj, name, value, NativeOpWrapper(getter), NativeOpWrapper(setter), 2237 attrs, 0); 2238 } 2239 2240 JS_PUBLIC_API(bool) 2241 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleObject valueArg, 2242 unsigned attrs, 2243 Native getter /* = nullptr */, Native setter /* = nullptr */) 2244 { 2245 RootedValue value(cx, ObjectValue(*valueArg)); 2246 return DefineProperty(cx, obj, name, value, NativeOpWrapper(getter), NativeOpWrapper(setter), 2247 attrs, 0); 2248 } 2249 2250 JS_PUBLIC_API(bool) 2251 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, HandleString valueArg, 2252 unsigned attrs, 2253 Native getter /* = nullptr */, Native setter /* = nullptr */) 2254 { 2255 RootedValue value(cx, StringValue(valueArg)); 2256 return DefineProperty(cx, obj, name, value, NativeOpWrapper(getter), NativeOpWrapper(setter), 2257 attrs, 0); 2258 } 2259 2260 JS_PUBLIC_API(bool) 2261 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, int32_t valueArg, 2262 unsigned attrs, 2263 Native getter /* = nullptr */, Native setter /* = nullptr */) 2264 { 2265 Value value = Int32Value(valueArg); 2266 return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value), 2267 NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0); 2268 } 2269 2270 JS_PUBLIC_API(bool) 2271 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, uint32_t valueArg, 2272 unsigned attrs, 2273 Native getter /* = nullptr */, Native setter /* = nullptr */) 2274 { 2275 Value value = NumberValue(valueArg); 2276 return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value), 2277 NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0); 2278 } 2279 2280 JS_PUBLIC_API(bool) 2281 JS_DefineProperty(JSContext* cx, HandleObject obj, const char* name, double valueArg, 2282 unsigned attrs, 2283 Native getter /* = nullptr */, Native setter /* = nullptr */) 2284 { 2285 Value value = NumberValue(valueArg); 2286 return DefineProperty(cx, obj, name, HandleValue::fromMarkedLocation(&value), 2287 NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0); 2288 } 2289 2290 #define AUTO_NAMELEN(s,n) (((n) == (size_t)-1) ? js_strlen(s) : (n)) 2291 2292 JS_PUBLIC_API(bool) 2293 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2294 Handle<PropertyDescriptor> desc, 2295 ObjectOpResult& result) 2296 { 2297 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2298 if (!atom) 2299 return false; 2300 RootedId id(cx, AtomToId(atom)); 2301 return DefinePropertyByDescriptor(cx, obj, id, desc, result); 2302 } 2303 2304 JS_PUBLIC_API(bool) 2305 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2306 Handle<PropertyDescriptor> desc) 2307 { 2308 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2309 if (!atom) 2310 return false; 2311 RootedId id(cx, AtomToId(atom)); 2312 ObjectOpResult result; 2313 return DefinePropertyByDescriptor(cx, obj, id, desc, result) && 2314 result.checkStrict(cx, obj, id); 2315 } 2316 2317 static bool 2318 DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2319 const Value& value_, Native getter, Native setter, unsigned attrs, 2320 unsigned flags) 2321 { 2322 RootedValue value(cx, value_); 2323 AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); 2324 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2325 if (!atom) 2326 return false; 2327 RootedId id(cx, AtomToId(atom)); 2328 return DefinePropertyById(cx, obj, id, value, NativeOpWrapper(getter), NativeOpWrapper(setter), 2329 attrs, flags); 2330 } 2331 2332 JS_PUBLIC_API(bool) 2333 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2334 HandleValue value, unsigned attrs, Native getter, Native setter) 2335 { 2336 return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0); 2337 } 2338 2339 JS_PUBLIC_API(bool) 2340 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2341 HandleObject valueArg, unsigned attrs, Native getter, Native setter) 2342 { 2343 RootedValue value(cx, ObjectValue(*valueArg)); 2344 return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0); 2345 } 2346 2347 JS_PUBLIC_API(bool) 2348 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2349 HandleString valueArg, unsigned attrs, Native getter, Native setter) 2350 { 2351 RootedValue value(cx, StringValue(valueArg)); 2352 return DefineUCProperty(cx, obj, name, namelen, value, getter, setter, attrs, 0); 2353 } 2354 2355 JS_PUBLIC_API(bool) 2356 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2357 int32_t valueArg, unsigned attrs, Native getter, Native setter) 2358 { 2359 Value value = Int32Value(valueArg); 2360 return DefineUCProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value), 2361 getter, setter, attrs, 0); 2362 } 2363 2364 JS_PUBLIC_API(bool) 2365 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2366 uint32_t valueArg, unsigned attrs, Native getter, Native setter) 2367 { 2368 Value value = NumberValue(valueArg); 2369 return DefineUCProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value), 2370 getter, setter, attrs, 0); 2371 } 2372 2373 JS_PUBLIC_API(bool) 2374 JS_DefineUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2375 double valueArg, unsigned attrs, Native getter, Native setter) 2376 { 2377 Value value = NumberValue(valueArg); 2378 return DefineUCProperty(cx, obj, name, namelen, HandleValue::fromMarkedLocation(&value), 2379 getter, setter, attrs, 0); 2380 } 2381 2382 static bool 2383 DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value, 2384 unsigned attrs, Native getter, Native setter) 2385 { 2386 AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); 2387 AssertHeapIsIdle(cx); 2388 CHECK_REQUEST(cx); 2389 RootedId id(cx); 2390 if (!IndexToId(cx, index, &id)) 2391 return false; 2392 return DefinePropertyById(cx, obj, id, value, 2393 NativeOpWrapper(getter), NativeOpWrapper(setter), 2394 attrs, 0); 2395 } 2396 2397 JS_PUBLIC_API(bool) 2398 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue value, 2399 unsigned attrs, Native getter, Native setter) 2400 { 2401 return DefineElement(cx, obj, index, value, attrs, getter, setter); 2402 } 2403 2404 JS_PUBLIC_API(bool) 2405 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleObject valueArg, 2406 unsigned attrs, Native getter, Native setter) 2407 { 2408 RootedValue value(cx, ObjectValue(*valueArg)); 2409 return DefineElement(cx, obj, index, value, attrs, getter, setter); 2410 } 2411 2412 JS_PUBLIC_API(bool) 2413 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, HandleString valueArg, 2414 unsigned attrs, Native getter, Native setter) 2415 { 2416 RootedValue value(cx, StringValue(valueArg)); 2417 return DefineElement(cx, obj, index, value, attrs, getter, setter); 2418 } 2419 2420 JS_PUBLIC_API(bool) 2421 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, int32_t valueArg, 2422 unsigned attrs, Native getter, Native setter) 2423 { 2424 Value value = Int32Value(valueArg); 2425 return DefineElement(cx, obj, index, HandleValue::fromMarkedLocation(&value), 2426 attrs, getter, setter); 2427 } 2428 2429 JS_PUBLIC_API(bool) 2430 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, uint32_t valueArg, 2431 unsigned attrs, Native getter, Native setter) 2432 { 2433 Value value = NumberValue(valueArg); 2434 return DefineElement(cx, obj, index, HandleValue::fromMarkedLocation(&value), 2435 attrs, getter, setter); 2436 } 2437 2438 JS_PUBLIC_API(bool) 2439 JS_DefineElement(JSContext* cx, HandleObject obj, uint32_t index, double valueArg, 2440 unsigned attrs, Native getter, Native setter) 2441 { 2442 Value value = NumberValue(valueArg); 2443 return DefineElement(cx, obj, index, HandleValue::fromMarkedLocation(&value), 2444 attrs, getter, setter); 2445 } 2446 2447 JS_PUBLIC_API(bool) 2448 JS_HasPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp) 2449 { 2450 AssertHeapIsIdle(cx); 2451 CHECK_REQUEST(cx); 2452 2453 return HasProperty(cx, obj, id, foundp); 2454 } 2455 2456 JS_PUBLIC_API(bool) 2457 JS_HasProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp) 2458 { 2459 JSAtom* atom = Atomize(cx, name, strlen(name)); 2460 if (!atom) 2461 return false; 2462 RootedId id(cx, AtomToId(atom)); 2463 return JS_HasPropertyById(cx, obj, id, foundp); 2464 } 2465 2466 JS_PUBLIC_API(bool) 2467 JS_HasUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, bool* foundp) 2468 { 2469 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2470 if (!atom) 2471 return false; 2472 RootedId id(cx, AtomToId(atom)); 2473 return JS_HasPropertyById(cx, obj, id, foundp); 2474 } 2475 2476 JS_PUBLIC_API(bool) 2477 JS_HasElement(JSContext* cx, HandleObject obj, uint32_t index, bool* foundp) 2478 { 2479 AssertHeapIsIdle(cx); 2480 CHECK_REQUEST(cx); 2481 RootedId id(cx); 2482 if (!IndexToId(cx, index, &id)) 2483 return false; 2484 return JS_HasPropertyById(cx, obj, id, foundp); 2485 } 2486 2487 JS_PUBLIC_API(bool) 2488 JS_HasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp) 2489 { 2490 AssertHeapIsIdle(cx); 2491 CHECK_REQUEST(cx); 2492 assertSameCompartment(cx, obj, id); 2493 2494 return HasOwnProperty(cx, obj, id, foundp); 2495 } 2496 2497 JS_PUBLIC_API(bool) 2498 JS_HasOwnProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp) 2499 { 2500 JSAtom* atom = Atomize(cx, name, strlen(name)); 2501 if (!atom) 2502 return false; 2503 RootedId id(cx, AtomToId(atom)); 2504 return JS_HasOwnPropertyById(cx, obj, id, foundp); 2505 } 2506 2507 JS_PUBLIC_API(bool) 2508 JS_ForwardGetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValue receiver, 2509 MutableHandleValue vp) 2510 { 2511 AssertHeapIsIdle(cx); 2512 CHECK_REQUEST(cx); 2513 assertSameCompartment(cx, obj, id, receiver); 2514 2515 return GetProperty(cx, obj, receiver, id, vp); 2516 } 2517 2518 JS_PUBLIC_API(bool) 2519 JS_ForwardGetElementTo(JSContext* cx, HandleObject obj, uint32_t index, HandleObject receiver, 2520 MutableHandleValue vp) 2521 { 2522 AssertHeapIsIdle(cx); 2523 CHECK_REQUEST(cx); 2524 assertSameCompartment(cx, obj); 2525 2526 return GetElement(cx, obj, receiver, index, vp); 2527 } 2528 2529 JS_PUBLIC_API(bool) 2530 JS_GetPropertyById(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp) 2531 { 2532 RootedValue receiver(cx, ObjectValue(*obj)); 2533 return JS_ForwardGetPropertyTo(cx, obj, id, receiver, vp); 2534 } 2535 2536 JS_PUBLIC_API(bool) 2537 JS_GetProperty(JSContext* cx, HandleObject obj, const char* name, MutableHandleValue vp) 2538 { 2539 JSAtom* atom = Atomize(cx, name, strlen(name)); 2540 if (!atom) 2541 return false; 2542 RootedId id(cx, AtomToId(atom)); 2543 return JS_GetPropertyById(cx, obj, id, vp); 2544 } 2545 2546 JS_PUBLIC_API(bool) 2547 JS_GetUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2548 MutableHandleValue vp) 2549 { 2550 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2551 if (!atom) 2552 return false; 2553 RootedId id(cx, AtomToId(atom)); 2554 return JS_GetPropertyById(cx, obj, id, vp); 2555 } 2556 2557 JS_PUBLIC_API(bool) 2558 JS_GetElement(JSContext* cx, HandleObject objArg, uint32_t index, MutableHandleValue vp) 2559 { 2560 return JS_ForwardGetElementTo(cx, objArg, index, objArg, vp); 2561 } 2562 2563 JS_PUBLIC_API(bool) 2564 JS_ForwardSetPropertyTo(JSContext* cx, HandleObject obj, HandleId id, HandleValue v, 2565 HandleValue receiver, ObjectOpResult& result) 2566 { 2567 AssertHeapIsIdle(cx); 2568 CHECK_REQUEST(cx); 2569 assertSameCompartment(cx, obj, id, receiver); 2570 2571 return SetProperty(cx, obj, id, v, receiver, result); 2572 } 2573 2574 JS_PUBLIC_API(bool) 2575 JS_SetPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue v) 2576 { 2577 AssertHeapIsIdle(cx); 2578 CHECK_REQUEST(cx); 2579 assertSameCompartment(cx, obj, id); 2580 2581 RootedValue receiver(cx, ObjectValue(*obj)); 2582 ObjectOpResult ignored; 2583 return SetProperty(cx, obj, id, v, receiver, ignored); 2584 } 2585 2586 JS_PUBLIC_API(bool) 2587 JS_SetProperty(JSContext* cx, HandleObject obj, const char* name, HandleValue v) 2588 { 2589 JSAtom* atom = Atomize(cx, name, strlen(name)); 2590 if (!atom) 2591 return false; 2592 RootedId id(cx, AtomToId(atom)); 2593 return JS_SetPropertyById(cx, obj, id, v); 2594 } 2595 2596 JS_PUBLIC_API(bool) 2597 JS_SetUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2598 HandleValue v) 2599 { 2600 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2601 if (!atom) 2602 return false; 2603 RootedId id(cx, AtomToId(atom)); 2604 return JS_SetPropertyById(cx, obj, id, v); 2605 } 2606 2607 static bool 2608 SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v) 2609 { 2610 AssertHeapIsIdle(cx); 2611 CHECK_REQUEST(cx); 2612 assertSameCompartment(cx, obj, v); 2613 2614 RootedValue receiver(cx, ObjectValue(*obj)); 2615 ObjectOpResult ignored; 2616 return SetElement(cx, obj, index, v, receiver, ignored); 2617 } 2618 2619 JS_PUBLIC_API(bool) 2620 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v) 2621 { 2622 return SetElement(cx, obj, index, v); 2623 } 2624 2625 JS_PUBLIC_API(bool) 2626 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleObject v) 2627 { 2628 RootedValue value(cx, ObjectOrNullValue(v)); 2629 return SetElement(cx, obj, index, value); 2630 } 2631 2632 JS_PUBLIC_API(bool) 2633 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleString v) 2634 { 2635 RootedValue value(cx, StringValue(v)); 2636 return SetElement(cx, obj, index, value); 2637 } 2638 2639 JS_PUBLIC_API(bool) 2640 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, int32_t v) 2641 { 2642 RootedValue value(cx, NumberValue(v)); 2643 return SetElement(cx, obj, index, value); 2644 } 2645 2646 JS_PUBLIC_API(bool) 2647 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, uint32_t v) 2648 { 2649 RootedValue value(cx, NumberValue(v)); 2650 return SetElement(cx, obj, index, value); 2651 } 2652 2653 JS_PUBLIC_API(bool) 2654 JS_SetElement(JSContext* cx, HandleObject obj, uint32_t index, double v) 2655 { 2656 RootedValue value(cx, NumberValue(v)); 2657 return SetElement(cx, obj, index, value); 2658 } 2659 2660 JS_PUBLIC_API(bool) 2661 JS_DeletePropertyById(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result) 2662 { 2663 AssertHeapIsIdle(cx); 2664 CHECK_REQUEST(cx); 2665 assertSameCompartment(cx, obj, id); 2666 2667 return DeleteProperty(cx, obj, id, result); 2668 } 2669 2670 JS_PUBLIC_API(bool) 2671 JS_DeleteProperty(JSContext* cx, HandleObject obj, const char* name, ObjectOpResult& result) 2672 { 2673 CHECK_REQUEST(cx); 2674 assertSameCompartment(cx, obj); 2675 2676 JSAtom* atom = Atomize(cx, name, strlen(name)); 2677 if (!atom) 2678 return false; 2679 RootedId id(cx, AtomToId(atom)); 2680 return DeleteProperty(cx, obj, id, result); 2681 } 2682 2683 JS_PUBLIC_API(bool) 2684 JS_DeleteUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2685 ObjectOpResult& result) 2686 { 2687 CHECK_REQUEST(cx); 2688 assertSameCompartment(cx, obj); 2689 2690 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2691 if (!atom) 2692 return false; 2693 RootedId id(cx, AtomToId(atom)); 2694 return DeleteProperty(cx, obj, id, result); 2695 } 2696 2697 JS_PUBLIC_API(bool) 2698 JS_DeleteElement(JSContext* cx, HandleObject obj, uint32_t index, ObjectOpResult& result) 2699 { 2700 AssertHeapIsIdle(cx); 2701 CHECK_REQUEST(cx); 2702 assertSameCompartment(cx, obj); 2703 2704 return DeleteElement(cx, obj, index, result); 2705 } 2706 2707 JS_PUBLIC_API(bool) 2708 JS_DeletePropertyById(JSContext* cx, HandleObject obj, HandleId id) 2709 { 2710 ObjectOpResult ignored; 2711 return JS_DeletePropertyById(cx, obj, id, ignored); 2712 } 2713 2714 JS_PUBLIC_API(bool) 2715 JS_DeleteProperty(JSContext* cx, HandleObject obj, const char* name) 2716 { 2717 ObjectOpResult ignored; 2718 return JS_DeleteProperty(cx, obj, name, ignored); 2719 } 2720 2721 JS_PUBLIC_API(bool) 2722 JS_DeleteElement(JSContext* cx, HandleObject obj, uint32_t index) 2723 { 2724 ObjectOpResult ignored; 2725 return JS_DeleteElement(cx, obj, index, ignored); 2726 } 2727 2728 JS_PUBLIC_API(bool) 2729 JS_Enumerate(JSContext* cx, HandleObject obj, JS::MutableHandle<IdVector> props) 2730 { 2731 AssertHeapIsIdle(cx); 2732 CHECK_REQUEST(cx); 2733 assertSameCompartment(cx, obj); 2734 MOZ_ASSERT(props.empty()); 2735 2736 AutoIdVector ids(cx); 2737 if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY, &ids)) 2738 return false; 2739 2740 return props.append(ids.begin(), ids.end()); 2741 } 2742 2743 JS_PUBLIC_API(bool) 2744 JS::IsCallable(JSObject* obj) 2745 { 2746 return obj->isCallable(); 2747 } 2748 2749 JS_PUBLIC_API(bool) 2750 JS::IsConstructor(JSObject* obj) 2751 { 2752 return obj->isConstructor(); 2753 } 2754 2755 JS_PUBLIC_API(bool) 2756 JS_CallFunctionValue(JSContext* cx, HandleObject obj, HandleValue fval, const HandleValueArray& args, 2757 MutableHandleValue rval) 2758 { 2759 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 2760 AssertHeapIsIdle(cx); 2761 CHECK_REQUEST(cx); 2762 assertSameCompartment(cx, obj, fval, args); 2763 2764 InvokeArgs iargs(cx); 2765 if (!FillArgumentsFromArraylike(cx, iargs, args)) 2766 return false; 2767 2768 RootedValue thisv(cx, ObjectOrNullValue(obj)); 2769 return Call(cx, fval, thisv, iargs, rval); 2770 } 2771 2772 JS_PUBLIC_API(bool) 2773 JS_CallFunction(JSContext* cx, HandleObject obj, HandleFunction fun, const HandleValueArray& args, 2774 MutableHandleValue rval) 2775 { 2776 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 2777 AssertHeapIsIdle(cx); 2778 CHECK_REQUEST(cx); 2779 assertSameCompartment(cx, obj, fun, args); 2780 2781 InvokeArgs iargs(cx); 2782 if (!FillArgumentsFromArraylike(cx, iargs, args)) 2783 return false; 2784 2785 RootedValue fval(cx, ObjectValue(*fun)); 2786 RootedValue thisv(cx, ObjectOrNullValue(obj)); 2787 return Call(cx, fval, thisv, iargs, rval); 2788 } 2789 2790 JS_PUBLIC_API(bool) 2791 JS_CallFunctionName(JSContext* cx, HandleObject obj, const char* name, const HandleValueArray& args, 2792 MutableHandleValue rval) 2793 { 2794 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 2795 AssertHeapIsIdle(cx); 2796 CHECK_REQUEST(cx); 2797 assertSameCompartment(cx, obj, args); 2798 2799 JSAtom* atom = Atomize(cx, name, strlen(name)); 2800 if (!atom) 2801 return false; 2802 2803 RootedValue fval(cx); 2804 RootedId id(cx, AtomToId(atom)); 2805 if (!GetProperty(cx, obj, obj, id, &fval)) 2806 return false; 2807 2808 InvokeArgs iargs(cx); 2809 if (!FillArgumentsFromArraylike(cx, iargs, args)) 2810 return false; 2811 2812 RootedValue thisv(cx, ObjectOrNullValue(obj)); 2813 return Call(cx, fval, thisv, iargs, rval); 2814 } 2815 2816 JS_PUBLIC_API(bool) 2817 JS::Call(JSContext* cx, HandleValue thisv, HandleValue fval, const JS::HandleValueArray& args, 2818 MutableHandleValue rval) 2819 { 2820 AssertHeapIsIdle(cx); 2821 CHECK_REQUEST(cx); 2822 assertSameCompartment(cx, thisv, fval, args); 2823 2824 InvokeArgs iargs(cx); 2825 if (!FillArgumentsFromArraylike(cx, iargs, args)) 2826 return false; 2827 2828 return Call(cx, fval, thisv, iargs, rval); 2829 } 2830 2831 JS_PUBLIC_API(bool) 2832 JS::Construct(JSContext* cx, HandleValue fval, HandleObject newTarget, const JS::HandleValueArray& args, 2833 MutableHandleObject objp) 2834 { 2835 AssertHeapIsIdle(cx); 2836 CHECK_REQUEST(cx); 2837 assertSameCompartment(cx, fval, newTarget, args); 2838 2839 if (!IsConstructor(fval)) { 2840 ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval, nullptr); 2841 return false; 2842 } 2843 2844 RootedValue newTargetVal(cx, ObjectValue(*newTarget)); 2845 if (!IsConstructor(newTargetVal)) { 2846 ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, newTargetVal, nullptr); 2847 return false; 2848 } 2849 2850 ConstructArgs cargs(cx); 2851 if (!FillArgumentsFromArraylike(cx, cargs, args)) 2852 return false; 2853 2854 return js::Construct(cx, fval, cargs, newTargetVal, objp); 2855 } 2856 2857 JS_PUBLIC_API(bool) 2858 JS::Construct(JSContext* cx, HandleValue fval, const JS::HandleValueArray& args, 2859 MutableHandleObject objp) 2860 { 2861 AssertHeapIsIdle(cx); 2862 CHECK_REQUEST(cx); 2863 assertSameCompartment(cx, fval, args); 2864 2865 if (!IsConstructor(fval)) { 2866 ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, fval, nullptr); 2867 return false; 2868 } 2869 2870 ConstructArgs cargs(cx); 2871 if (!FillArgumentsFromArraylike(cx, cargs, args)) 2872 return false; 2873 2874 return js::Construct(cx, fval, cargs, fval, objp); 2875 } 2876 2877 2878 /* * */ 2879 2880 JS_PUBLIC_API(bool) 2881 JS_AlreadyHasOwnPropertyById(JSContext* cx, HandleObject obj, HandleId id, bool* foundp) 2882 { 2883 AssertHeapIsIdle(cx); 2884 CHECK_REQUEST(cx); 2885 assertSameCompartment(cx, obj, id); 2886 2887 if (!obj->isNative()) 2888 return js::HasOwnProperty(cx, obj, id, foundp); 2889 2890 RootedNativeObject nativeObj(cx, &obj->as<NativeObject>()); 2891 RootedShape prop(cx); 2892 NativeLookupOwnPropertyNoResolve(cx, nativeObj, id, &prop); 2893 *foundp = !!prop; 2894 return true; 2895 } 2896 2897 JS_PUBLIC_API(bool) 2898 JS_AlreadyHasOwnProperty(JSContext* cx, HandleObject obj, const char* name, bool* foundp) 2899 { 2900 JSAtom* atom = Atomize(cx, name, strlen(name)); 2901 if (!atom) 2902 return false; 2903 RootedId id(cx, AtomToId(atom)); 2904 return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp); 2905 } 2906 2907 JS_PUBLIC_API(bool) 2908 JS_AlreadyHasOwnUCProperty(JSContext* cx, HandleObject obj, const char16_t* name, size_t namelen, 2909 bool* foundp) 2910 { 2911 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 2912 if (!atom) 2913 return false; 2914 RootedId id(cx, AtomToId(atom)); 2915 return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp); 2916 } 2917 2918 JS_PUBLIC_API(bool) 2919 JS_AlreadyHasOwnElement(JSContext* cx, HandleObject obj, uint32_t index, bool* foundp) 2920 { 2921 AssertHeapIsIdle(cx); 2922 CHECK_REQUEST(cx); 2923 RootedId id(cx); 2924 if (!IndexToId(cx, index, &id)) 2925 return false; 2926 return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp); 2927 } 2928 2929 JS_PUBLIC_API(bool) 2930 JS_FreezeObject(JSContext* cx, HandleObject obj) 2931 { 2932 AssertHeapIsIdle(cx); 2933 CHECK_REQUEST(cx); 2934 assertSameCompartment(cx, obj); 2935 return FreezeObject(cx, obj); 2936 } 2937 2938 static bool 2939 DeepFreezeSlot(JSContext* cx, const Value& v) 2940 { 2941 if (v.isPrimitive()) 2942 return true; 2943 RootedObject obj(cx, &v.toObject()); 2944 return JS_DeepFreezeObject(cx, obj); 2945 } 2946 2947 JS_PUBLIC_API(bool) 2948 JS_DeepFreezeObject(JSContext* cx, HandleObject obj) 2949 { 2950 AssertHeapIsIdle(cx); 2951 CHECK_REQUEST(cx); 2952 assertSameCompartment(cx, obj); 2953 2954 /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */ 2955 bool extensible; 2956 if (!IsExtensible(cx, obj, &extensible)) 2957 return false; 2958 if (!extensible) 2959 return true; 2960 2961 if (!FreezeObject(cx, obj)) 2962 return false; 2963 2964 /* Walk slots in obj and if any value is a non-null object, seal it. */ 2965 if (obj->isNative()) { 2966 RootedNativeObject nobj(cx, &obj->as<NativeObject>()); 2967 for (uint32_t i = 0, n = nobj->slotSpan(); i < n; ++i) { 2968 if (!DeepFreezeSlot(cx, nobj->getSlot(i))) 2969 return false; 2970 } 2971 for (uint32_t i = 0, n = nobj->getDenseInitializedLength(); i < n; ++i) { 2972 if (!DeepFreezeSlot(cx, nobj->getDenseElement(i))) 2973 return false; 2974 } 2975 } 2976 2977 return true; 2978 } 2979 2980 static bool 2981 DefineSelfHostedProperty(JSContext* cx, HandleObject obj, HandleId id, 2982 const char* getterName, const char* setterName, 2983 unsigned attrs, unsigned flags) 2984 { 2985 JSAtom* getterNameAtom = Atomize(cx, getterName, strlen(getterName)); 2986 if (!getterNameAtom) 2987 return false; 2988 RootedPropertyName getterNameName(cx, getterNameAtom->asPropertyName()); 2989 2990 RootedAtom name(cx, IdToFunctionName(cx, id)); 2991 if (!name) 2992 return false; 2993 2994 RootedValue getterValue(cx); 2995 if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), getterNameName, name, 0, 2996 &getterValue)) 2997 { 2998 return false; 2999 } 3000 MOZ_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>()); 3001 RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>()); 3002 JSNative getterOp = JS_DATA_TO_FUNC_PTR(JSNative, getterFunc.get()); 3003 3004 RootedFunction setterFunc(cx); 3005 if (setterName) { 3006 JSAtom* setterNameAtom = Atomize(cx, setterName, strlen(setterName)); 3007 if (!setterNameAtom) 3008 return false; 3009 RootedPropertyName setterNameName(cx, setterNameAtom->asPropertyName()); 3010 3011 RootedValue setterValue(cx); 3012 if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), setterNameName, name, 0, 3013 &setterValue)) 3014 { 3015 return false; 3016 } 3017 MOZ_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>()); 3018 setterFunc = &setterValue.toObject().as<JSFunction>(); 3019 } 3020 JSNative setterOp = JS_DATA_TO_FUNC_PTR(JSNative, setterFunc.get()); 3021 3022 return DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue, 3023 NativeOpWrapper(getterOp), NativeOpWrapper(setterOp), 3024 attrs, flags); 3025 } 3026 3027 JS_PUBLIC_API(JSObject*) 3028 JS_DefineObject(JSContext* cx, HandleObject obj, const char* name, const JSClass* jsclasp, 3029 unsigned attrs) 3030 { 3031 AssertHeapIsIdle(cx); 3032 CHECK_REQUEST(cx); 3033 assertSameCompartment(cx, obj); 3034 3035 const Class* clasp = Valueify(jsclasp); 3036 if (!clasp) 3037 clasp = &PlainObject::class_; /* default class is Object */ 3038 3039 RootedObject nobj(cx, NewObjectWithClassProto(cx, clasp, nullptr)); 3040 if (!nobj) 3041 return nullptr; 3042 3043 RootedValue nobjValue(cx, ObjectValue(*nobj)); 3044 if (!DefineProperty(cx, obj, name, nobjValue, NativeOpWrapper(nullptr), NativeOpWrapper(nullptr), 3045 attrs, 0)) { 3046 return nullptr; 3047 } 3048 3049 return nobj; 3050 } 3051 3052 static inline Value 3053 ValueFromScalar(double x) 3054 { 3055 return DoubleValue(x); 3056 } 3057 static inline Value 3058 ValueFromScalar(int32_t x) 3059 { 3060 return Int32Value(x); 3061 } 3062 3063 template<typename T> 3064 static bool 3065 DefineConstScalar(JSContext* cx, HandleObject obj, const JSConstScalarSpec<T>* cds) 3066 { 3067 AssertHeapIsIdle(cx); 3068 CHECK_REQUEST(cx); 3069 JSNativeWrapper noget = NativeOpWrapper(nullptr); 3070 JSNativeWrapper noset = NativeOpWrapper(nullptr); 3071 unsigned attrs = JSPROP_READONLY | JSPROP_PERMANENT; 3072 for (; cds->name; cds++) { 3073 RootedValue value(cx, ValueFromScalar(cds->val)); 3074 if (!DefineProperty(cx, obj, cds->name, value, noget, noset, attrs, 0)) 3075 return false; 3076 } 3077 return true; 3078 } 3079 3080 JS_PUBLIC_API(bool) 3081 JS_DefineConstDoubles(JSContext* cx, HandleObject obj, const JSConstDoubleSpec* cds) 3082 { 3083 return DefineConstScalar(cx, obj, cds); 3084 } 3085 JS_PUBLIC_API(bool) 3086 JS_DefineConstIntegers(JSContext* cx, HandleObject obj, const JSConstIntegerSpec* cis) 3087 { 3088 return DefineConstScalar(cx, obj, cis); 3089 } 3090 3091 JS_PUBLIC_API(bool) 3092 JSPropertySpec::getValue(JSContext* cx, MutableHandleValue vp) const 3093 { 3094 MOZ_ASSERT(!isAccessor()); 3095 3096 if (value.type == JSVAL_TYPE_STRING) { 3097 RootedAtom atom(cx, Atomize(cx, value.string, strlen(value.string))); 3098 if (!atom) 3099 return false; 3100 vp.setString(atom); 3101 } else { 3102 MOZ_ASSERT(value.type == JSVAL_TYPE_INT32); 3103 vp.setInt32(value.int32); 3104 } 3105 3106 return true; 3107 } 3108 3109 static JS::SymbolCode 3110 PropertySpecNameToSymbolCode(const char* name) 3111 { 3112 MOZ_ASSERT(JS::PropertySpecNameIsSymbol(name)); 3113 uintptr_t u = reinterpret_cast<uintptr_t>(name); 3114 return JS::SymbolCode(u - 1); 3115 } 3116 3117 bool 3118 PropertySpecNameToId(JSContext* cx, const char* name, MutableHandleId id, 3119 js::PinningBehavior pin = js::DoNotPinAtom) 3120 { 3121 if (JS::PropertySpecNameIsSymbol(name)) { 3122 JS::SymbolCode which = PropertySpecNameToSymbolCode(name); 3123 id.set(SYMBOL_TO_JSID(cx->wellKnownSymbols().get(which))); 3124 } else { 3125 JSAtom* atom = Atomize(cx, name, strlen(name), pin); 3126 if (!atom) 3127 return false; 3128 id.set(AtomToId(atom)); 3129 } 3130 return true; 3131 } 3132 3133 JS_PUBLIC_API(bool) 3134 JS::PropertySpecNameToPermanentId(JSContext* cx, const char* name, jsid* idp) 3135 { 3136 // We are calling fromMarkedLocation(idp) even though idp points to a 3137 // location that will never be marked. This is OK because the whole point 3138 // of this API is to populate *idp with a jsid that does not need to be 3139 // marked. 3140 return PropertySpecNameToId(cx, name, MutableHandleId::fromMarkedLocation(idp), 3141 js::PinAtom); 3142 } 3143 3144 JS_PUBLIC_API(bool) 3145 JS_DefineProperties(JSContext* cx, HandleObject obj, const JSPropertySpec* ps) 3146 { 3147 RootedId id(cx); 3148 3149 for (; ps->name; ps++) { 3150 if (!PropertySpecNameToId(cx, ps->name, &id)) 3151 return false; 3152 3153 if (ps->isAccessor()) { 3154 if (ps->isSelfHosted()) { 3155 if (!DefineSelfHostedProperty(cx, obj, id, 3156 ps->accessors.getter.selfHosted.funname, 3157 ps->accessors.setter.selfHosted.funname, 3158 ps->flags, 0)) 3159 { 3160 return false; 3161 } 3162 } else { 3163 if (!DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue, 3164 ps->accessors.getter.native, ps->accessors.setter.native, 3165 ps->flags, 0)) 3166 { 3167 return false; 3168 } 3169 } 3170 } else { 3171 RootedValue v(cx); 3172 if (!ps->getValue(cx, &v)) 3173 return false; 3174 3175 if (!DefinePropertyById(cx, obj, id, v, NativeOpWrapper(nullptr), 3176 NativeOpWrapper(nullptr), ps->flags & ~JSPROP_INTERNAL_USE_BIT, 0)) 3177 { 3178 return false; 3179 } 3180 } 3181 } 3182 return true; 3183 } 3184 3185 JS_PUBLIC_API(bool) 3186 JS::ObjectToCompletePropertyDescriptor(JSContext* cx, 3187 HandleObject obj, 3188 HandleValue descObj, 3189 MutableHandle<PropertyDescriptor> desc) 3190 { 3191 if (!ToPropertyDescriptor(cx, descObj, true, desc)) 3192 return false; 3193 CompletePropertyDescriptor(desc); 3194 desc.object().set(obj); 3195 return true; 3196 } 3197 3198 JS_PUBLIC_API(void) 3199 JS_SetAllNonReservedSlotsToUndefined(JSContext* cx, JSObject* objArg) 3200 { 3201 RootedObject obj(cx, objArg); 3202 AssertHeapIsIdle(cx); 3203 CHECK_REQUEST(cx); 3204 assertSameCompartment(cx, obj); 3205 3206 if (!obj->isNative()) 3207 return; 3208 3209 const Class* clasp = obj->getClass(); 3210 unsigned numReserved = JSCLASS_RESERVED_SLOTS(clasp); 3211 unsigned numSlots = obj->as<NativeObject>().slotSpan(); 3212 for (unsigned i = numReserved; i < numSlots; i++) 3213 obj->as<NativeObject>().setSlot(i, UndefinedValue()); 3214 } 3215 3216 JS_PUBLIC_API(Value) 3217 JS_GetReservedSlot(JSObject* obj, uint32_t index) 3218 { 3219 return obj->as<NativeObject>().getReservedSlot(index); 3220 } 3221 3222 JS_PUBLIC_API(void) 3223 JS_SetReservedSlot(JSObject* obj, uint32_t index, const Value& value) 3224 { 3225 obj->as<NativeObject>().setReservedSlot(index, value); 3226 } 3227 3228 JS_PUBLIC_API(JSObject*) 3229 JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents) 3230 { 3231 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3232 AssertHeapIsIdle(cx); 3233 CHECK_REQUEST(cx); 3234 3235 assertSameCompartment(cx, contents); 3236 return NewDenseCopiedArray(cx, contents.length(), contents.begin()); 3237 } 3238 3239 JS_PUBLIC_API(JSObject*) 3240 JS_NewArrayObject(JSContext* cx, size_t length) 3241 { 3242 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3243 AssertHeapIsIdle(cx); 3244 CHECK_REQUEST(cx); 3245 3246 return NewDenseFullyAllocatedArray(cx, length); 3247 } 3248 3249 inline bool 3250 IsGivenTypeObject(JSContext* cx, JS::HandleObject obj, const ESClass& typeClass, bool* isType) 3251 { 3252 assertSameCompartment(cx, obj); 3253 3254 ESClass cls; 3255 if (!GetBuiltinClass(cx, obj, &cls)) 3256 return false; 3257 3258 *isType = cls == typeClass; 3259 return true; 3260 } 3261 3262 JS_PUBLIC_API(bool) 3263 JS_IsArrayObject(JSContext* cx, JS::HandleObject obj, bool* isArray) 3264 { 3265 return IsGivenTypeObject(cx, obj, ESClass::Array, isArray); 3266 } 3267 3268 JS_PUBLIC_API(bool) 3269 JS_IsArrayObject(JSContext* cx, JS::HandleValue value, bool* isArray) 3270 { 3271 if (!value.isObject()) { 3272 *isArray = false; 3273 return true; 3274 } 3275 3276 RootedObject obj(cx, &value.toObject()); 3277 return JS_IsArrayObject(cx, obj, isArray); 3278 } 3279 3280 JS_PUBLIC_API(bool) 3281 JS_GetArrayLength(JSContext* cx, HandleObject obj, uint32_t* lengthp) 3282 { 3283 AssertHeapIsIdle(cx); 3284 CHECK_REQUEST(cx); 3285 assertSameCompartment(cx, obj); 3286 return GetLengthProperty(cx, obj, lengthp); 3287 } 3288 3289 JS_PUBLIC_API(bool) 3290 JS_SetArrayLength(JSContext* cx, HandleObject obj, uint32_t length) 3291 { 3292 AssertHeapIsIdle(cx); 3293 CHECK_REQUEST(cx); 3294 assertSameCompartment(cx, obj); 3295 return SetLengthProperty(cx, obj, length); 3296 } 3297 3298 JS_PUBLIC_API(bool) 3299 JS::IsMapObject(JSContext* cx, JS::HandleObject obj, bool* isMap) 3300 { 3301 return IsGivenTypeObject(cx, obj, ESClass::Map, isMap); 3302 } 3303 3304 JS_PUBLIC_API(bool) 3305 JS::IsSetObject(JSContext* cx, JS::HandleObject obj, bool* isSet) 3306 { 3307 return IsGivenTypeObject(cx, obj, ESClass::Set, isSet); 3308 } 3309 3310 JS_PUBLIC_API(void) 3311 JS_HoldPrincipals(JSPrincipals* principals) 3312 { 3313 ++principals->refcount; 3314 } 3315 3316 JS_PUBLIC_API(void) 3317 JS_DropPrincipals(JSContext* cx, JSPrincipals* principals) 3318 { 3319 int rc = --principals->refcount; 3320 if (rc == 0) 3321 cx->destroyPrincipals(principals); 3322 } 3323 3324 JS_PUBLIC_API(void) 3325 JS_SetSecurityCallbacks(JSContext* cx, const JSSecurityCallbacks* scb) 3326 { 3327 MOZ_ASSERT(scb != &NullSecurityCallbacks); 3328 cx->securityCallbacks = scb ? scb : &NullSecurityCallbacks; 3329 } 3330 3331 JS_PUBLIC_API(const JSSecurityCallbacks*) 3332 JS_GetSecurityCallbacks(JSContext* cx) 3333 { 3334 return (cx->securityCallbacks != &NullSecurityCallbacks) ? cx->securityCallbacks : nullptr; 3335 } 3336 3337 JS_PUBLIC_API(void) 3338 JS_SetTrustedPrincipals(JSContext* cx, JSPrincipals* prin) 3339 { 3340 cx->setTrustedPrincipals(prin); 3341 } 3342 3343 extern JS_PUBLIC_API(void) 3344 JS_InitDestroyPrincipalsCallback(JSContext* cx, JSDestroyPrincipalsOp destroyPrincipals) 3345 { 3346 MOZ_ASSERT(destroyPrincipals); 3347 MOZ_ASSERT(!cx->destroyPrincipals); 3348 cx->destroyPrincipals = destroyPrincipals; 3349 } 3350 3351 extern JS_PUBLIC_API(void) 3352 JS_InitReadPrincipalsCallback(JSContext* cx, JSReadPrincipalsOp read) 3353 { 3354 MOZ_ASSERT(read); 3355 MOZ_ASSERT(!cx->readPrincipals); 3356 cx->readPrincipals = read; 3357 } 3358 3359 JS_PUBLIC_API(JSFunction*) 3360 JS_NewFunction(JSContext* cx, JSNative native, unsigned nargs, unsigned flags, 3361 const char* name) 3362 { 3363 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3364 3365 AssertHeapIsIdle(cx); 3366 CHECK_REQUEST(cx); 3367 3368 RootedAtom atom(cx); 3369 if (name) { 3370 atom = Atomize(cx, name, strlen(name)); 3371 if (!atom) 3372 return nullptr; 3373 } 3374 3375 return (flags & JSFUN_CONSTRUCTOR) 3376 ? NewNativeConstructor(cx, native, nargs, atom) 3377 : NewNativeFunction(cx, native, nargs, atom); 3378 } 3379 3380 JS_PUBLIC_API(JSFunction*) 3381 JS::GetSelfHostedFunction(JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs) 3382 { 3383 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3384 AssertHeapIsIdle(cx); 3385 CHECK_REQUEST(cx); 3386 3387 RootedAtom name(cx, IdToFunctionName(cx, id)); 3388 if (!name) 3389 return nullptr; 3390 3391 JSAtom* shAtom = Atomize(cx, selfHostedName, strlen(selfHostedName)); 3392 if (!shAtom) 3393 return nullptr; 3394 RootedPropertyName shName(cx, shAtom->asPropertyName()); 3395 RootedValue funVal(cx); 3396 if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, nargs, &funVal)) 3397 return nullptr; 3398 return &funVal.toObject().as<JSFunction>(); 3399 } 3400 3401 JS_PUBLIC_API(JSFunction*) 3402 JS::NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id) 3403 { 3404 // Delay cloning self-hosted functions until they are called. This is 3405 // achieved by passing DefineFunction a nullptr JSNative which produces an 3406 // interpreted JSFunction where !hasScript. Interpreted call paths then 3407 // call InitializeLazyFunctionScript if !hasScript. 3408 if (fs->selfHostedName) { 3409 MOZ_ASSERT(!fs->call.op); 3410 MOZ_ASSERT(!fs->call.info); 3411 3412 JSAtom* shAtom = Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)); 3413 if (!shAtom) 3414 return nullptr; 3415 RootedPropertyName shName(cx, shAtom->asPropertyName()); 3416 RootedAtom name(cx, IdToFunctionName(cx, id)); 3417 if (!name) 3418 return nullptr; 3419 RootedValue funVal(cx); 3420 if (!GlobalObject::getSelfHostedFunction(cx, cx->global(), shName, name, fs->nargs, 3421 &funVal)) 3422 { 3423 return nullptr; 3424 } 3425 JSFunction* fun = &funVal.toObject().as<JSFunction>(); 3426 if (fs->flags & JSFUN_HAS_REST) 3427 fun->setHasRest(); 3428 return fun; 3429 } 3430 3431 RootedAtom atom(cx, IdToFunctionName(cx, id)); 3432 if (!atom) 3433 return nullptr; 3434 3435 JSFunction* fun; 3436 if (!fs->call.op) 3437 fun = NewScriptedFunction(cx, fs->nargs, JSFunction::INTERPRETED_LAZY, atom); 3438 else if (fs->flags & JSFUN_CONSTRUCTOR) 3439 fun = NewNativeConstructor(cx, fs->call.op, fs->nargs, atom); 3440 else 3441 fun = NewNativeFunction(cx, fs->call.op, fs->nargs, atom); 3442 if (!fun) 3443 return nullptr; 3444 3445 if (fs->call.info) 3446 fun->setJitInfo(fs->call.info); 3447 return fun; 3448 } 3449 3450 static bool 3451 CreateNonSyntacticEnvironmentChain(JSContext* cx, AutoObjectVector& envChain, 3452 MutableHandleObject env, MutableHandleScope scope) 3453 { 3454 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 3455 if (!js::CreateObjectsForEnvironmentChain(cx, envChain, globalLexical, env)) 3456 return false; 3457 3458 if (!envChain.empty()) { 3459 scope.set(GlobalScope::createEmpty(cx, ScopeKind::NonSyntactic)); 3460 if (!scope) 3461 return false; 3462 3463 // The XPConnect subscript loader, which may pass in its own 3464 // environments to load scripts in, expects the environment chain to 3465 // be the holder of "var" declarations. In SpiderMonkey, such objects 3466 // are called "qualified varobjs", the "qualified" part meaning the 3467 // declaration was qualified by "var". There is only sadness. 3468 // 3469 // See JSObject::isQualifiedVarObj. 3470 if (!env->setQualifiedVarObj(cx)) 3471 return false; 3472 3473 // Also get a non-syntactic lexical environment to capture 'let' and 3474 // 'const' bindings. To persist lexical bindings, we have a 1-1 3475 // mapping with the final unwrapped environment object (the 3476 // environment that stores the 'var' bindings) and the lexical 3477 // environment. 3478 // 3479 // TODOshu: disallow the subscript loader from using non-distinguished 3480 // objects as dynamic scopes. 3481 env.set(cx->compartment()->getOrCreateNonSyntacticLexicalEnvironment(cx, env)); 3482 if (!env) 3483 return false; 3484 } else { 3485 scope.set(&cx->global()->emptyGlobalScope()); 3486 } 3487 3488 return true; 3489 } 3490 3491 static bool 3492 IsFunctionCloneable(HandleFunction fun) 3493 { 3494 if (!fun->isInterpreted()) 3495 return true; 3496 3497 // If a function was compiled with non-global syntactic environments on 3498 // the environment chain, we could have baked in EnvironmentCoordinates 3499 // into the script. We cannot clone it without breaking the compiler's 3500 // assumptions. 3501 for (ScopeIter si(fun->nonLazyScript()->enclosingScope()); si; si++) { 3502 if (si.scope()->is<GlobalScope>()) 3503 return true; 3504 if (si.hasSyntacticEnvironment()) 3505 return false; 3506 } 3507 3508 return true; 3509 } 3510 3511 static JSObject* 3512 CloneFunctionObject(JSContext* cx, HandleObject funobj, HandleObject env, HandleScope scope) 3513 { 3514 AssertHeapIsIdle(cx); 3515 CHECK_REQUEST(cx); 3516 assertSameCompartment(cx, env); 3517 MOZ_ASSERT(env); 3518 // Note that funobj can be in a different compartment. 3519 3520 if (!funobj->is<JSFunction>()) { 3521 AutoCompartment ac(cx, funobj); 3522 RootedValue v(cx, ObjectValue(*funobj)); 3523 ReportIsNotFunction(cx, v); 3524 return nullptr; 3525 } 3526 3527 RootedFunction fun(cx, &funobj->as<JSFunction>()); 3528 if (fun->isInterpretedLazy()) { 3529 AutoCompartment ac(cx, funobj); 3530 if (!fun->getOrCreateScript(cx)) 3531 return nullptr; 3532 } 3533 3534 if (!IsFunctionCloneable(fun)) { 3535 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_CLONE_FUNOBJ_SCOPE); 3536 return nullptr; 3537 } 3538 3539 if (fun->isBoundFunction()) { 3540 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT); 3541 return nullptr; 3542 } 3543 3544 if (IsAsmJSModule(fun)) { 3545 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT); 3546 return nullptr; 3547 } 3548 3549 if (IsWrappedAsyncFunction(fun)) { 3550 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CLONE_OBJECT); 3551 return nullptr; 3552 } 3553 3554 if (CanReuseScriptForClone(cx->compartment(), fun, env)) { 3555 // If the script is to be reused, either the script can already handle 3556 // non-syntactic scopes, or there is only the standard global lexical 3557 // scope. 3558 #ifdef DEBUG 3559 // Fail here if we OOM during debug asserting. 3560 // CloneFunctionReuseScript will delazify the script anyways, so we 3561 // are not creating an extra failure condition for DEBUG builds. 3562 if (!fun->getOrCreateScript(cx)) 3563 return nullptr; 3564 MOZ_ASSERT(scope->as<GlobalScope>().isSyntactic() || 3565 fun->nonLazyScript()->hasNonSyntacticScope()); 3566 #endif 3567 return CloneFunctionReuseScript(cx, fun, env, fun->getAllocKind()); 3568 } 3569 3570 JSFunction* clone = CloneFunctionAndScript(cx, fun, env, scope, fun->getAllocKind()); 3571 3572 #ifdef DEBUG 3573 // The cloned function should itself be cloneable. 3574 RootedFunction cloneRoot(cx, clone); 3575 MOZ_ASSERT_IF(cloneRoot, IsFunctionCloneable(cloneRoot)); 3576 #endif 3577 3578 return clone; 3579 } 3580 3581 JS_PUBLIC_API(JSObject*) 3582 JS::CloneFunctionObject(JSContext* cx, HandleObject funobj) 3583 { 3584 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 3585 RootedScope emptyGlobalScope(cx, &cx->global()->emptyGlobalScope()); 3586 return CloneFunctionObject(cx, funobj, globalLexical, emptyGlobalScope); 3587 } 3588 3589 extern JS_PUBLIC_API(JSObject*) 3590 JS::CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& envChain) 3591 { 3592 RootedObject env(cx); 3593 RootedScope scope(cx); 3594 if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope)) 3595 return nullptr; 3596 return CloneFunctionObject(cx, funobj, env, scope); 3597 } 3598 3599 JS_PUBLIC_API(JSObject*) 3600 JS_GetFunctionObject(JSFunction* fun) 3601 { 3602 return fun; 3603 } 3604 3605 JS_PUBLIC_API(JSString*) 3606 JS_GetFunctionId(JSFunction* fun) 3607 { 3608 return fun->name(); 3609 } 3610 3611 JS_PUBLIC_API(JSString*) 3612 JS_GetFunctionDisplayId(JSFunction* fun) 3613 { 3614 return fun->displayAtom(); 3615 } 3616 3617 JS_PUBLIC_API(uint16_t) 3618 JS_GetFunctionArity(JSFunction* fun) 3619 { 3620 return fun->nargs(); 3621 } 3622 3623 JS_PUBLIC_API(bool) 3624 JS_ObjectIsFunction(JSContext* cx, JSObject* obj) 3625 { 3626 return obj->is<JSFunction>(); 3627 } 3628 3629 JS_PUBLIC_API(bool) 3630 JS_IsNativeFunction(JSObject* funobj, JSNative call) 3631 { 3632 if (!funobj->is<JSFunction>()) 3633 return false; 3634 JSFunction* fun = &funobj->as<JSFunction>(); 3635 return fun->isNative() && fun->native() == call; 3636 } 3637 3638 extern JS_PUBLIC_API(bool) 3639 JS_IsConstructor(JSFunction* fun) 3640 { 3641 return fun->isConstructor(); 3642 } 3643 3644 JS_PUBLIC_API(bool) 3645 JS_DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs) 3646 { 3647 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3648 AssertHeapIsIdle(cx); 3649 CHECK_REQUEST(cx); 3650 assertSameCompartment(cx, obj); 3651 3652 return DefineFunctions(cx, obj, fs, NotIntrinsic); 3653 } 3654 3655 JS_PUBLIC_API(JSFunction*) 3656 JS_DefineFunction(JSContext* cx, HandleObject obj, const char* name, JSNative call, 3657 unsigned nargs, unsigned attrs) 3658 { 3659 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3660 AssertHeapIsIdle(cx); 3661 CHECK_REQUEST(cx); 3662 assertSameCompartment(cx, obj); 3663 JSAtom* atom = Atomize(cx, name, strlen(name)); 3664 if (!atom) 3665 return nullptr; 3666 Rooted<jsid> id(cx, AtomToId(atom)); 3667 return DefineFunction(cx, obj, id, call, nargs, attrs); 3668 } 3669 3670 JS_PUBLIC_API(JSFunction*) 3671 JS_DefineUCFunction(JSContext* cx, HandleObject obj, 3672 const char16_t* name, size_t namelen, JSNative call, 3673 unsigned nargs, unsigned attrs) 3674 { 3675 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3676 AssertHeapIsIdle(cx); 3677 CHECK_REQUEST(cx); 3678 assertSameCompartment(cx, obj); 3679 JSAtom* atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen)); 3680 if (!atom) 3681 return nullptr; 3682 Rooted<jsid> id(cx, AtomToId(atom)); 3683 return DefineFunction(cx, obj, id, call, nargs, attrs); 3684 } 3685 3686 extern JS_PUBLIC_API(JSFunction*) 3687 JS_DefineFunctionById(JSContext* cx, HandleObject obj, HandleId id, JSNative call, 3688 unsigned nargs, unsigned attrs) 3689 { 3690 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3691 AssertHeapIsIdle(cx); 3692 CHECK_REQUEST(cx); 3693 assertSameCompartment(cx, obj); 3694 return DefineFunction(cx, obj, id, call, nargs, attrs); 3695 } 3696 3697 /* Use the fastest available getc. */ 3698 #if defined(HAVE_GETC_UNLOCKED) 3699 # define fast_getc getc_unlocked 3700 #elif defined(HAVE__GETC_NOLOCK) 3701 # define fast_getc _getc_nolock 3702 #else 3703 # define fast_getc getc 3704 #endif 3705 3706 typedef Vector<char, 8, TempAllocPolicy> FileContents; 3707 3708 static bool 3709 ReadCompleteFile(JSContext* cx, FILE* fp, FileContents& buffer) 3710 { 3711 /* Get the complete length of the file, if possible. */ 3712 struct stat st; 3713 int ok = fstat(fileno(fp), &st); 3714 if (ok != 0) 3715 return false; 3716 if (st.st_size > 0) { 3717 if (!buffer.reserve(st.st_size)) 3718 return false; 3719 } 3720 3721 // Read in the whole file. Note that we can't assume the data's length 3722 // is actually st.st_size, because 1) some files lie about their size 3723 // (/dev/zero and /dev/random), and 2) reading files in text mode on 3724 // Windows collapses "\r\n" pairs to single \n characters. 3725 for (;;) { 3726 int c = fast_getc(fp); 3727 if (c == EOF) 3728 break; 3729 if (!buffer.append(c)) 3730 return false; 3731 } 3732 3733 return true; 3734 } 3735 3736 namespace { 3737 3738 class AutoFile 3739 { 3740 FILE* fp_; 3741 public: 3742 AutoFile() 3743 : fp_(nullptr) 3744 {} 3745 ~AutoFile() 3746 { 3747 if (fp_ && fp_ != stdin) 3748 fclose(fp_); 3749 } 3750 FILE* fp() const { return fp_; } 3751 bool open(JSContext* cx, const char* filename); 3752 bool readAll(JSContext* cx, FileContents& buffer) 3753 { 3754 MOZ_ASSERT(fp_); 3755 return ReadCompleteFile(cx, fp_, buffer); 3756 } 3757 }; 3758 3759 } /* anonymous namespace */ 3760 3761 /* 3762 * Open a source file for reading. Supports "-" and nullptr to mean stdin. The 3763 * return value must be fclosed unless it is stdin. 3764 */ 3765 bool 3766 AutoFile::open(JSContext* cx, const char* filename) 3767 { 3768 if (!filename || strcmp(filename, "-") == 0) { 3769 fp_ = stdin; 3770 } else { 3771 fp_ = fopen(filename, "r"); 3772 if (!fp_) { 3773 /* 3774 * Use Latin1 variant here because the encoding of filename is 3775 * platform dependent. 3776 */ 3777 JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_CANT_OPEN, 3778 filename, "No such file or directory"); 3779 return false; 3780 } 3781 } 3782 return true; 3783 } 3784 3785 void 3786 JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOptions& rhs) 3787 { 3788 mutedErrors_ = rhs.mutedErrors_; 3789 version = rhs.version; 3790 versionSet = rhs.versionSet; 3791 utf8 = rhs.utf8; 3792 selfHostingMode = rhs.selfHostingMode; 3793 canLazilyParse = rhs.canLazilyParse; 3794 strictOption = rhs.strictOption; 3795 extraWarningsOption = rhs.extraWarningsOption; 3796 werrorOption = rhs.werrorOption; 3797 asmJSOption = rhs.asmJSOption; 3798 throwOnAsmJSValidationFailureOption = rhs.throwOnAsmJSValidationFailureOption; 3799 forceAsync = rhs.forceAsync; 3800 installedFile = rhs.installedFile; 3801 sourceIsLazy = rhs.sourceIsLazy; 3802 introductionType = rhs.introductionType; 3803 introductionLineno = rhs.introductionLineno; 3804 introductionOffset = rhs.introductionOffset; 3805 hasIntroductionInfo = rhs.hasIntroductionInfo; 3806 }; 3807 3808 void 3809 JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions& rhs) 3810 { 3811 copyPODTransitiveOptions(rhs); 3812 lineno = rhs.lineno; 3813 column = rhs.column; 3814 isRunOnce = rhs.isRunOnce; 3815 noScriptRval = rhs.noScriptRval; 3816 } 3817 3818 JS::OwningCompileOptions::OwningCompileOptions(JSContext* cx) 3819 : ReadOnlyCompileOptions(), 3820 elementRoot(cx), 3821 elementAttributeNameRoot(cx), 3822 introductionScriptRoot(cx) 3823 { 3824 } 3825 3826 JS::OwningCompileOptions::~OwningCompileOptions() 3827 { 3828 // OwningCompileOptions always owns these, so these casts are okay. 3829 js_free(const_cast<char*>(filename_)); 3830 js_free(const_cast<char16_t*>(sourceMapURL_)); 3831 js_free(const_cast<char*>(introducerFilename_)); 3832 } 3833 3834 bool 3835 JS::OwningCompileOptions::copy(JSContext* cx, const ReadOnlyCompileOptions& rhs) 3836 { 3837 copyPODOptions(rhs); 3838 3839 setElement(rhs.element()); 3840 setElementAttributeName(rhs.elementAttributeName()); 3841 setIntroductionScript(rhs.introductionScript()); 3842 3843 return setFileAndLine(cx, rhs.filename(), rhs.lineno) && 3844 setSourceMapURL(cx, rhs.sourceMapURL()) && 3845 setIntroducerFilename(cx, rhs.introducerFilename()); 3846 } 3847 3848 bool 3849 JS::OwningCompileOptions::setFile(JSContext* cx, const char* f) 3850 { 3851 char* copy = nullptr; 3852 if (f) { 3853 copy = JS_strdup(cx, f); 3854 if (!copy) 3855 return false; 3856 } 3857 3858 // OwningCompileOptions always owns filename_, so this cast is okay. 3859 js_free(const_cast<char*>(filename_)); 3860 3861 filename_ = copy; 3862 return true; 3863 } 3864 3865 bool 3866 JS::OwningCompileOptions::setFileAndLine(JSContext* cx, const char* f, unsigned l) 3867 { 3868 if (!setFile(cx, f)) 3869 return false; 3870 3871 lineno = l; 3872 return true; 3873 } 3874 3875 bool 3876 JS::OwningCompileOptions::setSourceMapURL(JSContext* cx, const char16_t* s) 3877 { 3878 UniqueTwoByteChars copy; 3879 if (s) { 3880 copy = DuplicateString(cx, s); 3881 if (!copy) 3882 return false; 3883 } 3884 3885 // OwningCompileOptions always owns sourceMapURL_, so this cast is okay. 3886 js_free(const_cast<char16_t*>(sourceMapURL_)); 3887 3888 sourceMapURL_ = copy.release(); 3889 return true; 3890 } 3891 3892 bool 3893 JS::OwningCompileOptions::setIntroducerFilename(JSContext* cx, const char* s) 3894 { 3895 char* copy = nullptr; 3896 if (s) { 3897 copy = JS_strdup(cx, s); 3898 if (!copy) 3899 return false; 3900 } 3901 3902 // OwningCompileOptions always owns introducerFilename_, so this cast is okay. 3903 js_free(const_cast<char*>(introducerFilename_)); 3904 3905 introducerFilename_ = copy; 3906 return true; 3907 } 3908 3909 JS::CompileOptions::CompileOptions(JSContext* cx, JSVersion version) 3910 : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx), 3911 introductionScriptRoot(cx) 3912 { 3913 this->version = (version != JSVERSION_UNKNOWN) ? version : cx->findVersion(); 3914 3915 strictOption = cx->options().strictMode(); 3916 extraWarningsOption = cx->compartment()->behaviors().extraWarnings(cx); 3917 werrorOption = cx->options().werror(); 3918 if (!cx->options().asmJS()) 3919 asmJSOption = AsmJSOption::Disabled; 3920 else if (cx->compartment()->debuggerObservesAsmJS()) 3921 asmJSOption = AsmJSOption::DisabledByDebugger; 3922 else 3923 asmJSOption = AsmJSOption::Enabled; 3924 throwOnAsmJSValidationFailureOption = cx->options().throwOnAsmJSValidationFailure(); 3925 } 3926 3927 static bool 3928 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind, 3929 SourceBufferHolder& srcBuf, MutableHandleScript script) 3930 { 3931 MOZ_ASSERT(scopeKind == ScopeKind::Global || scopeKind == ScopeKind::NonSyntactic); 3932 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 3933 AssertHeapIsIdle(cx); 3934 CHECK_REQUEST(cx); 3935 3936 script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf)); 3937 return !!script; 3938 } 3939 3940 static bool 3941 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind, 3942 const char16_t* chars, size_t length, MutableHandleScript script) 3943 { 3944 SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership); 3945 return ::Compile(cx, options, scopeKind, srcBuf, script); 3946 } 3947 3948 static bool 3949 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind, 3950 const char* bytes, size_t length, MutableHandleScript script) 3951 { 3952 UniqueTwoByteChars chars; 3953 if (options.utf8) 3954 chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get()); 3955 else 3956 chars.reset(InflateString(cx, bytes, &length)); 3957 if (!chars) 3958 return false; 3959 3960 return ::Compile(cx, options, scopeKind, chars.get(), length, script); 3961 } 3962 3963 static bool 3964 Compile(JSContext* cx, const ReadOnlyCompileOptions& options, ScopeKind scopeKind, 3965 FILE* fp, MutableHandleScript script) 3966 { 3967 FileContents buffer(cx); 3968 if (!ReadCompleteFile(cx, fp, buffer)) 3969 return false; 3970 3971 return ::Compile(cx, options, scopeKind, buffer.begin(), buffer.length(), script); 3972 } 3973 3974 static bool 3975 Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, ScopeKind scopeKind, 3976 const char* filename, MutableHandleScript script) 3977 { 3978 AutoFile file; 3979 if (!file.open(cx, filename)) 3980 return false; 3981 CompileOptions options(cx, optionsArg); 3982 options.setFileAndLine(filename, 1); 3983 return ::Compile(cx, options, scopeKind, file.fp(), script); 3984 } 3985 3986 bool 3987 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, 3988 SourceBufferHolder& srcBuf, JS::MutableHandleScript script) 3989 { 3990 return ::Compile(cx, options, ScopeKind::Global, srcBuf, script); 3991 } 3992 3993 bool 3994 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, 3995 const char* bytes, size_t length, JS::MutableHandleScript script) 3996 { 3997 return ::Compile(cx, options, ScopeKind::Global, bytes, length, script); 3998 } 3999 4000 bool 4001 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, 4002 const char16_t* chars, size_t length, JS::MutableHandleScript script) 4003 { 4004 return ::Compile(cx, options, ScopeKind::Global, chars, length, script); 4005 } 4006 4007 bool 4008 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, 4009 FILE* file, JS::MutableHandleScript script) 4010 { 4011 return ::Compile(cx, options, ScopeKind::Global, file, script); 4012 } 4013 4014 bool 4015 JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options, 4016 const char* filename, JS::MutableHandleScript script) 4017 { 4018 return ::Compile(cx, options, ScopeKind::Global, filename, script); 4019 } 4020 4021 bool 4022 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, 4023 SourceBufferHolder& srcBuf, JS::MutableHandleScript script) 4024 { 4025 return ::Compile(cx, options, ScopeKind::NonSyntactic, srcBuf, script); 4026 } 4027 4028 bool 4029 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, 4030 const char* bytes, size_t length, JS::MutableHandleScript script) 4031 { 4032 return ::Compile(cx, options, ScopeKind::NonSyntactic, bytes, length, script); 4033 } 4034 4035 bool 4036 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, 4037 const char16_t* chars, size_t length, 4038 JS::MutableHandleScript script) 4039 { 4040 return ::Compile(cx, options, ScopeKind::NonSyntactic, chars, length, script); 4041 } 4042 4043 bool 4044 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, 4045 FILE* file, JS::MutableHandleScript script) 4046 { 4047 return ::Compile(cx, options, ScopeKind::NonSyntactic, file, script); 4048 } 4049 4050 bool 4051 JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options, 4052 const char* filename, JS::MutableHandleScript script) 4053 { 4054 return ::Compile(cx, options, ScopeKind::NonSyntactic, filename, script); 4055 } 4056 4057 JS_PUBLIC_API(bool) 4058 JS::CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length) 4059 { 4060 static const size_t TINY_LENGTH = 5 * 1000; 4061 static const size_t HUGE_LENGTH = 100 * 1000; 4062 4063 // These are heuristics which the caller may choose to ignore (e.g., for 4064 // testing purposes). 4065 if (!options.forceAsync) { 4066 // Compiling off the main thread inolves creating a new Zone and other 4067 // significant overheads. Don't bother if the script is tiny. 4068 if (length < TINY_LENGTH) 4069 return false; 4070 4071 // If the parsing task would have to wait for GC to complete, it'll probably 4072 // be faster to just start it synchronously on the main thread unless the 4073 // script is huge. 4074 if (OffThreadParsingMustWaitForGC(cx->runtime()) && length < HUGE_LENGTH) 4075 return false; 4076 } 4077 4078 return cx->runtime()->canUseParallelParsing() && CanUseExtraThreads(); 4079 } 4080 4081 JS_PUBLIC_API(bool) 4082 JS::CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, 4083 const char16_t* chars, size_t length, 4084 OffThreadCompileCallback callback, void* callbackData) 4085 { 4086 MOZ_ASSERT(CanCompileOffThread(cx, options, length)); 4087 return StartOffThreadParseScript(cx, options, chars, length, callback, callbackData); 4088 } 4089 4090 JS_PUBLIC_API(JSScript*) 4091 JS::FinishOffThreadScript(JSContext* cx, void* token) 4092 { 4093 MOZ_ASSERT(cx); 4094 MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx)); 4095 return HelperThreadState().finishScriptParseTask(cx, token); 4096 } 4097 4098 JS_PUBLIC_API(void) 4099 JS::CancelOffThreadScript(JSContext* cx, void* token) 4100 { 4101 MOZ_ASSERT(cx); 4102 MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx)); 4103 HelperThreadState().cancelParseTask(cx, ParseTaskKind::Script, token); 4104 } 4105 4106 JS_PUBLIC_API(bool) 4107 JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options, 4108 const char16_t* chars, size_t length, 4109 OffThreadCompileCallback callback, void* callbackData) 4110 { 4111 MOZ_ASSERT(CanCompileOffThread(cx, options, length)); 4112 return StartOffThreadParseModule(cx, options, chars, length, callback, callbackData); 4113 } 4114 4115 JS_PUBLIC_API(JSObject*) 4116 JS::FinishOffThreadModule(JSContext* cx, void* token) 4117 { 4118 MOZ_ASSERT(cx); 4119 MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx)); 4120 return HelperThreadState().finishModuleParseTask(cx, token); 4121 } 4122 4123 JS_PUBLIC_API(void) 4124 JS::CancelOffThreadModule(JSContext* cx, void* token) 4125 { 4126 MOZ_ASSERT(cx); 4127 MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx)); 4128 HelperThreadState().cancelParseTask(cx, ParseTaskKind::Module, token); 4129 } 4130 4131 JS_PUBLIC_API(bool) 4132 JS_CompileScript(JSContext* cx, const char* ascii, size_t length, 4133 const JS::CompileOptions& options, MutableHandleScript script) 4134 { 4135 return Compile(cx, options, ascii, length, script); 4136 } 4137 4138 JS_PUBLIC_API(bool) 4139 JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length, 4140 const JS::CompileOptions& options, MutableHandleScript script) 4141 { 4142 return Compile(cx, options, chars, length, script); 4143 } 4144 4145 JS_PUBLIC_API(bool) 4146 JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, size_t length) 4147 { 4148 AssertHeapIsIdle(cx); 4149 CHECK_REQUEST(cx); 4150 assertSameCompartment(cx, obj); 4151 4152 cx->clearPendingException(); 4153 4154 char16_t* chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get(); 4155 if (!chars) 4156 return true; 4157 4158 // Return true on any out-of-memory error or non-EOF-related syntax error, so our 4159 // caller doesn't try to collect more buffered source. 4160 bool result = true; 4161 4162 CompileOptions options(cx); 4163 frontend::UsedNameTracker usedNames(cx); 4164 if (!usedNames.init()) 4165 return false; 4166 frontend::Parser<frontend::FullParseHandler> parser(cx, cx->tempLifoAlloc(), 4167 options, chars, length, 4168 /* foldConstants = */ true, 4169 usedNames, nullptr, nullptr); 4170 JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr); 4171 if (!parser.checkOptions() || !parser.parse()) { 4172 // We ran into an error. If it was because we ran out of source, we 4173 // return false so our caller knows to try to collect more buffered 4174 // source. 4175 if (parser.isUnexpectedEOF()) 4176 result = false; 4177 4178 cx->clearPendingException(); 4179 } 4180 JS::SetWarningReporter(cx, older); 4181 4182 js_free(chars); 4183 return result; 4184 } 4185 4186 JS_PUBLIC_API(JSObject*) 4187 JS_GetGlobalFromScript(JSScript* script) 4188 { 4189 MOZ_ASSERT(!script->isCachedEval()); 4190 return &script->global(); 4191 } 4192 4193 JS_PUBLIC_API(const char*) 4194 JS_GetScriptFilename(JSScript* script) 4195 { 4196 // This is called from ThreadStackHelper which can be called from another 4197 // thread or inside a signal hander, so we need to be careful in case a 4198 // copmacting GC is currently moving things around. 4199 return script->maybeForwardedFilename(); 4200 } 4201 4202 JS_PUBLIC_API(unsigned) 4203 JS_GetScriptBaseLineNumber(JSContext* cx, JSScript* script) 4204 { 4205 return script->lineno(); 4206 } 4207 4208 JS_PUBLIC_API(JSScript*) 4209 JS_GetFunctionScript(JSContext* cx, HandleFunction fun) 4210 { 4211 if (fun->isNative()) 4212 return nullptr; 4213 if (fun->isInterpretedLazy()) { 4214 AutoCompartment funCompartment(cx, fun); 4215 JSScript* script = fun->getOrCreateScript(cx); 4216 if (!script) 4217 MOZ_CRASH(); 4218 return script; 4219 } 4220 return fun->nonLazyScript(); 4221 } 4222 4223 /* 4224 * enclosingScope is a static enclosing scope, if any (e.g. a WithScope). If 4225 * the enclosing scope is the global scope, this must be null. 4226 * 4227 * enclosingDynamicScope is a dynamic scope to use, if it's not the global. 4228 */ 4229 static bool 4230 CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, 4231 const char* name, unsigned nargs, const char* const* argnames, 4232 SourceBufferHolder& srcBuf, 4233 HandleObject enclosingEnv, HandleScope enclosingScope, 4234 MutableHandleFunction fun) 4235 { 4236 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 4237 AssertHeapIsIdle(cx); 4238 CHECK_REQUEST(cx); 4239 assertSameCompartment(cx, enclosingEnv); 4240 RootedAtom funAtom(cx); 4241 4242 if (name) { 4243 funAtom = Atomize(cx, name, strlen(name)); 4244 if (!funAtom) 4245 return false; 4246 } 4247 4248 Rooted<PropertyNameVector> formals(cx, PropertyNameVector(cx)); 4249 for (unsigned i = 0; i < nargs; i++) { 4250 RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i]))); 4251 if (!argAtom || !formals.append(argAtom->asPropertyName())) 4252 return false; 4253 } 4254 4255 fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL, funAtom, 4256 /* proto = */ nullptr, 4257 gc::AllocKind::FUNCTION, TenuredObject, 4258 enclosingEnv)); 4259 if (!fun) 4260 return false; 4261 4262 // Make sure the static scope chain matches up when we have a 4263 // non-syntactic scope. 4264 MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(enclosingEnv), 4265 enclosingScope->hasOnChain(ScopeKind::NonSyntactic)); 4266 4267 if (!frontend::CompileFunctionBody(cx, fun, optionsArg, formals, srcBuf, enclosingScope)) 4268 return false; 4269 4270 return true; 4271 } 4272 4273 JS_PUBLIC_API(bool) 4274 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain, 4275 const ReadOnlyCompileOptions& options, 4276 const char* name, unsigned nargs, const char* const* argnames, 4277 SourceBufferHolder& srcBuf, MutableHandleFunction fun) 4278 { 4279 RootedObject env(cx); 4280 RootedScope scope(cx); 4281 if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope)) 4282 return false; 4283 return CompileFunction(cx, options, name, nargs, argnames, srcBuf, env, scope, fun); 4284 } 4285 4286 JS_PUBLIC_API(bool) 4287 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain, 4288 const ReadOnlyCompileOptions& options, 4289 const char* name, unsigned nargs, const char* const* argnames, 4290 const char16_t* chars, size_t length, MutableHandleFunction fun) 4291 { 4292 SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership); 4293 return CompileFunction(cx, envChain, options, name, nargs, argnames, 4294 srcBuf, fun); 4295 } 4296 4297 JS_PUBLIC_API(bool) 4298 JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain, 4299 const ReadOnlyCompileOptions& options, 4300 const char* name, unsigned nargs, const char* const* argnames, 4301 const char* bytes, size_t length, MutableHandleFunction fun) 4302 { 4303 UniqueTwoByteChars chars; 4304 if (options.utf8) 4305 chars.reset(UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get()); 4306 else 4307 chars.reset(InflateString(cx, bytes, &length)); 4308 if (!chars) 4309 return false; 4310 4311 return CompileFunction(cx, envChain, options, name, nargs, argnames, 4312 chars.get(), length, fun); 4313 } 4314 4315 JS_PUBLIC_API(JSString*) 4316 JS_DecompileScript(JSContext* cx, HandleScript script, const char* name, unsigned indent) 4317 { 4318 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 4319 4320 AssertHeapIsIdle(cx); 4321 CHECK_REQUEST(cx); 4322 script->ensureNonLazyCanonicalFunction(cx); 4323 RootedFunction fun(cx, script->functionNonDelazifying()); 4324 if (fun) 4325 return JS_DecompileFunction(cx, fun, indent); 4326 bool haveSource = script->scriptSource()->hasSourceData(); 4327 if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource)) 4328 return nullptr; 4329 return haveSource ? script->sourceData(cx) : NewStringCopyZ<CanGC>(cx, "[no source]"); 4330 } 4331 4332 JS_PUBLIC_API(JSString*) 4333 JS_DecompileFunction(JSContext* cx, HandleFunction fun, unsigned indent) 4334 { 4335 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 4336 AssertHeapIsIdle(cx); 4337 CHECK_REQUEST(cx); 4338 assertSameCompartment(cx, fun); 4339 return FunctionToString(cx, fun, !(indent & JS_DONT_PRETTY_PRINT)); 4340 } 4341 4342 MOZ_NEVER_INLINE static bool 4343 ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval) 4344 { 4345 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 4346 AssertHeapIsIdle(cx); 4347 CHECK_REQUEST(cx); 4348 assertSameCompartment(cx, scope, script); 4349 MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(scope), script->hasNonSyntacticScope()); 4350 return Execute(cx, script, *scope, rval); 4351 } 4352 4353 static bool 4354 ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg, Value* rval) 4355 { 4356 RootedObject env(cx); 4357 RootedScope dummy(cx); 4358 if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &dummy)) 4359 return false; 4360 4361 RootedScript script(cx, scriptArg); 4362 if (!script->hasNonSyntacticScope() && !IsGlobalLexicalEnvironment(env)) { 4363 script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script); 4364 if (!script) 4365 return false; 4366 js::Debugger::onNewScript(cx, script); 4367 } 4368 4369 return ExecuteScript(cx, env, script, rval); 4370 } 4371 4372 MOZ_NEVER_INLINE JS_PUBLIC_API(bool) 4373 JS_ExecuteScript(JSContext* cx, HandleScript scriptArg, MutableHandleValue rval) 4374 { 4375 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 4376 return ExecuteScript(cx, globalLexical, scriptArg, rval.address()); 4377 } 4378 4379 MOZ_NEVER_INLINE JS_PUBLIC_API(bool) 4380 JS_ExecuteScript(JSContext* cx, HandleScript scriptArg) 4381 { 4382 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 4383 return ExecuteScript(cx, globalLexical, scriptArg, nullptr); 4384 } 4385 4386 MOZ_NEVER_INLINE JS_PUBLIC_API(bool) 4387 JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain, 4388 HandleScript scriptArg, MutableHandleValue rval) 4389 { 4390 return ExecuteScript(cx, envChain, scriptArg, rval.address()); 4391 } 4392 4393 MOZ_NEVER_INLINE JS_PUBLIC_API(bool) 4394 JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg) 4395 { 4396 return ExecuteScript(cx, envChain, scriptArg, nullptr); 4397 } 4398 4399 JS_PUBLIC_API(bool) 4400 JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg, 4401 JS::MutableHandleValue rval) 4402 { 4403 CHECK_REQUEST(cx); 4404 RootedScript script(cx, scriptArg); 4405 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 4406 if (script->compartment() != cx->compartment()) { 4407 script = CloneGlobalScript(cx, ScopeKind::Global, script); 4408 if (!script) 4409 return false; 4410 4411 js::Debugger::onNewScript(cx, script); 4412 } 4413 return ExecuteScript(cx, globalLexical, script, rval.address()); 4414 } 4415 4416 static const unsigned LARGE_SCRIPT_LENGTH = 500*1024; 4417 4418 static bool 4419 Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env, 4420 const ReadOnlyCompileOptions& optionsArg, 4421 SourceBufferHolder& srcBuf, MutableHandleValue rval) 4422 { 4423 CompileOptions options(cx, optionsArg); 4424 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 4425 AssertHeapIsIdle(cx); 4426 CHECK_REQUEST(cx); 4427 assertSameCompartment(cx, env); 4428 MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic); 4429 4430 options.setIsRunOnce(true); 4431 SourceCompressionTask sct(cx); 4432 RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), 4433 scopeKind, options, srcBuf, &sct)); 4434 if (!script) 4435 return false; 4436 4437 MOZ_ASSERT(script->getVersion() == options.version); 4438 4439 bool result = Execute(cx, script, *env, 4440 options.noScriptRval ? nullptr : rval.address()); 4441 if (!sct.complete()) 4442 result = false; 4443 4444 // After evaluation, the compiled script will not be run again. 4445 // script->ensureRanAnalysis allocated 1 analyze::Bytecode for every opcode 4446 // which for large scripts means significant memory. Perform a GC eagerly 4447 // to clear out this analysis data before anything happens to inhibit the 4448 // flushing of this memory (such as setting requestAnimationFrame). 4449 if (script->length() > LARGE_SCRIPT_LENGTH) { 4450 script = nullptr; 4451 PrepareZoneForGC(cx->zone()); 4452 cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUATE); 4453 } 4454 4455 return result; 4456 } 4457 4458 static bool 4459 Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg, 4460 SourceBufferHolder& srcBuf, MutableHandleValue rval) 4461 { 4462 RootedObject env(cx); 4463 RootedScope scope(cx); 4464 if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope)) 4465 return false; 4466 return ::Evaluate(cx, scope->kind(), env, optionsArg, srcBuf, rval); 4467 } 4468 4469 static bool 4470 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, 4471 const char16_t* chars, size_t length, MutableHandleValue rval) 4472 { 4473 SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership); 4474 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 4475 return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval); 4476 } 4477 4478 extern JS_PUBLIC_API(bool) 4479 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options, 4480 const char* bytes, size_t length, MutableHandleValue rval) 4481 { 4482 char16_t* chars; 4483 if (options.utf8) 4484 chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get(); 4485 else 4486 chars = InflateString(cx, bytes, &length); 4487 if (!chars) 4488 return false; 4489 4490 SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership); 4491 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 4492 bool ok = ::Evaluate(cx, ScopeKind::Global, globalLexical, options, srcBuf, rval); 4493 return ok; 4494 } 4495 4496 static bool 4497 Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, 4498 const char* filename, MutableHandleValue rval) 4499 { 4500 FileContents buffer(cx); 4501 { 4502 AutoFile file; 4503 if (!file.open(cx, filename) || !file.readAll(cx, buffer)) 4504 return false; 4505 } 4506 4507 CompileOptions options(cx, optionsArg); 4508 options.setFileAndLine(filename, 1); 4509 return Evaluate(cx, options, buffer.begin(), buffer.length(), rval); 4510 } 4511 4512 JS_PUBLIC_API(bool) 4513 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, 4514 SourceBufferHolder& srcBuf, MutableHandleValue rval) 4515 { 4516 RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment()); 4517 return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval); 4518 } 4519 4520 JS_PUBLIC_API(bool) 4521 JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg, 4522 SourceBufferHolder& srcBuf, MutableHandleValue rval) 4523 { 4524 return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval); 4525 } 4526 4527 JS_PUBLIC_API(bool) 4528 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, 4529 const char16_t* chars, size_t length, MutableHandleValue rval) 4530 { 4531 return ::Evaluate(cx, optionsArg, chars, length, rval); 4532 } 4533 4534 JS_PUBLIC_API(bool) 4535 JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg, 4536 const char16_t* chars, size_t length, MutableHandleValue rval) 4537 { 4538 SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership); 4539 return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval); 4540 } 4541 4542 JS_PUBLIC_API(bool) 4543 JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg, 4544 const char* filename, MutableHandleValue rval) 4545 { 4546 return ::Evaluate(cx, optionsArg, filename, rval); 4547 } 4548 4549 JS_PUBLIC_API(JSFunction*) 4550 JS::GetModuleResolveHook(JSContext* cx) 4551 { 4552 AssertHeapIsIdle(cx); 4553 CHECK_REQUEST(cx); 4554 return cx->global()->moduleResolveHook(); 4555 } 4556 4557 JS_PUBLIC_API(void) 4558 JS::SetModuleResolveHook(JSContext* cx, HandleFunction func) 4559 { 4560 AssertHeapIsIdle(cx); 4561 CHECK_REQUEST(cx); 4562 assertSameCompartment(cx, func); 4563 cx->global()->setModuleResolveHook(func); 4564 } 4565 4566 JS_PUBLIC_API(bool) 4567 JS::CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options, 4568 SourceBufferHolder& srcBuf, JS::MutableHandleObject module) 4569 { 4570 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 4571 AssertHeapIsIdle(cx); 4572 CHECK_REQUEST(cx); 4573 4574 module.set(frontend::CompileModule(cx, options, srcBuf)); 4575 return !!module; 4576 } 4577 4578 JS_PUBLIC_API(void) 4579 JS::SetModuleHostDefinedField(JSObject* module, const JS::Value& value) 4580 { 4581 module->as<ModuleObject>().setHostDefinedField(value); 4582 } 4583 4584 JS_PUBLIC_API(JS::Value) 4585 JS::GetModuleHostDefinedField(JSObject* module) 4586 { 4587 return module->as<ModuleObject>().hostDefinedField(); 4588 } 4589 4590 JS_PUBLIC_API(bool) 4591 JS::ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleArg) 4592 { 4593 AssertHeapIsIdle(cx); 4594 CHECK_REQUEST(cx); 4595 assertSameCompartment(cx, moduleArg); 4596 return ModuleObject::DeclarationInstantiation(cx, moduleArg.as<ModuleObject>()); 4597 } 4598 4599 JS_PUBLIC_API(bool) 4600 JS::ModuleEvaluation(JSContext* cx, JS::HandleObject moduleArg) 4601 { 4602 AssertHeapIsIdle(cx); 4603 CHECK_REQUEST(cx); 4604 assertSameCompartment(cx, moduleArg); 4605 return ModuleObject::Evaluation(cx, moduleArg.as<ModuleObject>()); 4606 } 4607 4608 JS_PUBLIC_API(JSObject*) 4609 JS::GetRequestedModules(JSContext* cx, JS::HandleObject moduleArg) 4610 { 4611 AssertHeapIsIdle(cx); 4612 CHECK_REQUEST(cx); 4613 assertSameCompartment(cx, moduleArg); 4614 return &moduleArg->as<ModuleObject>().requestedModules(); 4615 } 4616 4617 JS_PUBLIC_API(JSScript*) 4618 JS::GetModuleScript(JSContext* cx, JS::HandleObject moduleArg) 4619 { 4620 AssertHeapIsIdle(cx); 4621 CHECK_REQUEST(cx); 4622 assertSameCompartment(cx, moduleArg); 4623 return moduleArg->as<ModuleObject>().script(); 4624 } 4625 4626 JS_PUBLIC_API(JSObject*) 4627 JS_New(JSContext* cx, HandleObject ctor, const JS::HandleValueArray& inputArgs) 4628 { 4629 AssertHeapIsIdle(cx); 4630 CHECK_REQUEST(cx); 4631 assertSameCompartment(cx, ctor, inputArgs); 4632 4633 RootedValue ctorVal(cx, ObjectValue(*ctor)); 4634 if (!IsConstructor(ctorVal)) { 4635 ReportValueError(cx, JSMSG_NOT_CONSTRUCTOR, JSDVG_IGNORE_STACK, ctorVal, nullptr); 4636 return nullptr; 4637 } 4638 4639 ConstructArgs args(cx); 4640 if (!FillArgumentsFromArraylike(cx, args, inputArgs)) 4641 return nullptr; 4642 4643 RootedObject obj(cx); 4644 if (!js::Construct(cx, ctorVal, args, ctorVal, &obj)) 4645 return nullptr; 4646 4647 return obj; 4648 } 4649 4650 JS_PUBLIC_API(bool) 4651 JS_CheckForInterrupt(JSContext* cx) 4652 { 4653 return js::CheckForInterrupt(cx); 4654 } 4655 4656 JS_PUBLIC_API(bool) 4657 JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback) 4658 { 4659 return cx->interruptCallbacks.append(callback); 4660 } 4661 4662 JS_PUBLIC_API(bool) 4663 JS_DisableInterruptCallback(JSContext* cx) 4664 { 4665 bool result = cx->interruptCallbackDisabled; 4666 cx->interruptCallbackDisabled = true; 4667 return result; 4668 } 4669 4670 JS_PUBLIC_API(void) 4671 JS_ResetInterruptCallback(JSContext* cx, bool enable) 4672 { 4673 cx->interruptCallbackDisabled = enable; 4674 } 4675 4676 /************************************************************************/ 4677 4678 /* 4679 * Promises. 4680 */ 4681 JS_PUBLIC_API(void) 4682 JS::SetGetIncumbentGlobalCallback(JSContext* cx, JSGetIncumbentGlobalCallback callback) 4683 { 4684 cx->getIncumbentGlobalCallback = callback; 4685 } 4686 4687 JS_PUBLIC_API(void) 4688 JS::SetEnqueuePromiseJobCallback(JSContext* cx, JSEnqueuePromiseJobCallback callback, 4689 void* data /* = nullptr */) 4690 { 4691 cx->enqueuePromiseJobCallback = callback; 4692 cx->enqueuePromiseJobCallbackData = data; 4693 } 4694 4695 extern JS_PUBLIC_API(void) 4696 JS::SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerCallback callback, 4697 void* data /* = nullptr */) 4698 { 4699 cx->promiseRejectionTrackerCallback = callback; 4700 cx->promiseRejectionTrackerCallbackData = data; 4701 } 4702 4703 JS_PUBLIC_API(JSObject*) 4704 JS::NewPromiseObject(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */) 4705 { 4706 MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment())); 4707 MOZ_ASSERT(IsCallable(executor)); 4708 AssertHeapIsIdle(cx); 4709 CHECK_REQUEST(cx); 4710 assertSameCompartment(cx, executor, proto); 4711 4712 return PromiseObject::create(cx, executor, proto); 4713 } 4714 4715 JS_PUBLIC_API(bool) 4716 JS::IsPromiseObject(JS::HandleObject obj) 4717 { 4718 return obj->is<PromiseObject>(); 4719 } 4720 4721 JS_PUBLIC_API(JSObject*) 4722 JS::GetPromiseConstructor(JSContext* cx) 4723 { 4724 CHECK_REQUEST(cx); 4725 Rooted<GlobalObject*> global(cx, cx->global()); 4726 return GlobalObject::getOrCreatePromiseConstructor(cx, global); 4727 } 4728 4729 JS_PUBLIC_API(JSObject*) 4730 JS::GetPromisePrototype(JSContext* cx) 4731 { 4732 CHECK_REQUEST(cx); 4733 Rooted<GlobalObject*> global(cx, cx->global()); 4734 return GlobalObject::getOrCreatePromisePrototype(cx, global); 4735 } 4736 4737 JS_PUBLIC_API(JS::PromiseState) 4738 JS::GetPromiseState(JS::HandleObject promiseObj_) 4739 { 4740 JSObject* promiseObj = CheckedUnwrap(promiseObj_); 4741 if (!promiseObj || !promiseObj->is<PromiseObject>()) 4742 return JS::PromiseState::Pending; 4743 4744 return promiseObj->as<PromiseObject>().state(); 4745 } 4746 4747 JS_PUBLIC_API(uint64_t) 4748 JS::GetPromiseID(JS::HandleObject promise) 4749 { 4750 return promise->as<PromiseObject>().getID(); 4751 } 4752 4753 JS_PUBLIC_API(JS::Value) 4754 JS::GetPromiseResult(JS::HandleObject promiseObj) 4755 { 4756 PromiseObject* promise = &promiseObj->as<PromiseObject>(); 4757 MOZ_ASSERT(promise->state() != JS::PromiseState::Pending); 4758 return promise->state() == JS::PromiseState::Fulfilled ? promise->value() : promise->reason(); 4759 } 4760 4761 JS_PUBLIC_API(JSObject*) 4762 JS::GetPromiseAllocationSite(JS::HandleObject promise) 4763 { 4764 return promise->as<PromiseObject>().allocationSite(); 4765 } 4766 4767 JS_PUBLIC_API(JSObject*) 4768 JS::GetPromiseResolutionSite(JS::HandleObject promise) 4769 { 4770 return promise->as<PromiseObject>().resolutionSite(); 4771 } 4772 4773 #ifdef DEBUG 4774 JS_PUBLIC_API(void) 4775 JS::DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise) 4776 { 4777 RootedObject stack(cx, promise->as<PromiseObject>().allocationSite()); 4778 UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get())); 4779 if (stackStr.get()) 4780 fputs(stackStr.get(), stderr); 4781 } 4782 4783 JS_PUBLIC_API(void) 4784 JS::DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise) 4785 { 4786 RootedObject stack(cx, promise->as<PromiseObject>().resolutionSite()); 4787 UniqueChars stackStr(reinterpret_cast<char*>(BuildUTF8StackString(cx, stack).get())); 4788 if (stackStr.get()) 4789 fputs(stackStr.get(), stderr); 4790 } 4791 #endif 4792 4793 JS_PUBLIC_API(JSObject*) 4794 JS::CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue) 4795 { 4796 AssertHeapIsIdle(cx); 4797 CHECK_REQUEST(cx); 4798 assertSameCompartment(cx, resolutionValue); 4799 4800 RootedObject promise(cx, PromiseObject::unforgeableResolve(cx, resolutionValue)); 4801 MOZ_ASSERT_IF(promise, promise->is<PromiseObject>()); 4802 return promise; 4803 } 4804 4805 JS_PUBLIC_API(JSObject*) 4806 JS::CallOriginalPromiseReject(JSContext* cx, JS::HandleValue rejectionValue) 4807 { 4808 AssertHeapIsIdle(cx); 4809 CHECK_REQUEST(cx); 4810 assertSameCompartment(cx, rejectionValue); 4811 4812 RootedObject promise(cx, PromiseObject::unforgeableReject(cx, rejectionValue)); 4813 MOZ_ASSERT_IF(promise, promise->is<PromiseObject>()); 4814 return promise; 4815 } 4816 4817 static bool 4818 ResolveOrRejectPromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue resultOrReason_, 4819 bool reject) 4820 { 4821 AssertHeapIsIdle(cx); 4822 CHECK_REQUEST(cx); 4823 assertSameCompartment(cx, promiseObj, resultOrReason_); 4824 4825 mozilla::Maybe<AutoCompartment> ac; 4826 Rooted<PromiseObject*> promise(cx); 4827 RootedValue resultOrReason(cx, resultOrReason_); 4828 if (IsWrapper(promiseObj)) { 4829 JSObject* unwrappedPromiseObj = CheckedUnwrap(promiseObj); 4830 if (!unwrappedPromiseObj) { 4831 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_OBJECT_ACCESS_DENIED); 4832 return false; 4833 } 4834 promise = &unwrappedPromiseObj->as<PromiseObject>(); 4835 ac.emplace(cx, promise); 4836 if (!cx->compartment()->wrap(cx, &resultOrReason)) 4837 return false; 4838 } else { 4839 promise = promiseObj.as<PromiseObject>(); 4840 } 4841 4842 return reject 4843 ? promise->reject(cx, resultOrReason) 4844 : promise->resolve(cx, resultOrReason); 4845 } 4846 4847 JS_PUBLIC_API(bool) 4848 JS::ResolvePromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue resolutionValue) 4849 { 4850 return ResolveOrRejectPromise(cx, promiseObj, resolutionValue, false); 4851 } 4852 4853 JS_PUBLIC_API(bool) 4854 JS::RejectPromise(JSContext* cx, JS::HandleObject promiseObj, JS::HandleValue rejectionValue) 4855 { 4856 return ResolveOrRejectPromise(cx, promiseObj, rejectionValue, true); 4857 } 4858 4859 static bool 4860 CallOriginalPromiseThenImpl(JSContext* cx, JS::HandleObject promiseObj, 4861 JS::HandleObject onResolvedObj_, JS::HandleObject onRejectedObj_, 4862 JS::MutableHandleObject resultObj, bool createDependent) 4863 { 4864 AssertHeapIsIdle(cx); 4865 CHECK_REQUEST(cx); 4866 assertSameCompartment(cx, promiseObj, onResolvedObj_, onRejectedObj_); 4867 4868 MOZ_ASSERT_IF(onResolvedObj_, IsCallable(onResolvedObj_)); 4869 MOZ_ASSERT_IF(onRejectedObj_, IsCallable(onRejectedObj_)); 4870 4871 { 4872 mozilla::Maybe<AutoCompartment> ac; 4873 Rooted<PromiseObject*> promise(cx); 4874 RootedObject onResolvedObj(cx, onResolvedObj_); 4875 RootedObject onRejectedObj(cx, onRejectedObj_); 4876 if (IsWrapper(promiseObj)) { 4877 JSObject* unwrappedPromiseObj = CheckedUnwrap(promiseObj); 4878 if (!unwrappedPromiseObj) { 4879 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_OBJECT_ACCESS_DENIED); 4880 return false; 4881 } 4882 promise = &unwrappedPromiseObj->as<PromiseObject>(); 4883 ac.emplace(cx, promise); 4884 if (!cx->compartment()->wrap(cx, &onResolvedObj) || 4885 !cx->compartment()->wrap(cx, &onRejectedObj)) 4886 { 4887 return false; 4888 } 4889 } else { 4890 promise = promiseObj.as<PromiseObject>(); 4891 } 4892 4893 RootedValue onFulfilled(cx, ObjectOrNullValue(onResolvedObj)); 4894 RootedValue onRejected(cx, ObjectOrNullValue(onRejectedObj)); 4895 if (!OriginalPromiseThen(cx, promise, onFulfilled, onRejected, resultObj, createDependent)) 4896 return false; 4897 } 4898 4899 if (resultObj) { 4900 if (!cx->compartment()->wrap(cx, resultObj)) 4901 return false; 4902 } 4903 return true; 4904 4905 } 4906 4907 JS_PUBLIC_API(JSObject*) 4908 JS::CallOriginalPromiseThen(JSContext* cx, JS::HandleObject promiseObj, 4909 JS::HandleObject onResolvedObj, JS::HandleObject onRejectedObj) 4910 { 4911 RootedObject resultPromise(cx); 4912 if (!CallOriginalPromiseThenImpl(cx, promiseObj, onResolvedObj, onRejectedObj, &resultPromise, true)) 4913 return nullptr; 4914 return resultPromise; 4915 } 4916 4917 JS_PUBLIC_API(bool) 4918 JS::AddPromiseReactions(JSContext* cx, JS::HandleObject promiseObj, 4919 JS::HandleObject onResolvedObj, JS::HandleObject onRejectedObj) 4920 { 4921 RootedObject resultPromise(cx); 4922 bool result = CallOriginalPromiseThenImpl(cx, promiseObj, onResolvedObj, onRejectedObj, &resultPromise, false); 4923 MOZ_ASSERT(!resultPromise); 4924 return result; 4925 } 4926 4927 /** 4928 * Unforgeable version of Promise.all for internal use. 4929 * 4930 * Takes a dense array of Promise objects and returns a promise that's 4931 * resolved with an array of resolution values when all those promises ahve 4932 * been resolved, or rejected with the rejection value of the first rejected 4933 * promise. 4934 * 4935 * Asserts that the array is dense and all entries are Promise objects. 4936 */ 4937 JS_PUBLIC_API(JSObject*) 4938 JS::GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises) 4939 { 4940 AssertHeapIsIdle(cx); 4941 CHECK_REQUEST(cx); 4942 4943 return js::GetWaitForAllPromise(cx, promises); 4944 } 4945 4946 JS_PUBLIC_API(void) 4947 JS::SetAsyncTaskCallbacks(JSContext* cx, JS::StartAsyncTaskCallback start, 4948 JS::FinishAsyncTaskCallback finish) 4949 { 4950 cx->startAsyncTaskCallback = start; 4951 cx->finishAsyncTaskCallback = finish; 4952 } 4953 4954 JS_PUBLIC_API(void) 4955 JS_RequestInterruptCallback(JSContext* cx) 4956 { 4957 cx->requestInterrupt(JSRuntime::RequestInterruptUrgent); 4958 } 4959 4960 JS_PUBLIC_API(bool) 4961 JS_IsRunning(JSContext* cx) 4962 { 4963 return cx->currentlyRunning(); 4964 } 4965 4966 JS::AutoSetAsyncStackForNewCalls::AutoSetAsyncStackForNewCalls( 4967 JSContext* cx, HandleObject stack, const char* asyncCause, 4968 JS::AutoSetAsyncStackForNewCalls::AsyncCallKind kind) 4969 : cx(cx), 4970 oldAsyncStack(cx, cx->asyncStackForNewActivations), 4971 oldAsyncCause(cx->asyncCauseForNewActivations), 4972 oldAsyncCallIsExplicit(cx->asyncCallIsExplicit) 4973 { 4974 CHECK_REQUEST(cx); 4975 4976 // The option determines whether we actually use the new values at this 4977 // point. It will not affect restoring the previous values when the object 4978 // is destroyed, so if the option changes it won't cause consistency issues. 4979 if (!cx->options().asyncStack()) 4980 return; 4981 4982 SavedFrame* asyncStack = &stack->as<SavedFrame>(); 4983 4984 cx->asyncStackForNewActivations = asyncStack; 4985 cx->asyncCauseForNewActivations = asyncCause; 4986 cx->asyncCallIsExplicit = kind == AsyncCallKind::EXPLICIT; 4987 } 4988 4989 JS::AutoSetAsyncStackForNewCalls::~AutoSetAsyncStackForNewCalls() 4990 { 4991 cx->asyncCauseForNewActivations = oldAsyncCause; 4992 cx->asyncStackForNewActivations = 4993 oldAsyncStack ? &oldAsyncStack->as<SavedFrame>() : nullptr; 4994 cx->asyncCallIsExplicit = oldAsyncCallIsExplicit; 4995 } 4996 4997 /************************************************************************/ 4998 JS_PUBLIC_API(JSString*) 4999 JS_NewStringCopyN(JSContext* cx, const char* s, size_t n) 5000 { 5001 AssertHeapIsIdle(cx); 5002 CHECK_REQUEST(cx); 5003 return NewStringCopyN<CanGC>(cx, s, n); 5004 } 5005 5006 JS_PUBLIC_API(JSString*) 5007 JS_NewStringCopyZ(JSContext* cx, const char* s) 5008 { 5009 AssertHeapIsIdle(cx); 5010 CHECK_REQUEST(cx); 5011 if (!s) 5012 return cx->runtime()->emptyString; 5013 return NewStringCopyZ<CanGC>(cx, s); 5014 } 5015 5016 JS_PUBLIC_API(JSString*) 5017 JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s) 5018 { 5019 AssertHeapIsIdle(cx); 5020 CHECK_REQUEST(cx); 5021 return NewStringCopyUTF8Z<CanGC>(cx, s); 5022 } 5023 5024 JS_PUBLIC_API(JSString*) 5025 JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s) 5026 { 5027 AssertHeapIsIdle(cx); 5028 CHECK_REQUEST(cx); 5029 return NewStringCopyUTF8N<CanGC>(cx, s); 5030 } 5031 5032 JS_PUBLIC_API(bool) 5033 JS_StringHasBeenPinned(JSContext* cx, JSString* str) 5034 { 5035 AssertHeapIsIdle(cx); 5036 CHECK_REQUEST(cx); 5037 5038 if (!str->isAtom()) 5039 return false; 5040 5041 return AtomIsPinned(cx, &str->asAtom()); 5042 } 5043 5044 JS_PUBLIC_API(jsid) 5045 INTERNED_STRING_TO_JSID(JSContext* cx, JSString* str) 5046 { 5047 MOZ_ASSERT(str); 5048 MOZ_ASSERT(((size_t)str & JSID_TYPE_MASK) == 0); 5049 MOZ_ASSERT_IF(cx, JS_StringHasBeenPinned(cx, str)); 5050 return AtomToId(&str->asAtom()); 5051 } 5052 5053 JS_PUBLIC_API(JSString*) 5054 JS_AtomizeAndPinJSString(JSContext* cx, HandleString str) 5055 { 5056 AssertHeapIsIdle(cx); 5057 CHECK_REQUEST(cx); 5058 JSAtom* atom = AtomizeString(cx, str, PinAtom); 5059 MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom)); 5060 return atom; 5061 } 5062 5063 JS_PUBLIC_API(JSString*) 5064 JS_AtomizeString(JSContext* cx, const char* s) 5065 { 5066 return JS_AtomizeStringN(cx, s, strlen(s)); 5067 } 5068 5069 JS_PUBLIC_API(JSString*) 5070 JS_AtomizeStringN(JSContext* cx, const char* s, size_t length) 5071 { 5072 AssertHeapIsIdle(cx); 5073 CHECK_REQUEST(cx); 5074 return Atomize(cx, s, length, DoNotPinAtom); 5075 } 5076 5077 JS_PUBLIC_API(JSString*) 5078 JS_AtomizeAndPinString(JSContext* cx, const char* s) 5079 { 5080 return JS_AtomizeAndPinStringN(cx, s, strlen(s)); 5081 } 5082 5083 JS_PUBLIC_API(JSString*) 5084 JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length) 5085 { 5086 AssertHeapIsIdle(cx); 5087 CHECK_REQUEST(cx); 5088 JSAtom* atom = Atomize(cx, s, length, PinAtom); 5089 MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom)); 5090 return atom; 5091 } 5092 5093 JS_PUBLIC_API(JSString*) 5094 JS_NewUCString(JSContext* cx, char16_t* chars, size_t length) 5095 { 5096 AssertHeapIsIdle(cx); 5097 CHECK_REQUEST(cx); 5098 return NewString<CanGC>(cx, chars, length); 5099 } 5100 5101 JS_PUBLIC_API(JSString*) 5102 JS_NewUCStringCopyN(JSContext* cx, const char16_t* s, size_t n) 5103 { 5104 AssertHeapIsIdle(cx); 5105 CHECK_REQUEST(cx); 5106 if (!n) 5107 return cx->names().empty; 5108 return NewStringCopyN<CanGC>(cx, s, n); 5109 } 5110 5111 JS_PUBLIC_API(JSString*) 5112 JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s) 5113 { 5114 AssertHeapIsIdle(cx); 5115 CHECK_REQUEST(cx); 5116 if (!s) 5117 return cx->runtime()->emptyString; 5118 return NewStringCopyZ<CanGC>(cx, s); 5119 } 5120 5121 JS_PUBLIC_API(JSString*) 5122 JS_AtomizeUCString(JSContext* cx, const char16_t* s) 5123 { 5124 return JS_AtomizeUCStringN(cx, s, js_strlen(s)); 5125 } 5126 5127 JS_PUBLIC_API(JSString*) 5128 JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length) 5129 { 5130 AssertHeapIsIdle(cx); 5131 CHECK_REQUEST(cx); 5132 return AtomizeChars(cx, s, length, DoNotPinAtom); 5133 } 5134 5135 JS_PUBLIC_API(JSString*) 5136 JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length) 5137 { 5138 AssertHeapIsIdle(cx); 5139 CHECK_REQUEST(cx); 5140 JSAtom* atom = AtomizeChars(cx, s, length, PinAtom); 5141 MOZ_ASSERT_IF(atom, JS_StringHasBeenPinned(cx, atom)); 5142 return atom; 5143 } 5144 5145 JS_PUBLIC_API(JSString*) 5146 JS_AtomizeAndPinUCString(JSContext* cx, const char16_t* s) 5147 { 5148 return JS_AtomizeAndPinUCStringN(cx, s, js_strlen(s)); 5149 } 5150 5151 JS_PUBLIC_API(size_t) 5152 JS_GetStringLength(JSString* str) 5153 { 5154 return str->length(); 5155 } 5156 5157 JS_PUBLIC_API(bool) 5158 JS_StringIsFlat(JSString* str) 5159 { 5160 return str->isFlat(); 5161 } 5162 5163 JS_PUBLIC_API(bool) 5164 JS_StringHasLatin1Chars(JSString* str) 5165 { 5166 return str->hasLatin1Chars(); 5167 } 5168 5169 JS_PUBLIC_API(const JS::Latin1Char*) 5170 JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str, 5171 size_t* plength) 5172 { 5173 MOZ_ASSERT(plength); 5174 AssertHeapIsIdleOrStringIsFlat(cx, str); 5175 CHECK_REQUEST(cx); 5176 assertSameCompartment(cx, str); 5177 JSLinearString* linear = str->ensureLinear(cx); 5178 if (!linear) 5179 return nullptr; 5180 *plength = linear->length(); 5181 return linear->latin1Chars(nogc); 5182 } 5183 5184 JS_PUBLIC_API(const char16_t*) 5185 JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str, 5186 size_t* plength) 5187 { 5188 MOZ_ASSERT(plength); 5189 AssertHeapIsIdleOrStringIsFlat(cx, str); 5190 CHECK_REQUEST(cx); 5191 assertSameCompartment(cx, str); 5192 JSLinearString* linear = str->ensureLinear(cx); 5193 if (!linear) 5194 return nullptr; 5195 *plength = linear->length(); 5196 return linear->twoByteChars(nogc); 5197 } 5198 5199 JS_PUBLIC_API(const char16_t*) 5200 JS_GetTwoByteExternalStringChars(JSString* str) 5201 { 5202 return str->asExternal().twoByteChars(); 5203 } 5204 5205 JS_PUBLIC_API(bool) 5206 JS_GetStringCharAt(JSContext* cx, JSString* str, size_t index, char16_t* res) 5207 { 5208 AssertHeapIsIdleOrStringIsFlat(cx, str); 5209 CHECK_REQUEST(cx); 5210 assertSameCompartment(cx, str); 5211 5212 JSLinearString* linear = str->ensureLinear(cx); 5213 if (!linear) 5214 return false; 5215 5216 *res = linear->latin1OrTwoByteChar(index); 5217 return true; 5218 } 5219 5220 JS_PUBLIC_API(char16_t) 5221 JS_GetFlatStringCharAt(JSFlatString* str, size_t index) 5222 { 5223 return str->latin1OrTwoByteChar(index); 5224 } 5225 5226 JS_PUBLIC_API(bool) 5227 JS_CopyStringChars(JSContext* cx, mozilla::Range<char16_t> dest, JSString* str) 5228 { 5229 AssertHeapIsIdleOrStringIsFlat(cx, str); 5230 CHECK_REQUEST(cx); 5231 assertSameCompartment(cx, str); 5232 5233 JSLinearString* linear = str->ensureLinear(cx); 5234 if (!linear) 5235 return false; 5236 5237 MOZ_ASSERT(linear->length() <= dest.length()); 5238 CopyChars(dest.begin().get(), *linear); 5239 return true; 5240 } 5241 5242 JS_PUBLIC_API(const Latin1Char*) 5243 JS_GetLatin1InternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str) 5244 { 5245 MOZ_ASSERT(str->isAtom()); 5246 JSFlatString* flat = str->ensureFlat(nullptr); 5247 if (!flat) 5248 return nullptr; 5249 return flat->latin1Chars(nogc); 5250 } 5251 5252 JS_PUBLIC_API(const char16_t*) 5253 JS_GetTwoByteInternedStringChars(const JS::AutoCheckCannotGC& nogc, JSString* str) 5254 { 5255 MOZ_ASSERT(str->isAtom()); 5256 JSFlatString* flat = str->ensureFlat(nullptr); 5257 if (!flat) 5258 return nullptr; 5259 return flat->twoByteChars(nogc); 5260 } 5261 5262 extern JS_PUBLIC_API(JSFlatString*) 5263 JS_FlattenString(JSContext* cx, JSString* str) 5264 { 5265 AssertHeapIsIdle(cx); 5266 CHECK_REQUEST(cx); 5267 assertSameCompartment(cx, str); 5268 JSFlatString* flat = str->ensureFlat(cx); 5269 if (!flat) 5270 return nullptr; 5271 return flat; 5272 } 5273 5274 extern JS_PUBLIC_API(const Latin1Char*) 5275 JS_GetLatin1FlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str) 5276 { 5277 return str->latin1Chars(nogc); 5278 } 5279 5280 extern JS_PUBLIC_API(const char16_t*) 5281 JS_GetTwoByteFlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str) 5282 { 5283 return str->twoByteChars(nogc); 5284 } 5285 5286 JS_PUBLIC_API(bool) 5287 JS_CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result) 5288 { 5289 AssertHeapIsIdle(cx); 5290 CHECK_REQUEST(cx); 5291 5292 return CompareStrings(cx, str1, str2, result); 5293 } 5294 5295 JS_PUBLIC_API(bool) 5296 JS_StringEqualsAscii(JSContext* cx, JSString* str, const char* asciiBytes, bool* match) 5297 { 5298 AssertHeapIsIdle(cx); 5299 CHECK_REQUEST(cx); 5300 5301 JSLinearString* linearStr = str->ensureLinear(cx); 5302 if (!linearStr) 5303 return false; 5304 *match = StringEqualsAscii(linearStr, asciiBytes); 5305 return true; 5306 } 5307 5308 JS_PUBLIC_API(bool) 5309 JS_FlatStringEqualsAscii(JSFlatString* str, const char* asciiBytes) 5310 { 5311 return StringEqualsAscii(str, asciiBytes); 5312 } 5313 5314 JS_PUBLIC_API(size_t) 5315 JS_PutEscapedFlatString(char* buffer, size_t size, JSFlatString* str, char quote) 5316 { 5317 return PutEscapedString(buffer, size, str, quote); 5318 } 5319 5320 JS_PUBLIC_API(size_t) 5321 JS_PutEscapedString(JSContext* cx, char* buffer, size_t size, JSString* str, char quote) 5322 { 5323 AssertHeapIsIdle(cx); 5324 JSLinearString* linearStr = str->ensureLinear(cx); 5325 if (!linearStr) 5326 return size_t(-1); 5327 return PutEscapedString(buffer, size, linearStr, quote); 5328 } 5329 5330 JS_PUBLIC_API(bool) 5331 JS_FileEscapedString(FILE* fp, JSString* str, char quote) 5332 { 5333 JSLinearString* linearStr = str->ensureLinear(nullptr); 5334 return linearStr && FileEscapedString(fp, linearStr, quote); 5335 } 5336 5337 JS_PUBLIC_API(JSString*) 5338 JS_NewDependentString(JSContext* cx, HandleString str, size_t start, size_t length) 5339 { 5340 AssertHeapIsIdle(cx); 5341 CHECK_REQUEST(cx); 5342 return NewDependentString(cx, str, start, length); 5343 } 5344 5345 JS_PUBLIC_API(JSString*) 5346 JS_ConcatStrings(JSContext* cx, HandleString left, HandleString right) 5347 { 5348 AssertHeapIsIdle(cx); 5349 CHECK_REQUEST(cx); 5350 return ConcatStrings<CanGC>(cx, left, right); 5351 } 5352 5353 JS_PUBLIC_API(bool) 5354 JS_DecodeBytes(JSContext* cx, const char* src, size_t srclen, char16_t* dst, size_t* dstlenp) 5355 { 5356 AssertHeapIsIdle(cx); 5357 CHECK_REQUEST(cx); 5358 5359 if (!dst) { 5360 *dstlenp = srclen; 5361 return true; 5362 } 5363 5364 size_t dstlen = *dstlenp; 5365 5366 if (srclen > dstlen) { 5367 CopyAndInflateChars(dst, src, dstlen); 5368 5369 AutoSuppressGC suppress(cx); 5370 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BUFFER_TOO_SMALL); 5371 return false; 5372 } 5373 5374 CopyAndInflateChars(dst, src, srclen); 5375 *dstlenp = srclen; 5376 return true; 5377 } 5378 5379 static char* 5380 EncodeLatin1(ExclusiveContext* cx, JSString* str) 5381 { 5382 JSLinearString* linear = str->ensureLinear(cx); 5383 if (!linear) 5384 return nullptr; 5385 5386 JS::AutoCheckCannotGC nogc; 5387 if (linear->hasTwoByteChars()) 5388 return JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->twoByteRange(nogc)).c_str(); 5389 5390 size_t len = str->length(); 5391 Latin1Char* buf = cx->pod_malloc<Latin1Char>(len + 1); 5392 if (!buf) { 5393 ReportOutOfMemory(cx); 5394 return nullptr; 5395 } 5396 5397 mozilla::PodCopy(buf, linear->latin1Chars(nogc), len); 5398 buf[len] = '\0'; 5399 return reinterpret_cast<char*>(buf); 5400 } 5401 5402 JS_PUBLIC_API(char*) 5403 JS_EncodeString(JSContext* cx, JSString* str) 5404 { 5405 AssertHeapIsIdle(cx); 5406 CHECK_REQUEST(cx); 5407 5408 return EncodeLatin1(cx, str); 5409 } 5410 5411 JS_PUBLIC_API(char*) 5412 JS_EncodeStringToUTF8(JSContext* cx, HandleString str) 5413 { 5414 AssertHeapIsIdle(cx); 5415 CHECK_REQUEST(cx); 5416 5417 return StringToNewUTF8CharsZ(cx, *str).release(); 5418 } 5419 5420 JS_PUBLIC_API(size_t) 5421 JS_GetStringEncodingLength(JSContext* cx, JSString* str) 5422 { 5423 AssertHeapIsIdle(cx); 5424 CHECK_REQUEST(cx); 5425 5426 if (!str->ensureLinear(cx)) 5427 return size_t(-1); 5428 return str->length(); 5429 } 5430 5431 JS_PUBLIC_API(size_t) 5432 JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length) 5433 { 5434 AssertHeapIsIdle(cx); 5435 CHECK_REQUEST(cx); 5436 5437 /* 5438 * FIXME bug 612141 - fix DeflateStringToBuffer interface so the result 5439 * would allow to distinguish between insufficient buffer and encoding 5440 * error. 5441 */ 5442 size_t writtenLength = length; 5443 JSLinearString* linear = str->ensureLinear(cx); 5444 if (!linear) 5445 return size_t(-1); 5446 5447 bool res; 5448 if (linear->hasLatin1Chars()) { 5449 JS::AutoCheckCannotGC nogc; 5450 res = DeflateStringToBuffer(nullptr, linear->latin1Chars(nogc), linear->length(), buffer, 5451 &writtenLength); 5452 } else { 5453 JS::AutoCheckCannotGC nogc; 5454 res = DeflateStringToBuffer(nullptr, linear->twoByteChars(nogc), linear->length(), buffer, 5455 &writtenLength); 5456 } 5457 if (res) { 5458 MOZ_ASSERT(writtenLength <= length); 5459 return writtenLength; 5460 } 5461 MOZ_ASSERT(writtenLength <= length); 5462 size_t necessaryLength = str->length(); 5463 if (necessaryLength == size_t(-1)) 5464 return size_t(-1); 5465 MOZ_ASSERT(writtenLength == length); // C strings are NOT encoded. 5466 return necessaryLength; 5467 } 5468 5469 JS_PUBLIC_API(JS::Symbol*) 5470 JS::NewSymbol(JSContext* cx, HandleString description) 5471 { 5472 AssertHeapIsIdle(cx); 5473 CHECK_REQUEST(cx); 5474 if (description) 5475 assertSameCompartment(cx, description); 5476 5477 return Symbol::new_(cx, SymbolCode::UniqueSymbol, description); 5478 } 5479 5480 JS_PUBLIC_API(JS::Symbol*) 5481 JS::GetSymbolFor(JSContext* cx, HandleString key) 5482 { 5483 AssertHeapIsIdle(cx); 5484 CHECK_REQUEST(cx); 5485 assertSameCompartment(cx, key); 5486 5487 return Symbol::for_(cx, key); 5488 } 5489 5490 JS_PUBLIC_API(JSString*) 5491 JS::GetSymbolDescription(HandleSymbol symbol) 5492 { 5493 return symbol->description(); 5494 } 5495 5496 JS_PUBLIC_API(JS::SymbolCode) 5497 JS::GetSymbolCode(Handle<Symbol*> symbol) 5498 { 5499 return symbol->code(); 5500 } 5501 5502 JS_PUBLIC_API(JS::Symbol*) 5503 JS::GetWellKnownSymbol(JSContext* cx, JS::SymbolCode which) 5504 { 5505 return cx->wellKnownSymbols().get(uint32_t(which)); 5506 } 5507 5508 #ifdef DEBUG 5509 static bool 5510 PropertySpecNameIsDigits(const char* s) { 5511 if (JS::PropertySpecNameIsSymbol(s)) 5512 return false; 5513 if (!*s) 5514 return false; 5515 for (; *s; s++) { 5516 if (*s < '0' || *s > '9') 5517 return false; 5518 } 5519 return true; 5520 } 5521 #endif // DEBUG 5522 5523 JS_PUBLIC_API(bool) 5524 JS::PropertySpecNameEqualsId(const char* name, HandleId id) 5525 { 5526 if (JS::PropertySpecNameIsSymbol(name)) { 5527 if (!JSID_IS_SYMBOL(id)) 5528 return false; 5529 Symbol* sym = JSID_TO_SYMBOL(id); 5530 return sym->isWellKnownSymbol() && sym->code() == PropertySpecNameToSymbolCode(name); 5531 } 5532 5533 MOZ_ASSERT(!PropertySpecNameIsDigits(name)); 5534 return JSID_IS_ATOM(id) && JS_FlatStringEqualsAscii(JSID_TO_ATOM(id), name); 5535 } 5536 5537 JS_PUBLIC_API(bool) 5538 JS_Stringify(JSContext* cx, MutableHandleValue vp, HandleObject replacer, 5539 HandleValue space, JSONWriteCallback callback, void* data) 5540 { 5541 AssertHeapIsIdle(cx); 5542 CHECK_REQUEST(cx); 5543 assertSameCompartment(cx, replacer, space); 5544 StringBuffer sb(cx); 5545 if (!sb.ensureTwoByteChars()) 5546 return false; 5547 if (!Stringify(cx, vp, replacer, space, sb, StringifyBehavior::Normal)) 5548 return false; 5549 if (sb.empty() && !sb.append(cx->names().null)) 5550 return false; 5551 return callback(sb.rawTwoByteBegin(), sb.length(), data); 5552 } 5553 5554 JS_PUBLIC_API(bool) 5555 JS::ToJSONMaybeSafely(JSContext* cx, JS::HandleObject input, 5556 JSONWriteCallback callback, void* data) 5557 { 5558 AssertHeapIsIdle(cx); 5559 CHECK_REQUEST(cx); 5560 assertSameCompartment(cx, input); 5561 5562 StringBuffer sb(cx); 5563 if (!sb.ensureTwoByteChars()) 5564 return false; 5565 5566 RootedValue inputValue(cx, ObjectValue(*input)); 5567 if (!Stringify(cx, &inputValue, nullptr, NullHandleValue, sb, 5568 StringifyBehavior::RestrictedSafe)) 5569 return false; 5570 5571 if (sb.empty() && !sb.append(cx->names().null)) 5572 return false; 5573 5574 return callback(sb.rawTwoByteBegin(), sb.length(), data); 5575 } 5576 5577 JS_PUBLIC_API(bool) 5578 JS_ParseJSON(JSContext* cx, const char16_t* chars, uint32_t len, MutableHandleValue vp) 5579 { 5580 AssertHeapIsIdle(cx); 5581 CHECK_REQUEST(cx); 5582 return ParseJSONWithReviver(cx, mozilla::Range<const char16_t>(chars, len), NullHandleValue, vp); 5583 } 5584 5585 JS_PUBLIC_API(bool) 5586 JS_ParseJSON(JSContext* cx, HandleString str, MutableHandleValue vp) 5587 { 5588 return JS_ParseJSONWithReviver(cx, str, NullHandleValue, vp); 5589 } 5590 5591 JS_PUBLIC_API(bool) 5592 JS_ParseJSONWithReviver(JSContext* cx, const char16_t* chars, uint32_t len, HandleValue reviver, MutableHandleValue vp) 5593 { 5594 AssertHeapIsIdle(cx); 5595 CHECK_REQUEST(cx); 5596 return ParseJSONWithReviver(cx, mozilla::Range<const char16_t>(chars, len), reviver, vp); 5597 } 5598 5599 JS_PUBLIC_API(bool) 5600 JS_ParseJSONWithReviver(JSContext* cx, HandleString str, HandleValue reviver, MutableHandleValue vp) 5601 { 5602 AssertHeapIsIdle(cx); 5603 CHECK_REQUEST(cx); 5604 assertSameCompartment(cx, str); 5605 5606 AutoStableStringChars stableChars(cx); 5607 if (!stableChars.init(cx, str)) 5608 return false; 5609 5610 return stableChars.isLatin1() 5611 ? ParseJSONWithReviver(cx, stableChars.latin1Range(), reviver, vp) 5612 : ParseJSONWithReviver(cx, stableChars.twoByteRange(), reviver, vp); 5613 } 5614 5615 /************************************************************************/ 5616 5617 JS_PUBLIC_API(void) 5618 JS_ReportErrorASCII(JSContext* cx, const char* format, ...) 5619 { 5620 va_list ap; 5621 5622 AssertHeapIsIdle(cx); 5623 va_start(ap, format); 5624 ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreASCII, ap); 5625 va_end(ap); 5626 } 5627 5628 JS_PUBLIC_API(void) 5629 JS_ReportErrorLatin1(JSContext* cx, const char* format, ...) 5630 { 5631 va_list ap; 5632 5633 AssertHeapIsIdle(cx); 5634 va_start(ap, format); 5635 ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreLatin1, ap); 5636 va_end(ap); 5637 } 5638 5639 JS_PUBLIC_API(void) 5640 JS_ReportErrorUTF8(JSContext* cx, const char* format, ...) 5641 { 5642 va_list ap; 5643 5644 AssertHeapIsIdle(cx); 5645 va_start(ap, format); 5646 ReportErrorVA(cx, JSREPORT_ERROR, format, ArgumentsAreUTF8, ap); 5647 va_end(ap); 5648 } 5649 5650 JS_PUBLIC_API(void) 5651 JS_ReportErrorNumberASCII(JSContext* cx, JSErrorCallback errorCallback, 5652 void* userRef, const unsigned errorNumber, ...) 5653 { 5654 va_list ap; 5655 va_start(ap, errorNumber); 5656 JS_ReportErrorNumberASCIIVA(cx, errorCallback, userRef, errorNumber, ap); 5657 va_end(ap); 5658 } 5659 5660 JS_PUBLIC_API(void) 5661 JS_ReportErrorNumberASCIIVA(JSContext* cx, JSErrorCallback errorCallback, 5662 void* userRef, const unsigned errorNumber, 5663 va_list ap) 5664 { 5665 AssertHeapIsIdle(cx); 5666 ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, 5667 errorNumber, ArgumentsAreASCII, ap); 5668 } 5669 5670 JS_PUBLIC_API(void) 5671 JS_ReportErrorNumberLatin1(JSContext* cx, JSErrorCallback errorCallback, 5672 void* userRef, const unsigned errorNumber, ...) 5673 { 5674 va_list ap; 5675 va_start(ap, errorNumber); 5676 JS_ReportErrorNumberLatin1VA(cx, errorCallback, userRef, errorNumber, ap); 5677 va_end(ap); 5678 } 5679 5680 JS_PUBLIC_API(void) 5681 JS_ReportErrorNumberLatin1VA(JSContext* cx, JSErrorCallback errorCallback, 5682 void* userRef, const unsigned errorNumber, 5683 va_list ap) 5684 { 5685 AssertHeapIsIdle(cx); 5686 ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, 5687 errorNumber, ArgumentsAreLatin1, ap); 5688 } 5689 5690 JS_PUBLIC_API(void) 5691 JS_ReportErrorNumberUTF8(JSContext* cx, JSErrorCallback errorCallback, 5692 void* userRef, const unsigned errorNumber, ...) 5693 { 5694 va_list ap; 5695 va_start(ap, errorNumber); 5696 JS_ReportErrorNumberUTF8VA(cx, errorCallback, userRef, errorNumber, ap); 5697 va_end(ap); 5698 } 5699 5700 JS_PUBLIC_API(void) 5701 JS_ReportErrorNumberUTF8VA(JSContext* cx, JSErrorCallback errorCallback, 5702 void* userRef, const unsigned errorNumber, 5703 va_list ap) 5704 { 5705 AssertHeapIsIdle(cx); 5706 ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, 5707 errorNumber, ArgumentsAreUTF8, ap); 5708 } 5709 5710 JS_PUBLIC_API(void) 5711 JS_ReportErrorNumberUC(JSContext* cx, JSErrorCallback errorCallback, 5712 void* userRef, const unsigned errorNumber, ...) 5713 { 5714 va_list ap; 5715 5716 AssertHeapIsIdle(cx); 5717 va_start(ap, errorNumber); 5718 ReportErrorNumberVA(cx, JSREPORT_ERROR, errorCallback, userRef, 5719 errorNumber, ArgumentsAreUnicode, ap); 5720 va_end(ap); 5721 } 5722 5723 JS_PUBLIC_API(void) 5724 JS_ReportErrorNumberUCArray(JSContext* cx, JSErrorCallback errorCallback, 5725 void* userRef, const unsigned errorNumber, 5726 const char16_t** args) 5727 { 5728 AssertHeapIsIdle(cx); 5729 ReportErrorNumberUCArray(cx, JSREPORT_ERROR, errorCallback, userRef, 5730 errorNumber, args); 5731 } 5732 5733 JS_PUBLIC_API(bool) 5734 JS_ReportWarningASCII(JSContext* cx, const char* format, ...) 5735 { 5736 va_list ap; 5737 bool ok; 5738 5739 AssertHeapIsIdle(cx); 5740 va_start(ap, format); 5741 ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreASCII, ap); 5742 va_end(ap); 5743 return ok; 5744 } 5745 5746 JS_PUBLIC_API(bool) 5747 JS_ReportWarningLatin1(JSContext* cx, const char* format, ...) 5748 { 5749 va_list ap; 5750 bool ok; 5751 5752 AssertHeapIsIdle(cx); 5753 va_start(ap, format); 5754 ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreLatin1, ap); 5755 va_end(ap); 5756 return ok; 5757 } 5758 5759 JS_PUBLIC_API(bool) 5760 JS_ReportWarningUTF8(JSContext* cx, const char* format, ...) 5761 { 5762 va_list ap; 5763 bool ok; 5764 5765 AssertHeapIsIdle(cx); 5766 va_start(ap, format); 5767 ok = ReportErrorVA(cx, JSREPORT_WARNING, format, ArgumentsAreUTF8, ap); 5768 va_end(ap); 5769 return ok; 5770 } 5771 5772 JS_PUBLIC_API(bool) 5773 JS_ReportErrorFlagsAndNumberASCII(JSContext* cx, unsigned flags, 5774 JSErrorCallback errorCallback, void* userRef, 5775 const unsigned errorNumber, ...) 5776 { 5777 va_list ap; 5778 bool ok; 5779 5780 AssertHeapIsIdle(cx); 5781 va_start(ap, errorNumber); 5782 ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef, 5783 errorNumber, ArgumentsAreASCII, ap); 5784 va_end(ap); 5785 return ok; 5786 } 5787 5788 JS_PUBLIC_API(bool) 5789 JS_ReportErrorFlagsAndNumberLatin1(JSContext* cx, unsigned flags, 5790 JSErrorCallback errorCallback, void* userRef, 5791 const unsigned errorNumber, ...) 5792 { 5793 va_list ap; 5794 bool ok; 5795 5796 AssertHeapIsIdle(cx); 5797 va_start(ap, errorNumber); 5798 ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef, 5799 errorNumber, ArgumentsAreLatin1, ap); 5800 va_end(ap); 5801 return ok; 5802 } 5803 5804 JS_PUBLIC_API(bool) 5805 JS_ReportErrorFlagsAndNumberUTF8(JSContext* cx, unsigned flags, 5806 JSErrorCallback errorCallback, void* userRef, 5807 const unsigned errorNumber, ...) 5808 { 5809 va_list ap; 5810 bool ok; 5811 5812 AssertHeapIsIdle(cx); 5813 va_start(ap, errorNumber); 5814 ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef, 5815 errorNumber, ArgumentsAreUTF8, ap); 5816 va_end(ap); 5817 return ok; 5818 } 5819 5820 JS_PUBLIC_API(bool) 5821 JS_ReportErrorFlagsAndNumberUC(JSContext* cx, unsigned flags, 5822 JSErrorCallback errorCallback, void* userRef, 5823 const unsigned errorNumber, ...) 5824 { 5825 va_list ap; 5826 bool ok; 5827 5828 AssertHeapIsIdle(cx); 5829 va_start(ap, errorNumber); 5830 ok = ReportErrorNumberVA(cx, flags, errorCallback, userRef, 5831 errorNumber, ArgumentsAreUnicode, ap); 5832 va_end(ap); 5833 return ok; 5834 } 5835 5836 JS_PUBLIC_API(void) 5837 JS_ReportOutOfMemory(JSContext* cx) 5838 { 5839 ReportOutOfMemory(cx); 5840 } 5841 5842 JS_PUBLIC_API(void) 5843 JS_ReportAllocationOverflow(JSContext* cx) 5844 { 5845 ReportAllocationOverflow(cx); 5846 } 5847 5848 JS_PUBLIC_API(JS::WarningReporter) 5849 JS::GetWarningReporter(JSContext* cx) 5850 { 5851 return cx->warningReporter; 5852 } 5853 5854 JS_PUBLIC_API(JS::WarningReporter) 5855 JS::SetWarningReporter(JSContext* cx, JS::WarningReporter reporter) 5856 { 5857 WarningReporter older = cx->warningReporter; 5858 cx->warningReporter = reporter; 5859 return older; 5860 } 5861 5862 /************************************************************************/ 5863 5864 /* 5865 * Dates. 5866 */ 5867 JS_PUBLIC_API(JSObject*) 5868 JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min, int sec) 5869 { 5870 AssertHeapIsIdle(cx); 5871 CHECK_REQUEST(cx); 5872 return NewDateObject(cx, year, mon, mday, hour, min, sec); 5873 } 5874 5875 JS_PUBLIC_API(JSObject*) 5876 JS::NewDateObject(JSContext* cx, JS::ClippedTime time) 5877 { 5878 AssertHeapIsIdle(cx); 5879 CHECK_REQUEST(cx); 5880 return NewDateObjectMsec(cx, time); 5881 } 5882 5883 JS_PUBLIC_API(bool) 5884 JS_ObjectIsDate(JSContext* cx, HandleObject obj, bool* isDate) 5885 { 5886 assertSameCompartment(cx, obj); 5887 5888 ESClass cls; 5889 if (!GetBuiltinClass(cx, obj, &cls)) 5890 return false; 5891 5892 *isDate = cls == ESClass::Date; 5893 return true; 5894 } 5895 5896 /************************************************************************/ 5897 5898 /* 5899 * Regular Expressions. 5900 */ 5901 JS_PUBLIC_API(JSObject*) 5902 JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags) 5903 { 5904 AssertHeapIsIdle(cx); 5905 CHECK_REQUEST(cx); 5906 ScopedJSFreePtr<char16_t> chars(InflateString(cx, bytes, &length)); 5907 if (!chars) 5908 return nullptr; 5909 5910 RegExpObject* reobj = RegExpObject::create(cx, chars, length, 5911 RegExpFlag(flags), nullptr, cx->tempLifoAlloc()); 5912 return reobj; 5913 } 5914 5915 JS_PUBLIC_API(JSObject*) 5916 JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags) 5917 { 5918 AssertHeapIsIdle(cx); 5919 CHECK_REQUEST(cx); 5920 return RegExpObject::create(cx, chars, length, 5921 RegExpFlag(flags), nullptr, cx->tempLifoAlloc()); 5922 } 5923 5924 JS_PUBLIC_API(bool) 5925 JS_SetRegExpInput(JSContext* cx, HandleObject obj, HandleString input) 5926 { 5927 AssertHeapIsIdle(cx); 5928 CHECK_REQUEST(cx); 5929 assertSameCompartment(cx, input); 5930 5931 RegExpStatics* res = obj->as<GlobalObject>().getRegExpStatics(cx); 5932 if (!res) 5933 return false; 5934 5935 res->reset(cx, input); 5936 return true; 5937 } 5938 5939 JS_PUBLIC_API(bool) 5940 JS_ClearRegExpStatics(JSContext* cx, HandleObject obj) 5941 { 5942 AssertHeapIsIdle(cx); 5943 CHECK_REQUEST(cx); 5944 MOZ_ASSERT(obj); 5945 5946 RegExpStatics* res = obj->as<GlobalObject>().getRegExpStatics(cx); 5947 if (!res) 5948 return false; 5949 5950 res->clear(); 5951 return true; 5952 } 5953 5954 JS_PUBLIC_API(bool) 5955 JS_ExecuteRegExp(JSContext* cx, HandleObject obj, HandleObject reobj, char16_t* chars, 5956 size_t length, size_t* indexp, bool test, MutableHandleValue rval) 5957 { 5958 AssertHeapIsIdle(cx); 5959 CHECK_REQUEST(cx); 5960 5961 RegExpStatics* res = obj->as<GlobalObject>().getRegExpStatics(cx); 5962 if (!res) 5963 return false; 5964 5965 RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length)); 5966 if (!input) 5967 return false; 5968 5969 return ExecuteRegExpLegacy(cx, res, reobj->as<RegExpObject>(), input, indexp, test, rval); 5970 } 5971 5972 JS_PUBLIC_API(bool) 5973 JS_ExecuteRegExpNoStatics(JSContext* cx, HandleObject obj, char16_t* chars, size_t length, 5974 size_t* indexp, bool test, MutableHandleValue rval) 5975 { 5976 AssertHeapIsIdle(cx); 5977 CHECK_REQUEST(cx); 5978 5979 RootedLinearString input(cx, NewStringCopyN<CanGC>(cx, chars, length)); 5980 if (!input) 5981 return false; 5982 5983 return ExecuteRegExpLegacy(cx, nullptr, obj->as<RegExpObject>(), input, indexp, test, 5984 rval); 5985 } 5986 5987 JS_PUBLIC_API(bool) 5988 JS_ObjectIsRegExp(JSContext* cx, HandleObject obj, bool* isRegExp) 5989 { 5990 assertSameCompartment(cx, obj); 5991 5992 ESClass cls; 5993 if (!GetBuiltinClass(cx, obj, &cls)) 5994 return false; 5995 5996 *isRegExp = cls == ESClass::RegExp; 5997 return true; 5998 } 5999 6000 JS_PUBLIC_API(unsigned) 6001 JS_GetRegExpFlags(JSContext* cx, HandleObject obj) 6002 { 6003 AssertHeapIsIdle(cx); 6004 CHECK_REQUEST(cx); 6005 6006 RegExpGuard shared(cx); 6007 if (!RegExpToShared(cx, obj, &shared)) 6008 return false; 6009 return shared.re()->getFlags(); 6010 } 6011 6012 JS_PUBLIC_API(JSString*) 6013 JS_GetRegExpSource(JSContext* cx, HandleObject obj) 6014 { 6015 AssertHeapIsIdle(cx); 6016 CHECK_REQUEST(cx); 6017 6018 RegExpGuard shared(cx); 6019 if (!RegExpToShared(cx, obj, &shared)) 6020 return nullptr; 6021 return shared.re()->getSource(); 6022 } 6023 6024 /************************************************************************/ 6025 6026 JS_PUBLIC_API(bool) 6027 JS_SetDefaultLocale(JSContext* cx, const char* locale) 6028 { 6029 AssertHeapIsIdle(cx); 6030 return cx->setDefaultLocale(locale); 6031 } 6032 6033 JS_PUBLIC_API(UniqueChars) 6034 JS_GetDefaultLocale(JSContext* cx) 6035 { 6036 AssertHeapIsIdle(cx); 6037 if (const char* locale = cx->getDefaultLocale()) 6038 return UniqueChars(JS_strdup(cx, locale)); 6039 6040 return nullptr; 6041 } 6042 6043 JS_PUBLIC_API(void) 6044 JS_ResetDefaultLocale(JSContext* cx) 6045 { 6046 AssertHeapIsIdle(cx); 6047 cx->resetDefaultLocale(); 6048 } 6049 6050 JS_PUBLIC_API(void) 6051 JS_SetLocaleCallbacks(JSContext* cx, const JSLocaleCallbacks* callbacks) 6052 { 6053 AssertHeapIsIdle(cx); 6054 cx->localeCallbacks = callbacks; 6055 } 6056 6057 JS_PUBLIC_API(const JSLocaleCallbacks*) 6058 JS_GetLocaleCallbacks(JSContext* cx) 6059 { 6060 /* This function can be called by a finalizer. */ 6061 return cx->localeCallbacks; 6062 } 6063 6064 /************************************************************************/ 6065 6066 JS_PUBLIC_API(bool) 6067 JS_IsExceptionPending(JSContext* cx) 6068 { 6069 /* This function can be called by a finalizer. */ 6070 return (bool) cx->isExceptionPending(); 6071 } 6072 6073 JS_PUBLIC_API(bool) 6074 JS_GetPendingException(JSContext* cx, MutableHandleValue vp) 6075 { 6076 AssertHeapIsIdle(cx); 6077 CHECK_REQUEST(cx); 6078 if (!cx->isExceptionPending()) 6079 return false; 6080 return cx->getPendingException(vp); 6081 } 6082 6083 JS_PUBLIC_API(void) 6084 JS_SetPendingException(JSContext* cx, HandleValue value) 6085 { 6086 AssertHeapIsIdle(cx); 6087 CHECK_REQUEST(cx); 6088 assertSameCompartment(cx, value); 6089 cx->setPendingException(value); 6090 } 6091 6092 JS_PUBLIC_API(void) 6093 JS_ClearPendingException(JSContext* cx) 6094 { 6095 AssertHeapIsIdle(cx); 6096 cx->clearPendingException(); 6097 } 6098 6099 JS::AutoSaveExceptionState::AutoSaveExceptionState(JSContext* cx) 6100 : context(cx), 6101 wasPropagatingForcedReturn(cx->propagatingForcedReturn_), 6102 wasOverRecursed(cx->overRecursed_), 6103 wasThrowing(cx->throwing), 6104 exceptionValue(cx) 6105 { 6106 AssertHeapIsIdle(cx); 6107 CHECK_REQUEST(cx); 6108 if (wasPropagatingForcedReturn) 6109 cx->clearPropagatingForcedReturn(); 6110 if (wasOverRecursed) 6111 cx->overRecursed_ = false; 6112 if (wasThrowing) { 6113 exceptionValue = cx->unwrappedException_; 6114 cx->clearPendingException(); 6115 } 6116 } 6117 6118 void 6119 JS::AutoSaveExceptionState::restore() 6120 { 6121 context->propagatingForcedReturn_ = wasPropagatingForcedReturn; 6122 context->overRecursed_ = wasOverRecursed; 6123 context->throwing = wasThrowing; 6124 context->unwrappedException_ = exceptionValue; 6125 drop(); 6126 } 6127 6128 JS::AutoSaveExceptionState::~AutoSaveExceptionState() 6129 { 6130 if (!context->isExceptionPending()) { 6131 if (wasPropagatingForcedReturn) 6132 context->setPropagatingForcedReturn(); 6133 if (wasThrowing) { 6134 context->overRecursed_ = wasOverRecursed; 6135 context->throwing = true; 6136 context->unwrappedException_ = exceptionValue; 6137 } 6138 } 6139 } 6140 6141 struct JSExceptionState { 6142 explicit JSExceptionState(JSContext* cx) : exception(cx) {} 6143 bool throwing; 6144 PersistentRootedValue exception; 6145 }; 6146 6147 JS_PUBLIC_API(JSExceptionState*) 6148 JS_SaveExceptionState(JSContext* cx) 6149 { 6150 JSExceptionState* state; 6151 6152 AssertHeapIsIdle(cx); 6153 CHECK_REQUEST(cx); 6154 state = cx->new_<JSExceptionState>(cx); 6155 if (state) 6156 state->throwing = JS_GetPendingException(cx, &state->exception); 6157 return state; 6158 } 6159 6160 JS_PUBLIC_API(void) 6161 JS_RestoreExceptionState(JSContext* cx, JSExceptionState* state) 6162 { 6163 AssertHeapIsIdle(cx); 6164 CHECK_REQUEST(cx); 6165 if (state) { 6166 if (state->throwing) 6167 JS_SetPendingException(cx, state->exception); 6168 else 6169 JS_ClearPendingException(cx); 6170 JS_DropExceptionState(cx, state); 6171 } 6172 } 6173 6174 JS_PUBLIC_API(void) 6175 JS_DropExceptionState(JSContext* cx, JSExceptionState* state) 6176 { 6177 AssertHeapIsIdle(cx); 6178 CHECK_REQUEST(cx); 6179 js_delete(state); 6180 } 6181 6182 JS_PUBLIC_API(JSErrorReport*) 6183 JS_ErrorFromException(JSContext* cx, HandleObject obj) 6184 { 6185 AssertHeapIsIdle(cx); 6186 CHECK_REQUEST(cx); 6187 assertSameCompartment(cx, obj); 6188 return ErrorFromException(cx, obj); 6189 } 6190 6191 void 6192 JSErrorReport::initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, 6193 size_t tokenOffsetArg) 6194 { 6195 MOZ_ASSERT(linebufArg); 6196 MOZ_ASSERT(tokenOffsetArg <= linebufLengthArg); 6197 MOZ_ASSERT(linebufArg[linebufLengthArg] == '\0'); 6198 6199 linebuf_ = linebufArg; 6200 linebufLength_ = linebufLengthArg; 6201 tokenOffset_ = tokenOffsetArg; 6202 } 6203 6204 void 6205 JSErrorReport::freeLinebuf() 6206 { 6207 if (ownsLinebuf_ && linebuf_) { 6208 js_free((void*)linebuf_); 6209 ownsLinebuf_ = false; 6210 } 6211 linebuf_ = nullptr; 6212 } 6213 6214 JSString* 6215 JSErrorReport::newMessageString(JSContext* cx) 6216 { 6217 if (!message_) 6218 return cx->runtime()->emptyString; 6219 6220 return JS_NewStringCopyUTF8Z(cx, message_); 6221 } 6222 6223 void 6224 JSErrorReport::freeMessage() 6225 { 6226 if (ownsMessage_) { 6227 js_free((void*)message_.get()); 6228 ownsMessage_ = false; 6229 } 6230 message_ = JS::ConstUTF8CharsZ(); 6231 } 6232 6233 JS_PUBLIC_API(bool) 6234 JS_ThrowStopIteration(JSContext* cx) 6235 { 6236 AssertHeapIsIdle(cx); 6237 return ThrowStopIteration(cx); 6238 } 6239 6240 JS_PUBLIC_API(bool) 6241 JS_IsStopIteration(const Value& v) 6242 { 6243 return v.isObject() && v.toObject().is<StopIterationObject>(); 6244 } 6245 6246 extern MOZ_NEVER_INLINE JS_PUBLIC_API(void) 6247 JS_AbortIfWrongThread(JSContext* cx) 6248 { 6249 if (!CurrentThreadCanAccessRuntime(cx)) 6250 MOZ_CRASH(); 6251 if (!js::TlsPerThreadData.get()->associatedWith(cx)) 6252 MOZ_CRASH(); 6253 } 6254 6255 #ifdef JS_GC_ZEAL 6256 JS_PUBLIC_API(void) 6257 JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled) 6258 { 6259 cx->runtime()->gc.getZealBits(zealBits, frequency, nextScheduled); 6260 } 6261 6262 JS_PUBLIC_API(void) 6263 JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency) 6264 { 6265 cx->gc.setZeal(zeal, frequency); 6266 } 6267 6268 JS_PUBLIC_API(void) 6269 JS_ScheduleGC(JSContext* cx, uint32_t count) 6270 { 6271 cx->runtime()->gc.setNextScheduled(count); 6272 } 6273 #endif 6274 6275 JS_PUBLIC_API(void) 6276 JS_SetParallelParsingEnabled(JSContext* cx, bool enabled) 6277 { 6278 cx->setParallelParsingEnabled(enabled); 6279 } 6280 6281 JS_PUBLIC_API(void) 6282 JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled) 6283 { 6284 cx->setOffthreadIonCompilationEnabled(enabled); 6285 } 6286 6287 JS_PUBLIC_API(void) 6288 JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t value) 6289 { 6290 JSRuntime* rt = cx->runtime(); 6291 switch (opt) { 6292 case JSJITCOMPILER_BASELINE_WARMUP_TRIGGER: 6293 if (value == uint32_t(-1)) { 6294 jit::DefaultJitOptions defaultValues; 6295 value = defaultValues.baselineWarmUpThreshold; 6296 } 6297 jit::JitOptions.baselineWarmUpThreshold = value; 6298 break; 6299 case JSJITCOMPILER_ION_WARMUP_TRIGGER: 6300 if (value == uint32_t(-1)) { 6301 jit::JitOptions.resetCompilerWarmUpThreshold(); 6302 break; 6303 } 6304 jit::JitOptions.setCompilerWarmUpThreshold(value); 6305 if (value == 0) 6306 jit::JitOptions.setEagerCompilation(); 6307 break; 6308 case JSJITCOMPILER_ION_GVN_ENABLE: 6309 if (value == 0) { 6310 jit::JitOptions.enableGvn(false); 6311 JitSpew(js::jit::JitSpew_IonScripts, "Disable ion's GVN"); 6312 } else { 6313 jit::JitOptions.enableGvn(true); 6314 JitSpew(js::jit::JitSpew_IonScripts, "Enable ion's GVN"); 6315 } 6316 break; 6317 case JSJITCOMPILER_ION_FORCE_IC: 6318 if (value == 0) { 6319 jit::JitOptions.forceInlineCaches = false; 6320 JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable non-IC optimizations."); 6321 } else { 6322 jit::JitOptions.forceInlineCaches = true; 6323 JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable non-IC optimizations."); 6324 } 6325 break; 6326 case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS: 6327 if (value == 0) { 6328 jit::JitOptions.checkRangeAnalysis = false; 6329 JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Enable range analysis checks."); 6330 } else { 6331 jit::JitOptions.checkRangeAnalysis = true; 6332 JitSpew(js::jit::JitSpew_IonScripts, "IonBuilder: Disable range analysis checks."); 6333 } 6334 break; 6335 case JSJITCOMPILER_ION_ENABLE: 6336 if (value == 1) { 6337 JS::ContextOptionsRef(cx).setIon(true); 6338 JitSpew(js::jit::JitSpew_IonScripts, "Enable ion"); 6339 } else if (value == 0) { 6340 JS::ContextOptionsRef(cx).setIon(false); 6341 JitSpew(js::jit::JitSpew_IonScripts, "Disable ion"); 6342 } 6343 break; 6344 case JSJITCOMPILER_BASELINE_ENABLE: 6345 if (value == 1) { 6346 JS::ContextOptionsRef(cx).setBaseline(true); 6347 ReleaseAllJITCode(rt->defaultFreeOp()); 6348 JitSpew(js::jit::JitSpew_BaselineScripts, "Enable baseline"); 6349 } else if (value == 0) { 6350 JS::ContextOptionsRef(cx).setBaseline(false); 6351 ReleaseAllJITCode(rt->defaultFreeOp()); 6352 JitSpew(js::jit::JitSpew_BaselineScripts, "Disable baseline"); 6353 } 6354 break; 6355 case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE: 6356 if (value == 1) { 6357 rt->setOffthreadIonCompilationEnabled(true); 6358 JitSpew(js::jit::JitSpew_IonScripts, "Enable offthread compilation"); 6359 } else if (value == 0) { 6360 rt->setOffthreadIonCompilationEnabled(false); 6361 JitSpew(js::jit::JitSpew_IonScripts, "Disable offthread compilation"); 6362 } 6363 break; 6364 case JSJITCOMPILER_JUMP_THRESHOLD: 6365 if (value == uint32_t(-1)) { 6366 jit::DefaultJitOptions defaultValues; 6367 value = defaultValues.jumpThreshold; 6368 } 6369 jit::JitOptions.jumpThreshold = value; 6370 break; 6371 case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE: 6372 jit::JitOptions.asmJSAtomicsEnable = !!value; 6373 break; 6374 case JSJITCOMPILER_WASM_TEST_MODE: 6375 jit::JitOptions.wasmTestMode = !!value; 6376 break; 6377 case JSJITCOMPILER_WASM_FOLD_OFFSETS: 6378 jit::JitOptions.wasmFoldOffsets = !!value; 6379 break; 6380 case JSJITCOMPILER_ION_INTERRUPT_WITHOUT_SIGNAL: 6381 jit::JitOptions.ionInterruptWithoutSignals = !!value; 6382 break; 6383 default: 6384 break; 6385 } 6386 } 6387 6388 JS_PUBLIC_API(bool) 6389 JS_GetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t* valueOut) 6390 { 6391 MOZ_ASSERT(valueOut); 6392 #ifndef JS_CODEGEN_NONE 6393 JSRuntime* rt = cx->runtime(); 6394 switch (opt) { 6395 case JSJITCOMPILER_BASELINE_WARMUP_TRIGGER: 6396 *valueOut = jit::JitOptions.baselineWarmUpThreshold; 6397 break; 6398 case JSJITCOMPILER_ION_WARMUP_TRIGGER: 6399 *valueOut = jit::JitOptions.forcedDefaultIonWarmUpThreshold.isSome() 6400 ? jit::JitOptions.forcedDefaultIonWarmUpThreshold.ref() 6401 : jit::OptimizationInfo::CompilerWarmupThreshold; 6402 break; 6403 case JSJITCOMPILER_ION_FORCE_IC: 6404 *valueOut = jit::JitOptions.forceInlineCaches; 6405 break; 6406 case JSJITCOMPILER_ION_CHECK_RANGE_ANALYSIS: 6407 *valueOut = jit::JitOptions.checkRangeAnalysis; 6408 break; 6409 case JSJITCOMPILER_ION_ENABLE: 6410 *valueOut = JS::ContextOptionsRef(cx).ion(); 6411 break; 6412 case JSJITCOMPILER_BASELINE_ENABLE: 6413 *valueOut = JS::ContextOptionsRef(cx).baseline(); 6414 break; 6415 case JSJITCOMPILER_OFFTHREAD_COMPILATION_ENABLE: 6416 *valueOut = rt->canUseOffthreadIonCompilation(); 6417 break; 6418 case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE: 6419 *valueOut = jit::JitOptions.asmJSAtomicsEnable ? 1 : 0; 6420 break; 6421 case JSJITCOMPILER_WASM_TEST_MODE: 6422 *valueOut = jit::JitOptions.wasmTestMode ? 1 : 0; 6423 break; 6424 case JSJITCOMPILER_WASM_FOLD_OFFSETS: 6425 *valueOut = jit::JitOptions.wasmFoldOffsets ? 1 : 0; 6426 break; 6427 case JSJITCOMPILER_ION_INTERRUPT_WITHOUT_SIGNAL: 6428 *valueOut = jit::JitOptions.ionInterruptWithoutSignals ? 1 : 0; 6429 break; 6430 default: 6431 return false; 6432 } 6433 #else 6434 *valueOut = 0; 6435 #endif 6436 return true; 6437 } 6438 6439 /************************************************************************/ 6440 6441 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN) 6442 6443 #include "jswin.h" 6444 6445 /* 6446 * Initialization routine for the JS DLL. 6447 */ 6448 BOOL WINAPI DllMain (HINSTANCE hDLL, DWORD dwReason, LPVOID lpReserved) 6449 { 6450 return TRUE; 6451 } 6452 6453 #endif 6454 6455 JS_PUBLIC_API(bool) 6456 JS_IndexToId(JSContext* cx, uint32_t index, MutableHandleId id) 6457 { 6458 return IndexToId(cx, index, id); 6459 } 6460 6461 JS_PUBLIC_API(bool) 6462 JS_CharsToId(JSContext* cx, JS::TwoByteChars chars, MutableHandleId idp) 6463 { 6464 RootedAtom atom(cx, AtomizeChars(cx, chars.begin().get(), chars.length())); 6465 if (!atom) 6466 return false; 6467 #ifdef DEBUG 6468 uint32_t dummy; 6469 MOZ_ASSERT(!atom->isIndex(&dummy), "API misuse: |chars| must not encode an index"); 6470 #endif 6471 idp.set(AtomToId(atom)); 6472 return true; 6473 } 6474 6475 JS_PUBLIC_API(bool) 6476 JS_IsIdentifier(JSContext* cx, HandleString str, bool* isIdentifier) 6477 { 6478 assertSameCompartment(cx, str); 6479 6480 JSLinearString* linearStr = str->ensureLinear(cx); 6481 if (!linearStr) 6482 return false; 6483 6484 *isIdentifier = js::frontend::IsIdentifier(linearStr); 6485 return true; 6486 } 6487 6488 JS_PUBLIC_API(bool) 6489 JS_IsIdentifier(const char16_t* chars, size_t length) 6490 { 6491 return js::frontend::IsIdentifier(chars, length); 6492 } 6493 6494 namespace JS { 6495 6496 void AutoFilename::reset() 6497 { 6498 if (ss_) { 6499 ss_->decref(); 6500 ss_ = nullptr; 6501 } 6502 if (filename_.is<const char*>()) 6503 filename_.as<const char*>() = nullptr; 6504 else 6505 filename_.as<UniqueChars>().reset(); 6506 } 6507 6508 void AutoFilename::setScriptSource(js::ScriptSource* p) 6509 { 6510 MOZ_ASSERT(!ss_); 6511 MOZ_ASSERT(!get()); 6512 ss_ = p; 6513 if (p) { 6514 p->incref(); 6515 setUnowned(p->filename()); 6516 } 6517 } 6518 6519 void AutoFilename::setUnowned(const char* filename) 6520 { 6521 MOZ_ASSERT(!get()); 6522 filename_.as<const char*>() = filename ? filename : ""; 6523 } 6524 6525 void AutoFilename::setOwned(UniqueChars&& filename) 6526 { 6527 MOZ_ASSERT(!get()); 6528 filename_ = AsVariant(Move(filename)); 6529 } 6530 6531 const char* AutoFilename::get() const 6532 { 6533 if (filename_.is<const char*>()) 6534 return filename_.as<const char*>(); 6535 return filename_.as<UniqueChars>().get(); 6536 } 6537 6538 JS_PUBLIC_API(bool) 6539 DescribeScriptedCaller(JSContext* cx, AutoFilename* filename, unsigned* lineno, 6540 unsigned* column) 6541 { 6542 if (filename) 6543 filename->reset(); 6544 if (lineno) 6545 *lineno = 0; 6546 if (column) 6547 *column = 0; 6548 6549 if (!cx->compartment()) 6550 return false; 6551 6552 NonBuiltinFrameIter i(cx, cx->compartment()->principals()); 6553 if (i.done()) 6554 return false; 6555 6556 // If the caller is hidden, the embedding wants us to return false here so 6557 // that it can check its own stack (see HideScriptedCaller). 6558 if (i.activation()->scriptedCallerIsHidden()) 6559 return false; 6560 6561 if (filename) { 6562 if (i.isWasm()) { 6563 // For Wasm, copy out the filename, there is no script source. 6564 UniqueChars copy = DuplicateString(i.filename() ? i.filename() : ""); 6565 if (!copy) 6566 filename->setUnowned("out of memory"); 6567 else 6568 filename->setOwned(Move(copy)); 6569 } else { 6570 // All other frames have a script source to read the filename from. 6571 filename->setScriptSource(i.scriptSource()); 6572 } 6573 } 6574 6575 if (lineno) 6576 *lineno = i.computeLine(column); 6577 else if (column) 6578 i.computeLine(column); 6579 6580 return true; 6581 } 6582 6583 // Fast path to get the activation to use for GetScriptedCallerGlobal. If this 6584 // returns false, the fast path didn't work out and the caller has to use the 6585 // (much slower) NonBuiltinFrameIter path. 6586 // 6587 // The optimization here is that we skip Ion-inlined frames and only look at 6588 // 'outer' frames. That's fine: each activation is tied to a single compartment, 6589 // so if an activation contains at least one non-self-hosted frame, we can use 6590 // the activation's global for GetScriptedCallerGlobal. If, however, all 'outer' 6591 // frames are self-hosted, it's possible Ion inlined a non-self-hosted script, 6592 // so we must return false and use the slower path. 6593 static bool 6594 GetScriptedCallerActivationFast(JSContext* cx, Activation** activation) 6595 { 6596 ActivationIterator activationIter(cx->runtime()); 6597 6598 if (activationIter.done()) { 6599 *activation = nullptr; 6600 return true; 6601 } 6602 6603 *activation = activationIter.activation(); 6604 6605 if (activationIter->isJit()) { 6606 for (jit::JitFrameIterator iter(activationIter); !iter.done(); ++iter) { 6607 if (iter.isScripted() && !iter.script()->selfHosted()) 6608 return true; 6609 } 6610 } else if (activationIter->isInterpreter()) { 6611 for (InterpreterFrameIterator iter((*activation)->asInterpreter()); !iter.done(); ++iter) { 6612 if (!iter.frame()->script()->selfHosted()) 6613 return true; 6614 } 6615 } 6616 6617 return false; 6618 } 6619 6620 JS_PUBLIC_API(JSObject*) 6621 GetScriptedCallerGlobal(JSContext* cx) 6622 { 6623 Activation* activation; 6624 6625 if (GetScriptedCallerActivationFast(cx, &activation)) { 6626 if (!activation) 6627 return nullptr; 6628 } else { 6629 NonBuiltinFrameIter i(cx); 6630 if (i.done()) 6631 return nullptr; 6632 activation = i.activation(); 6633 } 6634 6635 // If the caller is hidden, the embedding wants us to return null here so 6636 // that it can check its own stack (see HideScriptedCaller). 6637 if (activation->scriptedCallerIsHidden()) 6638 return nullptr; 6639 6640 GlobalObject* global = activation->compartment()->maybeGlobal(); 6641 6642 // Noone should be running code in the atoms compartment or running code in 6643 // a compartment without any live objects, so there should definitely be a 6644 // live global. 6645 MOZ_ASSERT(global); 6646 6647 return global; 6648 } 6649 6650 JS_PUBLIC_API(void) 6651 HideScriptedCaller(JSContext* cx) 6652 { 6653 MOZ_ASSERT(cx); 6654 6655 // If there's no accessible activation on the stack, we'll return null from 6656 // DescribeScriptedCaller anyway, so there's no need to annotate anything. 6657 Activation* act = cx->runtime()->activation(); 6658 if (!act) 6659 return; 6660 act->hideScriptedCaller(); 6661 } 6662 6663 JS_PUBLIC_API(void) 6664 UnhideScriptedCaller(JSContext* cx) 6665 { 6666 Activation* act = cx->runtime()->activation(); 6667 if (!act) 6668 return; 6669 act->unhideScriptedCaller(); 6670 } 6671 6672 } /* namespace JS */ 6673 6674 AutoGCRooter::AutoGCRooter(JSContext* cx, ptrdiff_t tag) 6675 : AutoGCRooter(JS::RootingContext::get(cx), tag) 6676 {} 6677 6678 AutoGCRooter::AutoGCRooter(JS::RootingContext* cx, ptrdiff_t tag) 6679 : down(cx->roots.autoGCRooters_), 6680 tag_(tag), 6681 stackTop(&cx->roots.autoGCRooters_) 6682 { 6683 MOZ_ASSERT(this != *stackTop); 6684 *stackTop = this; 6685 } 6686 6687 #ifdef JS_DEBUG 6688 JS_PUBLIC_API(void) 6689 JS::detail::AssertArgumentsAreSane(JSContext* cx, HandleValue value) 6690 { 6691 AssertHeapIsIdle(cx); 6692 CHECK_REQUEST(cx); 6693 assertSameCompartment(cx, value); 6694 } 6695 #endif /* JS_DEBUG */ 6696 6697 JS_PUBLIC_API(JS::TranscodeResult) 6698 JS::EncodeScript(JSContext* cx, TranscodeBuffer& buffer, HandleScript scriptArg) 6699 { 6700 XDREncoder encoder(cx, buffer, buffer.length()); 6701 RootedScript script(cx, scriptArg); 6702 if (!encoder.codeScript(&script)) 6703 buffer.clearAndFree(); 6704 MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok)); 6705 return encoder.resultCode(); 6706 } 6707 6708 JS_PUBLIC_API(JS::TranscodeResult) 6709 JS::EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, HandleObject funobjArg) 6710 { 6711 XDREncoder encoder(cx, buffer, buffer.length()); 6712 RootedFunction funobj(cx, &funobjArg->as<JSFunction>()); 6713 if (!encoder.codeFunction(&funobj)) 6714 buffer.clearAndFree(); 6715 MOZ_ASSERT(!buffer.empty() == (encoder.resultCode() == TranscodeResult_Ok)); 6716 return encoder.resultCode(); 6717 } 6718 6719 JS_PUBLIC_API(JS::TranscodeResult) 6720 JS::DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp, 6721 size_t cursorIndex) 6722 { 6723 XDRDecoder decoder(cx, buffer, cursorIndex); 6724 decoder.codeScript(scriptp); 6725 MOZ_ASSERT(bool(scriptp) == (decoder.resultCode() == TranscodeResult_Ok)); 6726 return decoder.resultCode(); 6727 } 6728 6729 JS_PUBLIC_API(JS::TranscodeResult) 6730 JS::DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, 6731 JS::MutableHandleFunction funp, 6732 size_t cursorIndex) 6733 { 6734 XDRDecoder decoder(cx, buffer, cursorIndex); 6735 decoder.codeFunction(funp); 6736 MOZ_ASSERT(bool(funp) == (decoder.resultCode() == TranscodeResult_Ok)); 6737 return decoder.resultCode(); 6738 } 6739 6740 JS_PUBLIC_API(void) 6741 JS::SetBuildIdOp(JSContext* cx, JS::BuildIdOp buildIdOp) 6742 { 6743 cx->runtime()->buildIdOp = buildIdOp; 6744 } 6745 6746 JS_PUBLIC_API(void) 6747 JS::SetAsmJSCacheOps(JSContext* cx, const JS::AsmJSCacheOps* ops) 6748 { 6749 cx->runtime()->asmJSCacheOps = *ops; 6750 } 6751 6752 bool 6753 JS::IsWasmModuleObject(HandleObject obj) 6754 { 6755 JSObject* unwrapped = CheckedUnwrap(obj); 6756 if (!unwrapped) 6757 return false; 6758 return unwrapped->is<WasmModuleObject>(); 6759 } 6760 6761 JS_PUBLIC_API(RefPtr<JS::WasmModule>) 6762 JS::GetWasmModule(HandleObject obj) 6763 { 6764 MOZ_ASSERT(JS::IsWasmModuleObject(obj)); 6765 return &CheckedUnwrap(obj)->as<WasmModuleObject>().module(); 6766 } 6767 6768 JS_PUBLIC_API(bool) 6769 JS::CompiledWasmModuleAssumptionsMatch(PRFileDesc* compiled, JS::BuildIdCharVector&& buildId) 6770 { 6771 return wasm::CompiledModuleAssumptionsMatch(compiled, Move(buildId)); 6772 } 6773 6774 JS_PUBLIC_API(RefPtr<JS::WasmModule>) 6775 JS::DeserializeWasmModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled, 6776 JS::BuildIdCharVector&& buildId, UniqueChars file, 6777 unsigned line, unsigned column) 6778 { 6779 return wasm::DeserializeModule(bytecode, maybeCompiled, Move(buildId), Move(file), line, column); 6780 } 6781 6782 char* 6783 JSAutoByteString::encodeLatin1(ExclusiveContext* cx, JSString* str) 6784 { 6785 mBytes = EncodeLatin1(cx, str); 6786 return mBytes; 6787 } 6788 6789 JS_PUBLIC_API(void) 6790 JS::SetLargeAllocationFailureCallback(JSContext* cx, JS::LargeAllocationFailureCallback lafc, 6791 void* data) 6792 { 6793 cx->largeAllocationFailureCallback = lafc; 6794 cx->largeAllocationFailureCallbackData = data; 6795 } 6796 6797 JS_PUBLIC_API(void) 6798 JS::SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data) 6799 { 6800 cx->oomCallback = cb; 6801 cx->oomCallbackData = data; 6802 } 6803 6804 JS::FirstSubsumedFrame::FirstSubsumedFrame(JSContext* cx, 6805 bool ignoreSelfHostedFrames /* = true */) 6806 : JS::FirstSubsumedFrame(cx, cx->compartment()->principals(), ignoreSelfHostedFrames) 6807 { } 6808 6809 JS_PUBLIC_API(bool) 6810 JS::CaptureCurrentStack(JSContext* cx, JS::MutableHandleObject stackp, 6811 JS::StackCapture&& capture /* = JS::StackCapture(JS::AllFrames()) */) 6812 { 6813 AssertHeapIsIdle(cx); 6814 CHECK_REQUEST(cx); 6815 MOZ_RELEASE_ASSERT(cx->compartment()); 6816 6817 JSCompartment* compartment = cx->compartment(); 6818 Rooted<SavedFrame*> frame(cx); 6819 if (!compartment->savedStacks().saveCurrentStack(cx, &frame, mozilla::Move(capture))) 6820 return false; 6821 stackp.set(frame.get()); 6822 return true; 6823 } 6824 6825 JS_PUBLIC_API(bool) 6826 JS::CopyAsyncStack(JSContext* cx, JS::HandleObject asyncStack, 6827 JS::HandleString asyncCause, JS::MutableHandleObject stackp, 6828 unsigned maxFrameCount) 6829 { 6830 AssertHeapIsIdle(cx); 6831 CHECK_REQUEST(cx); 6832 MOZ_RELEASE_ASSERT(cx->compartment()); 6833 6834 js::AssertObjectIsSavedFrameOrWrapper(cx, asyncStack); 6835 JSCompartment* compartment = cx->compartment(); 6836 Rooted<SavedFrame*> frame(cx); 6837 if (!compartment->savedStacks().copyAsyncStack(cx, asyncStack, asyncCause, 6838 &frame, maxFrameCount)) 6839 return false; 6840 stackp.set(frame.get()); 6841 return true; 6842 } 6843 6844 JS_PUBLIC_API(Zone*) 6845 JS::GetObjectZone(JSObject* obj) 6846 { 6847 return obj->zone(); 6848 } 6849 6850 JS_PUBLIC_API(JS::TraceKind) 6851 JS::GCThingTraceKind(void* thing) 6852 { 6853 MOZ_ASSERT(thing); 6854 return static_cast<js::gc::Cell*>(thing)->getTraceKind(); 6855 } 6856 6857 JS_PUBLIC_API(void) 6858 js::SetStackFormat(JSContext* cx, js::StackFormat format) 6859 { 6860 cx->setStackFormat(format); 6861 } 6862 6863 JS_PUBLIC_API(js::StackFormat) 6864 js::GetStackFormat(JSContext* cx) 6865 { 6866 return cx->stackFormat(); 6867 } 6868