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 http://mozilla.org/MPL/2.0/. */
#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
* $JSGC_EXTRA_POISONING environment variable.
*/
extern JS_PUBLIC_API int 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);
#endif
/**
* 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);
#endif
// 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) {
MOZ_ASSERT(!js::UninlinedIsCrossCompartmentWrapper(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);
#else
inline void AssertSameCompartment(JSObject* objA, JSObject* objB) {}
#endif
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
* `JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS` as flags to get
* 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(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,
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 {
NukeWindowReferences,
DontNukeWindowReferences
} NukeReferencesToWindow;
typedef enum NukeReferencesFromTarget {
NukeAllReferences,
NukeIncomingReferences,
} 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
static MOZ_ALWAYS_INLINE const JSJitInfo* FUNCTION_VALUE_TO_JITINFO(
const JS::Value& v) {
JSObject* obj = &v.toObject();
MOZ_ASSERT(JS::GetClass(obj)->isJSFunction());
auto* fun = reinterpret_cast<JS::shadow::Function*>(obj);
MOZ_ASSERT(!(fun->flagsAndArgCount() & js::JS_FUNCTION_INTERPRETED_BITS),
"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));
fun->setJitInfoOrScript(const_cast<JSJitInfo*>(info));
}
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());
}
MOZ_ASSERT(id.isVoid());
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);
#endif
extern JS_PUBLIC_API bool ReportIsNotFunction(JSContext* cx, JS::HandleValue v);
class MOZ_STACK_CLASS JS_PUBLIC_API AutoAssertNoContentJS {
public:
explicit AutoAssertNoContentJS(JSContext* cx);
~AutoAssertNoContentJS();
private:
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;
#endif
}
size_t count;
size_t nbytes;
#ifdef DEBUG
MemoryUse use;
#endif
};
// 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 {
public:
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 */