jsfriendapi.h (30719B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 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 #ifndef jsfriendapi_h 8 #define jsfriendapi_h 9 10 #include "jspubtd.h" 11 12 #include "js/CallArgs.h" 13 #include "js/Class.h" 14 #include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin 15 #include "js/GCAPI.h" 16 #include "js/GCVector.h" 17 #include "js/HeapAPI.h" 18 #include "js/Object.h" // JS::GetClass 19 #include "js/shadow/Function.h" // JS::shadow::Function 20 #include "js/shadow/Object.h" // JS::shadow::Object 21 #include "js/TypeDecls.h" 22 23 class JSJitInfo; 24 25 /* 26 * Set a callback used to trace gray roots. 27 * 28 * The callback is called after the first slice of GC so the embedding must 29 * implement appropriate barriers on its gray roots to ensure correctness. 30 * 31 * This callback may be called multiple times for different sets of zones. Use 32 * JS::ZoneIsGrayMarking() to determine whether roots from a particular zone are 33 * required. 34 */ 35 extern JS_PUBLIC_API void JS_SetGrayGCRootsTracer(JSContext* cx, 36 JSGrayRootsTracer traceOp, 37 void* data); 38 39 extern JS_PUBLIC_API JSObject* JS_FindCompilationScope(JSContext* cx, 40 JS::HandleObject obj); 41 42 extern JS_PUBLIC_API JSFunction* JS_GetObjectFunction(JSObject* obj); 43 44 /** 45 * Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but 46 * without invoking the metadata callback on it. This allows creation of 47 * internal bookkeeping objects that are guaranteed to not have metadata 48 * attached to them. 49 */ 50 extern JS_PUBLIC_API JSObject* JS_NewObjectWithoutMetadata( 51 JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto); 52 53 extern JS_PUBLIC_API bool JS_NondeterministicGetWeakMapKeys( 54 JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret); 55 56 extern JS_PUBLIC_API bool JS_NondeterministicGetWeakSetKeys( 57 JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret); 58 59 // Raw JSScript* because this needs to be callable from a signal handler. 60 extern JS_PUBLIC_API unsigned JS_PCToLineNumber( 61 JSScript* script, jsbytecode* pc, 62 JS::LimitedColumnNumberOneOrigin* columnp = nullptr); 63 64 /** 65 * Determine whether the given object is backed by a DeadObjectProxy. 66 * 67 * Such objects hold no other objects (they have no outgoing reference edges) 68 * and will throw if you touch them (e.g. by reading/writing a property). 69 */ 70 extern JS_PUBLIC_API bool JS_IsDeadWrapper(JSObject* obj); 71 72 /** 73 * Creates a new dead wrapper object in the given scope. To be used when 74 * attempting to wrap objects from scopes which are already dead. 75 * 76 * If origObject is passed, it must be an proxy object, and will be 77 * used to determine the characteristics of the new dead wrapper. 78 */ 79 extern JS_PUBLIC_API JSObject* JS_NewDeadWrapper( 80 JSContext* cx, JSObject* origObject = nullptr); 81 82 /* 83 * Used by the cycle collector to trace through a shape and all 84 * cycle-participating data it reaches, using bounded stack space. 85 */ 86 extern JS_PUBLIC_API void JS_TraceShapeCycleCollectorChildren( 87 JS::CallbackTracer* trc, JS::GCCellPtr shape); 88 89 extern JS_PUBLIC_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script); 90 91 extern JS_PUBLIC_API bool JS_ScriptHasMutedErrors(JSScript* script); 92 93 extern JS_PUBLIC_API JSObject* JS_CloneObject(JSContext* cx, 94 JS::HandleObject obj, 95 JS::HandleObject proto); 96 97 /** 98 * Copy the own properties of src to dst in a fast way. src and dst must both 99 * be native and must be in the compartment of cx. They must have the same 100 * class, the same parent, and the same prototype. Class reserved slots will 101 * NOT be copied. 102 * 103 * dst must not have any properties on it before this function is called. 104 * 105 * src must have been allocated via JS_NewObjectWithoutMetadata so that we can 106 * be sure it has no metadata that needs copying to dst. This also means that 107 * dst needs to have the compartment global as its parent. This function will 108 * preserve the existing metadata on dst, if any. 109 */ 110 extern JS_PUBLIC_API bool JS_InitializePropertiesFromCompatibleNativeObject( 111 JSContext* cx, JS::HandleObject dst, JS::HandleObject src); 112 113 namespace js { 114 115 JS_PUBLIC_API bool IsArgumentsObject(JS::HandleObject obj); 116 117 JS_PUBLIC_API bool AddRawValueRoot(JSContext* cx, JS::Value* vp, 118 const char* name); 119 120 JS_PUBLIC_API void RemoveRawValueRoot(JSContext* cx, JS::Value* vp); 121 122 } // namespace js 123 124 namespace JS { 125 126 /** 127 * Set all of the uninitialized lexicals on an object to undefined. Return 128 * true if any lexicals were initialized and false otherwise. 129 * */ 130 extern JS_PUBLIC_API bool ForceLexicalInitialization(JSContext* cx, 131 HandleObject obj); 132 133 /** 134 * Whether we are poisoning unused/released data for error detection. Governed 135 * by the JS_GC_ALLOW_EXTRA_POISONING #ifdef as well as the 136 * javascript.options.extra_gc_poisoning pref. 137 */ 138 extern JS_PUBLIC_API bool IsGCPoisoning(); 139 140 extern JS_PUBLIC_API JSPrincipals* GetRealmPrincipals(JS::Realm* realm); 141 142 extern JS_PUBLIC_API void SetRealmPrincipals(JS::Realm* realm, 143 JSPrincipals* principals); 144 145 extern JS_PUBLIC_API bool GetIsSecureContext(JS::Realm* realm); 146 147 extern JS_PUBLIC_API bool GetDebuggerObservesWasm(JS::Realm* realm); 148 149 } // namespace JS 150 151 /** 152 * Copies all own properties and private fields from |obj| to |target|. Both 153 * |obj| and |target| must not be cross-compartment wrappers because we have to 154 * enter their realms. 155 * 156 * This function immediately enters a realm, and does not impose any 157 * restrictions on the realm of |cx|. 158 */ 159 extern JS_PUBLIC_API bool JS_CopyOwnPropertiesAndPrivateFields( 160 JSContext* cx, JS::HandleObject target, JS::HandleObject obj); 161 162 extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor( 163 JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc); 164 165 extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor( 166 JSContext* cx, 167 JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc); 168 169 struct JSFunctionSpecWithHelp { 170 const char* name; 171 JSNative call; 172 uint16_t nargs; 173 uint16_t flags; 174 const JSJitInfo* jitInfo; 175 const char* usage; 176 const char* help; 177 }; 178 179 #define JS_FN_HELP(name, call, nargs, flags, usage, help) \ 180 {name, call, nargs, (flags) | JSPROP_ENUMERATE, nullptr, usage, help} 181 #define JS_INLINABLE_FN_HELP(name, call, nargs, flags, native, usage, help) \ 182 {name, call, nargs, (flags) | JSPROP_ENUMERATE, &js::jit::JitInfo_##native, \ 183 usage, help} 184 #define JS_FS_HELP_END {nullptr, nullptr, 0, 0, nullptr, nullptr} 185 186 extern JS_PUBLIC_API bool JS_DefineFunctionsWithHelp( 187 JSContext* cx, JS::HandleObject obj, const JSFunctionSpecWithHelp* fs); 188 189 namespace js { 190 191 /** 192 * Use the runtime's internal handling of job queues for Promise jobs. 193 * 194 * Most embeddings, notably web browsers, will have their own task scheduling 195 * systems and need to integrate handling of Promise jobs into that, so they 196 * will want to manage job queues themselves. For basic embeddings such as the 197 * JS shell that don't have an event loop of their own, it's easier to have 198 * SpiderMonkey handle job queues internally. 199 * 200 * Note that the embedding still has to trigger processing of job queues at 201 * right time(s), such as after evaluation of a script has run to completion. 202 */ 203 extern JS_PUBLIC_API bool UseInternalJobQueues(JSContext* cx); 204 205 #ifdef DEBUG 206 /** 207 * Given internal job queues are used, return currently queued jobs as an 208 * array of job objects. 209 */ 210 extern JS_PUBLIC_API JSObject* GetJobsInInternalJobQueue(JSContext* cx); 211 #endif 212 213 /** 214 * Instruct the runtime to stop draining the internal job queue. 215 * 216 * Useful if the embedding is in the process of quitting in reaction to a 217 * builtin being called, or if it wants to resume executing jobs later on. 218 */ 219 extern JS_PUBLIC_API void StopDrainingJobQueue(JSContext* cx); 220 221 /** 222 * Instruct the runtime to restart draining the internal job queue after 223 * stopping it with StopDrainingJobQueue. 224 */ 225 extern JS_PUBLIC_API void RestartDrainingJobQueue(JSContext* cx); 226 227 extern JS_PUBLIC_API void RunJobs(JSContext* cx); 228 229 extern JS_PUBLIC_API JS::Zone* GetRealmZone(JS::Realm* realm); 230 231 using PreserveWrapperCallback = bool (*)(JSContext*, JS::HandleObject); 232 using HasReleasedWrapperCallback = bool (*)(JS::HandleObject); 233 234 extern JS_PUBLIC_API bool IsSystemRealm(JS::Realm* realm); 235 236 extern JS_PUBLIC_API bool IsSystemCompartment(JS::Compartment* comp); 237 238 extern JS_PUBLIC_API bool IsSystemZone(JS::Zone* zone); 239 240 struct WeakMapTracer { 241 JSRuntime* runtime; 242 243 explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {} 244 245 // Weak map tracer callback, called once for every binding of every 246 // weak map that was live at the time of the last garbage collection. 247 // 248 // m will be nullptr if the weak map is not contained in a JS Object. 249 // 250 // The callback should not GC (and will assert in a debug build if it does 251 // so.) 252 virtual void trace(JSObject* m, JS::GCCellPtr key, JS::GCCellPtr value) = 0; 253 }; 254 255 extern JS_PUBLIC_API void TraceWeakMaps(WeakMapTracer* trc); 256 257 extern JS_PUBLIC_API bool AreGCGrayBitsValid(JSRuntime* rt); 258 259 extern JS_PUBLIC_API bool ZoneGlobalsAreAllGray(JS::Zone* zone); 260 261 extern JS_PUBLIC_API bool IsCompartmentZoneSweepingOrCompacting( 262 JS::Compartment* comp); 263 264 using IterateGCThingCallback = void (*)(void*, JS::GCCellPtr, 265 const JS::AutoRequireNoGC&); 266 267 extern JS_PUBLIC_API void TraceGrayWrapperTargets(JSTracer* trc, 268 JS::Zone* zone); 269 270 /** 271 * Invoke cellCallback on every gray JSObject in the given zone. 272 */ 273 extern JS_PUBLIC_API void IterateGrayObjects( 274 JS::Zone* zone, IterateGCThingCallback cellCallback, void* data); 275 276 #if defined(JS_GC_ZEAL) || defined(DEBUG) 277 // Trace the heap and check there are no black to gray edges. These are 278 // not allowed since the cycle collector could throw away the gray thing and 279 // leave a dangling pointer. 280 // 281 // This doesn't trace weak maps as these are handled separately. 282 extern JS_PUBLIC_API bool CheckGrayMarkingState(JSRuntime* rt); 283 #endif 284 285 // Note: this returns nullptr iff |zone| is the atoms zone. 286 extern JS_PUBLIC_API JS::Realm* GetAnyRealmInZone(JS::Zone* zone); 287 288 // Returns the first realm's global in a compartment. Note: this is not 289 // guaranteed to always be the same realm because individual realms can be 290 // collected by the GC. 291 extern JS_PUBLIC_API JSObject* GetFirstGlobalInCompartment( 292 JS::Compartment* comp); 293 294 // Returns true if the compartment contains a global object and this global is 295 // not being collected. 296 extern JS_PUBLIC_API bool CompartmentHasLiveGlobal(JS::Compartment* comp); 297 298 // Returns true if this compartment can be shared across multiple Realms. Used 299 // when we're looking for an existing compartment to place a new Realm in. 300 extern JS_PUBLIC_API bool IsSharableCompartment(JS::Compartment* comp); 301 302 // This is equal to |&JSObject::class_|. Use it in places where you don't want 303 // to #include vm/JSObject.h. 304 extern JS_PUBLIC_DATA const JSClass* const ObjectClassPtr; 305 306 JS_PUBLIC_API const JSClass* ProtoKeyToClass(JSProtoKey key); 307 308 // Returns the key for the class inherited by a given standard class (that 309 // is to say, the prototype of this standard class's prototype). 310 // 311 // You must be sure that this corresponds to a standard class with a cached 312 // JSProtoKey before calling this function. In general |key| will match the 313 // cached proto key, except in cases where multiple JSProtoKeys share a 314 // JSClass. 315 inline JSProtoKey InheritanceProtoKeyForStandardClass(JSProtoKey key) { 316 // [Object] has nothing to inherit from. 317 if (key == JSProto_Object) { 318 return JSProto_Null; 319 } 320 321 // If we're ClassSpec defined return the proto key from that 322 if (ProtoKeyToClass(key)->specDefined()) { 323 return ProtoKeyToClass(key)->specInheritanceProtoKey(); 324 } 325 326 // Otherwise, we inherit [Object]. 327 return JSProto_Object; 328 } 329 330 JS_PUBLIC_API bool ShouldIgnorePropertyDefinition(JSContext* cx, JSProtoKey key, 331 jsid id); 332 333 JS_PUBLIC_API bool IsFunctionObject(JSObject* obj); 334 335 JS_PUBLIC_API bool UninlinedIsCrossCompartmentWrapper(const JSObject* obj); 336 337 // CrossCompartmentWrappers are shared by all realms within the compartment, so 338 // getting a wrapper's realm usually doesn't make sense. 339 static MOZ_ALWAYS_INLINE JS::Realm* GetNonCCWObjectRealm(JSObject* obj) { 340 MOZ_ASSERT(!js::UninlinedIsCrossCompartmentWrapper(obj)); 341 return reinterpret_cast<JS::shadow::Object*>(obj)->shape->base->realm; 342 } 343 344 JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JSObject* obj); 345 346 JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JS::HandleValue v); 347 348 #ifdef JS_DEBUG 349 JS_PUBLIC_API void AssertSameCompartment(JSObject* objA, JSObject* objB); 350 #else 351 inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {} 352 #endif 353 354 JS_PUBLIC_API void NotifyAnimationActivity(JSObject* obj); 355 356 JS_PUBLIC_API JSFunction* DefineFunctionWithReserved( 357 JSContext* cx, JSObject* obj, const char* name, JSNative call, 358 unsigned nargs, unsigned attrs); 359 360 JS_PUBLIC_API JSFunction* NewFunctionWithReserved(JSContext* cx, JSNative call, 361 unsigned nargs, 362 unsigned flags, 363 const char* name); 364 365 JS_PUBLIC_API JSFunction* NewFunctionByIdWithReserved(JSContext* cx, 366 JSNative native, 367 unsigned nargs, 368 unsigned flags, jsid id); 369 370 JS_PUBLIC_API JSFunction* NewFunctionByIdWithReservedAndProto( 371 JSContext* cx, JSNative native, JS::Handle<JSObject*> proto, unsigned nargs, 372 unsigned flags, jsid id); 373 374 /** 375 * Get or set function's reserved slot value. 376 * `fun` should be a function created with `*WithReserved` API above. 377 * Such functions have 2 reserved slots, and `which` can be either 0 or 1. 378 */ 379 JS_PUBLIC_API const JS::Value& GetFunctionNativeReserved(JSObject* fun, 380 size_t which); 381 382 JS_PUBLIC_API void SetFunctionNativeReserved(JSObject* fun, size_t which, 383 const JS::Value& val); 384 385 JS_PUBLIC_API bool FunctionHasNativeReserved(JSObject* fun); 386 387 JS_PUBLIC_API bool GetObjectProto(JSContext* cx, JS::HandleObject obj, 388 JS::MutableHandleObject proto); 389 390 extern JS_PUBLIC_API JSObject* GetStaticPrototype(JSObject* obj); 391 392 JS_PUBLIC_API bool GetRealmOriginalEval(JSContext* cx, 393 JS::MutableHandleObject eval); 394 395 /** 396 * Add some or all property keys of obj to the id vector *props. 397 * 398 * The flags parameter controls which property keys are added. Pass a 399 * combination of the following bits: 400 * 401 * JSITER_OWNONLY - Don't also search the prototype chain; only consider 402 * obj's own properties. 403 * 404 * JSITER_HIDDEN - Include nonenumerable properties. 405 * 406 * JSITER_SYMBOLS - Include property keys that are symbols. The default 407 * behavior is to filter out symbols. 408 * 409 * JSITER_SYMBOLSONLY - Exclude non-symbol property keys. 410 * 411 * This is the closest C++ API we have to `Reflect.ownKeys(obj)`, or 412 * equivalently, the ES6 [[OwnPropertyKeys]] internal method. Pass 413 * `JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS` as flags to get 414 * results that match the output of Reflect.ownKeys. 415 */ 416 JS_PUBLIC_API bool GetPropertyKeys(JSContext* cx, JS::HandleObject obj, 417 unsigned flags, 418 JS::MutableHandleIdVector props); 419 420 JS_PUBLIC_API bool AppendUnique(JSContext* cx, JS::MutableHandleIdVector base, 421 JS::HandleIdVector others); 422 423 /** 424 * Direct embedder access for retrieving a copy of all entries in a Set or Map 425 * object. 426 */ 427 JS_PUBLIC_API bool GetSetObjectKeys( 428 JSContext* cx, JS::HandleObject obj, 429 JS::MutableHandle<JS::GCVector<JS::Value>> keys); 430 431 JS_PUBLIC_API bool GetMapObjectKeysAndValuesInterleaved( 432 JSContext* cx, JS::HandleObject obj, 433 JS::MutableHandle<JS::GCVector<JS::Value>> entries); 434 435 /** 436 * Determine whether the given string is an array index in the sense of 437 * <https://tc39.github.io/ecma262/#array-index>. 438 * 439 * If it isn't, returns false. 440 * 441 * If it is, returns true and outputs the index in *indexp. 442 */ 443 JS_PUBLIC_API bool StringIsArrayIndex(const JSLinearString* str, 444 uint32_t* indexp); 445 446 /** 447 * Overload of StringIsArrayIndex taking a (char16_t*,length) pair. Behaves 448 * the same as the JSLinearString version. 449 */ 450 JS_PUBLIC_API bool StringIsArrayIndex(const char16_t* str, uint32_t length, 451 uint32_t* indexp); 452 453 JS_PUBLIC_API void SetPreserveWrapperCallbacks( 454 JSContext* cx, PreserveWrapperCallback preserveWrapper, 455 HasReleasedWrapperCallback hasReleasedWrapper); 456 457 JS_PUBLIC_API void CommitPendingWrapperPreservations(JSContext* cx); 458 459 JS_PUBLIC_API bool IsObjectInContextCompartment(JSObject* obj, 460 const JSContext* cx); 461 462 /* 463 * NB: keep these in sync with the copy in builtin/SelfHostingDefines.h. 464 */ 465 /* 0x1 is no longer used */ 466 /* 0x2 is no longer used */ 467 #define JSITER_PRIVATE 0x4 /* Include private names in iteration */ 468 #define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */ 469 #define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */ 470 #define JSITER_SYMBOLS 0x20 /* also include symbol property keys */ 471 #define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */ 472 #define JSITER_FORAWAITOF 0x80 /* for-await-of */ 473 474 using DOMInstanceClassHasProtoAtDepth = bool (*)(const JSClass*, uint32_t, 475 uint32_t); 476 using DOMInstanceClassIsError = bool (*)(const JSClass*); 477 478 using DOMExtractExceptionInfo = bool (*)(JSContext*, JS::HandleObject, bool*, 479 JS::MutableHandle<JSString*>, 480 uint32_t*, uint32_t*, 481 JS::MutableHandle<JSString*>); 482 483 struct JSDOMCallbacks { 484 DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto; 485 DOMInstanceClassIsError instanceClassIsError; 486 DOMExtractExceptionInfo extractExceptionInfo; 487 }; 488 using DOMCallbacks = struct JSDOMCallbacks; 489 490 extern JS_PUBLIC_API void SetDOMCallbacks(JSContext* cx, 491 const DOMCallbacks* callbacks); 492 493 extern JS_PUBLIC_API const DOMCallbacks* GetDOMCallbacks(JSContext* cx); 494 495 extern JS_PUBLIC_API JSObject* GetTestingFunctions(JSContext* cx); 496 497 /* Implemented in jsexn.cpp. */ 498 499 /** 500 * Get an error type name from a JSExnType constant. 501 * Returns nullptr for invalid arguments and JSEXN_INTERNALERR 502 */ 503 extern JS_PUBLIC_API JSLinearString* GetErrorTypeName(JSContext* cx, 504 int16_t exnType); 505 506 /* Implemented in CrossCompartmentWrapper.cpp. */ 507 enum NukeReferencesToWindow { NukeWindowReferences, DontNukeWindowReferences }; 508 509 enum NukeReferencesFromTarget { 510 NukeAllReferences, 511 NukeIncomingReferences, 512 }; 513 514 /* 515 * These filters are designed to be ephemeral stack classes, and thus don't 516 * do any rooting or holding of their members. 517 */ 518 struct CompartmentFilter { 519 virtual bool match(JS::Compartment* c) const = 0; 520 }; 521 522 struct AllCompartments : public CompartmentFilter { 523 virtual bool match(JS::Compartment* c) const override { return true; } 524 }; 525 526 struct SingleCompartment : public CompartmentFilter { 527 JS::Compartment* ours; 528 explicit SingleCompartment(JS::Compartment* c) : ours(c) {} 529 virtual bool match(JS::Compartment* c) const override { return c == ours; } 530 }; 531 532 extern JS_PUBLIC_API bool NukeCrossCompartmentWrappers( 533 JSContext* cx, const CompartmentFilter& sourceFilter, JS::Realm* target, 534 NukeReferencesToWindow nukeReferencesToWindow, 535 NukeReferencesFromTarget nukeReferencesFromTarget); 536 537 extern JS_PUBLIC_API bool AllowNewWrapper(JS::Compartment* target, 538 JSObject* obj); 539 540 extern JS_PUBLIC_API bool NukedObjectRealm(JSObject* obj); 541 542 /* Implemented in jsdate.cpp. */ 543 544 /** Detect whether the internal date value is NaN. */ 545 extern JS_PUBLIC_API bool DateIsValid(JSContext* cx, JS::HandleObject obj, 546 bool* isValid); 547 548 extern JS_PUBLIC_API bool DateGetMsecSinceEpoch(JSContext* cx, 549 JS::HandleObject obj, 550 double* msecSinceEpoch); 551 552 } /* namespace js */ 553 554 namespace js { 555 556 /* Implemented in vm/StructuredClone.cpp. */ 557 extern JS_PUBLIC_API uint64_t GetSCOffset(JSStructuredCloneWriter* writer); 558 559 } // namespace js 560 561 namespace js { 562 563 /* Statically asserted in FunctionFlags.cpp. */ 564 static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x0060; 565 566 } // namespace js 567 568 static MOZ_ALWAYS_INLINE const JSJitInfo* FUNCTION_VALUE_TO_JITINFO( 569 const JS::Value& v) { 570 JSObject* obj = &v.toObject(); 571 MOZ_ASSERT(JS::GetClass(obj)->isJSFunction()); 572 573 auto* fun = reinterpret_cast<JS::shadow::Function*>(obj); 574 MOZ_ASSERT(!(fun->flagsAndArgCount() & js::JS_FUNCTION_INTERPRETED_BITS), 575 "Unexpected non-native function"); 576 577 return static_cast<const JSJitInfo*>(fun->jitInfoOrScript()); 578 } 579 580 static MOZ_ALWAYS_INLINE void SET_JITINFO(JSFunction* func, 581 const JSJitInfo* info) { 582 auto* fun = reinterpret_cast<JS::shadow::Function*>(func); 583 MOZ_ASSERT(!(fun->flagsAndArgCount() & js::JS_FUNCTION_INTERPRETED_BITS)); 584 585 fun->setJitInfoOrScript(const_cast<JSJitInfo*>(info)); 586 } 587 588 static_assert(sizeof(jsid) == sizeof(void*)); 589 590 namespace js { 591 592 static MOZ_ALWAYS_INLINE JS::Value IdToValue(jsid id) { 593 if (id.isString()) { 594 return JS::StringValue(id.toString()); 595 } 596 if (id.isInt()) { 597 return JS::Int32Value(id.toInt()); 598 } 599 if (id.isSymbol()) { 600 return JS::SymbolValue(id.toSymbol()); 601 } 602 MOZ_ASSERT(id.isVoid()); 603 return JS::UndefinedValue(); 604 } 605 606 /** 607 * PrepareScriptEnvironmentAndInvoke asserts the embedder has registered a 608 * ScriptEnvironmentPreparer and then it calls the preparer's 'invoke' method 609 * with the given |closure|, with the assumption that the preparer will set up 610 * any state necessary to run script in |global|, invoke |closure| with a valid 611 * JSContext*, report any exceptions thrown from the closure, and return. 612 * 613 * PrepareScriptEnvironmentAndInvoke will report any exceptions that are thrown 614 * by the closure. Consumers who want to propagate back whether the closure 615 * succeeded should do so via members of the closure itself. 616 */ 617 618 struct ScriptEnvironmentPreparer { 619 struct Closure { 620 virtual bool operator()(JSContext* cx) = 0; 621 }; 622 623 virtual void invoke(JS::HandleObject global, Closure& closure) = 0; 624 }; 625 626 extern JS_PUBLIC_API void PrepareScriptEnvironmentAndInvoke( 627 JSContext* cx, JS::HandleObject global, 628 ScriptEnvironmentPreparer::Closure& closure); 629 630 JS_PUBLIC_API void SetScriptEnvironmentPreparer( 631 JSContext* cx, ScriptEnvironmentPreparer* preparer); 632 633 // Abstract base class for objects that build allocation metadata for JavaScript 634 // values. 635 struct AllocationMetadataBuilder { 636 AllocationMetadataBuilder() = default; 637 638 // Return a metadata object for the newly constructed object |obj|, or 639 // nullptr if there's no metadata to attach. 640 // 641 // Implementations should treat all errors as fatal; there is no way to 642 // report errors from this callback. In particular, the caller provides an 643 // oomUnsafe for overriding implementations to use. 644 virtual JSObject* build(JSContext* cx, JS::HandleObject obj, 645 AutoEnterOOMUnsafeRegion& oomUnsafe) const { 646 return nullptr; 647 } 648 }; 649 650 /** 651 * Specify a callback to invoke when creating each JS object in the current 652 * compartment, which may return a metadata object to associate with the 653 * object. 654 */ 655 JS_PUBLIC_API void SetAllocationMetadataBuilder( 656 JSContext* cx, const AllocationMetadataBuilder* callback); 657 658 /** Get the metadata associated with an object. */ 659 JS_PUBLIC_API JSObject* GetAllocationMetadata(JSObject* obj); 660 661 JS_PUBLIC_API bool GetElementsWithAdder(JSContext* cx, JS::HandleObject obj, 662 JS::HandleObject receiver, 663 uint32_t begin, uint32_t end, 664 js::ElementAdder* adder); 665 666 JS_PUBLIC_API bool ForwardToNative(JSContext* cx, JSNative native, 667 const JS::CallArgs& args); 668 669 /** 670 * Helper function for HTMLDocument and HTMLFormElement. 671 * 672 * These are the only two interfaces that have [OverrideBuiltins], a named 673 * getter, and no named setter. They're implemented as proxies with a custom 674 * getOwnPropertyDescriptor() method. Unfortunately, overriding 675 * getOwnPropertyDescriptor() automatically affects the behavior of set(), 676 * which normally is just common sense but is *not* desired for these two 677 * interfaces. 678 * 679 * The fix is for these two interfaces to override set() to ignore the 680 * getOwnPropertyDescriptor() override. 681 * 682 * SetPropertyIgnoringNamedGetter is exposed to make it easier to override 683 * set() in this way. It carries out all the steps of BaseProxyHandler::set() 684 * except the initial getOwnPropertyDescriptor() call. The caller must supply 685 * that descriptor as the 'ownDesc' parameter. 686 * 687 * Implemented in proxy/BaseProxyHandler.cpp. 688 */ 689 JS_PUBLIC_API bool SetPropertyIgnoringNamedGetter( 690 JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v, 691 JS::HandleValue receiver, 692 JS::Handle<mozilla::Maybe<JS::PropertyDescriptor>> ownDesc, 693 JS::ObjectOpResult& result); 694 695 // This function is for one specific use case, please don't use this for 696 // anything else! 697 extern JS_PUBLIC_API bool ExecuteInFrameScriptEnvironment( 698 JSContext* cx, JS::HandleObject obj, JS::HandleScript script, 699 JS::MutableHandleObject scope); 700 701 extern JS_PUBLIC_API bool IsSavedFrame(JSObject* obj); 702 703 // Matches the condition in js/src/jit/ProcessExecutableMemory.cpp 704 #if defined(XP_WIN) 705 // Parameters use void* types to avoid #including windows.h. The return value of 706 // this function is returned from the exception handler. 707 using JitExceptionHandler = long (*)(void* exceptionRecord, // PEXECTION_RECORD 708 void* context); // PCONTEXT 709 710 /** 711 * Windows uses "structured exception handling" to handle faults. When a fault 712 * occurs, the stack is searched for a handler (similar to C++ exception 713 * handling). If the search does not find a handler, the "unhandled exception 714 * filter" is called. Breakpad uses the unhandled exception filter to do crash 715 * reporting. Unfortunately, on Win64, JIT code on the stack completely throws 716 * off this unwinding process and prevents the unhandled exception filter from 717 * being called. The reason is that Win64 requires unwind information be 718 * registered for all code regions and JIT code has none. While it is possible 719 * to register full unwind information for JIT code, this is a lot of work (one 720 * has to be able to recover the frame pointer at any PC) so instead we register 721 * a handler for all JIT code that simply calls breakpad's unhandled exception 722 * filter (which will perform crash reporting and then terminate the process). 723 * This would be wrong if there was an outer __try block that expected to handle 724 * the fault, but this is not generally allowed. 725 * 726 * Gecko must call SetJitExceptionFilter before any JIT code is compiled and 727 * only once per process. 728 */ 729 extern JS_PUBLIC_API void SetJitExceptionHandler(JitExceptionHandler handler); 730 #endif 731 732 extern JS_PUBLIC_API bool ReportIsNotFunction(JSContext* cx, JS::HandleValue v); 733 734 class MOZ_STACK_CLASS JS_PUBLIC_API AutoAssertNoContentJS { 735 public: 736 explicit AutoAssertNoContentJS(JSContext* cx); 737 ~AutoAssertNoContentJS(); 738 739 private: 740 JSContext* context_; 741 bool prevAllowContentJS_; 742 }; 743 744 /** 745 * This function reports memory used by a zone in bytes, this includes: 746 * * The size of this JS GC zone. 747 * * Malloc memory referred to from this zone. 748 * * JIT memory for this zone. 749 * 750 * Note that malloc memory referred to from this zone can include 751 * SharedArrayBuffers which may also be referred to from other zones. Adding the 752 * memory usage of multiple zones may lead to an over-estimate. 753 */ 754 extern JS_PUBLIC_API uint64_t GetMemoryUsageForZone(JS::Zone* zone); 755 756 enum class MemoryUse : uint8_t; 757 758 namespace gc { 759 760 struct SharedMemoryUse { 761 explicit SharedMemoryUse(MemoryUse use) : count(0), nbytes(0) { 762 #ifdef DEBUG 763 this->use = use; 764 #endif 765 } 766 767 size_t count; 768 size_t nbytes; 769 #ifdef DEBUG 770 MemoryUse use; 771 #endif 772 }; 773 774 // A map which tracks shared memory uses (shared in the sense that an allocation 775 // can be referenced by more than one GC thing in a zone). This allows us to 776 // only account for the memory once. 777 using SharedMemoryMap = 778 HashMap<void*, SharedMemoryUse, DefaultHasher<void*>, SystemAllocPolicy>; 779 780 } /* namespace gc */ 781 782 extern JS_PUBLIC_API const gc::SharedMemoryMap& GetSharedMemoryUsageForZone( 783 JS::Zone* zone); 784 785 // Get the total amount of GC heap memory used by the runtime, including malloc 786 // memory. 787 extern JS_PUBLIC_API uint64_t GetGCHeapUsage(JSContext* cx); 788 789 class JS_PUBLIC_API CompartmentTransplantCallback { 790 public: 791 virtual JSObject* getObjectToTransplant(JS::Compartment* compartment) = 0; 792 }; 793 794 // Gather a set of remote window proxies by calling the callback on every 795 // compartment, then transform them into cross-compartment wrappers to newTarget 796 // via brain transplants. If there's a proxy in newTarget's compartment, it will 797 // get swapped with newTarget, and the value of newTarget will be updated. If 798 // the callback returns null for a compartment, no cross-compartment wrapper 799 // will be created for that compartment. Any non-null values it returns must be 800 // DOM remote proxies from the compartment that was passed in. 801 extern JS_PUBLIC_API void RemapRemoteWindowProxies( 802 JSContext* cx, CompartmentTransplantCallback* callback, 803 JS::MutableHandleObject newTarget); 804 805 extern JS_PUBLIC_API JS::Zone* GetObjectZoneFromAnyThread(const JSObject* obj); 806 807 } /* namespace js */ 808 809 #endif /* jsfriendapi_h */