Source code

Revision control

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* 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/Range.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/RefPtr.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Utf8.h"
#include "mozilla/Variant.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#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/ErrorReport.h"
#include "js/GCVector.h"
#include "js/HashTable.h"
#include "js/Id.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/RealmOptions.h"
#include "js/RefCounted.h"
#include "js/RootingAPI.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"
/************************************************************************/
struct JSFunctionSpec;
struct JSPropertySpec;
namespace JS {
template <typename UnitT>
class SourceText;
class TwoByteChars;
using ValueVector = JS::GCVector<JS::Value>;
using IdVector = JS::GCVector<jsid>;
using ScriptVector = JS::GCVector<JSScript*>;
using StringVector = JS::GCVector<JSString*>;
/**
* Custom rooting behavior for internal and external clients.
*/
class MOZ_RAII JS_PUBLIC_API CustomAutoRooter : private AutoGCRooter {
public:
template <typename CX>
explicit CustomAutoRooter(const CX& cx)
: AutoGCRooter(cx, AutoGCRooter::Kind::Custom) {}
friend void AutoGCRooter::trace(JSTracer* trc);
protected:
virtual ~CustomAutoRooter() = default;
/** Supplied by derived class to trace roots. */
virtual void trace(JSTracer* trc) = 0;
private:
};
} /* namespace JS */
/* Callbacks and their arguments. */
/************************************************************************/
using JSGetElementCallback = JSObject* (*)(JSContext* aCx,
JS::HandleValue privateValue);
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;
};
using JSDestroyZoneCallback = void (*)(JSFreeOp*, JS::Zone*);
using JSDestroyCompartmentCallback = void (*)(JSFreeOp*, JS::Compartment*);
using JSSizeOfIncludingThisCompartmentCallback =
size_t (*)(mozilla::MallocSizeOf, JS::Compartment*);
/**
* 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);
/** Don't want to export data, so provide accessors for non-inline Values. */
extern JS_PUBLIC_API JS::Value JS_GetEmptyStringValue(JSContext* cx);
extern JS_PUBLIC_API JSString* JS_GetEmptyString(JSContext* cx);
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<JS::Value> v);
extern JS_PUBLIC_API bool JS_DoubleIsInt32(double d, int32_t* ip);
extern JS_PUBLIC_API JSType JS_TypeOfValue(JSContext* cx,
JS::Handle<JS::Value> 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
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);
/************************************************************************/
// [SMDOC] Data Structures (JSContext, JSRuntime, Realm, Compartment, Zone)
//
// SpiderMonkey uses some data structures that behave a lot like Russian dolls:
// runtimes contain zones, zones contain compartments, compartments contain
// realms. Each layer has its own purpose.
//
// Realm
// -----
// Data associated with a global object. In the browser each frame has its
// own global/realm.
//
// Compartment
// -----------
// Security membrane; when an object from compartment A is used in compartment
// B, a cross-compartment wrapper (a kind of proxy) is used. In the browser,
// same-origin realms can share a compartment.
//
// Zone
// ----
// A Zone is a group of compartments that share GC resources (arenas, strings,
// etc) for memory usage and performance reasons. Zone is the GC unit: the GC
// can operate on one or more zones at a time. The browser uses roughly one zone
// per tab.
//
// Context
// -------
// JSContext represents a thread: there must be exactly one JSContext for each
// thread running JS/Wasm.
//
// Internally, helper threads can also have a JSContext. They do not always have
// an active context, but one may be requested by AutoSetHelperThreadContext,
// which activates a pre-allocated JSContext for the duration of its lifetime.
//
// Runtime
// -------
// JSRuntime is very similar to JSContext: each runtime belongs to one context
// (thread), but helper threads don't have their own runtimes (they're shared by
// all runtimes in the process and use the runtime of the task they're
// executing).
/*
* Locking, contexts, and memory allocation.
*
* It is important that SpiderMonkey be initialized, and the first context
* be created, in a single-threaded fashion. Otherwise the behavior of the
* library is undefined.
* See:
*/
// Create a new context (and runtime) for this thread.
extern JS_PUBLIC_API JSContext* JS_NewContext(
uint32_t maxbytes, JSRuntime* parentRuntime = nullptr);
// Destroy a context allocated with JS_NewContext. Must be called on the thread
// that called JS_NewContext.
extern JS_PUBLIC_API void JS_DestroyContext(JSContext* cx);
JS_PUBLIC_API void* JS_GetContextPrivate(JSContext* cx);
JS_PUBLIC_API void JS_SetContextPrivate(JSContext* cx, void* data);
extern JS_PUBLIC_API JSRuntime* JS_GetParentRuntime(JSContext* cx);
extern JS_PUBLIC_API JSRuntime* JS_GetRuntime(JSContext* cx);
extern JS_PUBLIC_API void JS_SetFutexCanWait(JSContext* cx);
namespace js {
void AssertHeapIsIdle();
} /* namespace js */
namespace JS {
/**
* Initialize the runtime's self-hosted code. Embeddings should call this
* exactly once per runtime/context, before the first JS_NewGlobalObject
* call.
*
* NOTE: This may not set a pending exception in the case of OOM since this
* runs very early in startup.
*/
JS_PUBLIC_API bool InitSelfHostedCode(JSContext* cx);
/**
* Asserts (in debug and release builds) that `obj` belongs to the current
* thread's context.
*/
JS_PUBLIC_API void AssertObjectBelongsToCurrentThread(JSObject* obj);
/**
* Install a process-wide callback to validate script filenames. The JS engine
* will invoke this callback for each JS script it parses or XDR decodes.
*
* If the callback returns |false|, an exception is thrown and parsing/decoding
* will be aborted.
*
* See also CompileOptions::setSkipFilenameValidation to opt-out of the callback
* for specific parse jobs.
*/
using FilenameValidationCallback = bool (*)(const char* filename,
bool isSystemRealm);
JS_PUBLIC_API void SetFilenameValidationCallback(FilenameValidationCallback cb);
} /* namespace JS */
/**
* Set callback to send tasks to XPCOM thread pools
*/
JS_PUBLIC_API void SetHelperThreadTaskCallback(
bool (*callback)(js::UniquePtr<js::RunnableTask>));
extern JS_PUBLIC_API const char* JS_GetImplementationVersion(void);
extern JS_PUBLIC_API void JS_SetDestroyZoneCallback(
JSContext* cx, JSDestroyZoneCallback callback);
extern JS_PUBLIC_API void JS_SetDestroyCompartmentCallback(
JSContext* cx, JSDestroyCompartmentCallback callback);
extern JS_PUBLIC_API void JS_SetSizeOfIncludingThisCompartmentCallback(
JSContext* cx, JSSizeOfIncludingThisCompartmentCallback callback);
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<JSExnType> JS_GetErrorType(
const JS::Value& val);
extern JS_PUBLIC_API void JS_SetCompartmentPrivate(JS::Compartment* compartment,
void* data);
extern JS_PUBLIC_API void* JS_GetCompartmentPrivate(
JS::Compartment* compartment);
extern JS_PUBLIC_API void JS_SetZoneUserData(JS::Zone* zone, void* data);
extern JS_PUBLIC_API void* JS_GetZoneUserData(JS::Zone* zone);
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);
extern JS_PUBLIC_API bool JS_RefreshCrossCompartmentWrappers(
JSContext* cx, JS::Handle<JSObject*> obj);
/*
* At any time, a JSContext has a current (possibly-nullptr) realm.
* Realms are described in:
*
* developer.mozilla.org/en-US/docs/SpiderMonkey/SpiderMonkey_compartments
*
* The current realm of a context may be changed. The preferred way to do
* this is with JSAutoRealm:
*
* void foo(JSContext* cx, JSObject* obj) {
* // in some realm 'r'
* {
* JSAutoRealm ar(cx, obj); // constructor enters
* // in the realm of 'obj'
* } // destructor leaves
* // back in realm 'r'
* }
*
* The object passed to JSAutoRealm must *not* be a cross-compartment wrapper,
* because CCWs are not associated with a single realm.
*
* For more complicated uses that don't neatly fit in a C++ stack frame, the
* realm can be entered and left using separate function calls:
*
* void foo(JSContext* cx, JSObject* obj) {
* // in 'oldRealm'
* JS::Realm* oldRealm = JS::EnterRealm(cx, obj);
* // in the realm of 'obj'
* JS::LeaveRealm(cx, oldRealm);
* // back in 'oldRealm'
* }
*
* Note: these calls must still execute in a LIFO manner w.r.t all other
* enter/leave calls on the context. Furthermore, only the return value of a
* JS::EnterRealm call may be passed as the 'oldRealm' argument of
* the corresponding JS::LeaveRealm call.
*
* Entering a realm roots the realm and its global object for the lifetime of
* the JSAutoRealm.
*/
class MOZ_RAII JS_PUBLIC_API JSAutoRealm {
JSContext* cx_;
JS::Realm* oldRealm_;
public:
JSAutoRealm(JSContext* cx, JSObject* target);
JSAutoRealm(JSContext* cx, JSScript* target);
~JSAutoRealm();
};
class MOZ_RAII JS_PUBLIC_API JSAutoNullableRealm {
JSContext* cx_;
JS::Realm* oldRealm_;
public:
explicit JSAutoNullableRealm(JSContext* cx, JSObject* targetOrNull);
~JSAutoNullableRealm();
};
namespace JS {
/** NB: This API is infallible; a nullptr return value does not indicate error.
*
* |target| must not be a cross-compartment wrapper because CCWs are not
* associated with a single realm.
*
* Entering a realm roots the realm and its global object until the matching
* JS::LeaveRealm() call.
*/
extern JS_PUBLIC_API JS::Realm* EnterRealm(JSContext* cx, JSObject* target);
extern JS_PUBLIC_API void LeaveRealm(JSContext* cx, JS::Realm* oldRealm);
using IterateRealmCallback = void (*)(JSContext* cx, void* data, Realm* realm,
const AutoRequireNoGC& nogc);
/**
* This function calls |realmCallback| on every realm. Beware that there is no
* guarantee that the realm will survive after the callback returns. Also,
* barriers are disabled via the TraceSession.
*/
extern JS_PUBLIC_API void IterateRealms(JSContext* cx, void* data,
IterateRealmCallback realmCallback);
/**
* Like IterateRealms, but only call the callback for realms using |principals|.
*/
extern JS_PUBLIC_API void IterateRealmsWithPrincipals(
JSContext* cx, JSPrincipals* principals, void* data,
IterateRealmCallback realmCallback);
/**
* Like IterateRealms, but only iterates realms in |compartment|.
*/
extern JS_PUBLIC_API void IterateRealmsInCompartment(
JSContext* cx, JS::Compartment* compartment, void* data,
IterateRealmCallback realmCallback);
} // namespace JS
/**
* An enum that JSIterateCompartmentCallback can return to indicate
* whether to keep iterating.
*/
namespace JS {
enum class CompartmentIterResult { KeepGoing, Stop };
} // namespace JS
using JSIterateCompartmentCallback =
JS::CompartmentIterResult (*)(JSContext*, void*, JS::Compartment*);
/**
* This function calls |compartmentCallback| on every compartment until either
* all compartments have been iterated or CompartmentIterResult::Stop is
* returned. Beware that there is no guarantee that the compartment will survive
* after the callback returns. Also, barriers are disabled via the TraceSession.
*/
extern JS_PUBLIC_API void JS_IterateCompartments(
JSContext* cx, void* data,
JSIterateCompartmentCallback compartmentCallback);
/**
* This function calls |compartmentCallback| on every compartment in the given
* zone until either all compartments have been iterated or
* CompartmentIterResult::Stop is returned. Beware that there is no guarantee
* that the compartment will survive after the callback returns. Also, barriers
* are disabled via the TraceSession.
*/
extern JS_PUBLIC_API void JS_IterateCompartmentsInZone(
JSContext* cx, JS::Zone* zone, void* data,
JSIterateCompartmentCallback compartmentCallback);
/**
* Mark a jsid after entering a new compartment. Different zones separately
* mark the ids in a runtime, and this must be used any time an id is obtained
* from one compartment and then used in another compartment, unless the two
* compartments are guaranteed to be in the same zone.
*/
extern JS_PUBLIC_API void JS_MarkCrossZoneId(JSContext* cx, jsid id);
/**
* If value stores a jsid (an atomized string or symbol), mark that id as for
* JS_MarkCrossZoneId.
*/
extern JS_PUBLIC_API void JS_MarkCrossZoneIdValue(JSContext* cx,
const JS::Value& value);
/**
* 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<JSObject*> objp);
extern JS_PUBLIC_API bool JS_GetClassPrototype(
JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> 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<JS::Value> 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<JSObject*> ctor, JS::Handle<JSObject*> proto);
extern JS_PUBLIC_API bool JS_InstanceOf(JSContext* cx,
JS::Handle<JSObject*> obj,
const JSClass* clasp,
JS::CallArgs* args);
extern JS_PUBLIC_API bool JS_HasInstance(JSContext* cx,
JS::Handle<JSObject*> obj,
JS::Handle<JS::Value> v, bool* bp);
namespace JS {
// Implementation of
// 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
// 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<JSObject*> obj,
const JSClass* clasp,
JS::CallArgs* args);
extern JS_PUBLIC_API JSObject* JS_GetConstructor(JSContext* cx,
JS::Handle<JSObject*> 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<JSObject*> 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<JSObject*> obj);
/**
* Freezes an object; see ES5's Object.freeze(obj) method.
*/
extern JS_PUBLIC_API bool JS_FreezeObject(JSContext* cx,
JS::Handle<JSObject*> 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<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API bool JS_GetOwnPropertyDescriptor(
JSContext* cx, JS::HandleObject obj, const char* name,
JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API bool JS_GetOwnUCPropertyDescriptor(
JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::MutableHandle<JS::PropertyDescriptor> desc);
/**
* 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 desc.object(). If the property is not found
* on the prototype chain, this returns true with desc.object() set to null.
*/
extern JS_PUBLIC_API bool JS_GetPropertyDescriptorById(
JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API bool JS_GetPropertyDescriptor(
JSContext* cx, JS::HandleObject obj, const char* name,
JS::MutableHandle<JS::PropertyDescriptor> desc);
extern JS_PUBLIC_API bool JS_GetUCPropertyDescriptor(
JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
JS::MutableHandle<JS::PropertyDescriptor> desc);
/**
* 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<JS::PropertyDescriptor> 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<JS::PropertyDescriptor> 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<JS::PropertyDescriptor> 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<JS::PropertyDescriptor> 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<JS::IdVector>.
*/
extern JS_PUBLIC_API bool JS_Enumerate(JSContext* cx, JS::HandleObject obj,
JS::MutableHandle<JS::IdVector> 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 */
/**