/* -*- 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/CallArgs.h" #include "js/CharacterEncoding.h" #include "js/Class.h" #include "js/CompileOptions.h" #include "js/Context.h" #include "js/ErrorReport.h" #include "js/Exception.h" #include "js/GCAPI.h" #include "js/GCVector.h" #include "js/HashTable.h" #include "js/Id.h" #include "js/MapAndSet.h" #include "js/MemoryFunctions.h" #include "js/OffThreadScriptCompilation.h" #include "js/Principals.h" #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/String.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/WeakMap.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 */ /* Callbacks and their arguments. */ /************************************************************************/ // Callback for the embedding to map from a ScriptSourceObject private-value to // an object that is exposed as the source "element" in debugger API. This hook // must be infallible, but can return nullptr if no such element exists. using JSSourceElementCallback = JSObject* (*)(JSContext*, JS::HandleValue); using JSInterruptCallback = bool (*)(JSContext*); /** * Callback used to ask the embedding for the cross compartment wrapper handler * that implements the desired prolicy for this kind of object in the * destination compartment. |obj| is the object to be wrapped. If |existing| is * non-nullptr, it will point to an existing wrapper object that should be * re-used if possible. |existing| is guaranteed to be a cross-compartment * wrapper with a lazily-defined prototype and the correct global. It is * guaranteed not to wrap a function. */ using JSWrapObjectCallback = JSObject* (*)(JSContext*, JS::HandleObject, JS::HandleObject); /** * Callback used by the wrap hook to ask the embedding to prepare an object * for wrapping in a context. This might include unwrapping other wrappers * or even finding a more suitable object for the new compartment. If |origObj| * is non-null, then it is the original object we are going to swap into during * a transplant. */ using JSPreWrapCallback = void (*)(JSContext*, JS::HandleObject, JS::HandleObject, JS::HandleObject, JS::HandleObject, JS::MutableHandleObject); struct JSWrapObjectCallbacks { JSWrapObjectCallback wrap; JSPreWrapCallback preWrap; }; /** * Callback used to intercept JavaScript errors. */ struct JSErrorInterceptor { /** * This method is called whenever an error has been raised from JS code. * * This method MUST be infallible. */ virtual void interceptError(JSContext* cx, JS::HandleValue error) = 0; }; /************************************************************************/ 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); /** Timing information for telemetry purposes **/ struct JSTimers { mozilla::TimeDuration executionTime; // Total time spent executing mozilla::TimeDuration delazificationTime; // Total time spent delazifying mozilla::TimeDuration xdrEncodingTime; // Total time spent XDR encoding mozilla::TimeDuration gcTime; // Total time spent in GC mozilla::TimeDuration protectTime; // Total time spent protecting JIT executable memory mozilla::TimeDuration baselineCompileTime; // Total time spent in baseline compiler }; extern JS_PUBLIC_API JSTimers GetJSTimers(JSContext* cx); } /* 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); // Set a callback that will be called whenever an error // is thrown in this runtime. This is designed as a mechanism // for logging errors. Note that the VM makes no attempt to sanitize // the contents of the error (so it may contain private data) // or to sort out among errors (so it may not be the error you // are interested in or for the component in which you are // interested). // // If the callback sets a new error, this new error // will replace the original error. // // May be `nullptr`. // This is a no-op if built without NIGHTLY_BUILD. extern JS_PUBLIC_API void JS_SetErrorInterceptorCallback( JSRuntime*, JSErrorInterceptor* callback); // This returns nullptr if built without NIGHTLY_BUILD. extern JS_PUBLIC_API JSErrorInterceptor* JS_GetErrorInterceptorCallback( JSRuntime*); // 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 bool JS_IsGlobalObject(JSObject* obj); 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); namespace JS { /** * Get the current realm's global. Returns nullptr if no realm has been * entered. */ extern JS_PUBLIC_API JSObject* CurrentGlobalOrNull(JSContext* cx); /** * Get the global object associated with an object's realm. The object must not * be a cross-compartment wrapper (because CCWs are shared by all realms in the * compartment). */ extern JS_PUBLIC_API JSObject* GetNonCCWObjectGlobal(JSObject* obj); } // namespace JS /** * 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); /* Defined in vm/Debugger.cpp. */ extern JS_PUBLIC_API bool JS_DefineDebuggerObject(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 /** * Set the size of the native stack that should not be exceed. To disable * stack size checking pass 0. * * SpiderMonkey allows for a distinction between system code (such as GCs, which * may incidentally be triggered by script but are not strictly performed on * behalf of such script), trusted script (as determined by * JS_SetTrustedPrincipals), and untrusted script. Each kind of code may have a * different stack quota, allowing embedders to keep higher-priority machinery * running in the face of scripted stack exhaustion by something else. * * The stack quotas for each kind of code should be monotonically descending, * and may be specified with this function. If 0 is passed for a given kind * of code, it defaults to the value of the next-highest-priority kind. * * This function may only be called immediately after the runtime is initialized * and before any code is executed and/or interrupts requested. */ extern JS_PUBLIC_API void JS_SetNativeStackQuota( JSContext* cx, size_t systemCodeStackSize, size_t trustedScriptStackSize = 0, size_t untrustedScriptStackSize = 0); /************************************************************************/ 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 */ extern JS_PUBLIC_API JSObject* JS_InitClass( JSContext* cx, JS::HandleObject obj, JS::HandleObject parent_proto, const JSClass* clasp, 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); // Implementation of // https://www.ecma-international.org/ecma-262/6.0/#sec-instanceofoperator // This is almost identical to JS_HasInstance, except the latter may call a // custom hasInstance class op instead of InstanceofOperator. extern JS_PUBLIC_API bool InstanceofOperator(JSContext* cx, HandleObject obj, HandleValue v, bool* bp); } // namespace JS extern JS_PUBLIC_API void JS_InitPrivate(JSObject* obj, void* data, size_t nbytes, JS::MemoryUse use); extern JS_PUBLIC_API void* JS_GetInstancePrivate(JSContext* cx, JS::Handle obj, const JSClass* clasp, JS::CallArgs* args); extern JS_PUBLIC_API JSObject* JS_GetConstructor(JSContext* cx, JS::Handle proto); namespace JS { /** * During global creation, we fire notifications to callbacks registered * via the Debugger API. These callbacks are arbitrary script, and can touch * the global in arbitrary ways. When that happens, the global should not be * in a half-baked state. But this creates a problem for consumers that need * to set slots on the global to put it in a consistent state. * * This API provides a way for consumers to set slots atomically (immediately * after the global is created), before any debugger hooks are fired. It's * unfortunately on the clunky side, but that's the way the cookie crumbles. * * If callers have no additional state on the global to set up, they may pass * |FireOnNewGlobalHook| to JS_NewGlobalObject, which causes that function to * fire the hook as its final act before returning. Otherwise, callers should * pass |DontFireOnNewGlobalHook|, which means that they are responsible for * invoking JS_FireOnNewGlobalObject upon successfully creating the global. If * an error occurs and the operation aborts, callers should skip firing the * hook. But otherwise, callers must take care to fire the hook exactly once * before compiling any script in the global's scope (we have assertions in * place to enforce this). This lets us be sure that debugger clients never miss * breakpoints. */ enum OnNewGlobalHookOption { FireOnNewGlobalHook, DontFireOnNewGlobalHook }; } /* namespace JS */ extern JS_PUBLIC_API JSObject* JS_NewGlobalObject( JSContext* cx, const JSClass* clasp, JSPrincipals* principals, JS::OnNewGlobalHookOption hookOption, const JS::RealmOptions& options); /** * Spidermonkey does not have a good way of keeping track of what compartments * should be marked on their own. We can mark the roots unconditionally, but * marking GC things only relevant in live compartments is hard. To mitigate * this, we create a static trace hook, installed on each global object, from * which we can be sure the compartment is relevant, and mark it. * * It is still possible to specify custom trace hooks for global object classes. * They can be provided via the RealmOptions passed to JS_NewGlobalObject. */ extern JS_PUBLIC_API void JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global); namespace JS { /** * This allows easily constructing a global object without having to deal with * JSClassOps, forgetting to add JS_GlobalObjectTraceHook, or forgetting to call * JS::InitRealmStandardClasses(). Example: * * const JSClass globalClass = { "MyGlobal", JSCLASS_GLOBAL_FLAGS, * &JS::DefaultGlobalClassOps }; * JS_NewGlobalObject(cx, &globalClass, ...); */ extern JS_PUBLIC_DATA const JSClassOps DefaultGlobalClassOps; } // namespace JS extern JS_PUBLIC_API void JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global); 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); /** * Get a description of one of obj's own properties. If no such property exists * on obj, return true with desc.object() set to null. * * Implements: ES6 [[GetOwnProperty]] internal method. */ extern JS_PUBLIC_API bool JS_GetOwnPropertyDescriptorById( JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandle> desc); extern JS_PUBLIC_API bool JS_GetOwnPropertyDescriptor( JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandle> desc); extern JS_PUBLIC_API bool JS_GetOwnUCPropertyDescriptor( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::MutableHandle> desc); /** * DEPRECATED * * Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain * if no own property is found directly on obj. The object on which the * property is found is returned in holder. If the property is not found * on the prototype chain, then desc is Nothing. */ extern JS_PUBLIC_API bool JS_GetPropertyDescriptorById( JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandle> desc, JS::MutableHandleObject holder); extern JS_PUBLIC_API bool JS_GetPropertyDescriptor( JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandle> desc, JS::MutableHandleObject holder); extern JS_PUBLIC_API bool JS_GetUCPropertyDescriptor( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::MutableHandle> desc, JS::MutableHandleObject holder); /** * Define a property on obj. * * This function uses JS::ObjectOpResult to indicate conditions that ES6 * specifies as non-error failures. This is inconvenient at best, so use this * function only if you are implementing a proxy handler's defineProperty() * method. For all other purposes, use one of the many DefineProperty functions * below that throw an exception in all failure cases. * * Implements: ES6 [[DefineOwnProperty]] internal method. */ extern JS_PUBLIC_API bool JS_DefinePropertyById( JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::Handle desc, JS::ObjectOpResult& result); /** * Define a property on obj, throwing a TypeError if the attempt fails. * This is the C++ equivalent of `Object.defineProperty(obj, id, desc)`. */ extern JS_PUBLIC_API bool JS_DefinePropertyById( JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::Handle desc); extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefinePropertyById( JSContext* cx, JS::HandleObject obj, JS::HandleId id, JSNative getter, JSNative setter, unsigned attrs); extern JS_PUBLIC_API bool JS_DefinePropertyById( JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject getter, JS::HandleObject setter, unsigned attrs); extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, int32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, uint32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, double value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JSNative getter, JSNative setter, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject getter, JS::HandleObject setter, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleString value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, int32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, uint32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, double value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineUCProperty( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::Handle desc, JS::ObjectOpResult& result); extern JS_PUBLIC_API bool JS_DefineUCProperty( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::Handle desc); extern JS_PUBLIC_API bool JS_DefineUCProperty( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::HandleValue value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineUCProperty( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::HandleObject getter, JS::HandleObject setter, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineUCProperty( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::HandleObject value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineUCProperty( JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::HandleString value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, int32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, uint32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, double value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject getter, JS::HandleObject setter, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t value, unsigned attrs); extern JS_PUBLIC_API bool JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double value, unsigned attrs); /** * Compute the expression `id in obj`. * * If obj has an own or inherited property obj[id], set *foundp = true and * return true. If not, set *foundp = false and return true. On error, return * false with an exception pending. * * Implements: ES6 [[Has]] internal method. */ extern JS_PUBLIC_API bool JS_HasPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp); extern JS_PUBLIC_API bool JS_HasProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp); extern JS_PUBLIC_API bool JS_HasUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, bool* vp); extern JS_PUBLIC_API bool JS_HasElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp); /** * Determine whether obj has an own property with the key `id`. * * Implements: ES6 7.3.11 HasOwnProperty(O, P). */ extern JS_PUBLIC_API bool JS_HasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp); extern JS_PUBLIC_API bool JS_HasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp); /** * Get the value of the property `obj[id]`, or undefined if no such property * exists. This is the C++ equivalent of `vp = Reflect.get(obj, id, receiver)`. * * Most callers don't need the `receiver` argument. Consider using * JS_GetProperty instead. (But if you're implementing a proxy handler's set() * method, it's often correct to call this function and pass the receiver * through.) * * Implements: ES6 [[Get]] internal method. */ extern JS_PUBLIC_API bool JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue receiver, JS::MutableHandleValue vp); extern JS_PUBLIC_API bool JS_ForwardGetElementTo(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject receiver, JS::MutableHandleValue vp); /** * Get the value of the property `obj[id]`, or undefined if no such property * exists. The result is stored in vp. * * Implements: ES6 7.3.1 Get(O, P). */ extern JS_PUBLIC_API bool JS_GetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp); extern JS_PUBLIC_API bool JS_GetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandleValue vp); extern JS_PUBLIC_API bool JS_GetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::MutableHandleValue vp); extern JS_PUBLIC_API bool JS_GetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp); /** * Perform the same property assignment as `Reflect.set(obj, id, v, receiver)`. * * This function has a `receiver` argument that most callers don't need. * Consider using JS_SetProperty instead. * * Implements: ES6 [[Set]] internal method. */ extern JS_PUBLIC_API bool JS_ForwardSetPropertyTo( JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v, JS::HandleValue receiver, JS::ObjectOpResult& result); /** * Perform the assignment `obj[id] = v`. * * This function performs non-strict assignment, so if the property is * read-only, nothing happens and no error is thrown. */ extern JS_PUBLIC_API bool JS_SetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v); extern JS_PUBLIC_API bool JS_SetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue v); extern JS_PUBLIC_API bool JS_SetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::HandleValue v); extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue v); extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject v); extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString v); extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t v); extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t v); extern JS_PUBLIC_API bool JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double v); /** * Delete a property. This is the C++ equivalent of * `result = Reflect.deleteProperty(obj, id)`. * * This function has a `result` out parameter that most callers don't need. * Unless you can pass through an ObjectOpResult provided by your caller, it's * probably best to use the JS_DeletePropertyById signature with just 3 * arguments. * * Implements: ES6 [[Delete]] internal method. */ extern JS_PUBLIC_API bool JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::ObjectOpResult& result); extern JS_PUBLIC_API bool JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::ObjectOpResult& result); extern JS_PUBLIC_API bool JS_DeleteUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, JS::ObjectOpResult& result); extern JS_PUBLIC_API bool JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::ObjectOpResult& result); /** * Delete a property, ignoring strict failures. This is the C++ equivalent of * the JS `delete obj[id]` in non-strict mode code. */ extern JS_PUBLIC_API bool JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, jsid id); extern JS_PUBLIC_API bool JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name); extern JS_PUBLIC_API bool JS_DeleteElement(JSContext* cx, JS::HandleObject obj, uint32_t index); /** * Get an array of the non-symbol enumerable properties of obj. * This function is roughly equivalent to: * * var result = []; * for (key in obj) { * result.push(key); * } * return result; * * This is the closest thing we currently have to the ES6 [[Enumerate]] * internal method. * * The array of ids returned by JS_Enumerate must be rooted to protect its * contents from garbage collection. Use JS::Rooted. */ extern JS_PUBLIC_API bool JS_Enumerate(JSContext* cx, JS::HandleObject obj, JS::MutableHandle props); /** * 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); /* * API for determining callability and constructability. [[Call]] and * [[Construct]] are internal methods that aren't present on all objects, so it * is useful to ask if they are there or not. The standard itself asks these * questions routinely. */ namespace JS { /** * Return true if the given object is callable. In ES6 terms, an object is * callable if it has a [[Call]] internal method. * * Implements: ES6 7.2.3 IsCallable(argument). * * Functions are callable. A scripted proxy or wrapper is callable if its * target is callable. Most other objects aren't callable. */ extern JS_PUBLIC_API bool IsCallable(JSObject* obj); /** * Return true if the given object is a constructor. In ES6 terms, an object is * a constructor if it has a [[Construct]] internal method. The expression * `new obj()` throws a TypeError if obj is not a constructor. * * Implements: ES6 7.2.4 IsConstructor(argument). * * JS functions and classes are constructors. Arrow functions and most builtin * functions are not. A scripted proxy or wrapper is a constructor if its * target is a constructor. */ extern JS_PUBLIC_API bool IsConstructor(JSObject* obj); } /* namespace JS */ /** * Call a function, passing a this-value and arguments. This is the C++ * equivalent of `rval = Reflect.apply(fun, obj, args)`. * * Implements: ES6 7.3.12 Call(F, V, [argumentsList]). * Use this function to invoke the [[Call]] internal method. */ extern JS_PUBLIC_API bool JS_CallFunctionValue(JSContext* cx, JS::HandleObject obj, JS::HandleValue fval, const JS::HandleValueArray& args, JS::MutableHandleValue rval); extern JS_PUBLIC_API bool JS_CallFunction(JSContext* cx, JS::HandleObject obj, JS::HandleFunction fun, const JS::HandleValueArray& args, JS::MutableHandleValue rval); /** * Perform the method call `rval = obj[name](args)`. */ extern JS_PUBLIC_API bool JS_CallFunctionName(JSContext* cx, JS::HandleObject obj, const char* name, const JS::HandleValueArray& args, JS::MutableHandleValue rval); namespace JS { static inline bool Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleFunction fun, const JS::HandleValueArray& args, MutableHandleValue rval) { return !!JS_CallFunction(cx, thisObj, fun, args, rval); } static inline bool Call(JSContext* cx, JS::HandleObject thisObj, JS::HandleValue fun, const JS::HandleValueArray& args, MutableHandleValue rval) { return !!JS_CallFunctionValue(cx, thisObj, fun, args, rval); } static inline bool Call(JSContext* cx, JS::HandleObject thisObj, const char* name, const JS::HandleValueArray& args, MutableHandleValue rval) { return !!JS_CallFunctionName(cx, thisObj, name, args, rval); } extern JS_PUBLIC_API bool Call(JSContext* cx, JS::HandleValue thisv, JS::HandleValue fun, const JS::HandleValueArray& args, MutableHandleValue rval); static inline bool Call(JSContext* cx, JS::HandleValue thisv, JS::HandleObject funObj, const JS::HandleValueArray& args, MutableHandleValue rval) { MOZ_ASSERT(funObj); JS::RootedValue fun(cx, JS::ObjectValue(*funObj)); return Call(cx, thisv, fun, args, rval); } /** * Invoke a constructor. This is the C++ equivalent of * `rval = Reflect.construct(fun, args, newTarget)`. * * JS::Construct() takes a `newTarget` argument that most callers don't need. * Consider using the four-argument Construct signature instead. (But if you're * implementing a subclass or a proxy handler's construct() method, this is the * right function to call.) * * Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]). * Use this function to invoke the [[Construct]] internal method. */ extern JS_PUBLIC_API bool Construct(JSContext* cx, JS::HandleValue fun, HandleObject newTarget, const JS::HandleValueArray& args, MutableHandleObject objp); /** * Invoke a constructor. This is the C++ equivalent of * `rval = new fun(...args)`. * * Implements: ES6 7.3.13 Construct(F, [argumentsList], [newTarget]), when * newTarget is omitted. */ extern JS_PUBLIC_API bool Construct(JSContext* cx, JS::HandleValue fun, const JS::HandleValueArray& args, MutableHandleObject objp); } /* namespace JS */ /*** Other property-defining functions **************************************/ extern JS_PUBLIC_API JSObject* JS_DefineObject(JSContext* cx, JS::HandleObject obj, const char* name, const JSClass* clasp = nullptr, unsigned attrs = 0); extern JS_PUBLIC_API bool JS_DefineProperties(JSContext* cx, JS::HandleObject obj, const JSPropertySpec* ps); /* * */ extern JS_PUBLIC_API bool JS_AlreadyHasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp); extern JS_PUBLIC_API bool JS_AlreadyHasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp); extern JS_PUBLIC_API bool JS_AlreadyHasOwnUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, bool* foundp); extern JS_PUBLIC_API bool JS_AlreadyHasOwnElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp); 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); } extern JS_PUBLIC_API void JS_InitPrivate(JSObject* obj, void* data, size_t nbytes, JS::MemoryUse 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_DefineFunctions(JSContext* cx, JS::Handle obj, const JSFunctionSpec* fs); extern JS_PUBLIC_API JSFunction* JS_DefineFunction( JSContext* cx, JS::Handle obj, const char* name, JSNative call, unsigned nargs, unsigned attrs); extern JS_PUBLIC_API JSFunction* JS_DefineUCFunction( JSContext* cx, JS::Handle obj, const char16_t* name, size_t namelen, JSNative call, unsigned nargs, unsigned attrs); extern JS_PUBLIC_API JSFunction* JS_DefineFunctionById( JSContext* cx, JS::Handle obj, JS::Handle id, JSNative call, unsigned nargs, unsigned attrs); extern JS_PUBLIC_API bool JS_IsFunctionBound(JSFunction* fun); extern JS_PUBLIC_API JSObject* JS_GetBoundFunctionTarget(JSFunction* fun); 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 { /** * Set a private value associated with a script. Note that this value is shared * by all nested scripts compiled from a single source file. */ extern JS_PUBLIC_API void SetScriptPrivate(JSScript* script, const JS::Value& value); /** * Get the private value associated with a script. Note that this value is * shared by all nested scripts compiled from a single source file. */ extern JS_PUBLIC_API JS::Value GetScriptPrivate(JSScript* script); /* * Return the private value associated with currently executing script or * module, or undefined if there is no such script. */ extern JS_PUBLIC_API JS::Value GetScriptedCallerPrivate(JSContext* cx); /** * Hooks called when references to a script private value are created or * destroyed. This allows use of a reference counted object as the * script private. */ using ScriptPrivateReferenceHook = void (*)(const JS::Value&); /** * Set the script private finalize hook for the runtime to the given function. */ extern JS_PUBLIC_API void SetScriptPrivateReferenceHooks( JSRuntime* rt, ScriptPrivateReferenceHook addRefHook, ScriptPrivateReferenceHook releaseHook); } /* namespace JS */ extern JS_PUBLIC_API bool JS_CheckForInterrupt(JSContext* cx); /* * These functions allow setting an interrupt callback that will be called * from the JS thread some time after any thread triggered the callback using * JS_RequestInterruptCallback(cx). * * To schedule the GC and for other activities the engine internally triggers * interrupt callbacks. The embedding should thus not rely on callbacks being * triggered through the external API only. * * Important note: Additional callbacks can occur inside the callback handler * if it re-enters the JS engine. The embedding must ensure that the callback * is disconnected before attempting such re-entry. */ extern JS_PUBLIC_API bool JS_AddInterruptCallback(JSContext* cx, JSInterruptCallback callback); extern JS_PUBLIC_API bool JS_DisableInterruptCallback(JSContext* cx); extern JS_PUBLIC_API void JS_ResetInterruptCallback(JSContext* cx, bool enable); extern JS_PUBLIC_API void JS_RequestInterruptCallback(JSContext* cx); extern JS_PUBLIC_API void JS_RequestInterruptCallbackCanWait(JSContext* cx); namespace JS { /** * The ConsumeStreamCallback is called from an active JSContext, passing a * StreamConsumer that wishes to consume the given host object as a stream of * bytes with the given MIME type. On failure, the embedding must report the * appropriate error on 'cx'. On success, the embedding must call * consumer->consumeChunk() repeatedly on any thread until exactly one of: * - consumeChunk() returns false * - the embedding calls consumer->streamEnd() * - the embedding calls consumer->streamError() * before JS_DestroyContext(cx) or JS::ShutdownAsyncTasks(cx) is called. * * Note: consumeChunk(), streamEnd() and streamError() may be called * synchronously by ConsumeStreamCallback. * * When streamEnd() is called, the embedding may optionally pass an * OptimizedEncodingListener*, indicating that there is a cache entry associated * with this stream that can store an optimized encoding of the bytes that were * just streamed at some point in the future by having SpiderMonkey call * storeOptimizedEncoding(). Until the optimized encoding is ready, SpiderMonkey * will hold an outstanding refcount to keep the listener alive. * * After storeOptimizedEncoding() is called, on cache hit, the embedding * may call consumeOptimizedEncoding() instead of consumeChunk()/streamEnd(). * The embedding must ensure that the GetOptimizedEncodingBuildId() (see * js/BuildId.h) at the time when an optimized encoding is created is the same * as when it is later consumed. */ using OptimizedEncodingBytes = js::Vector; using UniqueOptimizedEncodingBytes = js::UniquePtr; class OptimizedEncodingListener { protected: virtual ~OptimizedEncodingListener() = default; public: // SpiderMonkey will hold an outstanding reference count as long as it holds // a pointer to OptimizedEncodingListener. virtual MozExternalRefCountType MOZ_XPCOM_ABI AddRef() = 0; virtual MozExternalRefCountType MOZ_XPCOM_ABI Release() = 0; // SpiderMonkey may optionally call storeOptimizedEncoding() after it has // finished processing a streamed resource. virtual void storeOptimizedEncoding(UniqueOptimizedEncodingBytes bytes) = 0; }; class JS_PUBLIC_API StreamConsumer { protected: // AsyncStreamConsumers are created and destroyed by SpiderMonkey. StreamConsumer() = default; virtual ~StreamConsumer() = default; public: // Called by the embedding as each chunk of bytes becomes available. // If this function returns 'false', the stream must drop all pointers to // this StreamConsumer. virtual bool consumeChunk(const uint8_t* begin, size_t length) = 0; // Called by the embedding when the stream reaches end-of-file, passing the // listener described above. virtual void streamEnd(OptimizedEncodingListener* listener = nullptr) = 0; // Called by the embedding when there is an error during streaming. The // given error code should be passed to the ReportStreamErrorCallback on the // main thread to produce the semantically-correct rejection value. virtual void streamError(size_t errorCode) = 0; // Called by the embedding *instead of* consumeChunk()/streamEnd() if an // optimized encoding is available from a previous streaming of the same // contents with the same optimized build id. virtual void consumeOptimizedEncoding(const uint8_t* begin, size_t length) = 0; // Provides optional stream attributes such as base or source mapping URLs. // Necessarily called before consumeChunk(), streamEnd(), streamError() or // consumeOptimizedEncoding(). The caller retains ownership of the strings. virtual void noteResponseURLs(const char* maybeUrl, const char* maybeSourceMapUrl) = 0; }; enum class MimeType { Wasm }; using ConsumeStreamCallback = bool (*)(JSContext*, JS::HandleObject, MimeType, StreamConsumer*); using ReportStreamErrorCallback = void (*)(JSContext*, size_t); extern JS_PUBLIC_API void InitConsumeStreamCallback( JSContext* cx, ConsumeStreamCallback consume, ReportStreamErrorCallback report); /** * 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(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(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(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); /** * 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; }; } /* namespace JS */ namespace js { enum class StackFormat { SpiderMonkey, V8, Default }; /* * Sets the format used for stringifying Error stacks. * * The default format is StackFormat::SpiderMonkey. Use StackFormat::V8 * in order to emulate V8's stack formatting. StackFormat::Default can't be * used here. */ extern JS_PUBLIC_API void SetStackFormat(JSContext* cx, StackFormat format); extern JS_PUBLIC_API StackFormat GetStackFormat(JSContext* cx); } // namespace js namespace JS { /** * 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(); /** * If a large allocation fails when calling pod_{calloc,realloc}CanGC, the JS * engine may call the large-allocation-failure callback, if set, to allow the * embedding to flush caches, possibly perform shrinking GCs, etc. to make some * room. The allocation will then be retried (and may still fail.) This callback * can be called on any thread and must be set at most once in a process. */ using LargeAllocationFailureCallback = void (*)(); extern JS_PUBLIC_API void SetProcessLargeAllocationFailureCallback( LargeAllocationFailureCallback afc); /** * Unlike the error reporter, which is only called if the exception for an OOM * bubbles up and is not caught, the OutOfMemoryCallback is called immediately * at the OOM site to allow the embedding to capture the current state of heap * allocation before anything is freed. If the large-allocation-failure callback * is called at all (not all allocation sites call the large-allocation-failure * callback on failure), it is called before the out-of-memory callback; the * out-of-memory callback is only called if the allocation still fails after the * large-allocation-failure callback has returned. */ using OutOfMemoryCallback = void (*)(JSContext*, void*); extern JS_PUBLIC_API void SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data); /** * When the JSRuntime is about to block in an Atomics.wait() JS call or in a * `wait` instruction in WebAssembly, it can notify the host by means of a call * to BeforeWaitCallback. After the wait, it can notify the host by means of a * call to AfterWaitCallback. Both callbacks must be null, or neither. * * (If you change the callbacks from null to not-null or vice versa while some * thread on the runtime is in a wait, you will be sorry.) * * The argument to the BeforeWaitCallback is a pointer to uninitialized * stack-allocated working memory of size WAIT_CALLBACK_CLIENT_MAXMEM bytes. * The caller of SetWaitCallback() must pass the amount of memory it will need, * and this amount will be checked against that limit and the process will crash * reliably if the check fails. * * The value returned by the BeforeWaitCallback will be passed to the * AfterWaitCallback. * * The AfterWaitCallback will be called even if the wakeup is spurious and the * thread goes right back to waiting again. Of course the thread will call the * BeforeWaitCallback once more before it goes to sleep in this situation. */ static constexpr size_t WAIT_CALLBACK_CLIENT_MAXMEM = 32; using BeforeWaitCallback = void* (*)(uint8_t* memory); using AfterWaitCallback = void (*)(void* cookie); extern JS_PUBLIC_API void SetWaitCallback(JSRuntime* rt, BeforeWaitCallback beforeWait, AfterWaitCallback afterWait, size_t requiredMemory); /** * Capture all frames. */ struct AllFrames {}; /** * Capture at most this many frames. */ struct MaxFrames { uint32_t maxFrames; explicit MaxFrames(uint32_t max) : maxFrames(max) { MOZ_ASSERT(max > 0); } }; /** * Capture the first frame with the given principals. By default, do not * consider self-hosted frames with the given principals as satisfying the stack * capture. */ struct JS_PUBLIC_API FirstSubsumedFrame { JSContext* cx; JSPrincipals* principals; bool ignoreSelfHosted; /** * Use the cx's current compartment's principals. */ explicit FirstSubsumedFrame(JSContext* cx, bool ignoreSelfHostedFrames = true); explicit FirstSubsumedFrame(JSContext* ctx, JSPrincipals* p, bool ignoreSelfHostedFrames = true) : cx(ctx), principals(p), ignoreSelfHosted(ignoreSelfHostedFrames) { if (principals) { JS_HoldPrincipals(principals); } } // No copying because we want to avoid holding and dropping principals // unnecessarily. FirstSubsumedFrame(const FirstSubsumedFrame&) = delete; FirstSubsumedFrame& operator=(const FirstSubsumedFrame&) = delete; FirstSubsumedFrame(FirstSubsumedFrame&& rhs) : principals(rhs.principals), ignoreSelfHosted(rhs.ignoreSelfHosted) { MOZ_ASSERT(this != &rhs, "self move disallowed"); rhs.principals = nullptr; } FirstSubsumedFrame& operator=(FirstSubsumedFrame&& rhs) { new (this) FirstSubsumedFrame(std::move(rhs)); return *this; } ~FirstSubsumedFrame() { if (principals) { JS_DropPrincipals(cx, principals); } } }; using StackCapture = mozilla::Variant; /** * Capture the current call stack as a chain of SavedFrame JSObjects, and set * |stackp| to the SavedFrame for the youngest stack frame, or nullptr if there * are no JS frames on the stack. * * The |capture| parameter describes the portion of the JS stack to capture: * * * |JS::AllFrames|: Capture all frames on the stack. * * * |JS::MaxFrames|: Capture no more than |JS::MaxFrames::maxFrames| from the * stack. * * * |JS::FirstSubsumedFrame|: Capture the first frame whose principals are * subsumed by |JS::FirstSubsumedFrame::principals|. By default, do not * consider self-hosted frames; this can be controlled via the * |JS::FirstSubsumedFrame::ignoreSelfHosted| flag. Do not capture any async * stack. */ extern JS_PUBLIC_API bool CaptureCurrentStack( JSContext* cx, MutableHandleObject stackp, StackCapture&& capture = StackCapture(AllFrames())); /** * Returns true if capturing stack trace data to associate with an asynchronous * operation is currently enabled for the current context realm. * * Users should check this state before capturing a stack that will be passed * back to AutoSetAsyncStackForNewCalls later, in order to avoid capturing a * stack for async use when we don't actually want to capture it. */ extern JS_PUBLIC_API bool IsAsyncStackCaptureEnabledForRealm(JSContext* cx); /* * This is a utility function for preparing an async stack to be used * by some other object. This may be used when you need to treat a * given stack trace as an async parent. If you just need to capture * the current stack, async parents and all, use CaptureCurrentStack * instead. * * Here |asyncStack| is the async stack to prepare. It is copied into * |cx|'s current compartment, and the newest frame is given * |asyncCause| as its asynchronous cause. If |maxFrameCount| is * |Some(n)|, capture at most the youngest |n| frames. The * new stack object is written to |stackp|. Returns true on success, * or sets an exception and returns |false| on error. */ extern JS_PUBLIC_API bool CopyAsyncStack( JSContext* cx, HandleObject asyncStack, HandleString asyncCause, MutableHandleObject stackp, const mozilla::Maybe& maxFrameCount); /** * Given a SavedFrame JSObject stack, stringify it in the same format as * Error.prototype.stack. The stringified stack out parameter is placed in the * cx's compartment. Defaults to the empty string. * * The same notes above about SavedFrame accessors applies here as well: cx * doesn't need to be in stack's compartment, and stack can be null, a * SavedFrame object, or a wrapper (CCW or Xray) around a SavedFrame object. * SavedFrames not subsumed by |principals| are skipped. * * Optional indent parameter specifies the number of white spaces to indent * each line. */ extern JS_PUBLIC_API bool BuildStackString( JSContext* cx, JSPrincipals* principals, HandleObject stack, MutableHandleString stringp, size_t indent = 0, js::StackFormat stackFormat = js::StackFormat::Default); /** * 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 */ namespace js { enum class CompletionKind { Normal, Return, Throw }; } /* namespace js */ #ifdef DEBUG namespace JS { extern JS_PUBLIC_API void SetSupportDifferentialTesting(bool value); } #endif /* DEBUG */ #endif /* jsapi_h */