From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- js/src/jsfriendapi.h | 808 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 808 insertions(+) create mode 100644 js/src/jsfriendapi.h (limited to 'js/src/jsfriendapi.h') diff --git a/js/src/jsfriendapi.h b/js/src/jsfriendapi.h new file mode 100644 index 0000000000..74ceb75f6b --- /dev/null +++ b/js/src/jsfriendapi.h @@ -0,0 +1,808 @@ +/* -*- 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/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 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, + unsigned* 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 desc); + +extern JS_PUBLIC_API bool JS_WrapPropertyDescriptor( + JSContext* cx, + JS::MutableHandle> 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); + +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(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); + +/** + * 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(obj); + MOZ_ASSERT(!(fun->flagsAndArgCount() & js::JS_FUNCTION_INTERPRETED_BITS), + "Unexpected non-native function"); + + return static_cast(fun->jitInfoOrScript()); +} + +static MOZ_ALWAYS_INLINE void SET_JITINFO(JSFunction* func, + const JSJitInfo* info) { + auto* fun = reinterpret_cast(func); + MOZ_ASSERT(!(fun->flagsAndArgCount() & js::JS_FUNCTION_INTERPRETED_BITS)); + + fun->setJitInfoOrScript(const_cast(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> 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, 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 */ -- cgit v1.2.3