Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at */
#ifndef jsfriendapi_h
#define jsfriendapi_h
#include "jspubtd.h"
#include "js/CallArgs.h"
#include "js/Class.h"
#include "js/ColumnNumber.h" // JS::LimitedColumnNumberOneOrigin
#include "js/GCAPI.h"
#include "js/HeapAPI.h"
#include "js/Object.h" // JS::GetClass
#include "js/shadow/Function.h" // JS::shadow::Function
#include "js/shadow/Object.h" // JS::shadow::Object
#include "js/TypeDecls.h"
class JSJitInfo;
* Set a callback used to trace gray roots.
* The callback is called after the first slice of GC so the embedding must
* implement appropriate barriers on its gray roots to ensure correctness.
* This callback may be called multiple times for different sets of zones. Use
* JS::ZoneIsGrayMarking() to determine whether roots from a particular zone are
* required.
extern JS_PUBLIC_API void JS_SetGrayGCRootsTracer(JSContext* cx,
JSGrayRootsTracer traceOp,
void* data);
extern JS_PUBLIC_API JSObject* JS_FindCompilationScope(JSContext* cx,
JS::HandleObject obj);
extern JS_PUBLIC_API JSFunction* JS_GetObjectFunction(JSObject* obj);
* Allocate an object in exactly the same way as JS_NewObjectWithGivenProto, but
* without invoking the metadata callback on it. This allows creation of
* internal bookkeeping objects that are guaranteed to not have metadata
* attached to them.
extern JS_PUBLIC_API JSObject* JS_NewObjectWithoutMetadata(
JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto);
extern JS_PUBLIC_API bool JS_NondeterministicGetWeakMapKeys(
JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
extern JS_PUBLIC_API bool JS_NondeterministicGetWeakSetKeys(
JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject ret);
// Raw JSScript* because this needs to be callable from a signal handler.
extern JS_PUBLIC_API unsigned JS_PCToLineNumber(
JSScript* script, jsbytecode* pc,
JS::LimitedColumnNumberOneOrigin* columnp = nullptr);
* Determine whether the given object is backed by a DeadObjectProxy.
* Such objects hold no other objects (they have no outgoing reference edges)
* and will throw if you touch them (e.g. by reading/writing a property).
extern JS_PUBLIC_API bool JS_IsDeadWrapper(JSObject* obj);
* Creates a new dead wrapper object in the given scope. To be used when
* attempting to wrap objects from scopes which are already dead.
* If origObject is passed, it must be an proxy object, and will be
* used to determine the characteristics of the new dead wrapper.
extern JS_PUBLIC_API JSObject* JS_NewDeadWrapper(
JSContext* cx, JSObject* origObject = nullptr);
namespace js {
* Get the script private value associated with an object, if any.
* The private value is set with SetScriptPrivate() or SetModulePrivate() and is
* internally stored on the relevant ScriptSourceObject.
* This is used by the cycle collector to trace through
* ScriptSourceObjects. This allows private values to contain an nsISupports
* pointer and hence support references to cycle collected C++ objects.
JS_PUBLIC_API JS::Value MaybeGetScriptPrivate(JSObject* object);
} // namespace js
* Used by the cycle collector to trace through a shape or object group and
* all cycle-participating data it reaches, using bounded stack space.
extern JS_PUBLIC_API void JS_TraceShapeCycleCollectorChildren(
JS::CallbackTracer* trc, JS::GCCellPtr shape);
extern JS_PUBLIC_API void JS_TraceObjectGroupCycleCollectorChildren(
JS::CallbackTracer* trc, JS::GCCellPtr group);
extern JS_PUBLIC_API JSPrincipals* JS_GetScriptPrincipals(JSScript* script);
extern JS_PUBLIC_API bool JS_ScriptHasMutedErrors(JSScript* script);
extern JS_PUBLIC_API JSObject* JS_CloneObject(JSContext* cx,
JS::HandleObject obj,
JS::HandleObject proto);
* Copy the own properties of src to dst in a fast way. src and dst must both
* be native and must be in the compartment of cx. They must have the same
* class, the same parent, and the same prototype. Class reserved slots will
* NOT be copied.
* dst must not have any properties on it before this function is called.
* src must have been allocated via JS_NewObjectWithoutMetadata so that we can
* be sure it has no metadata that needs copying to dst. This also means that
* dst needs to have the compartment global as its parent. This function will
* preserve the existing metadata on dst, if any.
extern JS_PUBLIC_API bool JS_InitializePropertiesFromCompatibleNativeObject(
JSContext* cx, JS::HandleObject dst, JS::HandleObject src);
namespace js {
JS_PUBLIC_API bool IsArgumentsObject(JS::HandleObject obj);
JS_PUBLIC_API bool AddRawValueRoot(JSContext* cx, JS::Value* vp,
const char* name);
JS_PUBLIC_API void RemoveRawValueRoot(JSContext* cx, JS::Value* vp);
} // namespace js
namespace JS {
* Set all of the uninitialized lexicals on an object to undefined. Return
* true if any lexicals were initialized and false otherwise.
* */
extern JS_PUBLIC_API bool ForceLexicalInitialization(JSContext* cx,
HandleObject obj);
* Whether we are poisoning unused/released data for error detection. Governed
* by the JS_GC_ALLOW_EXTRA_POISONING #ifdef as well as the
* javascript.options.extra_gc_poisoning pref.
extern JS_PUBLIC_API bool IsGCPoisoning();
extern JS_PUBLIC_API JSPrincipals* GetRealmPrincipals(JS::Realm* realm);
extern JS_PUBLIC_API void SetRealmPrincipals(JS::Realm* realm,
JSPrincipals* principals);
extern JS_PUBLIC_API bool GetIsSecureContext(JS::Realm* realm);
extern JS_PUBLIC_API bool GetDebuggerObservesWasm(JS::Realm* realm);
} // namespace JS
* Copies all own properties and private fields from |obj| to |target|. Both
* |obj| and |target| must not be cross-compartment wrappers because we have to
* enter their realms.
* This function immediately enters a realm, and does not impose any
* restrictions on the realm of |cx|.
extern JS_PUBLIC_API bool JS_CopyOwnPropertiesAndPrivateFields(
JSContext* cx, JS::HandleObject target, JS::HandleObject obj);
extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
JSContext* cx, JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor(
JSContext* cx,
JS::MutableHandle<mozilla::Maybe<JS::PropertyDescriptor>> desc);
struct JSFunctionSpecWithHelp {
const char* name;
JSNative call;
uint16_t nargs;
uint16_t flags;
const JSJitInfo* jitInfo;
const char* usage;
const char* help;
#define JS_FN_HELP(name, call, nargs, flags, usage, help) \
{name, call, nargs, (flags) | JSPROP_ENUMERATE, nullptr, usage, help}
#define JS_INLINABLE_FN_HELP(name, call, nargs, flags, native, usage, help) \
{name, call, nargs, (flags) | JSPROP_ENUMERATE, &js::jit::JitInfo_##native, \
usage, help}
#define JS_FS_HELP_END {nullptr, nullptr, 0, 0, nullptr, nullptr}
extern JS_PUBLIC_API bool JS_DefineFunctionsWithHelp(
JSContext* cx, JS::HandleObject obj, const JSFunctionSpecWithHelp* fs);
namespace js {
* Use the runtime's internal handling of job queues for Promise jobs.
* Most embeddings, notably web browsers, will have their own task scheduling
* systems and need to integrate handling of Promise jobs into that, so they
* will want to manage job queues themselves. For basic embeddings such as the
* JS shell that don't have an event loop of their own, it's easier to have
* SpiderMonkey handle job queues internally.
* Note that the embedding still has to trigger processing of job queues at
* right time(s), such as after evaluation of a script has run to completion.
extern JS_PUBLIC_API bool UseInternalJobQueues(JSContext* cx);
#ifdef DEBUG
* Given internal job queues are used, return currently queued jobs as an
* array of job objects.
extern JS_PUBLIC_API JSObject* GetJobsInInternalJobQueue(JSContext* cx);
* Enqueue |job| on the internal job queue.
* This is useful in tests for creating situations where a call occurs with no
* other JavaScript on the stack.
extern JS_PUBLIC_API bool EnqueueJob(JSContext* cx, JS::HandleObject job);
* Instruct the runtime to stop draining the internal job queue.
* Useful if the embedding is in the process of quitting in reaction to a
* builtin being called, or if it wants to resume executing jobs later on.
extern JS_PUBLIC_API void StopDrainingJobQueue(JSContext* cx);
* Instruct the runtime to restart draining the internal job queue after
* stopping it with StopDrainingJobQueue.
extern JS_PUBLIC_API void RestartDrainingJobQueue(JSContext* cx);
extern JS_PUBLIC_API void RunJobs(JSContext* cx);
extern JS_PUBLIC_API JS::Zone* GetRealmZone(JS::Realm* realm);
using PreserveWrapperCallback = bool (*)(JSContext*, JS::HandleObject);
using HasReleasedWrapperCallback = bool (*)(JS::HandleObject);
extern JS_PUBLIC_API bool IsSystemRealm(JS::Realm* realm);
extern JS_PUBLIC_API bool IsSystemCompartment(JS::Compartment* comp);
extern JS_PUBLIC_API bool IsSystemZone(JS::Zone* zone);
struct WeakMapTracer {
JSRuntime* runtime;
explicit WeakMapTracer(JSRuntime* rt) : runtime(rt) {}
// Weak map tracer callback, called once for every binding of every
// weak map that was live at the time of the last garbage collection.
// m will be nullptr if the weak map is not contained in a JS Object.
// The callback should not GC (and will assert in a debug build if it does
// so.)
virtual void trace(JSObject* m, JS::GCCellPtr key, JS::GCCellPtr value) = 0;
extern JS_PUBLIC_API void TraceWeakMaps(WeakMapTracer* trc);
extern JS_PUBLIC_API bool AreGCGrayBitsValid(JSRuntime* rt);
extern JS_PUBLIC_API bool ZoneGlobalsAreAllGray(JS::Zone* zone);
extern JS_PUBLIC_API bool IsCompartmentZoneSweepingOrCompacting(
JS::Compartment* comp);
using IterateGCThingCallback = void (*)(void*, JS::GCCellPtr,
const JS::AutoRequireNoGC&);
extern JS_PUBLIC_API void TraceGrayWrapperTargets(JSTracer* trc,
JS::Zone* zone);
* Invoke cellCallback on every gray JSObject in the given zone.
extern JS_PUBLIC_API void IterateGrayObjects(
JS::Zone* zone, IterateGCThingCallback cellCallback, void* data);
#if defined(JS_GC_ZEAL) || defined(DEBUG)
// Trace the heap and check there are no black to gray edges. These are
// not allowed since the cycle collector could throw away the gray thing and
// leave a dangling pointer.
// This doesn't trace weak maps as these are handled separately.
extern JS_PUBLIC_API bool CheckGrayMarkingState(JSRuntime* rt);
// Note: this returns nullptr iff |zone| is the atoms zone.
extern JS_PUBLIC_API JS::Realm* GetAnyRealmInZone(JS::Zone* zone);
// Returns the first realm's global in a compartment. Note: this is not
// guaranteed to always be the same realm because individual realms can be
// collected by the GC.
extern JS_PUBLIC_API JSObject* GetFirstGlobalInCompartment(
JS::Compartment* comp);
// Returns true if the compartment contains a global object and this global is
// not being collected.
extern JS_PUBLIC_API bool CompartmentHasLiveGlobal(JS::Compartment* comp);
// Returns true if this compartment can be shared across multiple Realms. Used
// when we're looking for an existing compartment to place a new Realm in.
extern JS_PUBLIC_API bool IsSharableCompartment(JS::Compartment* comp);
// This is equal to |&JSObject::class_|. Use it in places where you don't want
// to #include vm/JSObject.h.
extern JS_PUBLIC_DATA const JSClass* const ObjectClassPtr;
JS_PUBLIC_API const JSClass* ProtoKeyToClass(JSProtoKey key);
// Returns the key for the class inherited by a given standard class (that
// is to say, the prototype of this standard class's prototype).
// You must be sure that this corresponds to a standard class with a cached
// JSProtoKey before calling this function. In general |key| will match the
// cached proto key, except in cases where multiple JSProtoKeys share a
// JSClass.
inline JSProtoKey InheritanceProtoKeyForStandardClass(JSProtoKey key) {
// [Object] has nothing to inherit from.
if (key == JSProto_Object) {
return JSProto_Null;
// If we're ClassSpec defined return the proto key from that
if (ProtoKeyToClass(key)->specDefined()) {
return ProtoKeyToClass(key)->specInheritanceProtoKey();
// Otherwise, we inherit [Object].
return JSProto_Object;
JS_PUBLIC_API bool ShouldIgnorePropertyDefinition(JSContext* cx, JSProtoKey key,
jsid id);
JS_PUBLIC_API bool IsFunctionObject(JSObject* obj);
JS_PUBLIC_API bool UninlinedIsCrossCompartmentWrapper(const JSObject* obj);
// CrossCompartmentWrappers are shared by all realms within the compartment, so
// getting a wrapper's realm usually doesn't make sense.
static MOZ_ALWAYS_INLINE JS::Realm* GetNonCCWObjectRealm(JSObject* obj) {
return reinterpret_cast<JS::shadow::Object*>(obj)->shape->base->realm;
JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JSObject* obj);
JS_PUBLIC_API void AssertSameCompartment(JSContext* cx, JS::HandleValue v);
#ifdef JS_DEBUG
JS_PUBLIC_API void AssertSameCompartment(JSObject* objA, JSObject* objB);
inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {}
JS_PUBLIC_API void NotifyAnimationActivity(JSObject* obj);
JS_PUBLIC_API JSFunction* DefineFunctionWithReserved(
JSContext* cx, JSObject* obj, const char* name, JSNative call,
unsigned nargs, unsigned attrs);
JS_PUBLIC_API JSFunction* NewFunctionWithReserved(JSContext* cx, JSNative call,
unsigned nargs,
unsigned flags,
const char* name);
JS_PUBLIC_API JSFunction* NewFunctionByIdWithReserved(JSContext* cx,
JSNative native,
unsigned nargs,
unsigned flags, jsid id);
JS_PUBLIC_API JSFunction* NewFunctionByIdWithReservedAndProto(
JSContext* cx, JSNative native, JS::Handle<JSObject*> proto, unsigned nargs,
unsigned flags, jsid id);
* Get or set function's reserved slot value.
* `fun` should be a function created with `*WithReserved` API above.
* Such functions have 2 reserved slots, and `which` can be either 0 or 1.
JS_PUBLIC_API const JS::Value& GetFunctionNativeReserved(JSObject* fun,
size_t which);
JS_PUBLIC_API void SetFunctionNativeReserved(JSObject* fun, size_t which,
const JS::Value& val);
JS_PUBLIC_API bool FunctionHasNativeReserved(JSObject* fun);
JS_PUBLIC_API bool GetObjectProto(JSContext* cx, JS::HandleObject obj,
JS::MutableHandleObject proto);
extern JS_PUBLIC_API JSObject* GetStaticPrototype(JSObject* obj);
JS_PUBLIC_API bool GetRealmOriginalEval(JSContext* cx,
JS::MutableHandleObject eval);
* Add some or all property keys of obj to the id vector *props.
* The flags parameter controls which property keys are added. Pass a
* combination of the following bits:
* JSITER_OWNONLY - Don't also search the prototype chain; only consider
* obj's own properties.
* JSITER_HIDDEN - Include nonenumerable properties.
* JSITER_SYMBOLS - Include property keys that are symbols. The default
* behavior is to filter out symbols.
* JSITER_SYMBOLSONLY - Exclude non-symbol property keys.
* This is the closest C++ API we have to `Reflect.ownKeys(obj)`, or
* equivalently, the ES6 [[OwnPropertyKeys]] internal method. Pass
* results that match the output of Reflect.ownKeys.
JS_PUBLIC_API bool GetPropertyKeys(JSContext* cx, JS::HandleObject obj,
unsigned flags,
JS::MutableHandleIdVector props);
JS_PUBLIC_API bool AppendUnique(JSContext* cx, JS::MutableHandleIdVector base,
JS::HandleIdVector others);
* Determine whether the given string is an array index in the sense of
* If it isn't, returns false.
* If it is, returns true and outputs the index in *indexp.
JS_PUBLIC_API bool StringIsArrayIndex(const JSLinearString* str,
uint32_t* indexp);
* Overload of StringIsArrayIndex taking a (char16_t*,length) pair. Behaves
* the same as the JSLinearString version.
JS_PUBLIC_API bool StringIsArrayIndex(const char16_t* str, uint32_t length,
uint32_t* indexp);
JS_PUBLIC_API void SetPreserveWrapperCallbacks(
JSContext* cx, PreserveWrapperCallback preserveWrapper,
HasReleasedWrapperCallback hasReleasedWrapper);
JS_PUBLIC_API bool IsObjectInContextCompartment(JSObject* obj,
const JSContext* cx);
* NB: keep these in sync with the copy in builtin/SelfHostingDefines.h.
/* 0x1 is no longer used */
/* 0x2 is no longer used */
#define JSITER_PRIVATE 0x4 /* Include private names in iteration */
#define JSITER_OWNONLY 0x8 /* iterate over obj's own properties only */
#define JSITER_HIDDEN 0x10 /* also enumerate non-enumerable properties */
#define JSITER_SYMBOLS 0x20 /* also include symbol property keys */
#define JSITER_SYMBOLSONLY 0x40 /* exclude string property keys */
#define JSITER_FORAWAITOF 0x80 /* for-await-of */
using DOMInstanceClassHasProtoAtDepth = bool (*)(const JSClass*, uint32_t,
struct JSDOMCallbacks {
DOMInstanceClassHasProtoAtDepth instanceClassMatchesProto;
using DOMCallbacks = struct JSDOMCallbacks;
extern JS_PUBLIC_API void SetDOMCallbacks(JSContext* cx,
const DOMCallbacks* callbacks);
extern JS_PUBLIC_API const DOMCallbacks* GetDOMCallbacks(JSContext* cx);
extern JS_PUBLIC_API JSObject* GetTestingFunctions(JSContext* cx);
/* Implemented in jsexn.cpp. */
* Get an error type name from a JSExnType constant.
* Returns nullptr for invalid arguments and JSEXN_INTERNALERR
extern JS_PUBLIC_API JSLinearString* GetErrorTypeName(JSContext* cx,
int16_t exnType);
/* Implemented in CrossCompartmentWrapper.cpp. */
typedef enum NukeReferencesToWindow {
} NukeReferencesToWindow;
typedef enum NukeReferencesFromTarget {
} NukeReferencesFromTarget;
* These filters are designed to be ephemeral stack classes, and thus don't
* do any rooting or holding of their members.
struct CompartmentFilter {
virtual bool match(JS::Compartment* c) const = 0;
struct AllCompartments : public CompartmentFilter {
virtual bool match(JS::Compartment* c) const override { return true; }
struct SingleCompartment : public CompartmentFilter {
JS::Compartment* ours;
explicit SingleCompartment(JS::Compartment* c) : ours(c) {}
virtual bool match(JS::Compartment* c) const override { return c == ours; }
extern JS_PUBLIC_API bool NukeCrossCompartmentWrappers(
JSContext* cx, const CompartmentFilter& sourceFilter, JS::Realm* target,
NukeReferencesToWindow nukeReferencesToWindow,
NukeReferencesFromTarget nukeReferencesFromTarget);
extern JS_PUBLIC_API bool AllowNewWrapper(JS::Compartment* target,
JSObject* obj);
extern JS_PUBLIC_API bool NukedObjectRealm(JSObject* obj);
/* Implemented in jsdate.cpp. */
/** Detect whether the internal date value is NaN. */
extern JS_PUBLIC_API bool DateIsValid(JSContext* cx, JS::HandleObject obj,
bool* isValid);
extern JS_PUBLIC_API bool DateGetMsecSinceEpoch(JSContext* cx,
JS::HandleObject obj,
double* msecSinceEpoch);
} /* namespace js */
namespace js {
/* Implemented in vm/StructuredClone.cpp. */
extern JS_PUBLIC_API uint64_t GetSCOffset(JSStructuredCloneWriter* writer);
} // namespace js
namespace js {
/* Statically asserted in FunctionFlags.cpp. */
static const unsigned JS_FUNCTION_INTERPRETED_BITS = 0x0060;
} // namespace js
const JS::Value& v) {
JSObject* obj = &v.toObject();
auto* fun = reinterpret_cast<JS::shadow::Function*>(obj);
"Unexpected non-native function");
return static_cast<const JSJitInfo*>(fun->jitInfoOrScript());
static MOZ_ALWAYS_INLINE void SET_JITINFO(JSFunction* func,
const JSJitInfo* info) {
auto* fun = reinterpret_cast<JS::shadow::Function*>(func);
MOZ_ASSERT(!(fun->flagsAndArgCount() & js::JS_FUNCTION_INTERPRETED_BITS));
static_assert(sizeof(jsid) == sizeof(void*));
namespace js {
static MOZ_ALWAYS_INLINE JS::Value IdToValue(jsid id) {
if (id.isString()) {
return JS::StringValue(id.toString());
if (id.isInt()) {
return JS::Int32Value(id.toInt());
if (id.isSymbol()) {
return JS::SymbolValue(id.toSymbol());
return JS::UndefinedValue();
* PrepareScriptEnvironmentAndInvoke asserts the embedder has registered a
* ScriptEnvironmentPreparer and then it calls the preparer's 'invoke' method
* with the given |closure|, with the assumption that the preparer will set up
* any state necessary to run script in |global|, invoke |closure| with a valid
* JSContext*, report any exceptions thrown from the closure, and return.
* PrepareScriptEnvironmentAndInvoke will report any exceptions that are thrown
* by the closure. Consumers who want to propagate back whether the closure
* succeeded should do so via members of the closure itself.
struct ScriptEnvironmentPreparer {
struct Closure {
virtual bool operator()(JSContext* cx) = 0;
virtual void invoke(JS::HandleObject global, Closure& closure) = 0;
extern JS_PUBLIC_API void PrepareScriptEnvironmentAndInvoke(
JSContext* cx, JS::HandleObject global,
ScriptEnvironmentPreparer::Closure& closure);
JS_PUBLIC_API void SetScriptEnvironmentPreparer(
JSContext* cx, ScriptEnvironmentPreparer* preparer);
// Abstract base class for objects that build allocation metadata for JavaScript
// values.
struct AllocationMetadataBuilder {
AllocationMetadataBuilder() = default;
// Return a metadata object for the newly constructed object |obj|, or
// nullptr if there's no metadata to attach.
// Implementations should treat all errors as fatal; there is no way to
// report errors from this callback. In particular, the caller provides an
// oomUnsafe for overriding implementations to use.
virtual JSObject* build(JSContext* cx, JS::HandleObject obj,
AutoEnterOOMUnsafeRegion& oomUnsafe) const {
return nullptr;
* Specify a callback to invoke when creating each JS object in the current
* compartment, which may return a metadata object to associate with the
* object.
JS_PUBLIC_API void SetAllocationMetadataBuilder(
JSContext* cx, const AllocationMetadataBuilder* callback);
/** Get the metadata associated with an object. */
JS_PUBLIC_API JSObject* GetAllocationMetadata(JSObject* obj);
JS_PUBLIC_API bool GetElementsWithAdder(JSContext* cx, JS::HandleObject obj,
JS::HandleObject receiver,
uint32_t begin, uint32_t end,
js::ElementAdder* adder);
JS_PUBLIC_API bool ForwardToNative(JSContext* cx, JSNative native,
const JS::CallArgs& args);
* Helper function for HTMLDocument and HTMLFormElement.
* These are the only two interfaces that have [OverrideBuiltins], a named
* getter, and no named setter. They're implemented as proxies with a custom
* getOwnPropertyDescriptor() method. Unfortunately, overriding
* getOwnPropertyDescriptor() automatically affects the behavior of set(),
* which normally is just common sense but is *not* desired for these two
* interfaces.
* The fix is for these two interfaces to override set() to ignore the
* getOwnPropertyDescriptor() override.
* SetPropertyIgnoringNamedGetter is exposed to make it easier to override
* set() in this way. It carries out all the steps of BaseProxyHandler::set()
* except the initial getOwnPropertyDescriptor() call. The caller must supply
* that descriptor as the 'ownDesc' parameter.
* Implemented in proxy/BaseProxyHandler.cpp.
JS_PUBLIC_API bool SetPropertyIgnoringNamedGetter(
JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver,
JS::Handle<mozilla::Maybe<JS::PropertyDescriptor>> ownDesc,
JS::ObjectOpResult& result);
// This function is for one specific use case, please don't use this for
// anything else!
extern JS_PUBLIC_API bool ExecuteInFrameScriptEnvironment(
JSContext* cx, JS::HandleObject obj, JS::HandleScript script,
JS::MutableHandleObject scope);
extern JS_PUBLIC_API bool IsSavedFrame(JSObject* obj);
// Matches the condition in js/src/jit/ProcessExecutableMemory.cpp
#if defined(XP_WIN)
// Parameters use void* types to avoid #including windows.h. The return value of
// this function is returned from the exception handler.
typedef long (*JitExceptionHandler)(void* exceptionRecord, // PEXECTION_RECORD
void* context); // PCONTEXT
* Windows uses "structured exception handling" to handle faults. When a fault
* occurs, the stack is searched for a handler (similar to C++ exception
* handling). If the search does not find a handler, the "unhandled exception
* filter" is called. Breakpad uses the unhandled exception filter to do crash
* reporting. Unfortunately, on Win64, JIT code on the stack completely throws
* off this unwinding process and prevents the unhandled exception filter from
* being called. The reason is that Win64 requires unwind information be
* registered for all code regions and JIT code has none. While it is possible
* to register full unwind information for JIT code, this is a lot of work (one
* has to be able to recover the frame pointer at any PC) so instead we register
* a handler for all JIT code that simply calls breakpad's unhandled exception
* filter (which will perform crash reporting and then terminate the process).
* This would be wrong if there was an outer __try block that expected to handle
* the fault, but this is not generally allowed.
* Gecko must call SetJitExceptionFilter before any JIT code is compiled and
* only once per process.
extern JS_PUBLIC_API void SetJitExceptionHandler(JitExceptionHandler handler);
extern JS_PUBLIC_API bool ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
explicit AutoAssertNoContentJS(JSContext* cx);
JSContext* context_;
bool prevAllowContentJS_;
* This function reports memory used by a zone in bytes, this includes:
* * The size of this JS GC zone.
* * Malloc memory referred to from this zone.
* * JIT memory for this zone.
* Note that malloc memory referred to from this zone can include
* SharedArrayBuffers which may also be referred to from other zones. Adding the
* memory usage of multiple zones may lead to an over-estimate.
extern JS_PUBLIC_API uint64_t GetMemoryUsageForZone(JS::Zone* zone);
enum class MemoryUse : uint8_t;
namespace gc {
struct SharedMemoryUse {
explicit SharedMemoryUse(MemoryUse use) : count(0), nbytes(0) {
#ifdef DEBUG
this->use = use;
size_t count;
size_t nbytes;
#ifdef DEBUG
MemoryUse use;
// A map which tracks shared memory uses (shared in the sense that an allocation
// can be referenced by more than one GC thing in a zone). This allows us to
// only account for the memory once.
using SharedMemoryMap =
HashMap<void*, SharedMemoryUse, DefaultHasher<void*>, SystemAllocPolicy>;
} /* namespace gc */
extern JS_PUBLIC_API const gc::SharedMemoryMap& GetSharedMemoryUsageForZone(
JS::Zone* zone);
* This function only reports GC heap memory,
* and not malloc allocated memory associated with GC things.
* It reports the total of all memory for the whole Runtime.
extern JS_PUBLIC_API uint64_t GetGCHeapUsage(JSContext* cx);
class JS_PUBLIC_API CompartmentTransplantCallback {
virtual JSObject* getObjectToTransplant(JS::Compartment* compartment) = 0;
// Gather a set of remote window proxies by calling the callback on every
// compartment, then transform them into cross-compartment wrappers to newTarget
// via brain transplants. If there's a proxy in newTarget's compartment, it will
// get swapped with newTarget, and the value of newTarget will be updated. If
// the callback returns null for a compartment, no cross-compartment wrapper
// will be created for that compartment. Any non-null values it returns must be
// DOM remote proxies from the compartment that was passed in.
extern JS_PUBLIC_API void RemapRemoteWindowProxies(
JSContext* cx, CompartmentTransplantCallback* callback,
JS::MutableHandleObject newTarget);
extern JS_PUBLIC_API JS::Zone* GetObjectZoneFromAnyThread(const JSObject* obj);
} /* namespace js */
#endif /* jsfriendapi_h */