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/jsapi.h | 1007 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1007 insertions(+) create mode 100644 js/src/jsapi.h (limited to 'js/src/jsapi.h') diff --git a/js/src/jsapi.h b/js/src/jsapi.h new file mode 100644 index 0000000000..fe7a4d84e7 --- /dev/null +++ b/js/src/jsapi.h @@ -0,0 +1,1007 @@ +/* -*- 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/. */ + +/* JavaScript API. */ + +#ifndef jsapi_h +#define jsapi_h + +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/FloatingPoint.h" +#include "mozilla/Maybe.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/RangedPtr.h" +#include "mozilla/RefPtr.h" +#include "mozilla/TimeStamp.h" +#include "mozilla/Utf8.h" +#include "mozilla/Variant.h" + +#include +#include +#include +#include + +#include "jspubtd.h" + +#include "js/AllocPolicy.h" +#include "js/CallAndConstruct.h" // JS::Call, JS_CallFunction, JS_CallFunctionName, JS_CallFunctionValue +#include "js/CallArgs.h" +#include "js/CharacterEncoding.h" +#include "js/Class.h" +#include "js/CompileOptions.h" +#include "js/Context.h" +#include "js/Debug.h" +#include "js/ErrorInterceptor.h" +#include "js/ErrorReport.h" +#include "js/Exception.h" +#include "js/GCAPI.h" +#include "js/GCVector.h" +#include "js/GlobalObject.h" +#include "js/HashTable.h" +#include "js/Id.h" +#include "js/Interrupt.h" +#include "js/MapAndSet.h" +#include "js/MemoryCallbacks.h" +#include "js/MemoryFunctions.h" +#include "js/OffThreadScriptCompilation.h" +#include "js/Principals.h" +#include "js/PropertyAndElement.h" // JS_Enumerate +#include "js/PropertyDescriptor.h" +#include "js/PropertySpec.h" +#include "js/Realm.h" +#include "js/RealmIterators.h" +#include "js/RealmOptions.h" +#include "js/RefCounted.h" +#include "js/RootingAPI.h" +#include "js/ScriptPrivate.h" +#include "js/Stack.h" +#include "js/StreamConsumer.h" +#include "js/String.h" +#include "js/TelemetryTimers.h" +#include "js/TracingAPI.h" +#include "js/Transcoding.h" +#include "js/UniquePtr.h" +#include "js/Utility.h" +#include "js/Value.h" +#include "js/ValueArray.h" +#include "js/Vector.h" +#include "js/WaitCallbacks.h" +#include "js/WeakMap.h" +#include "js/WrapperCallbacks.h" +#include "js/Zone.h" + +/************************************************************************/ + +namespace JS { +/** + * Tell JS engine whether to use fdlibm for Math.sin, Math.cos, and Math.tan. + * Using fdlibm ensures that we don't expose a math fingerprint. + */ +extern JS_PUBLIC_API void SetUseFdlibmForSinCosTan(bool value); +} // namespace JS + +/************************************************************************/ + +struct JSFunctionSpec; +struct JSPropertySpec; + +namespace JS { + +template +class SourceText; + +class TwoByteChars; + +using ValueVector = JS::GCVector; +using IdVector = JS::GCVector; +using ScriptVector = JS::GCVector; +using StringVector = JS::GCVector; + +} /* namespace JS */ + +/************************************************************************/ + +static MOZ_ALWAYS_INLINE JS::Value JS_NumberValue(double d) { + int32_t i; + d = JS::CanonicalizeNaN(d); + if (mozilla::NumberIsInt32(d, &i)) { + return JS::Int32Value(i); + } + return JS::DoubleValue(d); +} + +/************************************************************************/ + +JS_PUBLIC_API bool JS_StringHasBeenPinned(JSContext* cx, JSString* str); + +/************************************************************************/ + +/** Microseconds since the epoch, midnight, January 1, 1970 UTC. */ +extern JS_PUBLIC_API int64_t JS_Now(void); + +extern JS_PUBLIC_API bool JS_ValueToObject(JSContext* cx, JS::HandleValue v, + JS::MutableHandleObject objp); + +extern JS_PUBLIC_API JSFunction* JS_ValueToFunction(JSContext* cx, + JS::HandleValue v); + +extern JS_PUBLIC_API JSFunction* JS_ValueToConstructor(JSContext* cx, + JS::HandleValue v); + +extern JS_PUBLIC_API JSString* JS_ValueToSource(JSContext* cx, + JS::Handle v); + +extern JS_PUBLIC_API bool JS_DoubleIsInt32(double d, int32_t* ip); + +extern JS_PUBLIC_API JSType JS_TypeOfValue(JSContext* cx, + JS::Handle v); + +namespace JS { + +extern JS_PUBLIC_API const char* InformalValueTypeName(const JS::Value& v); + +} /* namespace JS */ + +/** True iff fun is the global eval function. */ +extern JS_PUBLIC_API bool JS_IsBuiltinEvalFunction(JSFunction* fun); + +/** True iff fun is the Function constructor. */ +extern JS_PUBLIC_API bool JS_IsBuiltinFunctionConstructor(JSFunction* fun); + +extern JS_PUBLIC_API const char* JS_GetImplementationVersion(void); + +extern JS_PUBLIC_API void JS_SetWrapObjectCallbacks( + JSContext* cx, const JSWrapObjectCallbacks* callbacks); + +// Examine a value to determine if it is one of the built-in Error types. +// If so, return the error type. +extern JS_PUBLIC_API mozilla::Maybe JS_GetErrorType( + const JS::Value& val); + +extern JS_PUBLIC_API bool JS_WrapObject(JSContext* cx, + JS::MutableHandleObject objp); + +extern JS_PUBLIC_API bool JS_WrapValue(JSContext* cx, + JS::MutableHandleValue vp); + +extern JS_PUBLIC_API JSObject* JS_TransplantObject(JSContext* cx, + JS::HandleObject origobj, + JS::HandleObject target); + +/** + * Resolve id, which must contain either a string or an int, to a standard + * class name in obj if possible, defining the class's constructor and/or + * prototype and storing true in *resolved. If id does not name a standard + * class or a top-level property induced by initializing a standard class, + * store false in *resolved and just return true. Return false on error, + * as usual for bool result-typed API entry points. + * + * This API can be called directly from a global object class's resolve op, + * to define standard classes lazily. The class should either have an enumerate + * hook that calls JS_EnumerateStandardClasses, or a newEnumerate hook that + * calls JS_NewEnumerateStandardClasses. newEnumerate is preferred because it's + * faster (does not define all standard classes). + */ +extern JS_PUBLIC_API bool JS_ResolveStandardClass(JSContext* cx, + JS::HandleObject obj, + JS::HandleId id, + bool* resolved); + +extern JS_PUBLIC_API bool JS_MayResolveStandardClass(const JSAtomState& names, + jsid id, + JSObject* maybeObj); + +extern JS_PUBLIC_API bool JS_EnumerateStandardClasses(JSContext* cx, + JS::HandleObject obj); + +/** + * Fill "properties" with a list of standard class names that have not yet been + * resolved on "obj". This can be used as (part of) a newEnumerate class hook + * on a global. Already-resolved things are excluded because they might have + * been deleted by script after being resolved and enumeration considers + * already-defined properties anyway. + */ +extern JS_PUBLIC_API bool JS_NewEnumerateStandardClasses( + JSContext* cx, JS::HandleObject obj, JS::MutableHandleIdVector properties, + bool enumerableOnly); + +/** + * Fill "properties" with a list of standard class names. This can be used for + * proxies that want to define behavior that looks like enumerating a global + * without touching the global itself. + */ +extern JS_PUBLIC_API bool JS_NewEnumerateStandardClassesIncludingResolved( + JSContext* cx, JS::HandleObject obj, JS::MutableHandleIdVector properties, + bool enumerableOnly); + +extern JS_PUBLIC_API bool JS_GetClassObject(JSContext* cx, JSProtoKey key, + JS::MutableHandle objp); + +extern JS_PUBLIC_API bool JS_GetClassPrototype( + JSContext* cx, JSProtoKey key, JS::MutableHandle objp); + +namespace JS { + +/* + * Determine if the given object is an instance/prototype/constructor for a + * standard class. If so, return the associated JSProtoKey. If not, return + * JSProto_Null. + */ + +extern JS_PUBLIC_API JSProtoKey IdentifyStandardInstance(JSObject* obj); + +extern JS_PUBLIC_API JSProtoKey IdentifyStandardPrototype(JSObject* obj); + +extern JS_PUBLIC_API JSProtoKey +IdentifyStandardInstanceOrPrototype(JSObject* obj); + +extern JS_PUBLIC_API JSProtoKey IdentifyStandardConstructor(JSObject* obj); + +extern JS_PUBLIC_API void ProtoKeyToId(JSContext* cx, JSProtoKey key, + JS::MutableHandleId idp); + +} /* namespace JS */ + +extern JS_PUBLIC_API JSProtoKey JS_IdToProtoKey(JSContext* cx, JS::HandleId id); + +extern JS_PUBLIC_API JSObject* JS_GlobalLexicalEnvironment(JSObject* obj); + +extern JS_PUBLIC_API bool JS_HasExtensibleLexicalEnvironment(JSObject* obj); + +extern JS_PUBLIC_API JSObject* JS_ExtensibleLexicalEnvironment(JSObject* obj); + +/** + * Add 'Reflect.parse', a SpiderMonkey extension, to the Reflect object on the + * given global. + */ +extern JS_PUBLIC_API bool JS_InitReflectParse(JSContext* cx, + JS::HandleObject global); + +/** + * Add various profiling-related functions as properties of the given object. + * Defined in builtin/Profilers.cpp. + */ +extern JS_PUBLIC_API bool JS_DefineProfilingFunctions(JSContext* cx, + JS::HandleObject obj); + +namespace JS { + +/** + * Tell JS engine whether Profile Timeline Recording is enabled or not. + * If Profile Timeline Recording is enabled, data shown there like stack won't + * be optimized out. + * This is global state and not associated with specific runtime or context. + */ +extern JS_PUBLIC_API void SetProfileTimelineRecordingEnabled(bool enabled); + +extern JS_PUBLIC_API bool IsProfileTimelineRecordingEnabled(); + +} // namespace JS + +/************************************************************************/ + +extern JS_PUBLIC_API bool JS_ValueToId(JSContext* cx, JS::HandleValue v, + JS::MutableHandleId idp); + +extern JS_PUBLIC_API bool JS_StringToId(JSContext* cx, JS::HandleString s, + JS::MutableHandleId idp); + +extern JS_PUBLIC_API bool JS_IdToValue(JSContext* cx, jsid id, + JS::MutableHandle vp); + +namespace JS { + +/** + * Convert obj to a primitive value. On success, store the result in vp and + * return true. + * + * The hint argument must be JSTYPE_STRING, JSTYPE_NUMBER, or + * JSTYPE_UNDEFINED (no hint). + * + * Implements: ES6 7.1.1 ToPrimitive(input, [PreferredType]). + */ +extern JS_PUBLIC_API bool ToPrimitive(JSContext* cx, JS::HandleObject obj, + JSType hint, JS::MutableHandleValue vp); + +/** + * If args.get(0) is one of the strings "string", "number", or "default", set + * result to JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_UNDEFINED accordingly and + * return true. Otherwise, return false with a TypeError pending. + * + * This can be useful in implementing a @@toPrimitive method. + */ +extern JS_PUBLIC_API bool GetFirstArgumentAsTypeHint(JSContext* cx, + CallArgs args, + JSType* result); + +} /* namespace JS */ + +/** + * Defines a builtin constructor and prototype. Returns the prototype object. + * + * - Defines a property named `name` on `obj`, with its value set to a + * newly-created JS function that invokes the `constructor` JSNative. The + * `length` of the function is `nargs`. + * + * - Creates a prototype object with proto `protoProto` and class `protoClass`. + * If `protoProto` is `nullptr`, `Object.prototype` will be used instead. + * If `protoClass` is `nullptr`, the prototype object will be a plain JS + * object. + * + * - The `ps` and `fs` properties/functions will be defined on the prototype + * object. + * + * - The `static_ps` and `static_fs` properties/functions will be defined on the + * constructor. + */ +extern JS_PUBLIC_API JSObject* JS_InitClass( + JSContext* cx, JS::HandleObject obj, const JSClass* protoClass, + JS::HandleObject protoProto, const char* name, JSNative constructor, + unsigned nargs, const JSPropertySpec* ps, const JSFunctionSpec* fs, + const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs); + +/** + * Set up ctor.prototype = proto and proto.constructor = ctor with the + * right property flags. + */ +extern JS_PUBLIC_API bool JS_LinkConstructorAndPrototype( + JSContext* cx, JS::Handle ctor, JS::Handle proto); + +extern JS_PUBLIC_API bool JS_InstanceOf(JSContext* cx, + JS::Handle obj, + const JSClass* clasp, + JS::CallArgs* args); + +extern JS_PUBLIC_API bool JS_HasInstance(JSContext* cx, + JS::Handle obj, + JS::Handle v, bool* bp); + +namespace JS { + +// Implementation of +// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinaryhasinstance. If +// you're looking for the equivalent of "instanceof", you want JS_HasInstance, +// not this function. +extern JS_PUBLIC_API bool OrdinaryHasInstance(JSContext* cx, + HandleObject objArg, + HandleValue v, bool* bp); + +} // namespace JS + +extern JS_PUBLIC_API JSObject* JS_GetConstructor(JSContext* cx, + JS::Handle proto); + +extern JS_PUBLIC_API JSObject* JS_NewObject(JSContext* cx, + const JSClass* clasp); + +extern JS_PUBLIC_API bool JS_IsNative(JSObject* obj); + +/** + * Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default + * proto. If proto is nullptr, the JS object will have `null` as [[Prototype]]. + */ +extern JS_PUBLIC_API JSObject* JS_NewObjectWithGivenProto( + JSContext* cx, const JSClass* clasp, JS::Handle proto); + +/** + * Creates a new plain object, like `new Object()`, with Object.prototype as + * [[Prototype]]. + */ +extern JS_PUBLIC_API JSObject* JS_NewPlainObject(JSContext* cx); + +/** + * Freeze obj, and all objects it refers to, recursively. This will not recurse + * through non-extensible objects, on the assumption that those are already + * deep-frozen. + */ +extern JS_PUBLIC_API bool JS_DeepFreezeObject(JSContext* cx, + JS::Handle obj); + +/** + * Freezes an object; see ES5's Object.freeze(obj) method. + */ +extern JS_PUBLIC_API bool JS_FreezeObject(JSContext* cx, + JS::Handle obj); + +/*** Standard internal methods ********************************************** + * + * The functions below are the fundamental operations on objects. + * + * ES6 specifies 14 internal methods that define how objects behave. The + * standard is actually quite good on this topic, though you may have to read + * it a few times. See ES6 sections 6.1.7.2 and 6.1.7.3. + * + * When 'obj' is an ordinary object, these functions have boring standard + * behavior as specified by ES6 section 9.1; see the section about internal + * methods in js/src/vm/NativeObject.h. + * + * Proxies override the behavior of internal methods. So when 'obj' is a proxy, + * any one of the functions below could do just about anything. See + * js/public/Proxy.h. + */ + +/** + * Get the prototype of |obj|, storing it in |proto|. + * + * Implements: ES6 [[GetPrototypeOf]] internal method. + */ +extern JS_PUBLIC_API bool JS_GetPrototype(JSContext* cx, JS::HandleObject obj, + JS::MutableHandleObject result); + +/** + * If |obj| (underneath any functionally-transparent wrapper proxies) has as + * its [[GetPrototypeOf]] trap the ordinary [[GetPrototypeOf]] behavior defined + * for ordinary objects, set |*isOrdinary = true| and store |obj|'s prototype + * in |result|. Otherwise set |*isOrdinary = false|. In case of error, both + * outparams have unspecified value. + */ +extern JS_PUBLIC_API bool JS_GetPrototypeIfOrdinary( + JSContext* cx, JS::HandleObject obj, bool* isOrdinary, + JS::MutableHandleObject result); + +/** + * Change the prototype of obj. + * + * Implements: ES6 [[SetPrototypeOf]] internal method. + * + * In cases where ES6 [[SetPrototypeOf]] returns false without an exception, + * JS_SetPrototype throws a TypeError and returns false. + * + * Performance warning: JS_SetPrototype is very bad for performance. It may + * cause compiled jit-code to be invalidated. It also causes not only obj but + * all other objects in the same "group" as obj to be permanently deoptimized. + * It's better to create the object with the right prototype from the start. + */ +extern JS_PUBLIC_API bool JS_SetPrototype(JSContext* cx, JS::HandleObject obj, + JS::HandleObject proto); + +/** + * Determine whether obj is extensible. Extensible objects can have new + * properties defined on them. Inextensible objects can't, and their + * [[Prototype]] slot is fixed as well. + * + * Implements: ES6 [[IsExtensible]] internal method. + */ +extern JS_PUBLIC_API bool JS_IsExtensible(JSContext* cx, JS::HandleObject obj, + bool* extensible); + +/** + * Attempt to make |obj| non-extensible. + * + * Not all failures are treated as errors. See the comment on + * JS::ObjectOpResult in js/public/Class.h. + * + * Implements: ES6 [[PreventExtensions]] internal method. + */ +extern JS_PUBLIC_API bool JS_PreventExtensions(JSContext* cx, + JS::HandleObject obj, + JS::ObjectOpResult& result); + +/** + * Attempt to make the [[Prototype]] of |obj| immutable, such that any attempt + * to modify it will fail. If an error occurs during the attempt, return false + * (with a pending exception set, depending upon the nature of the error). If + * no error occurs, return true with |*succeeded| set to indicate whether the + * attempt successfully made the [[Prototype]] immutable. + * + * This is a nonstandard internal method. + */ +extern JS_PUBLIC_API bool JS_SetImmutablePrototype(JSContext* cx, + JS::HandleObject obj, + bool* succeeded); + +/** + * Equivalent to `Object.assign(target, src)`: Copies the properties from the + * `src` object (which must not be null) to `target` (which also must not be + * null). + */ +extern JS_PUBLIC_API bool JS_AssignObject(JSContext* cx, + JS::HandleObject target, + JS::HandleObject src); + +namespace JS { + +/** + * On success, returns true, setting |*isMap| to true if |obj| is a Map object + * or a wrapper around one, or to false if not. Returns false on failure. + * + * This method returns true with |*isMap == false| when passed an ES6 proxy + * whose target is a Map, or when passed a revoked proxy. + */ +extern JS_PUBLIC_API bool IsMapObject(JSContext* cx, JS::HandleObject obj, + bool* isMap); + +/** + * On success, returns true, setting |*isSet| to true if |obj| is a Set object + * or a wrapper around one, or to false if not. Returns false on failure. + * + * This method returns true with |*isSet == false| when passed an ES6 proxy + * whose target is a Set, or when passed a revoked proxy. + */ +extern JS_PUBLIC_API bool IsSetObject(JSContext* cx, JS::HandleObject obj, + bool* isSet); + +} /* namespace JS */ + +/** + * Assign 'undefined' to all of the object's non-reserved slots. Note: this is + * done for all slots, regardless of the associated property descriptor. + */ +JS_PUBLIC_API void JS_SetAllNonReservedSlotsToUndefined(JS::HandleObject obj); + +extern JS_PUBLIC_API void JS_SetReservedSlot(JSObject* obj, uint32_t index, + const JS::Value& v); + +extern JS_PUBLIC_API void JS_InitReservedSlot(JSObject* obj, uint32_t index, + void* ptr, size_t nbytes, + JS::MemoryUse use); + +template +void JS_InitReservedSlot(JSObject* obj, uint32_t index, T* ptr, + JS::MemoryUse use) { + JS_InitReservedSlot(obj, index, ptr, sizeof(T), use); +} + +/************************************************************************/ + +/* native that can be called as a ctor */ +static constexpr unsigned JSFUN_CONSTRUCTOR = 0x400; + +/* | of all the JSFUN_* flags */ +static constexpr unsigned JSFUN_FLAGS_MASK = 0x400; + +static_assert((JSPROP_FLAGS_MASK & JSFUN_FLAGS_MASK) == 0, + "JSFUN_* flags do not overlap JSPROP_* flags, because bits from " + "the two flag-sets appear in the same flag in some APIs"); + +/* + * Functions and scripts. + */ +extern JS_PUBLIC_API JSFunction* JS_NewFunction(JSContext* cx, JSNative call, + unsigned nargs, unsigned flags, + const char* name); + +namespace JS { + +extern JS_PUBLIC_API JSFunction* GetSelfHostedFunction( + JSContext* cx, const char* selfHostedName, HandleId id, unsigned nargs); + +/** + * Create a new function based on the given JSFunctionSpec, *fs. + * id is the result of a successful call to + * `PropertySpecNameToId(cx, fs->name, &id)` or + `PropertySpecNameToPermanentId(cx, fs->name, &id)`. + * + * Unlike JS_DefineFunctions, this does not treat fs as an array. + * *fs must not be JS_FS_END. + */ +extern JS_PUBLIC_API JSFunction* NewFunctionFromSpec(JSContext* cx, + const JSFunctionSpec* fs, + HandleId id); + +/** + * Same as above, but without an id arg, for callers who don't have + * the id already. + */ +extern JS_PUBLIC_API JSFunction* NewFunctionFromSpec(JSContext* cx, + const JSFunctionSpec* fs); + +} /* namespace JS */ + +extern JS_PUBLIC_API JSObject* JS_GetFunctionObject(JSFunction* fun); + +/** + * Return the function's identifier as a JSString, or null if fun is unnamed. + * The returned string lives as long as fun, so you don't need to root a saved + * reference to it if fun is well-connected or rooted, and provided you bound + * the use of the saved reference by fun's lifetime. + */ +extern JS_PUBLIC_API JSString* JS_GetFunctionId(JSFunction* fun); + +/** + * Return a function's display name. This is the defined name if one was given + * where the function was defined, or it could be an inferred name by the JS + * engine in the case that the function was defined to be anonymous. This can + * still return nullptr if a useful display name could not be inferred. The + * same restrictions on rooting as those in JS_GetFunctionId apply. + */ +extern JS_PUBLIC_API JSString* JS_GetFunctionDisplayId(JSFunction* fun); + +/* + * Return the arity of fun, which includes default parameters and rest + * parameter. This can be used as `nargs` parameter for other functions. + */ +extern JS_PUBLIC_API uint16_t JS_GetFunctionArity(JSFunction* fun); + +/* + * Return the length of fun, which is the original value of .length property. + */ +JS_PUBLIC_API bool JS_GetFunctionLength(JSContext* cx, JS::HandleFunction fun, + uint16_t* length); + +/** + * Infallible predicate to test whether obj is a function object (faster than + * comparing obj's class name to "Function", but equivalent unless someone has + * overwritten the "Function" identifier with a different constructor and then + * created instances using that constructor that might be passed in as obj). + */ +extern JS_PUBLIC_API bool JS_ObjectIsFunction(JSObject* obj); + +extern JS_PUBLIC_API bool JS_IsNativeFunction(JSObject* funobj, JSNative call); + +/** Return whether the given function is a valid constructor. */ +extern JS_PUBLIC_API bool JS_IsConstructor(JSFunction* fun); + +extern JS_PUBLIC_API bool JS_ObjectIsBoundFunction(JSObject* obj); + +extern JS_PUBLIC_API JSObject* JS_GetBoundFunctionTarget(JSObject* obj); + +extern JS_PUBLIC_API JSObject* JS_GetGlobalFromScript(JSScript* script); + +extern JS_PUBLIC_API const char* JS_GetScriptFilename(JSScript* script); + +extern JS_PUBLIC_API unsigned JS_GetScriptBaseLineNumber(JSContext* cx, + JSScript* script); + +extern JS_PUBLIC_API JSScript* JS_GetFunctionScript(JSContext* cx, + JS::HandleFunction fun); + +extern JS_PUBLIC_API JSString* JS_DecompileScript(JSContext* cx, + JS::Handle script); + +extern JS_PUBLIC_API JSString* JS_DecompileFunction( + JSContext* cx, JS::Handle fun); + +namespace JS { + +/** + * Supply an alternative stack to incorporate into captured SavedFrame + * backtraces as the imputed caller of asynchronous JavaScript calls, like async + * function resumptions and DOM callbacks. + * + * When one async function awaits the result of another, it's natural to think + * of that as a sort of function call: just as execution resumes from an + * ordinary call expression when the callee returns, with the return value + * providing the value of the call expression, execution resumes from an 'await' + * expression after the awaited asynchronous function call returns, passing the + * return value along. + * + * Call the two async functions in such a situation the 'awaiter' and the + * 'awaitee'. + * + * As an async function, the awaitee contains 'await' expressions of its own. + * Whenever it executes after its first 'await', there are never any actual + * frames on the JavaScript stack under it; its awaiter is certainly not there. + * An await expression's continuation is invoked as a promise callback, and + * those are always called directly from the event loop in their own microtick. + * (Ignore unusual cases like nested event loops.) + * + * But because await expressions bear such a strong resemblance to calls (and + * deliberately so!), it would be unhelpful for stacks captured within the + * awaitee to be empty; instead, they should present the awaiter as the caller. + * + * The AutoSetAsyncStackForNewCalls RAII class supplies a SavedFrame stack to + * treat as the caller of any JavaScript invocations that occur within its + * lifetime. Any SavedFrame stack captured during such an invocation uses the + * SavedFrame passed to the constructor's 'stack' parameter as the 'asyncParent' + * property of the SavedFrame for the invocation's oldest frame. Its 'parent' + * property will be null, so stack-walking code can distinguish this + * awaiter/awaitee transition from an ordinary caller/callee transition. + * + * The constructor's 'asyncCause' parameter supplies a string explaining what + * sort of asynchronous call caused 'stack' to be spliced into the backtrace; + * for example, async function resumptions use the string "async". This appears + * as the 'asyncCause' property of the 'asyncParent' SavedFrame. + * + * Async callers are distinguished in the string form of a SavedFrame chain by + * including the 'asyncCause' string in the frame. It appears before the + * function name, with the two separated by a '*'. + * + * Note that, as each compartment has its own set of SavedFrames, the + * 'asyncParent' may actually point to a copy of 'stack', rather than the exact + * SavedFrame object passed. + * + * The youngest frame of 'stack' is not mutated to take the asyncCause string as + * its 'asyncCause' property; SavedFrame objects are immutable. Rather, a fresh + * clone of the frame is created with the needed 'asyncCause' property. + * + * The 'kind' argument specifies how aggressively 'stack' supplants any + * JavaScript frames older than this AutoSetAsyncStackForNewCalls object. If + * 'kind' is 'EXPLICIT', then all captured SavedFrame chains take on 'stack' as + * their 'asyncParent' where the chain crosses this object's scope. If 'kind' is + * 'IMPLICIT', then 'stack' is only included in captured chains if there are no + * other JavaScript frames on the stack --- that is, only if the stack would + * otherwise end at that point. + * + * AutoSetAsyncStackForNewCalls affects only SavedFrame chains; it does not + * affect Debugger.Frame or js::FrameIter. SavedFrame chains are used for + * Error.stack, allocation profiling, Promise debugging, and so on. + * + * See also `js/src/doc/SavedFrame/SavedFrame.md` for documentation on async + * stack frames. + */ +class MOZ_STACK_CLASS JS_PUBLIC_API AutoSetAsyncStackForNewCalls { + JSContext* cx; + RootedObject oldAsyncStack; + const char* oldAsyncCause; + bool oldAsyncCallIsExplicit; + + public: + enum class AsyncCallKind { + // The ordinary kind of call, where we may apply an async + // parent if there is no ordinary parent. + IMPLICIT, + // An explicit async parent, e.g., callFunctionWithAsyncStack, + // where we always want to override any ordinary parent. + EXPLICIT + }; + + // The stack parameter cannot be null by design, because it would be + // ambiguous whether that would clear any scheduled async stack and make the + // normal stack reappear in the new call, or just keep the async stack + // already scheduled for the new call, if any. + // + // asyncCause is owned by the caller and its lifetime must outlive the + // lifetime of the AutoSetAsyncStackForNewCalls object. It is strongly + // encouraged that asyncCause be a string constant or similar statically + // allocated string. + AutoSetAsyncStackForNewCalls(JSContext* cx, HandleObject stack, + const char* asyncCause, + AsyncCallKind kind = AsyncCallKind::IMPLICIT); + ~AutoSetAsyncStackForNewCalls(); +}; + +} // namespace JS + +/************************************************************************/ + +namespace JS { + +JS_PUBLIC_API bool PropertySpecNameEqualsId(JSPropertySpec::Name name, + HandleId id); + +/** + * Create a jsid that does not need to be marked for GC. + * + * 'name' is a JSPropertySpec::name or JSFunctionSpec::name value. The + * resulting jsid, on success, is either an interned string or a well-known + * symbol; either way it is immune to GC so there is no need to visit *idp + * during GC marking. + */ +JS_PUBLIC_API bool PropertySpecNameToPermanentId(JSContext* cx, + JSPropertySpec::Name name, + jsid* idp); + +} /* namespace JS */ + +/************************************************************************/ + +/** + * A JS context always has an "owner thread". The owner thread is set when the + * context is created (to the current thread) and practically all entry points + * into the JS engine check that a context (or anything contained in the + * context: runtime, compartment, object, etc) is only touched by its owner + * thread. Embeddings may check this invariant outside the JS engine by calling + * JS_AbortIfWrongThread (which will abort if not on the owner thread, even for + * non-debug builds). + */ + +extern JS_PUBLIC_API void JS_AbortIfWrongThread(JSContext* cx); + +/************************************************************************/ + +/** + * A constructor can request that the JS engine create a default new 'this' + * object of the given class, using the callee to determine parentage and + * [[Prototype]]. + */ +extern JS_PUBLIC_API JSObject* JS_NewObjectForConstructor( + JSContext* cx, const JSClass* clasp, const JS::CallArgs& args); + +/************************************************************************/ + +extern JS_PUBLIC_API void JS_SetParallelParsingEnabled(JSContext* cx, + bool enabled); + +extern JS_PUBLIC_API void JS_SetOffthreadIonCompilationEnabled(JSContext* cx, + bool enabled); + +// clang-format off +#define JIT_COMPILER_OPTIONS(Register) \ + Register(BASELINE_INTERPRETER_WARMUP_TRIGGER, "blinterp.warmup.trigger") \ + Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger") \ + Register(IC_FORCE_MEGAMORPHIC, "ic.force-megamorphic") \ + Register(ION_NORMAL_WARMUP_TRIGGER, "ion.warmup.trigger") \ + Register(ION_GVN_ENABLE, "ion.gvn.enable") \ + Register(ION_FORCE_IC, "ion.forceinlineCaches") \ + Register(ION_ENABLE, "ion.enable") \ + Register(JIT_TRUSTEDPRINCIPALS_ENABLE, "jit_trustedprincipals.enable") \ + Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis") \ + Register(ION_FREQUENT_BAILOUT_THRESHOLD, "ion.frequent-bailout-threshold") \ + Register(BASE_REG_FOR_LOCALS, "base-reg-for-locals") \ + Register(INLINING_BYTECODE_MAX_LENGTH, "inlining.bytecode-max-length") \ + Register(BASELINE_INTERPRETER_ENABLE, "blinterp.enable") \ + Register(BASELINE_ENABLE, "baseline.enable") \ + Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \ + Register(FULL_DEBUG_CHECKS, "jit.full-debug-checks") \ + Register(JUMP_THRESHOLD, "jump-threshold") \ + Register(NATIVE_REGEXP_ENABLE, "native_regexp.enable") \ + Register(JIT_HINTS_ENABLE, "jitHints.enable") \ + Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt") \ + Register(SPECTRE_INDEX_MASKING, "spectre.index-masking") \ + Register(SPECTRE_OBJECT_MITIGATIONS, "spectre.object-mitigations") \ + Register(SPECTRE_STRING_MITIGATIONS, "spectre.string-mitigations") \ + Register(SPECTRE_VALUE_MASKING, "spectre.value-masking") \ + Register(SPECTRE_JIT_TO_CXX_CALLS, "spectre.jit-to-cxx-calls") \ + Register(WATCHTOWER_MEGAMORPHIC, "watchtower.megamorphic") \ + Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets") \ + Register(WASM_DELAY_TIER2, "wasm.delay-tier2") \ + Register(WASM_JIT_BASELINE, "wasm.baseline") \ + Register(WASM_JIT_OPTIMIZING, "wasm.optimizing") +// clang-format on + +typedef enum JSJitCompilerOption { +#define JIT_COMPILER_DECLARE(key, str) JSJITCOMPILER_##key, + + JIT_COMPILER_OPTIONS(JIT_COMPILER_DECLARE) +#undef JIT_COMPILER_DECLARE + + JSJITCOMPILER_NOT_AN_OPTION +} JSJitCompilerOption; + +extern JS_PUBLIC_API void JS_SetGlobalJitCompilerOption(JSContext* cx, + JSJitCompilerOption opt, + uint32_t value); +extern JS_PUBLIC_API bool JS_GetGlobalJitCompilerOption(JSContext* cx, + JSJitCompilerOption opt, + uint32_t* valueOut); + +namespace JS { + +// Disable all Spectre mitigations for this process after creating the initial +// JSContext. Must be called on this context's thread. +extern JS_PUBLIC_API void DisableSpectreMitigationsAfterInit(); + +}; // namespace JS + +/** + * Convert a uint32_t index into a jsid. + */ +extern JS_PUBLIC_API bool JS_IndexToId(JSContext* cx, uint32_t index, + JS::MutableHandleId); + +/** + * Convert chars into a jsid. + * + * |chars| may not be an index. + */ +extern JS_PUBLIC_API bool JS_CharsToId(JSContext* cx, JS::TwoByteChars chars, + JS::MutableHandleId); + +/** + * Test if the given string is a valid ECMAScript identifier + */ +extern JS_PUBLIC_API bool JS_IsIdentifier(JSContext* cx, JS::HandleString str, + bool* isIdentifier); + +/** + * Test whether the given chars + length are a valid ECMAScript identifier. + * This version is infallible, so just returns whether the chars are an + * identifier. + */ +extern JS_PUBLIC_API bool JS_IsIdentifier(const char16_t* chars, size_t length); + +namespace js { +class ScriptSource; +} // namespace js + +namespace JS { + +class MOZ_RAII JS_PUBLIC_API AutoFilename { + private: + js::ScriptSource* ss_; + mozilla::Variant filename_; + + AutoFilename(const AutoFilename&) = delete; + AutoFilename& operator=(const AutoFilename&) = delete; + + public: + AutoFilename() + : ss_(nullptr), filename_(mozilla::AsVariant(nullptr)) {} + + ~AutoFilename() { reset(); } + + void reset(); + + void setOwned(UniqueChars&& filename); + void setUnowned(const char* filename); + void setScriptSource(js::ScriptSource* ss); + + const char* get() const; +}; + +/** + * Return the current filename, line number and column number of the most + * currently running frame. Returns true if a scripted frame was found, false + * otherwise. + * + * If a the embedding has hidden the scripted caller for the topmost activation + * record, this will also return false. + */ +extern JS_PUBLIC_API bool DescribeScriptedCaller( + JSContext* cx, AutoFilename* filename = nullptr, unsigned* lineno = nullptr, + unsigned* column = nullptr); + +extern JS_PUBLIC_API JSObject* GetScriptedCallerGlobal(JSContext* cx); + +/** + * Informs the JS engine that the scripted caller should be hidden. This can be + * used by the embedding to maintain an override of the scripted caller in its + * calculations, by hiding the scripted caller in the JS engine and pushing data + * onto a separate stack, which it inspects when DescribeScriptedCaller returns + * null. + * + * We maintain a counter on each activation record. Add() increments the counter + * of the topmost activation, and Remove() decrements it. The count may never + * drop below zero, and must always be exactly zero when the activation is + * popped from the stack. + */ +extern JS_PUBLIC_API void HideScriptedCaller(JSContext* cx); + +extern JS_PUBLIC_API void UnhideScriptedCaller(JSContext* cx); + +class MOZ_RAII AutoHideScriptedCaller { + public: + explicit AutoHideScriptedCaller(JSContext* cx) : mContext(cx) { + HideScriptedCaller(mContext); + } + ~AutoHideScriptedCaller() { UnhideScriptedCaller(mContext); } + + protected: + JSContext* mContext; +}; + +/** + * Attempt to disable Wasm's usage of reserving a large virtual memory + * allocation to avoid bounds checking overhead. This must be called before any + * Wasm module or memory is created in this process, or else this function will + * fail. + */ +[[nodiscard]] extern JS_PUBLIC_API bool DisableWasmHugeMemory(); + +/** + * Return true iff the given object is either a SavedFrame object or wrapper + * around a SavedFrame object, and it is not the SavedFrame.prototype object. + */ +extern JS_PUBLIC_API bool IsMaybeWrappedSavedFrame(JSObject* obj); + +/** + * Return true iff the given object is a SavedFrame object and not the + * SavedFrame.prototype object. + */ +extern JS_PUBLIC_API bool IsUnwrappedSavedFrame(JSObject* obj); + +} /* namespace JS */ + +namespace js { + +/** + * Hint that we expect a crash. Currently, the only thing that cares is the + * breakpad injector, which (if loaded) will suppress minidump generation. + */ +extern JS_PUBLIC_API void NoteIntentionalCrash(); + +} /* namespace js */ + +#ifdef DEBUG +namespace JS { + +extern JS_PUBLIC_API void SetSupportDifferentialTesting(bool value); + +} +#endif /* DEBUG */ + +#endif /* jsapi_h */ -- cgit v1.2.3