summaryrefslogtreecommitdiffstats
path: root/js/src/jsapi.h
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /js/src/jsapi.h
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jsapi.h')
-rw-r--r--js/src/jsapi.h6634
1 files changed, 6634 insertions, 0 deletions
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
new file mode 100644
index 000000000..46aa15947
--- /dev/null
+++ b/js/src/jsapi.h
@@ -0,0 +1,6634 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * 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/MemoryReporting.h"
+#include "mozilla/Range.h"
+#include "mozilla/RangedPtr.h"
+#include "mozilla/RefCounted.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/Variant.h"
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "jsalloc.h"
+#include "jspubtd.h"
+
+#include "js/CallArgs.h"
+#include "js/CharacterEncoding.h"
+#include "js/Class.h"
+#include "js/GCVector.h"
+#include "js/HashTable.h"
+#include "js/Id.h"
+#include "js/Principals.h"
+#include "js/Realm.h"
+#include "js/RootingAPI.h"
+#include "js/TracingAPI.h"
+#include "js/Utility.h"
+#include "js/Value.h"
+#include "js/Vector.h"
+
+/************************************************************************/
+
+namespace JS {
+
+class TwoByteChars;
+
+#ifdef JS_DEBUG
+
+class JS_PUBLIC_API(AutoCheckRequestDepth)
+{
+ JSContext* cx;
+ public:
+ explicit AutoCheckRequestDepth(JSContext* cx);
+ explicit AutoCheckRequestDepth(js::ContextFriendFields* cx);
+ ~AutoCheckRequestDepth();
+};
+
+# define CHECK_REQUEST(cx) \
+ JS::AutoCheckRequestDepth _autoCheckRequestDepth(cx)
+
+#else
+
+# define CHECK_REQUEST(cx) \
+ ((void) 0)
+
+#endif /* JS_DEBUG */
+
+/** AutoValueArray roots an internal fixed-size array of Values. */
+template <size_t N>
+class MOZ_RAII AutoValueArray : public AutoGCRooter
+{
+ const size_t length_;
+ Value elements_[N];
+
+ public:
+ explicit AutoValueArray(JSContext* cx
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoGCRooter(cx, VALARRAY), length_(N)
+ {
+ /* Always initialize in case we GC before assignment. */
+ mozilla::PodArrayZero(elements_);
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ unsigned length() const { return length_; }
+ const Value* begin() const { return elements_; }
+ Value* begin() { return elements_; }
+
+ HandleValue operator[](unsigned i) const {
+ MOZ_ASSERT(i < N);
+ return HandleValue::fromMarkedLocation(&elements_[i]);
+ }
+ MutableHandleValue operator[](unsigned i) {
+ MOZ_ASSERT(i < N);
+ return MutableHandleValue::fromMarkedLocation(&elements_[i]);
+ }
+
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+template<class T>
+class MOZ_RAII AutoVectorRooterBase : protected AutoGCRooter
+{
+ typedef js::Vector<T, 8> VectorImpl;
+ VectorImpl vector;
+
+ public:
+ explicit AutoVectorRooterBase(JSContext* cx, ptrdiff_t tag
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoGCRooter(cx, tag), vector(cx)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ explicit AutoVectorRooterBase(js::ContextFriendFields* cx, ptrdiff_t tag
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoGCRooter(cx, tag), vector(cx)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ typedef T ElementType;
+ typedef typename VectorImpl::Range Range;
+
+ size_t length() const { return vector.length(); }
+ bool empty() const { return vector.empty(); }
+
+ MOZ_MUST_USE bool append(const T& v) { return vector.append(v); }
+ MOZ_MUST_USE bool appendN(const T& v, size_t len) { return vector.appendN(v, len); }
+ MOZ_MUST_USE bool append(const T* ptr, size_t len) { return vector.append(ptr, len); }
+ MOZ_MUST_USE bool appendAll(const AutoVectorRooterBase<T>& other) {
+ return vector.appendAll(other.vector);
+ }
+
+ MOZ_MUST_USE bool insert(T* p, const T& val) { return vector.insert(p, val); }
+
+ /* For use when space has already been reserved. */
+ void infallibleAppend(const T& v) { vector.infallibleAppend(v); }
+
+ void popBack() { vector.popBack(); }
+ T popCopy() { return vector.popCopy(); }
+
+ MOZ_MUST_USE bool growBy(size_t inc) {
+ size_t oldLength = vector.length();
+ if (!vector.growByUninitialized(inc))
+ return false;
+ makeRangeGCSafe(oldLength);
+ return true;
+ }
+
+ MOZ_MUST_USE bool resize(size_t newLength) {
+ size_t oldLength = vector.length();
+ if (newLength <= oldLength) {
+ vector.shrinkBy(oldLength - newLength);
+ return true;
+ }
+ if (!vector.growByUninitialized(newLength - oldLength))
+ return false;
+ makeRangeGCSafe(oldLength);
+ return true;
+ }
+
+ void clear() { vector.clear(); }
+
+ MOZ_MUST_USE bool reserve(size_t newLength) {
+ return vector.reserve(newLength);
+ }
+
+ JS::MutableHandle<T> operator[](size_t i) {
+ return JS::MutableHandle<T>::fromMarkedLocation(&vector[i]);
+ }
+ JS::Handle<T> operator[](size_t i) const {
+ return JS::Handle<T>::fromMarkedLocation(&vector[i]);
+ }
+
+ const T* begin() const { return vector.begin(); }
+ T* begin() { return vector.begin(); }
+
+ const T* end() const { return vector.end(); }
+ T* end() { return vector.end(); }
+
+ Range all() { return vector.all(); }
+
+ const T& back() const { return vector.back(); }
+
+ friend void AutoGCRooter::trace(JSTracer* trc);
+
+ private:
+ void makeRangeGCSafe(size_t oldLength) {
+ T* t = vector.begin() + oldLength;
+ for (size_t i = oldLength; i < vector.length(); ++i, ++t)
+ memset(t, 0, sizeof(T));
+ }
+
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+template <typename T>
+class MOZ_RAII AutoVectorRooter : public AutoVectorRooterBase<T>
+{
+ public:
+ explicit AutoVectorRooter(JSContext* cx
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoVectorRooterBase<T>(cx, this->GetTag(T()))
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ explicit AutoVectorRooter(js::ContextFriendFields* cx
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoVectorRooterBase<T>(cx, this->GetTag(T()))
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+class AutoValueVector : public Rooted<GCVector<Value, 8>> {
+ using Vec = GCVector<Value, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoValueVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoValueVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+};
+
+class AutoIdVector : public Rooted<GCVector<jsid, 8>> {
+ using Vec = GCVector<jsid, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoIdVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoIdVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+
+ bool appendAll(const AutoIdVector& other) { return this->Base::appendAll(other.get()); }
+};
+
+class AutoObjectVector : public Rooted<GCVector<JSObject*, 8>> {
+ using Vec = GCVector<JSObject*, 8>;
+ using Base = Rooted<Vec>;
+ public:
+ explicit AutoObjectVector(JSContext* cx) : Base(cx, Vec(cx)) {}
+ explicit AutoObjectVector(js::ContextFriendFields* cx) : Base(cx, Vec(cx)) {}
+};
+
+using ValueVector = JS::GCVector<JS::Value>;
+using IdVector = JS::GCVector<jsid>;
+using ScriptVector = JS::GCVector<JSScript*>;
+using StringVector = JS::GCVector<JSString*>;
+
+template<class Key, class Value>
+class MOZ_RAII AutoHashMapRooter : protected AutoGCRooter
+{
+ private:
+ typedef js::HashMap<Key, Value> HashMapImpl;
+
+ public:
+ explicit AutoHashMapRooter(JSContext* cx, ptrdiff_t tag
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoGCRooter(cx, tag), map(cx)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ typedef Key KeyType;
+ typedef Value ValueType;
+ typedef typename HashMapImpl::Entry Entry;
+ typedef typename HashMapImpl::Lookup Lookup;
+ typedef typename HashMapImpl::Ptr Ptr;
+ typedef typename HashMapImpl::AddPtr AddPtr;
+
+ bool init(uint32_t len = 16) {
+ return map.init(len);
+ }
+ bool initialized() const {
+ return map.initialized();
+ }
+ Ptr lookup(const Lookup& l) const {
+ return map.lookup(l);
+ }
+ void remove(Ptr p) {
+ map.remove(p);
+ }
+ AddPtr lookupForAdd(const Lookup& l) const {
+ return map.lookupForAdd(l);
+ }
+
+ template<typename KeyInput, typename ValueInput>
+ bool add(AddPtr& p, const KeyInput& k, const ValueInput& v) {
+ return map.add(p, k, v);
+ }
+
+ bool add(AddPtr& p, const Key& k) {
+ return map.add(p, k);
+ }
+
+ template<typename KeyInput, typename ValueInput>
+ bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) {
+ return map.relookupOrAdd(p, k, v);
+ }
+
+ typedef typename HashMapImpl::Range Range;
+ Range all() const {
+ return map.all();
+ }
+
+ typedef typename HashMapImpl::Enum Enum;
+
+ void clear() {
+ map.clear();
+ }
+
+ void finish() {
+ map.finish();
+ }
+
+ bool empty() const {
+ return map.empty();
+ }
+
+ uint32_t count() const {
+ return map.count();
+ }
+
+ size_t capacity() const {
+ return map.capacity();
+ }
+
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return map.sizeOfExcludingThis(mallocSizeOf);
+ }
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return map.sizeOfIncludingThis(mallocSizeOf);
+ }
+
+ /************************************************** Shorthand operations */
+
+ bool has(const Lookup& l) const {
+ return map.has(l);
+ }
+
+ template<typename KeyInput, typename ValueInput>
+ bool put(const KeyInput& k, const ValueInput& v) {
+ return map.put(k, v);
+ }
+
+ template<typename KeyInput, typename ValueInput>
+ bool putNew(const KeyInput& k, const ValueInput& v) {
+ return map.putNew(k, v);
+ }
+
+ Ptr lookupWithDefault(const Key& k, const Value& defaultValue) {
+ return map.lookupWithDefault(k, defaultValue);
+ }
+
+ void remove(const Lookup& l) {
+ map.remove(l);
+ }
+
+ friend void AutoGCRooter::trace(JSTracer* trc);
+
+ private:
+ AutoHashMapRooter(const AutoHashMapRooter& hmr) = delete;
+ AutoHashMapRooter& operator=(const AutoHashMapRooter& hmr) = delete;
+
+ HashMapImpl map;
+
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+template<class T>
+class MOZ_RAII AutoHashSetRooter : protected AutoGCRooter
+{
+ private:
+ typedef js::HashSet<T> HashSetImpl;
+
+ public:
+ explicit AutoHashSetRooter(JSContext* cx, ptrdiff_t tag
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoGCRooter(cx, tag), set(cx)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ typedef typename HashSetImpl::Lookup Lookup;
+ typedef typename HashSetImpl::Ptr Ptr;
+ typedef typename HashSetImpl::AddPtr AddPtr;
+
+ bool init(uint32_t len = 16) {
+ return set.init(len);
+ }
+ bool initialized() const {
+ return set.initialized();
+ }
+ Ptr lookup(const Lookup& l) const {
+ return set.lookup(l);
+ }
+ void remove(Ptr p) {
+ set.remove(p);
+ }
+ AddPtr lookupForAdd(const Lookup& l) const {
+ return set.lookupForAdd(l);
+ }
+
+ bool add(AddPtr& p, const T& t) {
+ return set.add(p, t);
+ }
+
+ bool relookupOrAdd(AddPtr& p, const Lookup& l, const T& t) {
+ return set.relookupOrAdd(p, l, t);
+ }
+
+ typedef typename HashSetImpl::Range Range;
+ Range all() const {
+ return set.all();
+ }
+
+ typedef typename HashSetImpl::Enum Enum;
+
+ void clear() {
+ set.clear();
+ }
+
+ void finish() {
+ set.finish();
+ }
+
+ bool empty() const {
+ return set.empty();
+ }
+
+ uint32_t count() const {
+ return set.count();
+ }
+
+ size_t capacity() const {
+ return set.capacity();
+ }
+
+ size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return set.sizeOfExcludingThis(mallocSizeOf);
+ }
+ size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
+ return set.sizeOfIncludingThis(mallocSizeOf);
+ }
+
+ /************************************************** Shorthand operations */
+
+ bool has(const Lookup& l) const {
+ return set.has(l);
+ }
+
+ bool put(const T& t) {
+ return set.put(t);
+ }
+
+ bool putNew(const T& t) {
+ return set.putNew(t);
+ }
+
+ void remove(const Lookup& l) {
+ set.remove(l);
+ }
+
+ friend void AutoGCRooter::trace(JSTracer* trc);
+
+ private:
+ AutoHashSetRooter(const AutoHashSetRooter& hmr) = delete;
+ AutoHashSetRooter& operator=(const AutoHashSetRooter& hmr) = delete;
+
+ HashSetImpl set;
+
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+/**
+ * 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 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : AutoGCRooter(cx, CUSTOM)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ friend void AutoGCRooter::trace(JSTracer* trc);
+
+ protected:
+ virtual ~CustomAutoRooter() {}
+
+ /** Supplied by derived class to trace roots. */
+ virtual void trace(JSTracer* trc) = 0;
+
+ private:
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+/** A handle to an array of rooted values. */
+class HandleValueArray
+{
+ const size_t length_;
+ const Value * const elements_;
+
+ HandleValueArray(size_t len, const Value* elements) : length_(len), elements_(elements) {}
+
+ public:
+ explicit HandleValueArray(const RootedValue& value) : length_(1), elements_(value.address()) {}
+
+ MOZ_IMPLICIT HandleValueArray(const AutoValueVector& values)
+ : length_(values.length()), elements_(values.begin()) {}
+
+ template <size_t N>
+ MOZ_IMPLICIT HandleValueArray(const AutoValueArray<N>& values) : length_(N), elements_(values.begin()) {}
+
+ /** CallArgs must already be rooted somewhere up the stack. */
+ MOZ_IMPLICIT HandleValueArray(const JS::CallArgs& args) : length_(args.length()), elements_(args.array()) {}
+
+ /** Use with care! Only call this if the data is guaranteed to be marked. */
+ static HandleValueArray fromMarkedLocation(size_t len, const Value* elements) {
+ return HandleValueArray(len, elements);
+ }
+
+ static HandleValueArray subarray(const HandleValueArray& values, size_t startIndex, size_t len) {
+ MOZ_ASSERT(startIndex + len <= values.length());
+ return HandleValueArray(len, values.begin() + startIndex);
+ }
+
+ static HandleValueArray empty() {
+ return HandleValueArray(0, nullptr);
+ }
+
+ size_t length() const { return length_; }
+ const Value* begin() const { return elements_; }
+
+ HandleValue operator[](size_t i) const {
+ MOZ_ASSERT(i < length_);
+ return HandleValue::fromMarkedLocation(&elements_[i]);
+ }
+};
+
+} /* namespace JS */
+
+/************************************************************************/
+
+struct JSFreeOp {
+ protected:
+ JSRuntime* runtime_;
+
+ explicit JSFreeOp(JSRuntime* rt)
+ : runtime_(rt) { }
+
+ public:
+ JSRuntime* runtime() const {
+ MOZ_ASSERT(runtime_);
+ return runtime_;
+ }
+};
+
+/* Callbacks and their arguments. */
+
+/************************************************************************/
+
+typedef enum JSGCStatus {
+ JSGC_BEGIN,
+ JSGC_END
+} JSGCStatus;
+
+typedef void
+(* JSGCCallback)(JSContext* cx, JSGCStatus status, void* data);
+
+typedef void
+(* JSObjectsTenuredCallback)(JSContext* cx, void* data);
+
+typedef enum JSFinalizeStatus {
+ /**
+ * Called when preparing to sweep a group of zones, before anything has been
+ * swept. The collector will not yield to the mutator before calling the
+ * callback with JSFINALIZE_GROUP_END status.
+ */
+ JSFINALIZE_GROUP_START,
+
+ /**
+ * Called when preparing to sweep a group of zones. Weak references to
+ * unmarked things have been removed and things that are not swept
+ * incrementally have been finalized at this point. The collector may yield
+ * to the mutator after this point.
+ */
+ JSFINALIZE_GROUP_END,
+
+ /**
+ * Called at the end of collection when everything has been swept.
+ */
+ JSFINALIZE_COLLECTION_END
+} JSFinalizeStatus;
+
+typedef void
+(* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, bool isZoneGC, void* data);
+
+typedef void
+(* JSWeakPointerZoneGroupCallback)(JSContext* cx, void* data);
+
+typedef void
+(* JSWeakPointerCompartmentCallback)(JSContext* cx, JSCompartment* comp, void* data);
+
+typedef bool
+(* JSInterruptCallback)(JSContext* cx);
+
+typedef JSObject*
+(* JSGetIncumbentGlobalCallback)(JSContext* cx);
+
+typedef bool
+(* JSEnqueuePromiseJobCallback)(JSContext* cx, JS::HandleObject job,
+ JS::HandleObject allocationSite, JS::HandleObject incumbentGlobal,
+ void* data);
+
+enum class PromiseRejectionHandlingState {
+ Unhandled,
+ Handled
+};
+
+typedef void
+(* JSPromiseRejectionTrackerCallback)(JSContext* cx, JS::HandleObject promise,
+ PromiseRejectionHandlingState state, void* data);
+
+typedef void
+(* JSProcessPromiseCallback)(JSContext* cx, JS::HandleObject promise);
+
+/**
+ * Possible exception types. These types are part of a JSErrorFormatString
+ * structure. They define which error to throw in case of a runtime error.
+ *
+ * JSEXN_WARN is used for warnings in js.msg files (for instance because we
+ * don't want to prepend 'Error:' to warning messages). This value can go away
+ * if we ever decide to use an entirely separate mechanism for warnings.
+ */
+typedef enum JSExnType {
+ JSEXN_ERR,
+ JSEXN_FIRST = JSEXN_ERR,
+ JSEXN_INTERNALERR,
+ JSEXN_EVALERR,
+ JSEXN_RANGEERR,
+ JSEXN_REFERENCEERR,
+ JSEXN_SYNTAXERR,
+ JSEXN_TYPEERR,
+ JSEXN_URIERR,
+ JSEXN_DEBUGGEEWOULDRUN,
+ JSEXN_WASMCOMPILEERROR,
+ JSEXN_WASMRUNTIMEERROR,
+ JSEXN_WARN,
+ JSEXN_LIMIT
+} JSExnType;
+
+typedef struct JSErrorFormatString {
+ /** The error message name in ASCII. */
+ const char* name;
+
+ /** The error format string in ASCII. */
+ const char* format;
+
+ /** The number of arguments to expand in the formatted error message. */
+ uint16_t argCount;
+
+ /** One of the JSExnType constants above. */
+ int16_t exnType;
+} JSErrorFormatString;
+
+typedef const JSErrorFormatString*
+(* JSErrorCallback)(void* userRef, const unsigned errorNumber);
+
+typedef bool
+(* JSLocaleToUpperCase)(JSContext* cx, JS::HandleString src, JS::MutableHandleValue rval);
+
+typedef bool
+(* JSLocaleToLowerCase)(JSContext* cx, JS::HandleString src, JS::MutableHandleValue rval);
+
+typedef bool
+(* JSLocaleCompare)(JSContext* cx, JS::HandleString src1, JS::HandleString src2,
+ JS::MutableHandleValue rval);
+
+typedef bool
+(* JSLocaleToUnicode)(JSContext* cx, const char* src, JS::MutableHandleValue rval);
+
+/**
+ * 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.
+ */
+typedef JSObject*
+(* JSWrapObjectCallback)(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj);
+
+/**
+ * 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.
+ */
+typedef void
+(* JSPreWrapCallback)(JSContext* cx, JS::HandleObject scope, JS::HandleObject obj,
+ JS::HandleObject objectPassedToWrap,
+ JS::MutableHandleObject retObj);
+
+struct JSWrapObjectCallbacks
+{
+ JSWrapObjectCallback wrap;
+ JSPreWrapCallback preWrap;
+};
+
+typedef void
+(* JSDestroyCompartmentCallback)(JSFreeOp* fop, JSCompartment* compartment);
+
+typedef size_t
+(* JSSizeOfIncludingThisCompartmentCallback)(mozilla::MallocSizeOf mallocSizeOf,
+ JSCompartment* compartment);
+
+typedef void
+(* JSZoneCallback)(JS::Zone* zone);
+
+typedef void
+(* JSCompartmentNameCallback)(JSContext* cx, JSCompartment* compartment,
+ char* buf, size_t bufsize);
+
+/************************************************************************/
+
+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);
+
+namespace JS {
+
+/**
+ * Container class for passing in script source buffers to the JS engine. This
+ * not only groups the buffer and length values, it also provides a way to
+ * optionally pass ownership of the buffer to the JS engine without copying.
+ * Rules for use:
+ *
+ * 1) The data array must be allocated with js_malloc() or js_realloc() if
+ * ownership is being granted to the SourceBufferHolder.
+ * 2) If ownership is not given to the SourceBufferHolder, then the memory
+ * must be kept alive until the JS compilation is complete.
+ * 3) Any code calling SourceBufferHolder::take() must guarantee to keep the
+ * memory alive until JS compilation completes. Normally only the JS
+ * engine should be calling take().
+ *
+ * Example use:
+ *
+ * size_t length = 512;
+ * char16_t* chars = static_cast<char16_t*>(js_malloc(sizeof(char16_t) * length));
+ * JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
+ * JS::Compile(cx, options, srcBuf);
+ */
+class MOZ_STACK_CLASS SourceBufferHolder final
+{
+ public:
+ enum Ownership {
+ NoOwnership,
+ GiveOwnership
+ };
+
+ SourceBufferHolder(const char16_t* data, size_t dataLength, Ownership ownership)
+ : data_(data),
+ length_(dataLength),
+ ownsChars_(ownership == GiveOwnership)
+ {
+ // Ensure that null buffers properly return an unowned, empty,
+ // null-terminated string.
+ static const char16_t NullChar_ = 0;
+ if (!get()) {
+ data_ = &NullChar_;
+ length_ = 0;
+ ownsChars_ = false;
+ }
+ }
+
+ SourceBufferHolder(SourceBufferHolder&& other)
+ : data_(other.data_),
+ length_(other.length_),
+ ownsChars_(other.ownsChars_)
+ {
+ other.data_ = nullptr;
+ other.length_ = 0;
+ other.ownsChars_ = false;
+ }
+
+ ~SourceBufferHolder() {
+ if (ownsChars_)
+ js_free(const_cast<char16_t*>(data_));
+ }
+
+ // Access the underlying source buffer without affecting ownership.
+ const char16_t* get() const { return data_; }
+
+ // Length of the source buffer in char16_t code units (not bytes)
+ size_t length() const { return length_; }
+
+ // Returns true if the SourceBufferHolder owns the buffer and will free
+ // it upon destruction. If true, it is legal to call take().
+ bool ownsChars() const { return ownsChars_; }
+
+ // Retrieve and take ownership of the underlying data buffer. The caller
+ // is now responsible for calling js_free() on the returned value, *but only
+ // after JS script compilation has completed*.
+ //
+ // After the buffer has been taken the SourceBufferHolder functions as if
+ // it had been constructed on an unowned buffer; get() and length() still
+ // work. In order for this to be safe the taken buffer must be kept alive
+ // until after JS script compilation completes as noted above.
+ //
+ // Note, it's the caller's responsibility to check ownsChars() before taking
+ // the buffer. Taking and then free'ing an unowned buffer will have dire
+ // consequences.
+ char16_t* take() {
+ MOZ_ASSERT(ownsChars_);
+ ownsChars_ = false;
+ return const_cast<char16_t*>(data_);
+ }
+
+ private:
+ SourceBufferHolder(SourceBufferHolder&) = delete;
+ SourceBufferHolder& operator=(SourceBufferHolder&) = delete;
+
+ const char16_t* data_;
+ size_t length_;
+ bool ownsChars_;
+};
+
+} /* namespace JS */
+
+/************************************************************************/
+
+/* Property attributes, set in JSPropertySpec and passed to API functions.
+ *
+ * NB: The data structure in which some of these values are stored only uses
+ * a uint8_t to store the relevant information. Proceed with caution if
+ * trying to reorder or change the the first byte worth of flags.
+ */
+#define JSPROP_ENUMERATE 0x01 /* property is visible to for/in loop */
+#define JSPROP_READONLY 0x02 /* not settable: assignment is no-op.
+ This flag is only valid when neither
+ JSPROP_GETTER nor JSPROP_SETTER is
+ set. */
+#define JSPROP_PERMANENT 0x04 /* property cannot be deleted */
+#define JSPROP_PROPOP_ACCESSORS 0x08 /* Passed to JS_Define(UC)Property* and
+ JS_DefineElement if getters/setters
+ are JSGetterOp/JSSetterOp */
+#define JSPROP_GETTER 0x10 /* property holds getter function */
+#define JSPROP_SETTER 0x20 /* property holds setter function */
+#define JSPROP_SHARED 0x40 /* don't allocate a value slot for this
+ property; don't copy the property on
+ set of the same-named property in an
+ object that delegates to a prototype
+ containing this property */
+#define JSPROP_INTERNAL_USE_BIT 0x80 /* internal JS engine use only */
+#define JSFUN_STUB_GSOPS 0x200 /* use JS_PropertyStub getter/setter
+ instead of defaulting to class gsops
+ for property holding function */
+
+#define JSFUN_CONSTRUCTOR 0x400 /* native that can be called as a ctor */
+
+// 0x800 /* Unused */
+
+#define JSFUN_HAS_REST 0x1000 /* function has ...rest parameter. */
+
+#define JSFUN_FLAGS_MASK 0x1e00 /* | of all the JSFUN_* flags */
+
+/*
+ * If set, will allow redefining a non-configurable property, but only on a
+ * non-DOM global. This is a temporary hack that will need to go away in bug
+ * 1105518.
+ */
+#define JSPROP_REDEFINE_NONCONFIGURABLE 0x1000
+
+/*
+ * Resolve hooks and enumerate hooks must pass this flag when calling
+ * JS_Define* APIs to reify lazily-defined properties.
+ *
+ * JSPROP_RESOLVING is used only with property-defining APIs. It tells the
+ * engine to skip the resolve hook when performing the lookup at the beginning
+ * of property definition. This keeps the resolve hook from accidentally
+ * triggering itself: unchecked recursion.
+ *
+ * For enumerate hooks, triggering the resolve hook would be merely silly, not
+ * fatal, except in some cases involving non-configurable properties.
+ */
+#define JSPROP_RESOLVING 0x2000
+
+#define JSPROP_IGNORE_ENUMERATE 0x4000 /* ignore the value in JSPROP_ENUMERATE.
+ This flag only valid when defining over
+ an existing property. */
+#define JSPROP_IGNORE_READONLY 0x8000 /* ignore the value in JSPROP_READONLY.
+ This flag only valid when defining over
+ an existing property. */
+#define JSPROP_IGNORE_PERMANENT 0x10000 /* ignore the value in JSPROP_PERMANENT.
+ This flag only valid when defining over
+ an existing property. */
+#define JSPROP_IGNORE_VALUE 0x20000 /* ignore the Value in the descriptor. Nothing was
+ specified when passed to Object.defineProperty
+ from script. */
+
+/** 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_GetNaNValue(JSContext* cx);
+
+extern JS_PUBLIC_API(JS::Value)
+JS_GetNegativeInfinityValue(JSContext* cx);
+
+extern JS_PUBLIC_API(JS::Value)
+JS_GetPositiveInfinityValue(JSContext* cx);
+
+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);
+
+} /* namespace JS */
+
+extern JS_PUBLIC_API(bool)
+JS_StrictlyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal);
+
+extern JS_PUBLIC_API(bool)
+JS_LooselyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal);
+
+extern JS_PUBLIC_API(bool)
+JS_SameValue(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* same);
+
+/** 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);
+
+/************************************************************************/
+
+/*
+ * 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: http://developer.mozilla.org/en/docs/Category:JSAPI_Reference
+ */
+
+extern JS_PUBLIC_API(JSContext*)
+JS_NewContext(uint32_t maxbytes,
+ uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
+ JSContext* parentContext = nullptr);
+
+extern JS_PUBLIC_API(void)
+JS_DestroyContext(JSContext* cx);
+
+typedef double (*JS_CurrentEmbedderTimeFunction)();
+
+/**
+ * The embedding can specify a time function that will be used in some
+ * situations. The function can return the time however it likes; but
+ * the norm is to return times in units of milliseconds since an
+ * arbitrary, but consistent, epoch. If the time function is not set,
+ * a built-in default will be used.
+ */
+JS_PUBLIC_API(void)
+JS_SetCurrentEmbedderTimeFunction(JS_CurrentEmbedderTimeFunction timeFn);
+
+/**
+ * Return the time as computed using the current time function, or a
+ * suitable default if one has not been set.
+ */
+JS_PUBLIC_API(double)
+JS_GetCurrentEmbedderTime();
+
+JS_PUBLIC_API(void*)
+JS_GetContextPrivate(JSContext* cx);
+
+JS_PUBLIC_API(void)
+JS_SetContextPrivate(JSContext* cx, void* data);
+
+extern JS_PUBLIC_API(JSContext*)
+JS_GetParentContext(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_BeginRequest(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_EndRequest(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_SetFutexCanWait(JSContext* cx);
+
+namespace js {
+
+void
+AssertHeapIsIdle(JSRuntime* rt);
+
+} /* namespace js */
+
+class MOZ_RAII JSAutoRequest
+{
+ public:
+ explicit JSAutoRequest(JSContext* cx
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : mContext(cx)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ JS_BeginRequest(mContext);
+ }
+ ~JSAutoRequest() {
+ JS_EndRequest(mContext);
+ }
+
+ protected:
+ JSContext* mContext;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+
+#if 0
+ private:
+ static void* operator new(size_t) CPP_THROW_NEW { return 0; }
+ static void operator delete(void*, size_t) { }
+#endif
+};
+
+extern JS_PUBLIC_API(JSVersion)
+JS_GetVersion(JSContext* cx);
+
+/**
+ * Mutate the version on the compartment. This is generally discouraged, but
+ * necessary to support the version mutation in the js and xpc shell command
+ * set.
+ *
+ * It would be nice to put this in jsfriendapi, but the linkage requirements
+ * of the shells make that impossible.
+ */
+JS_PUBLIC_API(void)
+JS_SetVersionForCompartment(JSCompartment* compartment, JSVersion version);
+
+extern JS_PUBLIC_API(const char*)
+JS_VersionToString(JSVersion version);
+
+extern JS_PUBLIC_API(JSVersion)
+JS_StringToVersion(const char* string);
+
+namespace JS {
+
+class JS_PUBLIC_API(ContextOptions) {
+ public:
+ ContextOptions()
+ : baseline_(true),
+ ion_(true),
+ asmJS_(true),
+ wasm_(false),
+ wasmAlwaysBaseline_(false),
+ throwOnAsmJSValidationFailure_(false),
+ nativeRegExp_(true),
+ unboxedArrays_(false),
+ asyncStack_(true),
+ throwOnDebuggeeWouldRun_(true),
+ dumpStackOnDebuggeeWouldRun_(false),
+ werror_(false),
+ strictMode_(false),
+ extraWarnings_(false)
+ {
+ }
+
+ bool baseline() const { return baseline_; }
+ ContextOptions& setBaseline(bool flag) {
+ baseline_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleBaseline() {
+ baseline_ = !baseline_;
+ return *this;
+ }
+
+ bool ion() const { return ion_; }
+ ContextOptions& setIon(bool flag) {
+ ion_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleIon() {
+ ion_ = !ion_;
+ return *this;
+ }
+
+ bool asmJS() const { return asmJS_; }
+ ContextOptions& setAsmJS(bool flag) {
+ asmJS_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleAsmJS() {
+ asmJS_ = !asmJS_;
+ return *this;
+ }
+
+ bool wasm() const { return wasm_; }
+ ContextOptions& setWasm(bool flag) {
+ wasm_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleWasm() {
+ wasm_ = !wasm_;
+ return *this;
+ }
+
+ bool wasmAlwaysBaseline() const { return wasmAlwaysBaseline_; }
+ ContextOptions& setWasmAlwaysBaseline(bool flag) {
+ wasmAlwaysBaseline_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleWasmAlwaysBaseline() {
+ wasmAlwaysBaseline_ = !wasmAlwaysBaseline_;
+ return *this;
+ }
+
+ bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; }
+ ContextOptions& setThrowOnAsmJSValidationFailure(bool flag) {
+ throwOnAsmJSValidationFailure_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleThrowOnAsmJSValidationFailure() {
+ throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_;
+ return *this;
+ }
+
+ bool nativeRegExp() const { return nativeRegExp_; }
+ ContextOptions& setNativeRegExp(bool flag) {
+ nativeRegExp_ = flag;
+ return *this;
+ }
+
+ bool unboxedArrays() const { return unboxedArrays_; }
+ ContextOptions& setUnboxedArrays(bool flag) {
+ unboxedArrays_ = flag;
+ return *this;
+ }
+
+ bool asyncStack() const { return asyncStack_; }
+ ContextOptions& setAsyncStack(bool flag) {
+ asyncStack_ = flag;
+ return *this;
+ }
+
+ bool throwOnDebuggeeWouldRun() const { return throwOnDebuggeeWouldRun_; }
+ ContextOptions& setThrowOnDebuggeeWouldRun(bool flag) {
+ throwOnDebuggeeWouldRun_ = flag;
+ return *this;
+ }
+
+ bool dumpStackOnDebuggeeWouldRun() const { return dumpStackOnDebuggeeWouldRun_; }
+ ContextOptions& setDumpStackOnDebuggeeWouldRun(bool flag) {
+ dumpStackOnDebuggeeWouldRun_ = flag;
+ return *this;
+ }
+
+ bool werror() const { return werror_; }
+ ContextOptions& setWerror(bool flag) {
+ werror_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleWerror() {
+ werror_ = !werror_;
+ return *this;
+ }
+
+ bool strictMode() const { return strictMode_; }
+ ContextOptions& setStrictMode(bool flag) {
+ strictMode_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleStrictMode() {
+ strictMode_ = !strictMode_;
+ return *this;
+ }
+
+ bool extraWarnings() const { return extraWarnings_; }
+ ContextOptions& setExtraWarnings(bool flag) {
+ extraWarnings_ = flag;
+ return *this;
+ }
+ ContextOptions& toggleExtraWarnings() {
+ extraWarnings_ = !extraWarnings_;
+ return *this;
+ }
+
+ private:
+ bool baseline_ : 1;
+ bool ion_ : 1;
+ bool asmJS_ : 1;
+ bool wasm_ : 1;
+ bool wasmAlwaysBaseline_ : 1;
+ bool throwOnAsmJSValidationFailure_ : 1;
+ bool nativeRegExp_ : 1;
+ bool unboxedArrays_ : 1;
+ bool asyncStack_ : 1;
+ bool throwOnDebuggeeWouldRun_ : 1;
+ bool dumpStackOnDebuggeeWouldRun_ : 1;
+ bool werror_ : 1;
+ bool strictMode_ : 1;
+ bool extraWarnings_ : 1;
+};
+
+JS_PUBLIC_API(ContextOptions&)
+ContextOptionsRef(JSContext* cx);
+
+/**
+ * Initialize the runtime's self-hosted code. Embeddings should call this
+ * exactly once per runtime/context, before the first JS_NewGlobalObject
+ * call.
+ */
+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);
+
+} /* namespace JS */
+
+extern JS_PUBLIC_API(const char*)
+JS_GetImplementationVersion(void);
+
+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_SetDestroyZoneCallback(JSContext* cx, JSZoneCallback callback);
+
+extern JS_PUBLIC_API(void)
+JS_SetSweepZoneCallback(JSContext* cx, JSZoneCallback callback);
+
+extern JS_PUBLIC_API(void)
+JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback);
+
+extern JS_PUBLIC_API(void)
+JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks);
+
+extern JS_PUBLIC_API(void)
+JS_SetCompartmentPrivate(JSCompartment* compartment, void* data);
+
+extern JS_PUBLIC_API(void*)
+JS_GetCompartmentPrivate(JSCompartment* 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) compartment.
+ * Compartments are described in:
+ *
+ * developer.mozilla.org/en-US/docs/SpiderMonkey/SpiderMonkey_compartments
+ *
+ * The current compartment of a context may be changed. The preferred way to do
+ * this is with JSAutoCompartment:
+ *
+ * void foo(JSContext* cx, JSObject* obj) {
+ * // in some compartment 'c'
+ * {
+ * JSAutoCompartment ac(cx, obj); // constructor enters
+ * // in the compartment of 'obj'
+ * } // destructor leaves
+ * // back in compartment 'c'
+ * }
+ *
+ * For more complicated uses that don't neatly fit in a C++ stack frame, the
+ * compartment can entered and left using separate function calls:
+ *
+ * void foo(JSContext* cx, JSObject* obj) {
+ * // in 'oldCompartment'
+ * JSCompartment* oldCompartment = JS_EnterCompartment(cx, obj);
+ * // in the compartment of 'obj'
+ * JS_LeaveCompartment(cx, oldCompartment);
+ * // back in 'oldCompartment'
+ * }
+ *
+ * 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_EnterCompartment call may be passed as the 'oldCompartment' argument of
+ * the corresponding JS_LeaveCompartment call.
+ */
+
+class MOZ_RAII JS_PUBLIC_API(JSAutoCompartment)
+{
+ JSContext* cx_;
+ JSCompartment* oldCompartment_;
+ public:
+ JSAutoCompartment(JSContext* cx, JSObject* target
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+ JSAutoCompartment(JSContext* cx, JSScript* target
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+ ~JSAutoCompartment();
+
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+class MOZ_RAII JS_PUBLIC_API(JSAutoNullableCompartment)
+{
+ JSContext* cx_;
+ JSCompartment* oldCompartment_;
+ public:
+ explicit JSAutoNullableCompartment(JSContext* cx, JSObject* targetOrNull
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+ ~JSAutoNullableCompartment();
+
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+/** NB: This API is infallible; a nullptr return value does not indicate error. */
+extern JS_PUBLIC_API(JSCompartment*)
+JS_EnterCompartment(JSContext* cx, JSObject* target);
+
+extern JS_PUBLIC_API(void)
+JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment);
+
+typedef void (*JSIterateCompartmentCallback)(JSContext* cx, void* data, JSCompartment* compartment);
+
+/**
+ * This function calls |compartmentCallback| on every compartment. 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);
+
+/**
+ * Initialize standard JS class constructors, prototypes, and any top-level
+ * functions and constants associated with the standard classes (e.g. isNaN
+ * for Number).
+ *
+ * NB: This sets cx's global object to obj if it was null.
+ */
+extern JS_PUBLIC_API(bool)
+JS_InitStandardClasses(JSContext* cx, JS::Handle<JSObject*> obj);
+
+/**
+ * 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's enumerate op should call
+ * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in
+ * loops any classes not yet resolved lazily.
+ */
+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);
+
+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);
+
+/**
+ * Returns the original value of |Function.prototype| from the global object in
+ * which |forObj| was created.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_GetFunctionPrototype(JSContext* cx, JS::HandleObject forObj);
+
+/**
+ * Returns the original value of |Object.prototype| from the global object in
+ * which |forObj| was created.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_GetObjectPrototype(JSContext* cx, JS::HandleObject forObj);
+
+/**
+ * Returns the original value of |Array.prototype| from the global object in
+ * which |forObj| was created.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_GetArrayPrototype(JSContext* cx, JS::HandleObject forObj);
+
+/**
+ * Returns the original value of |Error.prototype| from the global
+ * object of the current compartment of cx.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_GetErrorPrototype(JSContext* cx);
+
+/**
+ * Returns the %IteratorPrototype% object that all built-in iterator prototype
+ * chains go through for the global object of the current compartment of cx.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_GetIteratorPrototype(JSContext* cx);
+
+extern JS_PUBLIC_API(JSObject*)
+JS_GetGlobalForObject(JSContext* cx, JSObject* obj);
+
+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);
+
+/**
+ * May return nullptr, if |c| never had a global (e.g. the atoms compartment),
+ * or if |c|'s global has been collected.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_GetGlobalForCompartmentOrNull(JSContext* cx, JSCompartment* c);
+
+namespace JS {
+
+extern JS_PUBLIC_API(JSObject*)
+CurrentGlobalOrNull(JSContext* cx);
+
+} // 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);
+
+#ifdef JS_HAS_CTYPES
+/**
+ * Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes'
+ * object will be sealed.
+ */
+extern JS_PUBLIC_API(bool)
+JS_InitCTypesClass(JSContext* cx, JS::HandleObject global);
+
+/**
+ * Convert a unicode string 'source' of length 'slen' to the platform native
+ * charset, returning a null-terminated string allocated with JS_malloc. On
+ * failure, this function should report an error.
+ */
+typedef char*
+(* JSCTypesUnicodeToNativeFun)(JSContext* cx, const char16_t* source, size_t slen);
+
+/**
+ * Set of function pointers that ctypes can use for various internal functions.
+ * See JS_SetCTypesCallbacks below. Providing nullptr for a function is safe,
+ * and will result in the applicable ctypes functionality not being available.
+ */
+struct JSCTypesCallbacks {
+ JSCTypesUnicodeToNativeFun unicodeToNative;
+};
+
+typedef struct JSCTypesCallbacks JSCTypesCallbacks;
+
+/**
+ * Set the callbacks on the provided 'ctypesObj' object. 'callbacks' should be a
+ * pointer to static data that exists for the lifetime of 'ctypesObj', but it
+ * may safely be altered after calling this function and without having
+ * to call this function again.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetCTypesCallbacks(JSObject* ctypesObj, const JSCTypesCallbacks* callbacks);
+#endif
+
+extern JS_PUBLIC_API(void*)
+JS_malloc(JSContext* cx, size_t nbytes);
+
+extern JS_PUBLIC_API(void*)
+JS_realloc(JSContext* cx, void* p, size_t oldBytes, size_t newBytes);
+
+/**
+ * A wrapper for js_free(p) that may delay js_free(p) invocation as a
+ * performance optimization.
+ * cx may be nullptr.
+ */
+extern JS_PUBLIC_API(void)
+JS_free(JSContext* cx, void* p);
+
+/**
+ * A wrapper for js_free(p) that may delay js_free(p) invocation as a
+ * performance optimization as specified by the given JSFreeOp instance.
+ */
+extern JS_PUBLIC_API(void)
+JS_freeop(JSFreeOp* fop, void* p);
+
+extern JS_PUBLIC_API(void)
+JS_updateMallocCounter(JSContext* cx, size_t nbytes);
+
+extern JS_PUBLIC_API(char*)
+JS_strdup(JSContext* cx, const char* s);
+
+/**
+ * Register externally maintained GC roots.
+ *
+ * traceOp: the trace operation. For each root the implementation should call
+ * JS::TraceEdge whenever the root contains a traceable thing.
+ * data: the data argument to pass to each invocation of traceOp.
+ */
+extern JS_PUBLIC_API(bool)
+JS_AddExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
+
+/** Undo a call to JS_AddExtraGCRootsTracer. */
+extern JS_PUBLIC_API(void)
+JS_RemoveExtraGCRootsTracer(JSContext* cx, JSTraceDataOp traceOp, void* data);
+
+/*
+ * Garbage collector API.
+ */
+extern JS_PUBLIC_API(void)
+JS_GC(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_MaybeGC(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_SetGCCallback(JSContext* cx, JSGCCallback cb, void* data);
+
+extern JS_PUBLIC_API(void)
+JS_SetObjectsTenuredCallback(JSContext* cx, JSObjectsTenuredCallback cb,
+ void* data);
+
+extern JS_PUBLIC_API(bool)
+JS_AddFinalizeCallback(JSContext* cx, JSFinalizeCallback cb, void* data);
+
+extern JS_PUBLIC_API(void)
+JS_RemoveFinalizeCallback(JSContext* cx, JSFinalizeCallback cb);
+
+/*
+ * Weak pointers and garbage collection
+ *
+ * Weak pointers are by their nature not marked as part of garbage collection,
+ * but they may need to be updated in two cases after a GC:
+ *
+ * 1) Their referent was found not to be live and is about to be finalized
+ * 2) Their referent has been moved by a compacting GC
+ *
+ * To handle this, any part of the system that maintain weak pointers to
+ * JavaScript GC things must register a callback with
+ * JS_(Add,Remove)WeakPointer{ZoneGroup,Compartment}Callback(). This callback
+ * must then call JS_UpdateWeakPointerAfterGC() on all weak pointers it knows
+ * about.
+ *
+ * Since sweeping is incremental, we have several callbacks to avoid repeatedly
+ * having to visit all embedder structures. The WeakPointerZoneGroupCallback is
+ * called once for each strongly connected group of zones, whereas the
+ * WeakPointerCompartmentCallback is called once for each compartment that is
+ * visited while sweeping. Structures that cannot contain references in more
+ * than one compartment should sweep the relevant per-compartment structures
+ * using the latter callback to minimizer per-slice overhead.
+ *
+ * The argument to JS_UpdateWeakPointerAfterGC() is an in-out param. If the
+ * referent is about to be finalized the pointer will be set to null. If the
+ * referent has been moved then the pointer will be updated to point to the new
+ * location.
+ *
+ * Callers of this method are responsible for updating any state that is
+ * dependent on the object's address. For example, if the object's address is
+ * used as a key in a hashtable, then the object must be removed and
+ * re-inserted with the correct hash.
+ */
+
+extern JS_PUBLIC_API(bool)
+JS_AddWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb, void* data);
+
+extern JS_PUBLIC_API(void)
+JS_RemoveWeakPointerZoneGroupCallback(JSContext* cx, JSWeakPointerZoneGroupCallback cb);
+
+extern JS_PUBLIC_API(bool)
+JS_AddWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb,
+ void* data);
+
+extern JS_PUBLIC_API(void)
+JS_RemoveWeakPointerCompartmentCallback(JSContext* cx, JSWeakPointerCompartmentCallback cb);
+
+extern JS_PUBLIC_API(void)
+JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp);
+
+extern JS_PUBLIC_API(void)
+JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp);
+
+typedef enum JSGCParamKey {
+ /** Maximum nominal heap before last ditch GC. */
+ JSGC_MAX_BYTES = 0,
+
+ /** Number of JS_malloc bytes before last ditch GC. */
+ JSGC_MAX_MALLOC_BYTES = 1,
+
+ /** Amount of bytes allocated by the GC. */
+ JSGC_BYTES = 3,
+
+ /** Number of times GC has been invoked. Includes both major and minor GC. */
+ JSGC_NUMBER = 4,
+
+ /** Select GC mode. */
+ JSGC_MODE = 6,
+
+ /** Number of cached empty GC chunks. */
+ JSGC_UNUSED_CHUNKS = 7,
+
+ /** Total number of allocated GC chunks. */
+ JSGC_TOTAL_CHUNKS = 8,
+
+ /** Max milliseconds to spend in an incremental GC slice. */
+ JSGC_SLICE_TIME_BUDGET = 9,
+
+ /** Maximum size the GC mark stack can grow to. */
+ JSGC_MARK_STACK_LIMIT = 10,
+
+ /**
+ * GCs less than this far apart in time will be considered 'high-frequency GCs'.
+ * See setGCLastBytes in jsgc.cpp.
+ */
+ JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11,
+
+ /** Start of dynamic heap growth. */
+ JSGC_HIGH_FREQUENCY_LOW_LIMIT = 12,
+
+ /** End of dynamic heap growth. */
+ JSGC_HIGH_FREQUENCY_HIGH_LIMIT = 13,
+
+ /** Upper bound of heap growth. */
+ JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX = 14,
+
+ /** Lower bound of heap growth. */
+ JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN = 15,
+
+ /** Heap growth for low frequency GCs. */
+ JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16,
+
+ /**
+ * If false, the heap growth factor is fixed at 3. If true, it is determined
+ * based on whether GCs are high- or low- frequency.
+ */
+ JSGC_DYNAMIC_HEAP_GROWTH = 17,
+
+ /** If true, high-frequency GCs will use a longer mark slice. */
+ JSGC_DYNAMIC_MARK_SLICE = 18,
+
+ /** Lower limit after which we limit the heap growth. */
+ JSGC_ALLOCATION_THRESHOLD = 19,
+
+ /**
+ * We try to keep at least this many unused chunks in the free chunk pool at
+ * all times, even after a shrinking GC.
+ */
+ JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
+
+ /** We never keep more than this many unused chunks in the free chunk pool. */
+ JSGC_MAX_EMPTY_CHUNK_COUNT = 22,
+
+ /** Whether compacting GC is enabled. */
+ JSGC_COMPACTING_ENABLED = 23,
+
+ /** If true, painting can trigger IGC slices. */
+ JSGC_REFRESH_FRAME_SLICES_ENABLED = 24,
+} JSGCParamKey;
+
+extern JS_PUBLIC_API(void)
+JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
+
+extern JS_PUBLIC_API(uint32_t)
+JS_GetGCParameter(JSContext* cx, JSGCParamKey key);
+
+extern JS_PUBLIC_API(void)
+JS_SetGCParametersBasedOnAvailableMemory(JSContext* cx, uint32_t availMem);
+
+/**
+ * Create a new JSString whose chars member refers to external memory, i.e.,
+ * memory requiring application-specific finalization.
+ */
+extern JS_PUBLIC_API(JSString*)
+JS_NewExternalString(JSContext* cx, const char16_t* chars, size_t length,
+ const JSStringFinalizer* fin);
+
+/**
+ * Return whether 'str' was created with JS_NewExternalString or
+ * JS_NewExternalStringWithClosure.
+ */
+extern JS_PUBLIC_API(bool)
+JS_IsExternalString(JSString* str);
+
+/**
+ * Return the 'fin' arg passed to JS_NewExternalString.
+ */
+extern JS_PUBLIC_API(const JSStringFinalizer*)
+JS_GetExternalStringFinalizer(JSString* str);
+
+/**
+ * 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_VOID (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_VOID 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(bool)
+JS_PropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
+ JS::MutableHandleValue vp);
+
+extern JS_PUBLIC_API(bool)
+JS_StrictPropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
+ JS::MutableHandleValue vp, JS::ObjectOpResult& result);
+
+template<typename T>
+struct JSConstScalarSpec {
+ const char* name;
+ T val;
+};
+
+typedef JSConstScalarSpec<double> JSConstDoubleSpec;
+typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec;
+
+struct JSJitInfo;
+
+/**
+ * Wrapper to relace JSNative for JSPropertySpecs and JSFunctionSpecs. This will
+ * allow us to pass one JSJitInfo per function with the property/function spec,
+ * without additional field overhead.
+ */
+typedef struct JSNativeWrapper {
+ JSNative op;
+ const JSJitInfo* info;
+} JSNativeWrapper;
+
+/*
+ * Macro static initializers which make it easy to pass no JSJitInfo as part of a
+ * JSPropertySpec or JSFunctionSpec.
+ */
+#define JSNATIVE_WRAPPER(native) { {native, nullptr} }
+
+/**
+ * Description of a property. JS_DefineProperties and JS_InitClass take arrays
+ * of these and define many properties at once. JS_PSG, JS_PSGS and JS_PS_END
+ * are helper macros for defining such arrays.
+ */
+struct JSPropertySpec {
+ struct SelfHostedWrapper {
+ void* unused;
+ const char* funname;
+ };
+
+ struct ValueWrapper {
+ uintptr_t type;
+ union {
+ const char* string;
+ int32_t int32;
+ };
+ };
+
+ const char* name;
+ uint8_t flags;
+ union {
+ struct {
+ union {
+ JSNativeWrapper native;
+ SelfHostedWrapper selfHosted;
+ } getter;
+ union {
+ JSNativeWrapper native;
+ SelfHostedWrapper selfHosted;
+ } setter;
+ } accessors;
+ ValueWrapper value;
+ };
+
+ bool isAccessor() const {
+ return !(flags & JSPROP_INTERNAL_USE_BIT);
+ }
+ JS_PUBLIC_API(bool) getValue(JSContext* cx, JS::MutableHandleValue value) const;
+
+ bool isSelfHosted() const {
+ MOZ_ASSERT(isAccessor());
+
+#ifdef DEBUG
+ // Verify that our accessors match our JSPROP_GETTER flag.
+ if (flags & JSPROP_GETTER)
+ checkAccessorsAreSelfHosted();
+ else
+ checkAccessorsAreNative();
+#endif
+ return (flags & JSPROP_GETTER);
+ }
+
+ static_assert(sizeof(SelfHostedWrapper) == sizeof(JSNativeWrapper),
+ "JSPropertySpec::getter/setter must be compact");
+ static_assert(offsetof(SelfHostedWrapper, funname) == offsetof(JSNativeWrapper, info),
+ "JS_SELF_HOSTED* macros below require that "
+ "SelfHostedWrapper::funname overlay "
+ "JSNativeWrapper::info");
+private:
+ void checkAccessorsAreNative() const {
+ MOZ_ASSERT(accessors.getter.native.op);
+ // We may not have a setter at all. So all we can assert here, for the
+ // native case is that if we have a jitinfo for the setter then we have
+ // a setter op too. This is good enough to make sure we don't have a
+ // SelfHostedWrapper for the setter.
+ MOZ_ASSERT_IF(accessors.setter.native.info, accessors.setter.native.op);
+ }
+
+ void checkAccessorsAreSelfHosted() const {
+ MOZ_ASSERT(!accessors.getter.selfHosted.unused);
+ MOZ_ASSERT(!accessors.setter.selfHosted.unused);
+ }
+};
+
+namespace JS {
+namespace detail {
+
+/* NEVER DEFINED, DON'T USE. For use by JS_CAST_NATIVE_TO only. */
+inline int CheckIsNative(JSNative native);
+
+/* NEVER DEFINED, DON'T USE. For use by JS_CAST_STRING_TO only. */
+template<size_t N>
+inline int
+CheckIsCharacterLiteral(const char (&arr)[N]);
+
+/* NEVER DEFINED, DON'T USE. For use by JS_CAST_INT32_TO only. */
+inline int CheckIsInt32(int32_t value);
+
+/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_GETTER only. */
+inline int CheckIsGetterOp(JSGetterOp op);
+
+/* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_SETTER only. */
+inline int CheckIsSetterOp(JSSetterOp op);
+
+} // namespace detail
+} // namespace JS
+
+#define JS_CAST_NATIVE_TO(v, To) \
+ (static_cast<void>(sizeof(JS::detail::CheckIsNative(v))), \
+ reinterpret_cast<To>(v))
+
+#define JS_CAST_STRING_TO(s, To) \
+ (static_cast<void>(sizeof(JS::detail::CheckIsCharacterLiteral(s))), \
+ reinterpret_cast<To>(s))
+
+#define JS_CAST_INT32_TO(s, To) \
+ (static_cast<void>(sizeof(JS::detail::CheckIsInt32(s))), \
+ reinterpret_cast<To>(s))
+
+#define JS_CHECK_ACCESSOR_FLAGS(flags) \
+ (static_cast<mozilla::EnableIf<((flags) & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)) == 0>::Type>(0), \
+ (flags))
+
+#define JS_PROPERTYOP_GETTER(v) \
+ (static_cast<void>(sizeof(JS::detail::CheckIsGetterOp(v))), \
+ reinterpret_cast<JSNative>(v))
+
+#define JS_PROPERTYOP_SETTER(v) \
+ (static_cast<void>(sizeof(JS::detail::CheckIsSetterOp(v))), \
+ reinterpret_cast<JSNative>(v))
+
+#define JS_STUBGETTER JS_PROPERTYOP_GETTER(JS_PropertyStub)
+
+#define JS_STUBSETTER JS_PROPERTYOP_SETTER(JS_StrictPropertyStub)
+
+#define JS_PS_ACCESSOR_SPEC(name, getter, setter, flags, extraFlags) \
+ { name, uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | extraFlags), \
+ { { getter, setter } } }
+#define JS_PS_VALUE_SPEC(name, value, flags) \
+ { name, uint8_t(flags | JSPROP_INTERNAL_USE_BIT), \
+ { { value, JSNATIVE_WRAPPER(nullptr) } } }
+
+#define SELFHOSTED_WRAPPER(name) \
+ { { nullptr, JS_CAST_STRING_TO(name, const JSJitInfo*) } }
+#define STRINGVALUE_WRAPPER(value) \
+ { { reinterpret_cast<JSNative>(JSVAL_TYPE_STRING), JS_CAST_STRING_TO(value, const JSJitInfo*) } }
+#define INT32VALUE_WRAPPER(value) \
+ { { reinterpret_cast<JSNative>(JSVAL_TYPE_INT32), JS_CAST_INT32_TO(value, const JSJitInfo*) } }
+
+/*
+ * JSPropertySpec uses JSNativeWrapper. These macros encapsulate the definition
+ * of JSNative-backed JSPropertySpecs, by defining the JSNativeWrappers for
+ * them.
+ */
+#define JS_PSG(name, getter, flags) \
+ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED)
+#define JS_PSGS(name, getter, setter, flags) \
+ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \
+ JSPROP_SHARED)
+#define JS_SELF_HOSTED_GET(name, getterName, flags) \
+ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED | JSPROP_GETTER)
+#define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
+ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), SELFHOSTED_WRAPPER(setterName), \
+ flags, JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER)
+#define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
+ JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
+ SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
+ JSPROP_SHARED | JSPROP_GETTER)
+#define JS_STRING_PS(name, string, flags) \
+ JS_PS_VALUE_SPEC(name, STRINGVALUE_WRAPPER(string), flags)
+#define JS_STRING_SYM_PS(symbol, string, flags) \
+ JS_PS_VALUE_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
+ STRINGVALUE_WRAPPER(string), flags)
+#define JS_INT32_PS(name, value, flags) \
+ JS_PS_VALUE_SPEC(name, INT32VALUE_WRAPPER(value), flags)
+#define JS_PS_END \
+ JS_PS_ACCESSOR_SPEC(nullptr, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr), 0, 0)
+
+/**
+ * To define a native function, set call to a JSNativeWrapper. To define a
+ * self-hosted function, set selfHostedName to the name of a function
+ * compiled during JSRuntime::initSelfHosting.
+ */
+struct JSFunctionSpec {
+ const char* name;
+ JSNativeWrapper call;
+ uint16_t nargs;
+ uint16_t flags;
+ const char* selfHostedName;
+};
+
+/*
+ * Terminating sentinel initializer to put at the end of a JSFunctionSpec array
+ * that's passed to JS_DefineFunctions or JS_InitClass.
+ */
+#define JS_FS_END JS_FS(nullptr,nullptr,0,0)
+
+/*
+ * Initializer macros for a JSFunctionSpec array element. JS_FN (whose name pays
+ * homage to the old JSNative/JSFastNative split) simply adds the flag
+ * JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of
+ * JSJitInfos. JS_SELF_HOSTED_FN declares a self-hosted function.
+ * JS_INLINABLE_FN allows specifying an InlinableNative enum value for natives
+ * inlined or specialized by the JIT. Finally JS_FNSPEC has slots for all the
+ * fields.
+ *
+ * The _SYM variants allow defining a function with a symbol key rather than a
+ * string key. For example, use JS_SYM_FN(iterator, ...) to define an
+ * @@iterator method.
+ */
+#define JS_FS(name,call,nargs,flags) \
+ JS_FNSPEC(name, call, nullptr, nargs, flags, nullptr)
+#define JS_FN(name,call,nargs,flags) \
+ JS_FNSPEC(name, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
+#define JS_INLINABLE_FN(name,call,nargs,flags,native) \
+ JS_FNSPEC(name, call, &js::jit::JitInfo_##native, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
+#define JS_SYM_FN(symbol,call,nargs,flags) \
+ JS_SYM_FNSPEC(symbol, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
+#define JS_FNINFO(name,call,info,nargs,flags) \
+ JS_FNSPEC(name, call, info, nargs, flags, nullptr)
+#define JS_SELF_HOSTED_FN(name,selfHostedName,nargs,flags) \
+ JS_FNSPEC(name, nullptr, nullptr, nargs, flags, selfHostedName)
+#define JS_SELF_HOSTED_SYM_FN(symbol, selfHostedName, nargs, flags) \
+ JS_SYM_FNSPEC(symbol, nullptr, nullptr, nargs, flags, selfHostedName)
+#define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \
+ JS_FNSPEC(reinterpret_cast<const char*>( \
+ uint32_t(::JS::SymbolCode::symbol) + 1), \
+ call, info, nargs, flags, selfHostedName)
+#define JS_FNSPEC(name,call,info,nargs,flags,selfHostedName) \
+ {name, {call, info}, nargs, flags, selfHostedName}
+
+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(const JSClass*)
+JS_GetClass(JSObject* obj);
+
+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
+// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinaryhasinstance. If
+// you're looking for the equivalent of "instanceof", you want JS_HasInstance,
+// not this function.
+extern JS_PUBLIC_API(bool)
+OrdinaryHasInstance(JSContext* cx, HandleObject objArg, HandleValue v, bool* bp);
+
+} // namespace JS
+
+extern JS_PUBLIC_API(void*)
+JS_GetPrivate(JSObject* obj);
+
+extern JS_PUBLIC_API(void)
+JS_SetPrivate(JSObject* obj, void* data);
+
+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 {
+
+enum ZoneSpecifier {
+ FreshZone = 0,
+ SystemZone = 1
+};
+
+/**
+ * CompartmentCreationOptions specifies options relevant to creating a new
+ * compartment, that are either immutable characteristics of that compartment
+ * or that are discarded after the compartment has been created.
+ *
+ * Access to these options on an existing compartment is read-only: if you
+ * need particular selections, make them before you create the compartment.
+ */
+class JS_PUBLIC_API(CompartmentCreationOptions)
+{
+ public:
+ CompartmentCreationOptions()
+ : addonId_(nullptr),
+ traceGlobal_(nullptr),
+ invisibleToDebugger_(false),
+ mergeable_(false),
+ preserveJitCode_(false),
+ cloneSingletons_(false),
+ sharedMemoryAndAtomics_(false),
+ secureContext_(false)
+ {
+ zone_.spec = JS::FreshZone;
+ }
+
+ // A null add-on ID means that the compartment is not associated with an
+ // add-on.
+ JSAddonId* addonIdOrNull() const { return addonId_; }
+ CompartmentCreationOptions& setAddonId(JSAddonId* id) {
+ addonId_ = id;
+ return *this;
+ }
+
+ JSTraceOp getTrace() const {
+ return traceGlobal_;
+ }
+ CompartmentCreationOptions& setTrace(JSTraceOp op) {
+ traceGlobal_ = op;
+ return *this;
+ }
+
+ void* zonePointer() const {
+ MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
+ return zone_.pointer;
+ }
+ ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
+ CompartmentCreationOptions& setZone(ZoneSpecifier spec);
+ CompartmentCreationOptions& setSameZoneAs(JSObject* obj);
+
+ // Certain scopes (i.e. XBL compilation scopes) are implementation details
+ // of the embedding, and references to them should never leak out to script.
+ // This flag causes the this compartment to skip firing onNewGlobalObject
+ // and makes addDebuggee a no-op for this global.
+ bool invisibleToDebugger() const { return invisibleToDebugger_; }
+ CompartmentCreationOptions& setInvisibleToDebugger(bool flag) {
+ invisibleToDebugger_ = flag;
+ return *this;
+ }
+
+ // Compartments used for off-thread compilation have their contents merged
+ // into a target compartment when the compilation is finished. This is only
+ // allowed if this flag is set. The invisibleToDebugger flag must also be
+ // set for such compartments.
+ bool mergeable() const { return mergeable_; }
+ CompartmentCreationOptions& setMergeable(bool flag) {
+ mergeable_ = flag;
+ return *this;
+ }
+
+ // Determines whether this compartment should preserve JIT code on
+ // non-shrinking GCs.
+ bool preserveJitCode() const { return preserveJitCode_; }
+ CompartmentCreationOptions& setPreserveJitCode(bool flag) {
+ preserveJitCode_ = flag;
+ return *this;
+ }
+
+ bool cloneSingletons() const { return cloneSingletons_; }
+ CompartmentCreationOptions& setCloneSingletons(bool flag) {
+ cloneSingletons_ = flag;
+ return *this;
+ }
+
+ bool getSharedMemoryAndAtomicsEnabled() const;
+ CompartmentCreationOptions& setSharedMemoryAndAtomicsEnabled(bool flag);
+
+ // This flag doesn't affect JS engine behavior. It is used by Gecko to
+ // mark whether content windows and workers are "Secure Context"s. See
+ // https://w3c.github.io/webappsec-secure-contexts/
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1162772#c34
+ bool secureContext() const { return secureContext_; }
+ CompartmentCreationOptions& setSecureContext(bool flag) {
+ secureContext_ = flag;
+ return *this;
+ }
+
+ private:
+ JSAddonId* addonId_;
+ JSTraceOp traceGlobal_;
+ union {
+ ZoneSpecifier spec;
+ void* pointer; // js::Zone* is not exposed in the API.
+ } zone_;
+ bool invisibleToDebugger_;
+ bool mergeable_;
+ bool preserveJitCode_;
+ bool cloneSingletons_;
+ bool sharedMemoryAndAtomics_;
+ bool secureContext_;
+};
+
+/**
+ * CompartmentBehaviors specifies behaviors of a compartment that can be
+ * changed after the compartment's been created.
+ */
+class JS_PUBLIC_API(CompartmentBehaviors)
+{
+ public:
+ class Override {
+ public:
+ Override() : mode_(Default) {}
+
+ bool get(bool defaultValue) const {
+ if (mode_ == Default)
+ return defaultValue;
+ return mode_ == ForceTrue;
+ }
+
+ void set(bool overrideValue) {
+ mode_ = overrideValue ? ForceTrue : ForceFalse;
+ }
+
+ void reset() {
+ mode_ = Default;
+ }
+
+ private:
+ enum Mode {
+ Default,
+ ForceTrue,
+ ForceFalse
+ };
+
+ Mode mode_;
+ };
+
+ CompartmentBehaviors()
+ : version_(JSVERSION_UNKNOWN)
+ , discardSource_(false)
+ , disableLazyParsing_(false)
+ , singletonsAsTemplates_(true)
+ {
+ }
+
+ JSVersion version() const { return version_; }
+ CompartmentBehaviors& setVersion(JSVersion aVersion) {
+ MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN);
+ version_ = aVersion;
+ return *this;
+ }
+
+ // For certain globals, we know enough about the code that will run in them
+ // that we can discard script source entirely.
+ bool discardSource() const { return discardSource_; }
+ CompartmentBehaviors& setDiscardSource(bool flag) {
+ discardSource_ = flag;
+ return *this;
+ }
+
+ bool disableLazyParsing() const { return disableLazyParsing_; }
+ CompartmentBehaviors& setDisableLazyParsing(bool flag) {
+ disableLazyParsing_ = flag;
+ return *this;
+ }
+
+ bool extraWarnings(JSContext* cx) const;
+ Override& extraWarningsOverride() { return extraWarningsOverride_; }
+
+ bool getSingletonsAsTemplates() const {
+ return singletonsAsTemplates_;
+ }
+ CompartmentBehaviors& setSingletonsAsValues() {
+ singletonsAsTemplates_ = false;
+ return *this;
+ }
+
+ private:
+ JSVersion version_;
+ bool discardSource_;
+ bool disableLazyParsing_;
+ Override extraWarningsOverride_;
+
+ // To XDR singletons, we need to ensure that all singletons are all used as
+ // templates, by making JSOP_OBJECT return a clone of the JSScript
+ // singleton, instead of returning the value which is baked in the JSScript.
+ bool singletonsAsTemplates_;
+};
+
+/**
+ * CompartmentOptions specifies compartment characteristics: both those that
+ * can't be changed on a compartment once it's been created
+ * (CompartmentCreationOptions), and those that can be changed on an existing
+ * compartment (CompartmentBehaviors).
+ */
+class JS_PUBLIC_API(CompartmentOptions)
+{
+ public:
+ explicit CompartmentOptions()
+ : creationOptions_(),
+ behaviors_()
+ {}
+
+ CompartmentOptions(const CompartmentCreationOptions& compartmentCreation,
+ const CompartmentBehaviors& compartmentBehaviors)
+ : creationOptions_(compartmentCreation),
+ behaviors_(compartmentBehaviors)
+ {}
+
+ // CompartmentCreationOptions specify fundamental compartment
+ // characteristics that must be specified when the compartment is created,
+ // that can't be changed after the compartment is created.
+ CompartmentCreationOptions& creationOptions() {
+ return creationOptions_;
+ }
+ const CompartmentCreationOptions& creationOptions() const {
+ return creationOptions_;
+ }
+
+ // CompartmentBehaviors specify compartment characteristics that can be
+ // changed after the compartment is created.
+ CompartmentBehaviors& behaviors() {
+ return behaviors_;
+ }
+ const CompartmentBehaviors& behaviors() const {
+ return behaviors_;
+ }
+
+ private:
+ CompartmentCreationOptions creationOptions_;
+ CompartmentBehaviors behaviors_;
+};
+
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSCompartment* compartment);
+
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSObject* obj);
+
+JS_PUBLIC_API(const CompartmentCreationOptions&)
+CompartmentCreationOptionsRef(JSContext* cx);
+
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSCompartment* compartment);
+
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSObject* obj);
+
+JS_PUBLIC_API(CompartmentBehaviors&)
+CompartmentBehaviorsRef(JSContext* cx);
+
+/**
+ * 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::CompartmentOptions& 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 CompartmentOptions passed to JS_NewGlobalObject.
+ */
+extern JS_PUBLIC_API(void)
+JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global);
+
+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);
+
+
+/*** Property descriptors ************************************************************************/
+
+namespace JS {
+
+struct JS_PUBLIC_API(PropertyDescriptor) {
+ JSObject* obj;
+ unsigned attrs;
+ JSGetterOp getter;
+ JSSetterOp setter;
+ JS::Value value;
+
+ PropertyDescriptor()
+ : obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JS::UndefinedValue())
+ {}
+
+ static void trace(PropertyDescriptor* self, JSTracer* trc) { self->trace(trc); }
+ void trace(JSTracer* trc);
+};
+
+template <typename Outer>
+class PropertyDescriptorOperations
+{
+ const PropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
+
+ bool has(unsigned bit) const {
+ MOZ_ASSERT(bit != 0);
+ MOZ_ASSERT((bit & (bit - 1)) == 0); // only a single bit
+ return (desc().attrs & bit) != 0;
+ }
+
+ bool hasAny(unsigned bits) const {
+ return (desc().attrs & bits) != 0;
+ }
+
+ bool hasAll(unsigned bits) const {
+ return (desc().attrs & bits) == bits;
+ }
+
+ // Non-API attributes bit used internally for arguments objects.
+ enum { SHADOWABLE = JSPROP_INTERNAL_USE_BIT };
+
+ public:
+ // Descriptors with JSGetterOp/JSSetterOp are considered data
+ // descriptors. It's complicated.
+ bool isAccessorDescriptor() const { return hasAny(JSPROP_GETTER | JSPROP_SETTER); }
+ bool isGenericDescriptor() const {
+ return (desc().attrs&
+ (JSPROP_GETTER | JSPROP_SETTER | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE)) ==
+ (JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE);
+ }
+ bool isDataDescriptor() const { return !isAccessorDescriptor() && !isGenericDescriptor(); }
+
+ bool hasConfigurable() const { return !has(JSPROP_IGNORE_PERMANENT); }
+ bool configurable() const { MOZ_ASSERT(hasConfigurable()); return !has(JSPROP_PERMANENT); }
+
+ bool hasEnumerable() const { return !has(JSPROP_IGNORE_ENUMERATE); }
+ bool enumerable() const { MOZ_ASSERT(hasEnumerable()); return has(JSPROP_ENUMERATE); }
+
+ bool hasValue() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_VALUE); }
+ JS::HandleValue value() const {
+ return JS::HandleValue::fromMarkedLocation(&desc().value);
+ }
+
+ bool hasWritable() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_READONLY); }
+ bool writable() const { MOZ_ASSERT(hasWritable()); return !has(JSPROP_READONLY); }
+
+ bool hasGetterObject() const { return has(JSPROP_GETTER); }
+ JS::HandleObject getterObject() const {
+ MOZ_ASSERT(hasGetterObject());
+ return JS::HandleObject::fromMarkedLocation(
+ reinterpret_cast<JSObject* const*>(&desc().getter));
+ }
+ bool hasSetterObject() const { return has(JSPROP_SETTER); }
+ JS::HandleObject setterObject() const {
+ MOZ_ASSERT(hasSetterObject());
+ return JS::HandleObject::fromMarkedLocation(
+ reinterpret_cast<JSObject* const*>(&desc().setter));
+ }
+
+ bool hasGetterOrSetter() const { return desc().getter || desc().setter; }
+ bool isShared() const { return has(JSPROP_SHARED); }
+
+ JS::HandleObject object() const {
+ return JS::HandleObject::fromMarkedLocation(&desc().obj);
+ }
+ unsigned attributes() const { return desc().attrs; }
+ JSGetterOp getter() const { return desc().getter; }
+ JSSetterOp setter() const { return desc().setter; }
+
+ void assertValid() const {
+#ifdef DEBUG
+ MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE | JSPROP_IGNORE_ENUMERATE |
+ JSPROP_PERMANENT | JSPROP_IGNORE_PERMANENT |
+ JSPROP_READONLY | JSPROP_IGNORE_READONLY |
+ JSPROP_IGNORE_VALUE |
+ JSPROP_GETTER |
+ JSPROP_SETTER |
+ JSPROP_SHARED |
+ JSPROP_REDEFINE_NONCONFIGURABLE |
+ JSPROP_RESOLVING |
+ SHADOWABLE)) == 0);
+ MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE));
+ MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT));
+ if (isAccessorDescriptor()) {
+ MOZ_ASSERT(has(JSPROP_SHARED));
+ MOZ_ASSERT(!has(JSPROP_READONLY));
+ MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY));
+ MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE));
+ MOZ_ASSERT(!has(SHADOWABLE));
+ MOZ_ASSERT(value().isUndefined());
+ MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter());
+ MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter());
+ } else {
+ MOZ_ASSERT(!hasAll(JSPROP_IGNORE_READONLY | JSPROP_READONLY));
+ MOZ_ASSERT_IF(has(JSPROP_IGNORE_VALUE), value().isUndefined());
+ }
+ MOZ_ASSERT(getter() != JS_PropertyStub);
+ MOZ_ASSERT(setter() != JS_StrictPropertyStub);
+
+ MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_ENUMERATE));
+ MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_PERMANENT));
+ MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_READONLY));
+ MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_VALUE));
+ MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_REDEFINE_NONCONFIGURABLE));
+#endif
+ }
+
+ void assertComplete() const {
+#ifdef DEBUG
+ assertValid();
+ MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE |
+ JSPROP_PERMANENT |
+ JSPROP_READONLY |
+ JSPROP_GETTER |
+ JSPROP_SETTER |
+ JSPROP_SHARED |
+ JSPROP_REDEFINE_NONCONFIGURABLE |
+ JSPROP_RESOLVING |
+ SHADOWABLE)) == 0);
+ MOZ_ASSERT_IF(isAccessorDescriptor(), has(JSPROP_GETTER) && has(JSPROP_SETTER));
+#endif
+ }
+
+ void assertCompleteIfFound() const {
+#ifdef DEBUG
+ if (object())
+ assertComplete();
+#endif
+ }
+};
+
+template <typename Outer>
+class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer>
+{
+ PropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
+
+ public:
+ void clear() {
+ object().set(nullptr);
+ setAttributes(0);
+ setGetter(nullptr);
+ setSetter(nullptr);
+ value().setUndefined();
+ }
+
+ void initFields(HandleObject obj, HandleValue v, unsigned attrs,
+ JSGetterOp getterOp, JSSetterOp setterOp) {
+ MOZ_ASSERT(getterOp != JS_PropertyStub);
+ MOZ_ASSERT(setterOp != JS_StrictPropertyStub);
+
+ object().set(obj);
+ value().set(v);
+ setAttributes(attrs);
+ setGetter(getterOp);
+ setSetter(setterOp);
+ }
+
+ void assign(PropertyDescriptor& other) {
+ object().set(other.obj);
+ setAttributes(other.attrs);
+ setGetter(other.getter);
+ setSetter(other.setter);
+ value().set(other.value);
+ }
+
+ void setDataDescriptor(HandleValue v, unsigned attrs) {
+ MOZ_ASSERT((attrs & ~(JSPROP_ENUMERATE |
+ JSPROP_PERMANENT |
+ JSPROP_READONLY |
+ JSPROP_IGNORE_ENUMERATE |
+ JSPROP_IGNORE_PERMANENT |
+ JSPROP_IGNORE_READONLY)) == 0);
+ object().set(nullptr);
+ setAttributes(attrs);
+ setGetter(nullptr);
+ setSetter(nullptr);
+ value().set(v);
+ }
+
+ JS::MutableHandleObject object() {
+ return JS::MutableHandleObject::fromMarkedLocation(&desc().obj);
+ }
+ unsigned& attributesRef() { return desc().attrs; }
+ JSGetterOp& getter() { return desc().getter; }
+ JSSetterOp& setter() { return desc().setter; }
+ JS::MutableHandleValue value() {
+ return JS::MutableHandleValue::fromMarkedLocation(&desc().value);
+ }
+ void setValue(JS::HandleValue v) {
+ MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER)));
+ attributesRef() &= ~JSPROP_IGNORE_VALUE;
+ value().set(v);
+ }
+
+ void setConfigurable(bool configurable) {
+ setAttributes((desc().attrs & ~(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)) |
+ (configurable ? 0 : JSPROP_PERMANENT));
+ }
+ void setEnumerable(bool enumerable) {
+ setAttributes((desc().attrs & ~(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)) |
+ (enumerable ? JSPROP_ENUMERATE : 0));
+ }
+ void setWritable(bool writable) {
+ MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER)));
+ setAttributes((desc().attrs & ~(JSPROP_IGNORE_READONLY | JSPROP_READONLY)) |
+ (writable ? 0 : JSPROP_READONLY));
+ }
+ void setAttributes(unsigned attrs) { desc().attrs = attrs; }
+
+ void setGetter(JSGetterOp op) {
+ MOZ_ASSERT(op != JS_PropertyStub);
+ desc().getter = op;
+ }
+ void setSetter(JSSetterOp op) {
+ MOZ_ASSERT(op != JS_StrictPropertyStub);
+ desc().setter = op;
+ }
+ void setGetterObject(JSObject* obj) {
+ desc().getter = reinterpret_cast<JSGetterOp>(obj);
+ desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
+ desc().attrs |= JSPROP_GETTER | JSPROP_SHARED;
+ }
+ void setSetterObject(JSObject* obj) {
+ desc().setter = reinterpret_cast<JSSetterOp>(obj);
+ desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
+ desc().attrs |= JSPROP_SETTER | JSPROP_SHARED;
+ }
+
+ JS::MutableHandleObject getterObject() {
+ MOZ_ASSERT(this->hasGetterObject());
+ return JS::MutableHandleObject::fromMarkedLocation(
+ reinterpret_cast<JSObject**>(&desc().getter));
+ }
+ JS::MutableHandleObject setterObject() {
+ MOZ_ASSERT(this->hasSetterObject());
+ return JS::MutableHandleObject::fromMarkedLocation(
+ reinterpret_cast<JSObject**>(&desc().setter));
+ }
+};
+
+} /* namespace JS */
+
+namespace js {
+
+template <>
+class RootedBase<JS::PropertyDescriptor>
+ : public JS::MutablePropertyDescriptorOperations<JS::Rooted<JS::PropertyDescriptor>>
+{};
+
+template <>
+class HandleBase<JS::PropertyDescriptor>
+ : public JS::PropertyDescriptorOperations<JS::Handle<JS::PropertyDescriptor>>
+{};
+
+template <>
+class MutableHandleBase<JS::PropertyDescriptor>
+ : public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JS::PropertyDescriptor>>
+{};
+
+} /* namespace js */
+
+namespace JS {
+
+extern JS_PUBLIC_API(bool)
+ObjectToCompletePropertyDescriptor(JSContext* cx,
+ JS::HandleObject obj,
+ JS::HandleValue descriptor,
+ JS::MutableHandle<PropertyDescriptor> desc);
+
+/*
+ * ES6 draft rev 32 (2015 Feb 2) 6.2.4.4 FromPropertyDescriptor(Desc).
+ *
+ * If desc.object() is null, then vp is set to undefined.
+ */
+extern JS_PUBLIC_API(bool)
+FromPropertyDescriptor(JSContext* cx,
+ JS::Handle<JS::PropertyDescriptor> desc,
+ JS::MutableHandleValue vp);
+
+} // namespace JS
+
+
+/*** 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 result.
+ *
+ * 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,
+ 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);
+
+/**
+ * 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, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, double value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleString value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, int32_t value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, uint32_t value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, double value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+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,
+ JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
+ JS::HandleObject value, unsigned attrs,
+ JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
+ JS::HandleString value, unsigned attrs,
+ JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
+ int32_t value, unsigned attrs,
+ JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
+ uint32_t value, unsigned attrs,
+ JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen,
+ double value, unsigned attrs,
+ JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double value,
+ unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr);
+
+/**
+ * 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);
+
+/*
+ * 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 */
+
+/**
+ * Invoke a constructor, like the JS expression `new ctor(...args)`. Returns
+ * the new object, or null on error.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_New(JSContext* cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
+
+
+/*** 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_DefineConstDoubles(JSContext* cx, JS::HandleObject obj, const JSConstDoubleSpec* cds);
+
+extern JS_PUBLIC_API(bool)
+JS_DefineConstIntegers(JSContext* cx, JS::HandleObject obj, const JSConstIntegerSpec* cis);
+
+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);
+
+extern JS_PUBLIC_API(JSObject*)
+JS_NewArrayObject(JSContext* cx, const JS::HandleValueArray& contents);
+
+extern JS_PUBLIC_API(JSObject*)
+JS_NewArrayObject(JSContext* cx, size_t length);
+
+/**
+ * Returns true and sets |*isArray| indicating whether |value| is an Array
+ * object or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isArray == false| when passed a proxy whose
+ * target is an Array, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+JS_IsArrayObject(JSContext* cx, JS::HandleValue value, bool* isArray);
+
+/**
+ * Returns true and sets |*isArray| indicating whether |obj| is an Array object
+ * or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isArray == false| when passed a proxy whose
+ * target is an Array, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+JS_IsArrayObject(JSContext* cx, JS::HandleObject obj, bool* isArray);
+
+extern JS_PUBLIC_API(bool)
+JS_GetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t* lengthp);
+
+extern JS_PUBLIC_API(bool)
+JS_SetArrayLength(JSContext* cx, JS::Handle<JSObject*> obj, uint32_t length);
+
+namespace JS {
+
+/**
+ * Returns true and sets |*isMap| indicating whether |obj| is an Map object
+ * or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isMap == false| when passed a proxy whose
+ * target is an Map, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+IsMapObject(JSContext* cx, JS::HandleObject obj, bool* isMap);
+
+/**
+ * Returns true and sets |*isSet| indicating whether |obj| is an Set object
+ * or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isSet == false| when passed a proxy whose
+ * target is an 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(JSContext* cx, JSObject* objArg);
+
+/**
+ * Create a new array buffer with the given contents. It must be legal to pass
+ * these contents to free(). On success, the ownership is transferred to the
+ * new array buffer.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_NewArrayBufferWithContents(JSContext* cx, size_t nbytes, void* contents);
+
+/**
+ * Create a new array buffer with the given contents. The array buffer does not take ownership of
+ * contents, and JS_DetachArrayBuffer must be called before the contents are disposed of.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_NewArrayBufferWithExternalContents(JSContext* cx, size_t nbytes, void* contents);
+
+/**
+ * Steal the contents of the given array buffer. The array buffer has its
+ * length set to 0 and its contents array cleared. The caller takes ownership
+ * of the return value and must free it or transfer ownership via
+ * JS_NewArrayBufferWithContents when done using it.
+ */
+extern JS_PUBLIC_API(void*)
+JS_StealArrayBufferContents(JSContext* cx, JS::HandleObject obj);
+
+/**
+ * Returns a pointer to the ArrayBuffer |obj|'s data. |obj| and its views will store and expose
+ * the data in the returned pointer: assigning into the returned pointer will affect values exposed
+ * by views of |obj| and vice versa.
+ *
+ * The caller must ultimately deallocate the returned pointer to avoid leaking. The memory is
+ * *not* garbage-collected with |obj|. These steps must be followed to deallocate:
+ *
+ * 1. The ArrayBuffer |obj| must be detached using JS_DetachArrayBuffer.
+ * 2. The returned pointer must be freed using JS_free.
+ *
+ * To perform step 1, callers *must* hold a reference to |obj| until they finish using the returned
+ * pointer. They *must not* attempt to let |obj| be GC'd, then JS_free the pointer.
+ *
+ * If |obj| isn't an ArrayBuffer, this function returns null and reports an error.
+ */
+extern JS_PUBLIC_API(void*)
+JS_ExternalizeArrayBufferContents(JSContext* cx, JS::HandleObject obj);
+
+/**
+ * Create a new mapped array buffer with the given memory mapped contents. It
+ * must be legal to free the contents pointer by unmapping it. On success,
+ * ownership is transferred to the new mapped array buffer.
+ */
+extern JS_PUBLIC_API(JSObject*)
+JS_NewMappedArrayBufferWithContents(JSContext* cx, size_t nbytes, void* contents);
+
+/**
+ * Create memory mapped array buffer contents.
+ * Caller must take care of closing fd after calling this function.
+ */
+extern JS_PUBLIC_API(void*)
+JS_CreateMappedArrayBufferContents(int fd, size_t offset, size_t length);
+
+/**
+ * Release the allocated resource of mapped array buffer contents before the
+ * object is created.
+ * If a new object has been created by JS_NewMappedArrayBufferWithContents()
+ * with this content, then JS_DetachArrayBuffer() should be used instead to
+ * release the resource used by the object.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReleaseMappedArrayBufferContents(void* contents, size_t length);
+
+extern JS_PUBLIC_API(JS::Value)
+JS_GetReservedSlot(JSObject* obj, uint32_t index);
+
+extern JS_PUBLIC_API(void)
+JS_SetReservedSlot(JSObject* obj, uint32_t index, const JS::Value& v);
+
+
+/************************************************************************/
+
+/*
+ * 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
+ * `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);
+
+} /* 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 (length) of fun.
+ */
+extern JS_PUBLIC_API(uint16_t)
+JS_GetFunctionArity(JSFunction* fun);
+
+/**
+ * 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(JSContext* cx, 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<JSObject*> obj, const JSFunctionSpec* fs);
+
+extern JS_PUBLIC_API(JSFunction*)
+JS_DefineFunction(JSContext* cx, JS::Handle<JSObject*> obj, const char* name, JSNative call,
+ unsigned nargs, unsigned attrs);
+
+extern JS_PUBLIC_API(JSFunction*)
+JS_DefineUCFunction(JSContext* cx, JS::Handle<JSObject*> 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<JSObject*> obj, JS::Handle<jsid> 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);
+
+namespace JS {
+
+/**
+ * Clone a top-level function into cx's global. This function will dynamically
+ * fail if funobj was lexically nested inside some other function.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CloneFunctionObject(JSContext* cx, HandleObject funobj);
+
+/**
+ * As above, but providing an explicit scope chain. scopeChain must not include
+ * the global object on it; that's implicit. It needs to contain the other
+ * objects that should end up on the clone's scope chain.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CloneFunctionObject(JSContext* cx, HandleObject funobj, AutoObjectVector& scopeChain);
+
+} // namespace JS
+
+/**
+ * Given a buffer, return false if the buffer might become a valid
+ * javascript statement with the addition of more lines. Otherwise return
+ * true. The intent is to support interactive compilation - accumulate
+ * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
+ * the compiler.
+ */
+extern JS_PUBLIC_API(bool)
+JS_BufferIsCompilableUnit(JSContext* cx, JS::Handle<JSObject*> obj, const char* utf8,
+ size_t length);
+
+/**
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
+JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
+ const JS::CompileOptions& options,
+ JS::MutableHandleScript script);
+
+/**
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
+JS_CompileUCScript(JSContext* cx, const char16_t* chars, size_t length,
+ const JS::CompileOptions& options,
+ JS::MutableHandleScript script);
+
+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);
+
+namespace JS {
+
+/* Options for JavaScript compilation. */
+
+/*
+ * In the most common use case, a CompileOptions instance is allocated on the
+ * stack, and holds non-owning references to non-POD option values: strings;
+ * principals; objects; and so on. The code declaring the instance guarantees
+ * that such option values will outlive the CompileOptions itself: objects are
+ * otherwise rooted; principals have had their reference counts bumped; strings
+ * will not be freed until the CompileOptions goes out of scope. In this
+ * situation, CompileOptions only refers to things others own, so it can be
+ * lightweight.
+ *
+ * In some cases, however, we need to hold compilation options with a
+ * non-stack-like lifetime. For example, JS::CompileOffThread needs to save
+ * compilation options where a worker thread can find them, and then return
+ * immediately. The worker thread will come along at some later point, and use
+ * the options.
+ *
+ * The compiler itself just needs to be able to access a collection of options;
+ * it doesn't care who owns them, or what's keeping them alive. It does its own
+ * addrefs/copies/tracing/etc.
+ *
+ * Furthermore, in some cases compile options are propagated from one entity to
+ * another (e.g. from a scriipt to a function defined in that script). This
+ * involves copying over some, but not all, of the options.
+ *
+ * So, we have a class hierarchy that reflects these four use cases:
+ *
+ * - TransitiveCompileOptions is the common base class, representing options
+ * that should get propagated from a script to functions defined in that
+ * script. This is never instantiated directly.
+ *
+ * - ReadOnlyCompileOptions is the only subclass of TransitiveCompileOptions,
+ * representing a full set of compile options. It can be used by code that
+ * simply needs to access options set elsewhere, like the compiler. This,
+ * again, is never instantiated directly.
+ *
+ * - The usual CompileOptions class must be stack-allocated, and holds
+ * non-owning references to the filename, element, and so on. It's derived
+ * from ReadOnlyCompileOptions, so the compiler can use it.
+ *
+ * - OwningCompileOptions roots / copies / reference counts of all its values,
+ * and unroots / frees / releases them when it is destructed. It too is
+ * derived from ReadOnlyCompileOptions, so the compiler accepts it.
+ */
+
+enum class AsmJSOption : uint8_t { Enabled, Disabled, DisabledByDebugger };
+
+/**
+ * The common base class for the CompileOptions hierarchy.
+ *
+ * Use this in code that needs to propagate compile options from one compilation
+ * unit to another.
+ */
+class JS_FRIEND_API(TransitiveCompileOptions)
+{
+ protected:
+ // The Web Platform allows scripts to be loaded from arbitrary cross-origin
+ // sources. This allows an attack by which a malicious website loads a
+ // sensitive file (say, a bank statement) cross-origin (using the user's
+ // cookies), and sniffs the generated syntax errors (via a window.onerror
+ // handler) for juicy morsels of its contents.
+ //
+ // To counter this attack, HTML5 specifies that script errors should be
+ // sanitized ("muted") when the script is not same-origin with the global
+ // for which it is loaded. Callers should set this flag for cross-origin
+ // scripts, and it will be propagated appropriately to child scripts and
+ // passed back in JSErrorReports.
+ bool mutedErrors_;
+ const char* filename_;
+ const char* introducerFilename_;
+ const char16_t* sourceMapURL_;
+
+ // This constructor leaves 'version' set to JSVERSION_UNKNOWN. The structure
+ // is unusable until that's set to something more specific; the derived
+ // classes' constructors take care of that, in ways appropriate to their
+ // purpose.
+ TransitiveCompileOptions()
+ : mutedErrors_(false),
+ filename_(nullptr),
+ introducerFilename_(nullptr),
+ sourceMapURL_(nullptr),
+ version(JSVERSION_UNKNOWN),
+ versionSet(false),
+ utf8(false),
+ selfHostingMode(false),
+ canLazilyParse(true),
+ strictOption(false),
+ extraWarningsOption(false),
+ werrorOption(false),
+ asmJSOption(AsmJSOption::Disabled),
+ throwOnAsmJSValidationFailureOption(false),
+ forceAsync(false),
+ installedFile(false),
+ sourceIsLazy(false),
+ introductionType(nullptr),
+ introductionLineno(0),
+ introductionOffset(0),
+ hasIntroductionInfo(false)
+ { }
+
+ // Set all POD options (those not requiring reference counts, copies,
+ // rooting, or other hand-holding) to their values in |rhs|.
+ void copyPODTransitiveOptions(const TransitiveCompileOptions& rhs);
+
+ public:
+ // Read-only accessors for non-POD options. The proper way to set these
+ // depends on the derived type.
+ bool mutedErrors() const { return mutedErrors_; }
+ const char* filename() const { return filename_; }
+ const char* introducerFilename() const { return introducerFilename_; }
+ const char16_t* sourceMapURL() const { return sourceMapURL_; }
+ virtual JSObject* element() const = 0;
+ virtual JSString* elementAttributeName() const = 0;
+ virtual JSScript* introductionScript() const = 0;
+
+ // POD options.
+ JSVersion version;
+ bool versionSet;
+ bool utf8;
+ bool selfHostingMode;
+ bool canLazilyParse;
+ bool strictOption;
+ bool extraWarningsOption;
+ bool werrorOption;
+ AsmJSOption asmJSOption;
+ bool throwOnAsmJSValidationFailureOption;
+ bool forceAsync;
+ bool installedFile; // 'true' iff pre-compiling js file in packaged app
+ bool sourceIsLazy;
+
+ // |introductionType| is a statically allocated C string:
+ // one of "eval", "Function", or "GeneratorFunction".
+ const char* introductionType;
+ unsigned introductionLineno;
+ uint32_t introductionOffset;
+ bool hasIntroductionInfo;
+
+ private:
+ void operator=(const TransitiveCompileOptions&) = delete;
+};
+
+/**
+ * The class representing a full set of compile options.
+ *
+ * Use this in code that only needs to access compilation options created
+ * elsewhere, like the compiler. Don't instantiate this class (the constructor
+ * is protected anyway); instead, create instances only of the derived classes:
+ * CompileOptions and OwningCompileOptions.
+ */
+class JS_FRIEND_API(ReadOnlyCompileOptions) : public TransitiveCompileOptions
+{
+ friend class CompileOptions;
+
+ protected:
+ ReadOnlyCompileOptions()
+ : TransitiveCompileOptions(),
+ lineno(1),
+ column(0),
+ isRunOnce(false),
+ noScriptRval(false)
+ { }
+
+ // Set all POD options (those not requiring reference counts, copies,
+ // rooting, or other hand-holding) to their values in |rhs|.
+ void copyPODOptions(const ReadOnlyCompileOptions& rhs);
+
+ public:
+ // Read-only accessors for non-POD options. The proper way to set these
+ // depends on the derived type.
+ bool mutedErrors() const { return mutedErrors_; }
+ const char* filename() const { return filename_; }
+ const char* introducerFilename() const { return introducerFilename_; }
+ const char16_t* sourceMapURL() const { return sourceMapURL_; }
+ virtual JSObject* element() const = 0;
+ virtual JSString* elementAttributeName() const = 0;
+ virtual JSScript* introductionScript() const = 0;
+
+ // POD options.
+ unsigned lineno;
+ unsigned column;
+ // isRunOnce only applies to non-function scripts.
+ bool isRunOnce;
+ bool noScriptRval;
+
+ private:
+ void operator=(const ReadOnlyCompileOptions&) = delete;
+};
+
+/**
+ * Compilation options, with dynamic lifetime. An instance of this type
+ * makes a copy of / holds / roots all dynamically allocated resources
+ * (principals; elements; strings) that it refers to. Its destructor frees
+ * / drops / unroots them. This is heavier than CompileOptions, below, but
+ * unlike CompileOptions, it can outlive any given stack frame.
+ *
+ * Note that this *roots* any JS values it refers to - they're live
+ * unconditionally. Thus, instances of this type can't be owned, directly
+ * or indirectly, by a JavaScript object: if any value that this roots ever
+ * comes to refer to the object that owns this, then the whole cycle, and
+ * anything else it entrains, will never be freed.
+ */
+class JS_FRIEND_API(OwningCompileOptions) : public ReadOnlyCompileOptions
+{
+ PersistentRootedObject elementRoot;
+ PersistentRootedString elementAttributeNameRoot;
+ PersistentRootedScript introductionScriptRoot;
+
+ public:
+ // A minimal constructor, for use with OwningCompileOptions::copy. This
+ // leaves |this.version| set to JSVERSION_UNKNOWN; the instance
+ // shouldn't be used until we've set that to something real (as |copy|
+ // will).
+ explicit OwningCompileOptions(JSContext* cx);
+ ~OwningCompileOptions();
+
+ JSObject* element() const override { return elementRoot; }
+ JSString* elementAttributeName() const override { return elementAttributeNameRoot; }
+ JSScript* introductionScript() const override { return introductionScriptRoot; }
+
+ // Set this to a copy of |rhs|. Return false on OOM.
+ bool copy(JSContext* cx, const ReadOnlyCompileOptions& rhs);
+
+ /* These setters make copies of their string arguments, and are fallible. */
+ bool setFile(JSContext* cx, const char* f);
+ bool setFileAndLine(JSContext* cx, const char* f, unsigned l);
+ bool setSourceMapURL(JSContext* cx, const char16_t* s);
+ bool setIntroducerFilename(JSContext* cx, const char* s);
+
+ /* These setters are infallible, and can be chained. */
+ OwningCompileOptions& setLine(unsigned l) { lineno = l; return *this; }
+ OwningCompileOptions& setElement(JSObject* e) {
+ elementRoot = e;
+ return *this;
+ }
+ OwningCompileOptions& setElementAttributeName(JSString* p) {
+ elementAttributeNameRoot = p;
+ return *this;
+ }
+ OwningCompileOptions& setIntroductionScript(JSScript* s) {
+ introductionScriptRoot = s;
+ return *this;
+ }
+ OwningCompileOptions& setMutedErrors(bool mute) {
+ mutedErrors_ = mute;
+ return *this;
+ }
+ OwningCompileOptions& setVersion(JSVersion v) {
+ version = v;
+ versionSet = true;
+ return *this;
+ }
+ OwningCompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
+ OwningCompileOptions& setColumn(unsigned c) { column = c; return *this; }
+ OwningCompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
+ OwningCompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
+ OwningCompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
+ OwningCompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
+ OwningCompileOptions& setSourceIsLazy(bool l) { sourceIsLazy = l; return *this; }
+ OwningCompileOptions& setIntroductionType(const char* t) { introductionType = t; return *this; }
+ bool setIntroductionInfo(JSContext* cx, const char* introducerFn, const char* intro,
+ unsigned line, JSScript* script, uint32_t offset)
+ {
+ if (!setIntroducerFilename(cx, introducerFn))
+ return false;
+ introductionType = intro;
+ introductionLineno = line;
+ introductionScriptRoot = script;
+ introductionOffset = offset;
+ hasIntroductionInfo = true;
+ return true;
+ }
+
+ private:
+ void operator=(const CompileOptions& rhs) = delete;
+};
+
+/**
+ * Compilation options stored on the stack. An instance of this type
+ * simply holds references to dynamically allocated resources (element;
+ * filename; source map URL) that are owned by something else. If you
+ * create an instance of this type, it's up to you to guarantee that
+ * everything you store in it will outlive it.
+ */
+class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) final : public ReadOnlyCompileOptions
+{
+ RootedObject elementRoot;
+ RootedString elementAttributeNameRoot;
+ RootedScript introductionScriptRoot;
+
+ public:
+ explicit CompileOptions(JSContext* cx, JSVersion version = JSVERSION_UNKNOWN);
+ CompileOptions(js::ContextFriendFields* cx, const ReadOnlyCompileOptions& rhs)
+ : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
+ introductionScriptRoot(cx)
+ {
+ copyPODOptions(rhs);
+
+ filename_ = rhs.filename();
+ introducerFilename_ = rhs.introducerFilename();
+ sourceMapURL_ = rhs.sourceMapURL();
+ elementRoot = rhs.element();
+ elementAttributeNameRoot = rhs.elementAttributeName();
+ introductionScriptRoot = rhs.introductionScript();
+ }
+
+ CompileOptions(js::ContextFriendFields* cx, const TransitiveCompileOptions& rhs)
+ : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
+ introductionScriptRoot(cx)
+ {
+ copyPODTransitiveOptions(rhs);
+
+ filename_ = rhs.filename();
+ introducerFilename_ = rhs.introducerFilename();
+ sourceMapURL_ = rhs.sourceMapURL();
+ elementRoot = rhs.element();
+ elementAttributeNameRoot = rhs.elementAttributeName();
+ introductionScriptRoot = rhs.introductionScript();
+ }
+
+ JSObject* element() const override { return elementRoot; }
+ JSString* elementAttributeName() const override { return elementAttributeNameRoot; }
+ JSScript* introductionScript() const override { return introductionScriptRoot; }
+
+ CompileOptions& setFile(const char* f) { filename_ = f; return *this; }
+ CompileOptions& setLine(unsigned l) { lineno = l; return *this; }
+ CompileOptions& setFileAndLine(const char* f, unsigned l) {
+ filename_ = f; lineno = l; return *this;
+ }
+ CompileOptions& setSourceMapURL(const char16_t* s) { sourceMapURL_ = s; return *this; }
+ CompileOptions& setElement(JSObject* e) { elementRoot = e; return *this; }
+ CompileOptions& setElementAttributeName(JSString* p) {
+ elementAttributeNameRoot = p;
+ return *this;
+ }
+ CompileOptions& setIntroductionScript(JSScript* s) {
+ introductionScriptRoot = s;
+ return *this;
+ }
+ CompileOptions& setMutedErrors(bool mute) {
+ mutedErrors_ = mute;
+ return *this;
+ }
+ CompileOptions& setVersion(JSVersion v) {
+ version = v;
+ versionSet = true;
+ return *this;
+ }
+ CompileOptions& setUTF8(bool u) { utf8 = u; return *this; }
+ CompileOptions& setColumn(unsigned c) { column = c; return *this; }
+ CompileOptions& setIsRunOnce(bool once) { isRunOnce = once; return *this; }
+ CompileOptions& setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
+ CompileOptions& setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
+ CompileOptions& setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; }
+ CompileOptions& setSourceIsLazy(bool l) { sourceIsLazy = l; return *this; }
+ CompileOptions& setIntroductionType(const char* t) { introductionType = t; return *this; }
+ CompileOptions& setIntroductionInfo(const char* introducerFn, const char* intro,
+ unsigned line, JSScript* script, uint32_t offset)
+ {
+ introducerFilename_ = introducerFn;
+ introductionType = intro;
+ introductionLineno = line;
+ introductionScriptRoot = script;
+ introductionOffset = offset;
+ hasIntroductionInfo = true;
+ return *this;
+ }
+ CompileOptions& maybeMakeStrictMode(bool strict) {
+ strictOption = strictOption || strict;
+ return *this;
+ }
+
+ private:
+ void operator=(const CompileOptions& rhs) = delete;
+};
+
+/**
+ * |script| will always be set. On failure, it will be set to nullptr.
+ */
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+ SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char* bytes, size_t length, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+ FILE* file, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char* filename, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+ SourceBufferHolder& srcBuf, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char* bytes, size_t length, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+ FILE* file, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char* filename, JS::MutableHandleScript script);
+
+extern JS_PUBLIC_API(bool)
+CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
+
+/*
+ * Off thread compilation control flow.
+ *
+ * After successfully triggering an off thread compile of a script, the
+ * callback will eventually be invoked with the specified data and a token
+ * for the compilation. The callback will be invoked while off the main thread,
+ * so must ensure that its operations are thread safe. Afterwards, one of the
+ * following functions must be invoked on the main thread:
+ *
+ * - FinishOffThreadScript, to get the result script (or nullptr on failure).
+ * - CancelOffThreadScript, to free the resources without creating a script.
+ *
+ * The characters passed in to CompileOffThread must remain live until the
+ * callback is invoked, and the resulting script will be rooted until the call
+ * to FinishOffThreadScript.
+ */
+
+extern JS_PUBLIC_API(bool)
+CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length,
+ OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(JSScript*)
+FinishOffThreadScript(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadScript(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(bool)
+CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length,
+ OffThreadCompileCallback callback, void* callbackData);
+
+extern JS_PUBLIC_API(JSObject*)
+FinishOffThreadModule(JSContext* cx, void* token);
+
+extern JS_PUBLIC_API(void)
+CancelOffThreadModule(JSContext* cx, void* token);
+
+/**
+ * Compile a function with envChain plus the global as its scope chain.
+ * envChain must contain objects in the current compartment of cx. The actual
+ * scope chain used for the function will consist of With wrappers for those
+ * objects, followed by the current global of the compartment cx is in. This
+ * global must not be explicitly included in the scope chain.
+ */
+extern JS_PUBLIC_API(bool)
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
+ const ReadOnlyCompileOptions& options,
+ const char* name, unsigned nargs, const char* const* argnames,
+ const char16_t* chars, size_t length, JS::MutableHandleFunction fun);
+
+/**
+ * Same as above, but taking a SourceBufferHolder for the function body.
+ */
+extern JS_PUBLIC_API(bool)
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
+ const ReadOnlyCompileOptions& options,
+ const char* name, unsigned nargs, const char* const* argnames,
+ SourceBufferHolder& srcBuf, JS::MutableHandleFunction fun);
+
+/**
+ * Same as above, but taking a const char * for the function body.
+ */
+extern JS_PUBLIC_API(bool)
+CompileFunction(JSContext* cx, AutoObjectVector& envChain,
+ const ReadOnlyCompileOptions& options,
+ const char* name, unsigned nargs, const char* const* argnames,
+ const char* bytes, size_t length, JS::MutableHandleFunction fun);
+
+} /* namespace JS */
+
+extern JS_PUBLIC_API(JSString*)
+JS_DecompileScript(JSContext* cx, JS::Handle<JSScript*> script, const char* name, unsigned indent);
+
+/*
+ * API extension: OR this into indent to avoid pretty-printing the decompiled
+ * source resulting from JS_DecompileFunction.
+ */
+#define JS_DONT_PRETTY_PRINT ((unsigned)0x8000)
+
+extern JS_PUBLIC_API(JSString*)
+JS_DecompileFunction(JSContext* cx, JS::Handle<JSFunction*> fun, unsigned indent);
+
+
+/*
+ * NB: JS_ExecuteScript and the JS::Evaluate APIs come in two flavors: either
+ * they use the global as the scope, or they take an AutoObjectVector of objects
+ * to use as the scope chain. In the former case, the global is also used as
+ * the "this" keyword value and the variables object (ECMA parlance for where
+ * 'var' and 'function' bind names) of the execution context for script. In the
+ * latter case, the first object in the provided list is used, unless the list
+ * is empty, in which case the global is used.
+ *
+ * Why a runtime option? The alternative is to add APIs duplicating those
+ * for the other value of flags, and that doesn't seem worth the code bloat
+ * cost. Such new entry points would probably have less obvious names, too, so
+ * would not tend to be used. The ContextOptionsRef adjustment, OTOH, can be
+ * more easily hacked into existing code that does not depend on the bug; such
+ * code can continue to use the familiar JS::Evaluate, etc., entry points.
+ */
+
+/**
+ * Evaluate a script in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::HandleScript script, JS::MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::HandleScript script);
+
+/**
+ * As above, but providing an explicit scope chain. envChain must not include
+ * the global object on it; that's implicit. It needs to contain the other
+ * objects that should end up on the script's scope chain.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain,
+ JS::HandleScript script, JS::MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+JS_ExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain, JS::HandleScript script);
+
+namespace JS {
+
+/**
+ * Like the above, but handles a cross-compartment script. If the script is
+ * cross-compartment, it is cloned into the current compartment before executing.
+ */
+extern JS_PUBLIC_API(bool)
+CloneAndExecuteScript(JSContext* cx, JS::Handle<JSScript*> script,
+ JS::MutableHandleValue rval);
+
+} /* namespace JS */
+
+namespace JS {
+
+/**
+ * Evaluate the given source buffer in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
+ SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
+
+/**
+ * As above, but providing an explicit scope chain. envChain must not include
+ * the global object on it; that's implicit. It needs to contain the other
+ * objects that should end up on the script's scope chain.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
+ SourceBufferHolder& srcBuf, JS::MutableHandleValue rval);
+
+/**
+ * Evaluate the given character buffer in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length, JS::MutableHandleValue rval);
+
+/**
+ * As above, but providing an explicit scope chain. envChain must not include
+ * the global object on it; that's implicit. It needs to contain the other
+ * objects that should end up on the script's scope chain.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& options,
+ const char16_t* chars, size_t length, JS::MutableHandleValue rval);
+
+/**
+ * Evaluate the given byte buffer in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char* bytes, size_t length, JS::MutableHandleValue rval);
+
+/**
+ * Evaluate the given file in the scope of the current global of cx.
+ */
+extern JS_PUBLIC_API(bool)
+Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
+ const char* filename, JS::MutableHandleValue rval);
+
+/**
+ * Get the HostResolveImportedModule hook for a global.
+ */
+extern JS_PUBLIC_API(JSFunction*)
+GetModuleResolveHook(JSContext* cx);
+
+/**
+ * Set the HostResolveImportedModule hook for a global to the given function.
+ */
+extern JS_PUBLIC_API(void)
+SetModuleResolveHook(JSContext* cx, JS::HandleFunction func);
+
+/**
+ * Parse the given source buffer as a module in the scope of the current global
+ * of cx and return a source text module record.
+ */
+extern JS_PUBLIC_API(bool)
+CompileModule(JSContext* cx, const ReadOnlyCompileOptions& options,
+ SourceBufferHolder& srcBuf, JS::MutableHandleObject moduleRecord);
+
+/**
+ * Set the [[HostDefined]] field of a source text module record to the given
+ * value.
+ */
+extern JS_PUBLIC_API(void)
+SetModuleHostDefinedField(JSObject* module, const JS::Value& value);
+
+/**
+ * Get the [[HostDefined]] field of a source text module record.
+ */
+extern JS_PUBLIC_API(JS::Value)
+GetModuleHostDefinedField(JSObject* module);
+
+/*
+ * Perform the ModuleDeclarationInstantiation operation on on the give source
+ * text module record.
+ *
+ * This transitively resolves all module dependencies (calling the
+ * HostResolveImportedModule hook) and initializes the environment record for
+ * the module.
+ */
+extern JS_PUBLIC_API(bool)
+ModuleDeclarationInstantiation(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Perform the ModuleEvaluation operation on on the give source text module
+ * record.
+ *
+ * This does nothing if this module has already been evaluated. Otherwise, it
+ * transitively evaluates all dependences of this module and then evaluates this
+ * module.
+ *
+ * ModuleDeclarationInstantiation must have completed prior to calling this.
+ */
+extern JS_PUBLIC_API(bool)
+ModuleEvaluation(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Get a list of the module specifiers used by a source text module
+ * record to request importation of modules.
+ *
+ * The result is a JavaScript array of string values. To extract the individual
+ * values use only JS_GetArrayLength and JS_GetElement with indices 0 to
+ * length - 1.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetRequestedModules(JSContext* cx, JS::HandleObject moduleRecord);
+
+/*
+ * Get the script associated with a module.
+ */
+extern JS_PUBLIC_API(JSScript*)
+GetModuleScript(JSContext* cx, JS::HandleObject moduleRecord);
+
+} /* 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);
+
+namespace JS {
+
+/**
+ * Sets the callback that's invoked whenever an incumbent global is required.
+ *
+ * SpiderMonkey doesn't itself have a notion of incumbent globals as defined
+ * by the html spec, so we need the embedding to provide this.
+ * See dom/base/ScriptSettings.h for details.
+ */
+extern JS_PUBLIC_API(void)
+SetGetIncumbentGlobalCallback(JSContext* cx, JSGetIncumbentGlobalCallback callback);
+
+/**
+ * Sets the callback that's invoked whenever a Promise job should be enqeued.
+ *
+ * SpiderMonkey doesn't schedule Promise resolution jobs itself; instead,
+ * using this function the embedding can provide a callback to do that
+ * scheduling. The provided `callback` is invoked with the promise job,
+ * the corresponding Promise's allocation stack, and the `data` pointer
+ * passed here as arguments.
+ */
+extern JS_PUBLIC_API(void)
+SetEnqueuePromiseJobCallback(JSContext* cx, JSEnqueuePromiseJobCallback callback,
+ void* data = nullptr);
+
+/**
+ * Sets the callback that's invoked whenever a Promise is rejected without
+ * a rejection handler, and when a Promise that was previously rejected
+ * without a handler gets a handler attached.
+ */
+extern JS_PUBLIC_API(void)
+SetPromiseRejectionTrackerCallback(JSContext* cx, JSPromiseRejectionTrackerCallback callback,
+ void* data = nullptr);
+
+/**
+ * Returns a new instance of the Promise builtin class in the current
+ * compartment, with the right slot layout. If a `proto` is passed, that gets
+ * set as the instance's [[Prototype]] instead of the original value of
+ * `Promise.prototype`.
+ */
+extern JS_PUBLIC_API(JSObject*)
+NewPromiseObject(JSContext* cx, JS::HandleObject executor, JS::HandleObject proto = nullptr);
+
+/**
+ * Returns true if the given object is an unwrapped PromiseObject, false
+ * otherwise.
+ */
+extern JS_PUBLIC_API(bool)
+IsPromiseObject(JS::HandleObject obj);
+
+/**
+ * Returns the current compartment's original Promise constructor.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseConstructor(JSContext* cx);
+
+/**
+ * Returns the current compartment's original Promise.prototype.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromisePrototype(JSContext* cx);
+
+// Keep this in sync with the PROMISE_STATE defines in SelfHostingDefines.h.
+enum class PromiseState {
+ Pending,
+ Fulfilled,
+ Rejected
+};
+
+/**
+ * Returns the given Promise's state as a JS::PromiseState enum value.
+ *
+ * Returns JS::PromiseState::Pending if the given object is a wrapper that
+ * can't safely be unwrapped.
+ */
+extern JS_PUBLIC_API(PromiseState)
+GetPromiseState(JS::HandleObject promise);
+
+/**
+ * Returns the given Promise's process-unique ID.
+ */
+JS_PUBLIC_API(uint64_t)
+GetPromiseID(JS::HandleObject promise);
+
+/**
+ * Returns the given Promise's result: either the resolution value for
+ * fulfilled promises, or the rejection reason for rejected ones.
+ */
+extern JS_PUBLIC_API(JS::Value)
+GetPromiseResult(JS::HandleObject promise);
+
+/**
+ * Returns a js::SavedFrame linked list of the stack that lead to the given
+ * Promise's allocation.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseAllocationSite(JS::HandleObject promise);
+
+extern JS_PUBLIC_API(JSObject*)
+GetPromiseResolutionSite(JS::HandleObject promise);
+
+#ifdef DEBUG
+extern JS_PUBLIC_API(void)
+DumpPromiseAllocationSite(JSContext* cx, JS::HandleObject promise);
+
+extern JS_PUBLIC_API(void)
+DumpPromiseResolutionSite(JSContext* cx, JS::HandleObject promise);
+#endif
+
+/**
+ * Calls the current compartment's original Promise.resolve on the original
+ * Promise constructor, with `resolutionValue` passed as an argument.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseResolve(JSContext* cx, JS::HandleValue resolutionValue);
+
+/**
+ * Calls the current compartment's original Promise.reject on the original
+ * Promise constructor, with `resolutionValue` passed as an argument.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseReject(JSContext* cx, JS::HandleValue rejectionValue);
+
+/**
+ * Resolves the given Promise with the given `resolutionValue`.
+ *
+ * Calls the `resolve` function that was passed to the executor function when
+ * the Promise was created.
+ */
+extern JS_PUBLIC_API(bool)
+ResolvePromise(JSContext* cx, JS::HandleObject promise, JS::HandleValue resolutionValue);
+
+/**
+ * Rejects the given `promise` with the given `rejectionValue`.
+ *
+ * Calls the `reject` function that was passed to the executor function when
+ * the Promise was created.
+ */
+extern JS_PUBLIC_API(bool)
+RejectPromise(JSContext* cx, JS::HandleObject promise, JS::HandleValue rejectionValue);
+
+/**
+ * Calls the current compartment's original Promise.prototype.then on the
+ * given `promise`, with `onResolve` and `onReject` passed as arguments.
+ *
+ * Asserts if the passed-in `promise` object isn't an unwrapped instance of
+ * `Promise` or a subclass or `onResolve` and `onReject` aren't both either
+ * `nullptr` or callable objects.
+ */
+extern JS_PUBLIC_API(JSObject*)
+CallOriginalPromiseThen(JSContext* cx, JS::HandleObject promise,
+ JS::HandleObject onResolve, JS::HandleObject onReject);
+
+/**
+ * Unforgeable, optimized version of the JS builtin Promise.prototype.then.
+ *
+ * Takes a Promise instance and `onResolve`, `onReject` callables to enqueue
+ * as reactions for that promise. In difference to Promise.prototype.then,
+ * this doesn't create and return a new Promise instance.
+ *
+ * Asserts if the passed-in `promise` object isn't an unwrapped instance of
+ * `Promise` or a subclass or `onResolve` and `onReject` aren't both callable
+ * objects.
+ */
+extern JS_PUBLIC_API(bool)
+AddPromiseReactions(JSContext* cx, JS::HandleObject promise,
+ JS::HandleObject onResolve, JS::HandleObject onReject);
+
+/**
+ * Unforgeable version of the JS builtin Promise.all.
+ *
+ * Takes an AutoObjectVector of Promise objects and returns a promise that's
+ * resolved with an array of resolution values when all those promises have
+ * been resolved, or rejected with the rejection value of the first rejected
+ * promise.
+ *
+ * Asserts that all objects in the `promises` vector are, maybe wrapped,
+ * instances of `Promise` or a subclass of `Promise`.
+ */
+extern JS_PUBLIC_API(JSObject*)
+GetWaitForAllPromise(JSContext* cx, const JS::AutoObjectVector& promises);
+
+/**
+ * An AsyncTask represents a SpiderMonkey-internal operation that starts on a
+ * JSContext's owner thread, possibly executes on other threads, completes, and
+ * then needs to be scheduled to run again on the JSContext's owner thread. The
+ * embedding provides for this final dispatch back to the JSContext's owner
+ * thread by calling methods on this interface when requested.
+ */
+struct JS_PUBLIC_API(AsyncTask)
+{
+ AsyncTask() : user(nullptr) {}
+ virtual ~AsyncTask() {}
+
+ /**
+ * After the FinishAsyncTaskCallback is called and succeeds, one of these
+ * two functions will be called on the original JSContext's owner thread.
+ */
+ virtual void finish(JSContext* cx) = 0;
+ virtual void cancel(JSContext* cx) = 0;
+
+ /* The embedding may use this field to attach arbitrary data to a task. */
+ void* user;
+};
+
+/**
+ * A new AsyncTask object, created inside SpiderMonkey on the JSContext's owner
+ * thread, will be passed to the StartAsyncTaskCallback before it is dispatched
+ * to another thread. The embedding may use the AsyncTask::user field to attach
+ * additional task state.
+ *
+ * If this function succeeds, SpiderMonkey will call the FinishAsyncTaskCallback
+ * at some point in the future. Otherwise, FinishAsyncTaskCallback will *not*
+ * be called. SpiderMonkey assumes that, if StartAsyncTaskCallback fails, it is
+ * because the JSContext is being shut down.
+ */
+typedef bool
+(*StartAsyncTaskCallback)(JSContext* cx, AsyncTask* task);
+
+/**
+ * The FinishAsyncTaskCallback may be called from any thread and will only be
+ * passed AsyncTasks that have already been started via StartAsyncTaskCallback.
+ * If the embedding returns 'true', indicating success, the embedding must call
+ * either task->finish() or task->cancel() on the JSContext's owner thread at
+ * some point in the future.
+ */
+typedef bool
+(*FinishAsyncTaskCallback)(AsyncTask* task);
+
+/**
+ * Set the above callbacks for the given context.
+ */
+extern JS_PUBLIC_API(void)
+SetAsyncTaskCallbacks(JSContext* cx, StartAsyncTaskCallback start, FinishAsyncTaskCallback finish);
+
+} // namespace JS
+
+extern JS_PUBLIC_API(bool)
+JS_IsRunning(JSContext* cx);
+
+namespace JS {
+
+/**
+ * This class can be used to store a pointer to the youngest frame of a saved
+ * stack in the specified JSContext. This reference will be picked up by any new
+ * calls performed until the class is destroyed, with the specified asyncCause,
+ * that must not be empty.
+ *
+ * Any stack capture initiated during these new calls will go through the async
+ * stack instead of the current stack.
+ *
+ * Capturing the stack before a new call is performed will not be affected.
+ *
+ * The provided chain of SavedFrame objects can live in any compartment,
+ * although it will be copied to the compartment where the stack is captured.
+ *
+ * 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
+
+/************************************************************************/
+
+/*
+ * Strings.
+ *
+ * NB: JS_NewUCString takes ownership of bytes on success, avoiding a copy;
+ * but on error (signified by null return), it leaves chars owned by the
+ * caller. So the caller must free bytes in the error case, if it has no use
+ * for them. In contrast, all the JS_New*StringCopy* functions do not take
+ * ownership of the character memory passed to them -- they copy it.
+ */
+extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyN(JSContext* cx, const char* s, size_t n);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyZ(JSContext* cx, const char* s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyUTF8Z(JSContext* cx, const JS::ConstUTF8CharsZ s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewStringCopyUTF8N(JSContext* cx, const JS::UTF8Chars s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeAndPinJSString(JSContext* cx, JS::HandleString str);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeStringN(JSContext* cx, const char* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeString(JSContext* cx, const char* s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeAndPinStringN(JSContext* cx, const char* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeAndPinString(JSContext* cx, const char* s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewUCString(JSContext* cx, char16_t* chars, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewUCStringCopyN(JSContext* cx, const char16_t* s, size_t n);
+
+extern JS_PUBLIC_API(JSString*)
+JS_NewUCStringCopyZ(JSContext* cx, const char16_t* s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeUCStringN(JSContext* cx, const char16_t* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeUCString(JSContext* cx, const char16_t* s);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeAndPinUCStringN(JSContext* cx, const char16_t* s, size_t length);
+
+extern JS_PUBLIC_API(JSString*)
+JS_AtomizeAndPinUCString(JSContext* cx, const char16_t* s);
+
+extern JS_PUBLIC_API(bool)
+JS_CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result);
+
+extern JS_PUBLIC_API(bool)
+JS_StringEqualsAscii(JSContext* cx, JSString* str, const char* asciiBytes, bool* match);
+
+extern JS_PUBLIC_API(size_t)
+JS_PutEscapedString(JSContext* cx, char* buffer, size_t size, JSString* str, char quote);
+
+extern JS_PUBLIC_API(bool)
+JS_FileEscapedString(FILE* fp, JSString* str, char quote);
+
+/*
+ * Extracting string characters and length.
+ *
+ * While getting the length of a string is infallible, getting the chars can
+ * fail. As indicated by the lack of a JSContext parameter, there are two
+ * special cases where getting the chars is infallible:
+ *
+ * The first case is for strings that have been atomized, e.g. directly by
+ * JS_AtomizeAndPinString or implicitly because it is stored in a jsid.
+ *
+ * The second case is "flat" strings that have been explicitly prepared in a
+ * fallible context by JS_FlattenString. To catch errors, a separate opaque
+ * JSFlatString type is returned by JS_FlattenString and expected by
+ * JS_GetFlatStringChars. Note, though, that this is purely a syntactic
+ * distinction: the input and output of JS_FlattenString are the same actual
+ * GC-thing. If a JSString is known to be flat, JS_ASSERT_STRING_IS_FLAT can be
+ * used to make a debug-checked cast. Example:
+ *
+ * // in a fallible context
+ * JSFlatString* fstr = JS_FlattenString(cx, str);
+ * if (!fstr)
+ * return false;
+ * MOZ_ASSERT(fstr == JS_ASSERT_STRING_IS_FLAT(str));
+ *
+ * // in an infallible context, for the same 'str'
+ * AutoCheckCannotGC nogc;
+ * const char16_t* chars = JS_GetTwoByteFlatStringChars(nogc, fstr)
+ * MOZ_ASSERT(chars);
+ *
+ * Flat strings and interned strings are always null-terminated, so
+ * JS_FlattenString can be used to get a null-terminated string.
+ *
+ * Additionally, string characters are stored as either Latin1Char (8-bit)
+ * or char16_t (16-bit). Clients can use JS_StringHasLatin1Chars and can then
+ * call either the Latin1* or TwoByte* functions. Some functions like
+ * JS_CopyStringChars and JS_GetStringCharAt accept both Latin1 and TwoByte
+ * strings.
+ */
+
+extern JS_PUBLIC_API(size_t)
+JS_GetStringLength(JSString* str);
+
+extern JS_PUBLIC_API(bool)
+JS_StringIsFlat(JSString* str);
+
+/** Returns true iff the string's characters are stored as Latin1. */
+extern JS_PUBLIC_API(bool)
+JS_StringHasLatin1Chars(JSString* str);
+
+extern JS_PUBLIC_API(const JS::Latin1Char*)
+JS_GetLatin1StringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
+ size_t* length);
+
+extern JS_PUBLIC_API(const char16_t*)
+JS_GetTwoByteStringCharsAndLength(JSContext* cx, const JS::AutoCheckCannotGC& nogc, JSString* str,
+ size_t* length);
+
+extern JS_PUBLIC_API(bool)
+JS_GetStringCharAt(JSContext* cx, JSString* str, size_t index, char16_t* res);
+
+extern JS_PUBLIC_API(char16_t)
+JS_GetFlatStringCharAt(JSFlatString* str, size_t index);
+
+extern JS_PUBLIC_API(const char16_t*)
+JS_GetTwoByteExternalStringChars(JSString* str);
+
+extern JS_PUBLIC_API(bool)
+JS_CopyStringChars(JSContext* cx, mozilla::Range<char16_t> dest, JSString* str);
+
+extern JS_PUBLIC_API(JSFlatString*)
+JS_FlattenString(JSContext* cx, JSString* str);
+
+extern JS_PUBLIC_API(const JS::Latin1Char*)
+JS_GetLatin1FlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str);
+
+extern JS_PUBLIC_API(const char16_t*)
+JS_GetTwoByteFlatStringChars(const JS::AutoCheckCannotGC& nogc, JSFlatString* str);
+
+static MOZ_ALWAYS_INLINE JSFlatString*
+JSID_TO_FLAT_STRING(jsid id)
+{
+ MOZ_ASSERT(JSID_IS_STRING(id));
+ return (JSFlatString*)(JSID_BITS(id));
+}
+
+static MOZ_ALWAYS_INLINE JSFlatString*
+JS_ASSERT_STRING_IS_FLAT(JSString* str)
+{
+ MOZ_ASSERT(JS_StringIsFlat(str));
+ return (JSFlatString*)str;
+}
+
+static MOZ_ALWAYS_INLINE JSString*
+JS_FORGET_STRING_FLATNESS(JSFlatString* fstr)
+{
+ return (JSString*)fstr;
+}
+
+/*
+ * Additional APIs that avoid fallibility when given a flat string.
+ */
+
+extern JS_PUBLIC_API(bool)
+JS_FlatStringEqualsAscii(JSFlatString* str, const char* asciiBytes);
+
+extern JS_PUBLIC_API(size_t)
+JS_PutEscapedFlatString(char* buffer, size_t size, JSFlatString* str, char quote);
+
+/**
+ * Create a dependent string, i.e., a string that owns no character storage,
+ * but that refers to a slice of another string's chars. Dependent strings
+ * are mutable by definition, so the thread safety comments above apply.
+ */
+extern JS_PUBLIC_API(JSString*)
+JS_NewDependentString(JSContext* cx, JS::HandleString str, size_t start,
+ size_t length);
+
+/**
+ * Concatenate two strings, possibly resulting in a rope.
+ * See above for thread safety comments.
+ */
+extern JS_PUBLIC_API(JSString*)
+JS_ConcatStrings(JSContext* cx, JS::HandleString left, JS::HandleString right);
+
+/**
+ * For JS_DecodeBytes, set *dstlenp to the size of the destination buffer before
+ * the call; on return, *dstlenp contains the number of characters actually
+ * stored. To determine the necessary destination buffer size, make a sizing
+ * call that passes nullptr for dst.
+ *
+ * On errors, the functions report the error. In that case, *dstlenp contains
+ * the number of characters or bytes transferred so far. If cx is nullptr, no
+ * error is reported on failure, and the functions simply return false.
+ *
+ * NB: This function does not store an additional zero byte or char16_t after the
+ * transcoded string.
+ */
+JS_PUBLIC_API(bool)
+JS_DecodeBytes(JSContext* cx, const char* src, size_t srclen, char16_t* dst,
+ size_t* dstlenp);
+
+/**
+ * A variation on JS_EncodeCharacters where a null terminated string is
+ * returned that you are expected to call JS_free on when done.
+ */
+JS_PUBLIC_API(char*)
+JS_EncodeString(JSContext* cx, JSString* str);
+
+/**
+ * Same behavior as JS_EncodeString(), but encode into UTF-8 string
+ */
+JS_PUBLIC_API(char*)
+JS_EncodeStringToUTF8(JSContext* cx, JS::HandleString str);
+
+/**
+ * Get number of bytes in the string encoding (without accounting for a
+ * terminating zero bytes. The function returns (size_t) -1 if the string
+ * can not be encoded into bytes and reports an error using cx accordingly.
+ */
+JS_PUBLIC_API(size_t)
+JS_GetStringEncodingLength(JSContext* cx, JSString* str);
+
+/**
+ * Encode string into a buffer. The function does not stores an additional
+ * zero byte. The function returns (size_t) -1 if the string can not be
+ * encoded into bytes with no error reported. Otherwise it returns the number
+ * of bytes that are necessary to encode the string. If that exceeds the
+ * length parameter, the string will be cut and only length bytes will be
+ * written into the buffer.
+ */
+JS_PUBLIC_API(size_t)
+JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length);
+
+class MOZ_RAII JSAutoByteString
+{
+ public:
+ JSAutoByteString(JSContext* cx, JSString* str
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : mBytes(JS_EncodeString(cx, str))
+ {
+ MOZ_ASSERT(cx);
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ explicit JSAutoByteString(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+ : mBytes(nullptr)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ }
+
+ ~JSAutoByteString() {
+ JS_free(nullptr, mBytes);
+ }
+
+ /* Take ownership of the given byte array. */
+ void initBytes(char* bytes) {
+ MOZ_ASSERT(!mBytes);
+ mBytes = bytes;
+ }
+
+ char* encodeLatin1(JSContext* cx, JSString* str) {
+ MOZ_ASSERT(!mBytes);
+ MOZ_ASSERT(cx);
+ mBytes = JS_EncodeString(cx, str);
+ return mBytes;
+ }
+
+ char* encodeLatin1(js::ExclusiveContext* cx, JSString* str);
+
+ char* encodeUtf8(JSContext* cx, JS::HandleString str) {
+ MOZ_ASSERT(!mBytes);
+ MOZ_ASSERT(cx);
+ mBytes = JS_EncodeStringToUTF8(cx, str);
+ return mBytes;
+ }
+
+ void clear() {
+ js_free(mBytes);
+ mBytes = nullptr;
+ }
+
+ char* ptr() const {
+ return mBytes;
+ }
+
+ bool operator!() const {
+ return !mBytes;
+ }
+
+ size_t length() const {
+ if (!mBytes)
+ return 0;
+ return strlen(mBytes);
+ }
+
+ private:
+ char* mBytes;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+
+ /* Copy and assignment are not supported. */
+ JSAutoByteString(const JSAutoByteString& another);
+ JSAutoByteString& operator=(const JSAutoByteString& another);
+};
+
+namespace JS {
+
+extern JS_PUBLIC_API(JSAddonId*)
+NewAddonId(JSContext* cx, JS::HandleString str);
+
+extern JS_PUBLIC_API(JSString*)
+StringOfAddonId(JSAddonId* id);
+
+extern JS_PUBLIC_API(JSAddonId*)
+AddonIdOfObject(JSObject* obj);
+
+} // namespace JS
+
+/************************************************************************/
+/*
+ * Symbols
+ */
+
+namespace JS {
+
+/**
+ * Create a new Symbol with the given description. This function never returns
+ * a Symbol that is in the Runtime-wide symbol registry.
+ *
+ * If description is null, the new Symbol's [[Description]] attribute is
+ * undefined.
+ */
+JS_PUBLIC_API(Symbol*)
+NewSymbol(JSContext* cx, HandleString description);
+
+/**
+ * Symbol.for as specified in ES6.
+ *
+ * Get a Symbol with the description 'key' from the Runtime-wide symbol registry.
+ * If there is not already a Symbol with that description in the registry, a new
+ * Symbol is created and registered. 'key' must not be null.
+ */
+JS_PUBLIC_API(Symbol*)
+GetSymbolFor(JSContext* cx, HandleString key);
+
+/**
+ * Get the [[Description]] attribute of the given symbol.
+ *
+ * This function is infallible. If it returns null, that means the symbol's
+ * [[Description]] is undefined.
+ */
+JS_PUBLIC_API(JSString*)
+GetSymbolDescription(HandleSymbol symbol);
+
+/* Well-known symbols. */
+#define JS_FOR_EACH_WELL_KNOWN_SYMBOL(macro) \
+ macro(isConcatSpreadable) \
+ macro(iterator) \
+ macro(match) \
+ macro(replace) \
+ macro(search) \
+ macro(species) \
+ macro(hasInstance) \
+ macro(split) \
+ macro(toPrimitive) \
+ macro(toStringTag) \
+ macro(unscopables)
+
+enum class SymbolCode : uint32_t {
+ // There is one SymbolCode for each well-known symbol.
+#define JS_DEFINE_SYMBOL_ENUM(name) name,
+ JS_FOR_EACH_WELL_KNOWN_SYMBOL(JS_DEFINE_SYMBOL_ENUM) // SymbolCode::iterator, etc.
+#undef JS_DEFINE_SYMBOL_ENUM
+ Limit,
+ InSymbolRegistry = 0xfffffffe, // created by Symbol.for() or JS::GetSymbolFor()
+ UniqueSymbol = 0xffffffff // created by Symbol() or JS::NewSymbol()
+};
+
+/* For use in loops that iterate over the well-known symbols. */
+const size_t WellKnownSymbolLimit = size_t(SymbolCode::Limit);
+
+/**
+ * Return the SymbolCode telling what sort of symbol `symbol` is.
+ *
+ * A symbol's SymbolCode never changes once it is created.
+ */
+JS_PUBLIC_API(SymbolCode)
+GetSymbolCode(Handle<Symbol*> symbol);
+
+/**
+ * Get one of the well-known symbols defined by ES6. A single set of well-known
+ * symbols is shared by all compartments in a JSRuntime.
+ *
+ * `which` must be in the range [0, WellKnownSymbolLimit).
+ */
+JS_PUBLIC_API(Symbol*)
+GetWellKnownSymbol(JSContext* cx, SymbolCode which);
+
+/**
+ * Return true if the given JSPropertySpec::name or JSFunctionSpec::name value
+ * is actually a symbol code and not a string. See JS_SYM_FN.
+ */
+inline bool
+PropertySpecNameIsSymbol(const char* name)
+{
+ uintptr_t u = reinterpret_cast<uintptr_t>(name);
+ return u != 0 && u - 1 < WellKnownSymbolLimit;
+}
+
+JS_PUBLIC_API(bool)
+PropertySpecNameEqualsId(const char* 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, const char* name, jsid* idp);
+
+} /* namespace JS */
+
+/************************************************************************/
+/*
+ * JSON functions
+ */
+typedef bool (* JSONWriteCallback)(const char16_t* buf, uint32_t len, void* data);
+
+/**
+ * JSON.stringify as specified by ES5.
+ */
+JS_PUBLIC_API(bool)
+JS_Stringify(JSContext* cx, JS::MutableHandleValue value, JS::HandleObject replacer,
+ JS::HandleValue space, JSONWriteCallback callback, void* data);
+
+namespace JS {
+
+/**
+ * An API akin to JS_Stringify but with the goal of not having observable
+ * side-effects when the stringification is performed. This means it does not
+ * allow a replacer or a custom space, and has the following constraints on its
+ * input:
+ *
+ * 1) The input must be a plain object or array, not an abitrary value.
+ * 2) Every value in the graph reached by the algorithm starting with this
+ * object must be one of the following: null, undefined, a string (NOT a
+ * string object!), a boolean, a finite number (i.e. no NaN or Infinity or
+ * -Infinity), a plain object with no accessor properties, or an Array with
+ * no holes.
+ *
+ * The actual behavior differs from JS_Stringify only in asserting the above and
+ * NOT attempting to get the "toJSON" property from things, since that could
+ * clearly have side-effects.
+ */
+JS_PUBLIC_API(bool)
+ToJSONMaybeSafely(JSContext* cx, JS::HandleObject input,
+ JSONWriteCallback callback, void* data);
+
+} /* namespace JS */
+
+/**
+ * JSON.parse as specified by ES5.
+ */
+JS_PUBLIC_API(bool)
+JS_ParseJSON(JSContext* cx, const char16_t* chars, uint32_t len, JS::MutableHandleValue vp);
+
+JS_PUBLIC_API(bool)
+JS_ParseJSON(JSContext* cx, JS::HandleString str, JS::MutableHandleValue vp);
+
+JS_PUBLIC_API(bool)
+JS_ParseJSONWithReviver(JSContext* cx, const char16_t* chars, uint32_t len, JS::HandleValue reviver,
+ JS::MutableHandleValue vp);
+
+JS_PUBLIC_API(bool)
+JS_ParseJSONWithReviver(JSContext* cx, JS::HandleString str, JS::HandleValue reviver,
+ JS::MutableHandleValue vp);
+
+/************************************************************************/
+
+/**
+ * The default locale for the ECMAScript Internationalization API
+ * (Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat).
+ * Note that the Internationalization API encourages clients to
+ * specify their own locales.
+ * The locale string remains owned by the caller.
+ */
+extern JS_PUBLIC_API(bool)
+JS_SetDefaultLocale(JSContext* cx, const char* locale);
+
+/**
+ * Look up the default locale for the ECMAScript Internationalization API.
+ */
+extern JS_PUBLIC_API(JS::UniqueChars)
+JS_GetDefaultLocale(JSContext* cx);
+
+/**
+ * Reset the default locale to OS defaults.
+ */
+extern JS_PUBLIC_API(void)
+JS_ResetDefaultLocale(JSContext* cx);
+
+/**
+ * Locale specific string conversion and error message callbacks.
+ */
+struct JSLocaleCallbacks {
+ JSLocaleToUpperCase localeToUpperCase;
+ JSLocaleToLowerCase localeToLowerCase;
+ JSLocaleCompare localeCompare; // not used #if EXPOSE_INTL_API
+ JSLocaleToUnicode localeToUnicode;
+};
+
+/**
+ * Establish locale callbacks. The pointer must persist as long as the
+ * JSContext. Passing nullptr restores the default behaviour.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetLocaleCallbacks(JSContext* cx, const JSLocaleCallbacks* callbacks);
+
+/**
+ * Return the address of the current locale callbacks struct, which may
+ * be nullptr.
+ */
+extern JS_PUBLIC_API(const JSLocaleCallbacks*)
+JS_GetLocaleCallbacks(JSContext* cx);
+
+/************************************************************************/
+
+/*
+ * Error reporting.
+ */
+
+namespace JS {
+const uint16_t MaxNumErrorArguments = 10;
+};
+
+/**
+ * Report an exception represented by the sprintf-like conversion of format
+ * and its arguments.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportErrorASCII(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorLatin1(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorUTF8(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+/*
+ * Use an errorNumber to retrieve the format string, args are char*
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberASCII(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberASCIIVA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberLatin1(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberLatin1VA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUTF8(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+#ifdef va_start
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUTF8VA(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, va_list ap);
+#endif
+
+/*
+ * Use an errorNumber to retrieve the format string, args are char16_t*
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUC(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(void)
+JS_ReportErrorNumberUCArray(JSContext* cx, JSErrorCallback errorCallback,
+ void* userRef, const unsigned errorNumber,
+ const char16_t** args);
+
+/**
+ * As above, but report a warning instead (JSREPORT_IS_WARNING(report.flags)).
+ * Return true if there was no error trying to issue the warning, and if the
+ * warning was not converted into an error due to the JSOPTION_WERROR option
+ * being set, false otherwise.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ReportWarningASCII(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportWarningLatin1(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportWarningUTF8(JSContext* cx, const char* format, ...)
+ MOZ_FORMAT_PRINTF(2, 3);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberASCII(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberLatin1(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberUTF8(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
+
+extern JS_PUBLIC_API(bool)
+JS_ReportErrorFlagsAndNumberUC(JSContext* cx, unsigned flags,
+ JSErrorCallback errorCallback, void* userRef,
+ const unsigned errorNumber, ...);
+
+/**
+ * Complain when out of memory.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportOutOfMemory(JSContext* cx);
+
+/**
+ * Complain when an allocation size overflows the maximum supported limit.
+ */
+extern JS_PUBLIC_API(void)
+JS_ReportAllocationOverflow(JSContext* cx);
+
+class JSErrorReport
+{
+ // The (default) error message.
+ // If ownsMessage_ is true, the it is freed in destructor.
+ JS::ConstUTF8CharsZ message_;
+
+ // Offending source line without final '\n'.
+ // If ownsLinebuf__ is true, the buffer is freed in destructor.
+ const char16_t* linebuf_;
+
+ // Number of chars in linebuf_. Does not include trailing '\0'.
+ size_t linebufLength_;
+
+ // The 0-based offset of error token in linebuf_.
+ size_t tokenOffset_;
+
+ public:
+ JSErrorReport()
+ : linebuf_(nullptr), linebufLength_(0), tokenOffset_(0),
+ filename(nullptr), lineno(0), column(0),
+ flags(0), errorNumber(0),
+ exnType(0), isMuted(false),
+ ownsLinebuf_(false), ownsMessage_(false)
+ {}
+
+ ~JSErrorReport() {
+ freeLinebuf();
+ freeMessage();
+ }
+
+ const char* filename; /* source file name, URL, etc., or null */
+ unsigned lineno; /* source line number */
+ unsigned column; /* zero-based column index in line */
+ unsigned flags; /* error/warning, etc. */
+ unsigned errorNumber; /* the error number, e.g. see js.msg */
+ int16_t exnType; /* One of the JSExnType constants */
+ bool isMuted : 1; /* See the comment in ReadOnlyCompileOptions. */
+
+ private:
+ bool ownsLinebuf_ : 1;
+ bool ownsMessage_ : 1;
+
+ public:
+ const char16_t* linebuf() const {
+ return linebuf_;
+ }
+ size_t linebufLength() const {
+ return linebufLength_;
+ }
+ size_t tokenOffset() const {
+ return tokenOffset_;
+ }
+ void initOwnedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg) {
+ initBorrowedLinebuf(linebufArg, linebufLengthArg, tokenOffsetArg);
+ ownsLinebuf_ = true;
+ }
+ void initBorrowedLinebuf(const char16_t* linebufArg, size_t linebufLengthArg, size_t tokenOffsetArg);
+ void freeLinebuf();
+
+ const JS::ConstUTF8CharsZ message() const {
+ return message_;
+ }
+
+ void initOwnedMessage(const char* messageArg) {
+ initBorrowedMessage(messageArg);
+ ownsMessage_ = true;
+ }
+ void initBorrowedMessage(const char* messageArg) {
+ MOZ_ASSERT(!message_);
+ message_ = JS::ConstUTF8CharsZ(messageArg, strlen(messageArg));
+ }
+
+ JSString* newMessageString(JSContext* cx);
+
+ void freeMessage();
+};
+
+/*
+ * JSErrorReport flag values. These may be freely composed.
+ */
+#define JSREPORT_ERROR 0x0 /* pseudo-flag for default case */
+#define JSREPORT_WARNING 0x1 /* reported via JS_ReportWarning */
+#define JSREPORT_EXCEPTION 0x2 /* exception was thrown */
+#define JSREPORT_STRICT 0x4 /* error or warning due to strict option */
+
+#define JSREPORT_USER_1 0x8 /* user-defined flag */
+
+/*
+ * If JSREPORT_EXCEPTION is set, then a JavaScript-catchable exception
+ * has been thrown for this runtime error, and the host should ignore it.
+ * Exception-aware hosts should also check for JS_IsExceptionPending if
+ * JS_ExecuteScript returns failure, and signal or propagate the exception, as
+ * appropriate.
+ */
+#define JSREPORT_IS_WARNING(flags) (((flags) & JSREPORT_WARNING) != 0)
+#define JSREPORT_IS_EXCEPTION(flags) (((flags) & JSREPORT_EXCEPTION) != 0)
+#define JSREPORT_IS_STRICT(flags) (((flags) & JSREPORT_STRICT) != 0)
+
+namespace JS {
+
+using WarningReporter = void (*)(JSContext* cx, JSErrorReport* report);
+
+extern JS_PUBLIC_API(WarningReporter)
+SetWarningReporter(JSContext* cx, WarningReporter reporter);
+
+extern JS_PUBLIC_API(WarningReporter)
+GetWarningReporter(JSContext* cx);
+
+extern JS_PUBLIC_API(bool)
+CreateError(JSContext* cx, JSExnType type, HandleObject stack,
+ HandleString fileName, uint32_t lineNumber, uint32_t columnNumber,
+ JSErrorReport* report, HandleString message, MutableHandleValue rval);
+
+/************************************************************************/
+
+/*
+ * Weak Maps.
+ */
+
+extern JS_PUBLIC_API(JSObject*)
+NewWeakMapObject(JSContext* cx);
+
+extern JS_PUBLIC_API(bool)
+IsWeakMapObject(JSObject* obj);
+
+extern JS_PUBLIC_API(bool)
+GetWeakMapEntry(JSContext* cx, JS::HandleObject mapObj, JS::HandleObject key,
+ JS::MutableHandleValue val);
+
+extern JS_PUBLIC_API(bool)
+SetWeakMapEntry(JSContext* cx, JS::HandleObject mapObj, JS::HandleObject key,
+ JS::HandleValue val);
+
+/*
+ * Map
+ */
+extern JS_PUBLIC_API(JSObject*)
+NewMapObject(JSContext* cx);
+
+extern JS_PUBLIC_API(uint32_t)
+MapSize(JSContext* cx, HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+MapGet(JSContext* cx, HandleObject obj,
+ HandleValue key, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+MapHas(JSContext* cx, HandleObject obj, HandleValue key, bool* rval);
+
+extern JS_PUBLIC_API(bool)
+MapSet(JSContext* cx, HandleObject obj, HandleValue key, HandleValue val);
+
+extern JS_PUBLIC_API(bool)
+MapDelete(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
+
+extern JS_PUBLIC_API(bool)
+MapClear(JSContext* cx, HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+MapKeys(JSContext* cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+MapValues(JSContext* cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+MapEntries(JSContext* cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+MapForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal);
+
+/*
+ * Set
+ */
+extern JS_PUBLIC_API(JSObject *)
+NewSetObject(JSContext *cx);
+
+extern JS_PUBLIC_API(uint32_t)
+SetSize(JSContext *cx, HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+SetHas(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
+
+extern JS_PUBLIC_API(bool)
+SetDelete(JSContext *cx, HandleObject obj, HandleValue key, bool *rval);
+
+extern JS_PUBLIC_API(bool)
+SetAdd(JSContext *cx, HandleObject obj, HandleValue key);
+
+extern JS_PUBLIC_API(bool)
+SetClear(JSContext *cx, HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+SetKeys(JSContext *cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+SetValues(JSContext *cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+SetEntries(JSContext *cx, HandleObject obj, MutableHandleValue rval);
+
+extern JS_PUBLIC_API(bool)
+SetForEach(JSContext *cx, HandleObject obj, HandleValue callbackFn, HandleValue thisVal);
+
+} /* namespace JS */
+
+/*
+ * Dates.
+ */
+
+extern JS_PUBLIC_API(JSObject*)
+JS_NewDateObject(JSContext* cx, int year, int mon, int mday, int hour, int min, int sec);
+
+/**
+ * Returns true and sets |*isDate| indicating whether |obj| is a Date object or
+ * a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isDate == false| when passed a proxy whose
+ * target is a Date, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ObjectIsDate(JSContext* cx, JS::HandleObject obj, bool* isDate);
+
+/************************************************************************/
+
+/*
+ * Regular Expressions.
+ */
+#define JSREG_FOLD 0x01u /* fold uppercase to lowercase */
+#define JSREG_GLOB 0x02u /* global exec, creates array of matches */
+#define JSREG_MULTILINE 0x04u /* treat ^ and $ as begin and end of line */
+#define JSREG_STICKY 0x08u /* only match starting at lastIndex */
+#define JSREG_UNICODE 0x10u /* unicode */
+
+extern JS_PUBLIC_API(JSObject*)
+JS_NewRegExpObject(JSContext* cx, const char* bytes, size_t length, unsigned flags);
+
+extern JS_PUBLIC_API(JSObject*)
+JS_NewUCRegExpObject(JSContext* cx, const char16_t* chars, size_t length, unsigned flags);
+
+extern JS_PUBLIC_API(bool)
+JS_SetRegExpInput(JSContext* cx, JS::HandleObject obj, JS::HandleString input);
+
+extern JS_PUBLIC_API(bool)
+JS_ClearRegExpStatics(JSContext* cx, JS::HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+JS_ExecuteRegExp(JSContext* cx, JS::HandleObject obj, JS::HandleObject reobj,
+ char16_t* chars, size_t length, size_t* indexp, bool test,
+ JS::MutableHandleValue rval);
+
+/* RegExp interface for clients without a global object. */
+
+extern JS_PUBLIC_API(bool)
+JS_ExecuteRegExpNoStatics(JSContext* cx, JS::HandleObject reobj, char16_t* chars, size_t length,
+ size_t* indexp, bool test, JS::MutableHandleValue rval);
+
+/**
+ * Returns true and sets |*isRegExp| indicating whether |obj| is a RegExp
+ * object or a wrapper around one, otherwise returns false on failure.
+ *
+ * This method returns true with |*isRegExp == false| when passed a proxy whose
+ * target is a RegExp, or when passed a revoked proxy.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ObjectIsRegExp(JSContext* cx, JS::HandleObject obj, bool* isRegExp);
+
+extern JS_PUBLIC_API(unsigned)
+JS_GetRegExpFlags(JSContext* cx, JS::HandleObject obj);
+
+extern JS_PUBLIC_API(JSString*)
+JS_GetRegExpSource(JSContext* cx, JS::HandleObject obj);
+
+/************************************************************************/
+
+extern JS_PUBLIC_API(bool)
+JS_IsExceptionPending(JSContext* cx);
+
+extern JS_PUBLIC_API(bool)
+JS_GetPendingException(JSContext* cx, JS::MutableHandleValue vp);
+
+extern JS_PUBLIC_API(void)
+JS_SetPendingException(JSContext* cx, JS::HandleValue v);
+
+extern JS_PUBLIC_API(void)
+JS_ClearPendingException(JSContext* cx);
+
+namespace JS {
+
+/**
+ * Save and later restore the current exception state of a given JSContext.
+ * This is useful for implementing behavior in C++ that's like try/catch
+ * or try/finally in JS.
+ *
+ * Typical usage:
+ *
+ * bool ok = JS::Evaluate(cx, ...);
+ * AutoSaveExceptionState savedExc(cx);
+ * ... cleanup that might re-enter JS ...
+ * return ok;
+ */
+class JS_PUBLIC_API(AutoSaveExceptionState)
+{
+ private:
+ JSContext* context;
+ bool wasPropagatingForcedReturn;
+ bool wasOverRecursed;
+ bool wasThrowing;
+ RootedValue exceptionValue;
+
+ public:
+ /*
+ * Take a snapshot of cx's current exception state. Then clear any current
+ * pending exception in cx.
+ */
+ explicit AutoSaveExceptionState(JSContext* cx);
+
+ /*
+ * If neither drop() nor restore() was called, restore the exception
+ * state only if no exception is currently pending on cx.
+ */
+ ~AutoSaveExceptionState();
+
+ /*
+ * Discard any stored exception state.
+ * If this is called, the destructor is a no-op.
+ */
+ void drop() {
+ wasPropagatingForcedReturn = false;
+ wasOverRecursed = false;
+ wasThrowing = false;
+ exceptionValue.setUndefined();
+ }
+
+ /*
+ * Replace cx's exception state with the stored exception state. Then
+ * discard the stored exception state. If this is called, the
+ * destructor is a no-op.
+ */
+ void restore();
+};
+
+} /* namespace JS */
+
+/* Deprecated API. Use AutoSaveExceptionState instead. */
+extern JS_PUBLIC_API(JSExceptionState*)
+JS_SaveExceptionState(JSContext* cx);
+
+extern JS_PUBLIC_API(void)
+JS_RestoreExceptionState(JSContext* cx, JSExceptionState* state);
+
+extern JS_PUBLIC_API(void)
+JS_DropExceptionState(JSContext* cx, JSExceptionState* state);
+
+/**
+ * If the given object is an exception object, the exception will have (or be
+ * able to lazily create) an error report struct, and this function will return
+ * the address of that struct. Otherwise, it returns nullptr. The lifetime
+ * of the error report struct that might be returned is the same as the
+ * lifetime of the exception object.
+ */
+extern JS_PUBLIC_API(JSErrorReport*)
+JS_ErrorFromException(JSContext* cx, JS::HandleObject obj);
+
+/**
+ * If the given object is an exception object (or an unwrappable
+ * cross-compartment wrapper for one), return the stack for that exception, if
+ * any. Will return null if the given object is not an exception object
+ * (including if it's null or a security wrapper that can't be unwrapped) or if
+ * the exception has no stack.
+ */
+extern JS_PUBLIC_API(JSObject*)
+ExceptionStackOrNull(JS::HandleObject obj);
+
+/*
+ * Throws a StopIteration exception on cx.
+ */
+extern JS_PUBLIC_API(bool)
+JS_ThrowStopIteration(JSContext* cx);
+
+extern JS_PUBLIC_API(bool)
+JS_IsStopIteration(const JS::Value& v);
+
+/**
+ * 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);
+
+/************************************************************************/
+
+#ifdef JS_GC_ZEAL
+#define JS_DEFAULT_ZEAL_FREQ 100
+
+extern JS_PUBLIC_API(void)
+JS_GetGCZealBits(JSContext* cx, uint32_t* zealBits, uint32_t* frequency, uint32_t* nextScheduled);
+
+extern JS_PUBLIC_API(void)
+JS_SetGCZeal(JSContext* cx, uint8_t zeal, uint32_t frequency);
+
+extern JS_PUBLIC_API(void)
+JS_ScheduleGC(JSContext* cx, uint32_t count);
+#endif
+
+extern JS_PUBLIC_API(void)
+JS_SetParallelParsingEnabled(JSContext* cx, bool enabled);
+
+extern JS_PUBLIC_API(void)
+JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled);
+
+#define JIT_COMPILER_OPTIONS(Register) \
+ Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger") \
+ Register(ION_WARMUP_TRIGGER, "ion.warmup.trigger") \
+ Register(ION_GVN_ENABLE, "ion.gvn.enable") \
+ Register(ION_FORCE_IC, "ion.forceinlineCaches") \
+ Register(ION_ENABLE, "ion.enable") \
+ Register(ION_INTERRUPT_WITHOUT_SIGNAL, "ion.interrupt-without-signals") \
+ Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis") \
+ Register(BASELINE_ENABLE, "baseline.enable") \
+ Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
+ Register(JUMP_THRESHOLD, "jump-threshold") \
+ Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \
+ Register(WASM_TEST_MODE, "wasm.test-mode") \
+ Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets")
+
+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<const char*, UniqueChars> filename_;
+
+ AutoFilename(const AutoFilename&) = delete;
+ AutoFilename& operator=(const AutoFilename&) = delete;
+
+ public:
+ AutoFilename()
+ : ss_(nullptr),
+ filename_(mozilla::AsVariant<const char*>(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
+ MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+ : mContext(cx)
+ {
+ MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+ HideScriptedCaller(mContext);
+ }
+ ~AutoHideScriptedCaller() {
+ UnhideScriptedCaller(mContext);
+ }
+
+ protected:
+ JSContext* mContext;
+ MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+/*
+ * Encode/Decode interpreted scripts and functions to/from memory.
+ */
+
+typedef mozilla::Vector<uint8_t> TranscodeBuffer;
+
+enum TranscodeResult
+{
+ // Successful encoding / decoding.
+ TranscodeResult_Ok = 0,
+
+ // A warning message, is set to the message out-param.
+ TranscodeResult_Failure = 0x100,
+ TranscodeResult_Failure_BadBuildId = TranscodeResult_Failure | 0x1,
+ TranscodeResult_Failure_RunOnceNotSupported = TranscodeResult_Failure | 0x2,
+ TranscodeResult_Failure_AsmJSNotSupported = TranscodeResult_Failure | 0x3,
+ TranscodeResult_Failure_UnknownClassKind = TranscodeResult_Failure | 0x4,
+
+ // A error, the JSContext has a pending exception.
+ TranscodeResult_Throw = 0x200
+};
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::HandleScript script);
+
+extern JS_PUBLIC_API(TranscodeResult)
+EncodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::HandleObject funobj);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeScript(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleScript scriptp,
+ size_t cursorIndex = 0);
+
+extern JS_PUBLIC_API(TranscodeResult)
+DecodeInterpretedFunction(JSContext* cx, TranscodeBuffer& buffer, JS::MutableHandleFunction funp,
+ size_t cursorIndex = 0);
+
+} /* 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 {
+
+/*
+ * This callback represents a request by the JS engine to open for reading the
+ * existing cache entry for the given global and char range that may contain a
+ * module. If a cache entry exists, the callback shall return 'true' and return
+ * the size, base address and an opaque file handle as outparams. If the
+ * callback returns 'true', the JS engine guarantees a call to
+ * CloseAsmJSCacheEntryForReadOp, passing the same base address, size and
+ * handle.
+ */
+typedef bool
+(* OpenAsmJSCacheEntryForReadOp)(HandleObject global, const char16_t* begin, const char16_t* limit,
+ size_t* size, const uint8_t** memory, intptr_t* handle);
+typedef void
+(* CloseAsmJSCacheEntryForReadOp)(size_t size, const uint8_t* memory, intptr_t handle);
+
+/** The list of reasons why an asm.js module may not be stored in the cache. */
+enum AsmJSCacheResult
+{
+ AsmJSCache_Success,
+ AsmJSCache_MIN = AsmJSCache_Success,
+ AsmJSCache_ModuleTooSmall,
+ AsmJSCache_SynchronousScript,
+ AsmJSCache_QuotaExceeded,
+ AsmJSCache_StorageInitFailure,
+ AsmJSCache_Disabled_Internal,
+ AsmJSCache_Disabled_ShellFlags,
+ AsmJSCache_Disabled_JitInspector,
+ AsmJSCache_InternalError,
+ AsmJSCache_Disabled_PrivateBrowsing,
+ AsmJSCache_ESR52,
+ AsmJSCache_LIMIT
+};
+
+/*
+ * This callback represents a request by the JS engine to open for writing a
+ * cache entry of the given size for the given global and char range containing
+ * the just-compiled module. If cache entry space is available, the callback
+ * shall return 'true' and return the base address and an opaque file handle as
+ * outparams. If the callback returns 'true', the JS engine guarantees a call
+ * to CloseAsmJSCacheEntryForWriteOp passing the same base address, size and
+ * handle.
+ *
+ * If 'installed' is true, then the cache entry is associated with a permanently
+ * installed JS file (e.g., in a packaged webapp). This information allows the
+ * embedding to store the cache entry in a installed location associated with
+ * the principal of 'global' where it will not be evicted until the associated
+ * installed JS file is removed.
+ */
+typedef AsmJSCacheResult
+(* OpenAsmJSCacheEntryForWriteOp)(HandleObject global, bool installed,
+ const char16_t* begin, const char16_t* end,
+ size_t size, uint8_t** memory, intptr_t* handle);
+typedef void
+(* CloseAsmJSCacheEntryForWriteOp)(size_t size, uint8_t* memory, intptr_t handle);
+
+struct AsmJSCacheOps
+{
+ OpenAsmJSCacheEntryForReadOp openEntryForRead;
+ CloseAsmJSCacheEntryForReadOp closeEntryForRead;
+ OpenAsmJSCacheEntryForWriteOp openEntryForWrite;
+ CloseAsmJSCacheEntryForWriteOp closeEntryForWrite;
+};
+
+extern JS_PUBLIC_API(void)
+SetAsmJSCacheOps(JSContext* cx, const AsmJSCacheOps* callbacks);
+
+/**
+ * Return the buildId (represented as a sequence of characters) associated with
+ * the currently-executing build. If the JS engine is embedded such that a
+ * single cache entry can be observed by different compiled versions of the JS
+ * engine, it is critical that the buildId shall change for each new build of
+ * the JS engine.
+ */
+typedef js::Vector<char, 0, js::SystemAllocPolicy> BuildIdCharVector;
+
+typedef bool
+(* BuildIdOp)(BuildIdCharVector* buildId);
+
+extern JS_PUBLIC_API(void)
+SetBuildIdOp(JSContext* cx, BuildIdOp buildIdOp);
+
+/**
+ * The WasmModule interface allows the embedding to hold a reference to the
+ * underying C++ implementation of a JS WebAssembly.Module object for purposes
+ * of (de)serialization off the object's JSRuntime's thread.
+ *
+ * - Serialization starts when WebAssembly.Module is passed to the
+ * structured-clone algorithm. JS::GetWasmModule is called on the JSRuntime
+ * thread that initiated the structured clone to get the JS::WasmModule.
+ * This interface is then taken to a background thread where serializedSize()
+ * and serialize() are called to write the object to two files: a bytecode file
+ * that always allows successful deserialization and a compiled-code file keyed
+ * on cpu- and build-id that may become invalid if either of these change between
+ * serialization and deserialization. After serialization, the reference is
+ * dropped from the background thread.
+ *
+ * - Deserialization starts when the structured clone algorithm encounters a
+ * serialized WebAssembly.Module. On a background thread, the compiled-code file
+ * is opened and CompiledWasmModuleAssumptionsMatch is called to see if it is
+ * still valid (as described above). DeserializeWasmModule is then called to
+ * construct a JS::WasmModule (also on the background thread), passing the
+ * bytecode file descriptor and, if valid, the compiled-code file descriptor.
+ * The JS::WasmObject is then transported to the JSRuntime thread (which
+ * originated the request) and the wrapping WebAssembly.Module object is created
+ * by calling createObject().
+ */
+
+struct WasmModule : mozilla::external::AtomicRefCounted<WasmModule>
+{
+ MOZ_DECLARE_REFCOUNTED_TYPENAME(WasmModule)
+ virtual ~WasmModule() {}
+
+ virtual void serializedSize(size_t* maybeBytecodeSize, size_t* maybeCompiledSize) const = 0;
+ virtual void serialize(uint8_t* maybeBytecodeBegin, size_t maybeBytecodeSize,
+ uint8_t* maybeCompiledBegin, size_t maybeCompiledSize) const = 0;
+
+ virtual JSObject* createObject(JSContext* cx) = 0;
+};
+
+extern JS_PUBLIC_API(bool)
+IsWasmModuleObject(HandleObject obj);
+
+extern JS_PUBLIC_API(RefPtr<WasmModule>)
+GetWasmModule(HandleObject obj);
+
+extern JS_PUBLIC_API(bool)
+CompiledWasmModuleAssumptionsMatch(PRFileDesc* compiled, BuildIdCharVector&& buildId);
+
+extern JS_PUBLIC_API(RefPtr<WasmModule>)
+DeserializeWasmModule(PRFileDesc* bytecode, PRFileDesc* maybeCompiled, BuildIdCharVector&& buildId,
+ JS::UniqueChars filename, unsigned line, unsigned column);
+
+/**
+ * Convenience class for imitating a JS level for-of loop. Typical usage:
+ *
+ * ForOfIterator it(cx);
+ * if (!it.init(iterable))
+ * return false;
+ * RootedValue val(cx);
+ * while (true) {
+ * bool done;
+ * if (!it.next(&val, &done))
+ * return false;
+ * if (done)
+ * break;
+ * if (!DoStuff(cx, val))
+ * return false;
+ * }
+ */
+class MOZ_STACK_CLASS JS_PUBLIC_API(ForOfIterator) {
+ protected:
+ JSContext* cx_;
+ /*
+ * Use the ForOfPIC on the global object (see vm/GlobalObject.h) to try
+ * to optimize iteration across arrays.
+ *
+ * Case 1: Regular Iteration
+ * iterator - pointer to the iterator object.
+ * index - fixed to NOT_ARRAY (== UINT32_MAX)
+ *
+ * Case 2: Optimized Array Iteration
+ * iterator - pointer to the array object.
+ * index - current position in array.
+ *
+ * The cases are distinguished by whether or not |index| is equal to NOT_ARRAY.
+ */
+ JS::RootedObject iterator;
+ uint32_t index;
+
+ static const uint32_t NOT_ARRAY = UINT32_MAX;
+
+ ForOfIterator(const ForOfIterator&) = delete;
+ ForOfIterator& operator=(const ForOfIterator&) = delete;
+
+ public:
+ explicit ForOfIterator(JSContext* cx) : cx_(cx), iterator(cx_), index(NOT_ARRAY) { }
+
+ enum NonIterableBehavior {
+ ThrowOnNonIterable,
+ AllowNonIterable
+ };
+
+ /**
+ * Initialize the iterator. If AllowNonIterable is passed then if getting
+ * the @@iterator property from iterable returns undefined init() will just
+ * return true instead of throwing. Callers must then check
+ * valueIsIterable() before continuing with the iteration.
+ */
+ bool init(JS::HandleValue iterable,
+ NonIterableBehavior nonIterableBehavior = ThrowOnNonIterable);
+
+ /**
+ * Get the next value from the iterator. If false *done is true
+ * after this call, do not examine val.
+ */
+ bool next(JS::MutableHandleValue val, bool* done);
+
+ /**
+ * If initialized with throwOnNonCallable = false, check whether
+ * the value is iterable.
+ */
+ bool valueIsIterable() const {
+ return iterator;
+ }
+
+ private:
+ inline bool nextFromOptimizedArray(MutableHandleValue val, bool* done);
+ bool materializeArrayIterator();
+};
+
+
+/**
+ * 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.)
+ */
+
+typedef void
+(* LargeAllocationFailureCallback)(void* data);
+
+extern JS_PUBLIC_API(void)
+SetLargeAllocationFailureCallback(JSContext* cx, LargeAllocationFailureCallback afc, void* data);
+
+/**
+ * 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.
+ */
+
+typedef void
+(* OutOfMemoryCallback)(JSContext* cx, void* data);
+
+extern JS_PUBLIC_API(void)
+SetOutOfMemoryCallback(JSContext* cx, OutOfMemoryCallback cb, void* data);
+
+/**
+ * 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(mozilla::Move(rhs));
+ return *this;
+ }
+
+ ~FirstSubsumedFrame() {
+ if (principals)
+ JS_DropPrincipals(cx, principals);
+ }
+};
+
+using StackCapture = mozilla::Variant<AllFrames, MaxFrames, FirstSubsumedFrame>;
+
+/**
+ * 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()));
+
+/*
+ * 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
+ * non-zero, capture at most the youngest |maxFrameCount| 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,
+ unsigned maxFrameCount);
+
+/*
+ * Accessors for working with SavedFrame JSObjects
+ *
+ * Each of these functions assert that if their `HandleObject savedFrame`
+ * argument is non-null, its JSClass is the SavedFrame class (or it is a
+ * cross-compartment or Xray wrapper around an object with the SavedFrame class)
+ * and the object is not the SavedFrame.prototype object.
+ *
+ * Each of these functions will find the first SavedFrame object in the chain
+ * whose underlying stack frame principals are subsumed by the cx's current
+ * compartment's principals, and operate on that SavedFrame object. This
+ * prevents leaking information about privileged frames to un-privileged
+ * callers. As a result, the SavedFrame in parameters do _NOT_ need to be in the
+ * same compartment as the cx, and the various out parameters are _NOT_
+ * guaranteed to be in the same compartment as cx.
+ *
+ * You may consider or skip over self-hosted frames by passing
+ * `SavedFrameSelfHosted::Include` or `SavedFrameSelfHosted::Exclude`
+ * respectively.
+ *
+ * Additionally, it may be the case that there is no such SavedFrame object
+ * whose captured frame's principals are subsumed by the caller's compartment's
+ * principals! If the `HandleObject savedFrame` argument is null, or the
+ * caller's principals do not subsume any of the chained SavedFrame object's
+ * principals, `SavedFrameResult::AccessDenied` is returned and a (hopefully)
+ * sane default value is chosen for the out param.
+ *
+ * See also `js/src/doc/SavedFrame/SavedFrame.md`.
+ */
+
+enum class SavedFrameResult {
+ Ok,
+ AccessDenied
+};
+
+enum class SavedFrameSelfHosted {
+ Include,
+ Exclude
+};
+
+/**
+ * Given a SavedFrame JSObject, get its source property. Defaults to the empty
+ * string.
+ */
+extern JS_PUBLIC_API(SavedFrameResult)
+GetSavedFrameSource(JSContext* cx, HandleObject savedFrame, MutableHandleString sourcep,
+ SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
+
+/**
+ * Given a SavedFrame JSObject, get its line property. Defaults to 0.
+ */
+extern JS_PUBLIC_API(SavedFrameResult)
+GetSavedFrameLine(JSContext* cx, HandleObject savedFrame, uint32_t* linep,
+ SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
+
+/**
+ * Given a SavedFrame JSObject, get its column property. Defaults to 0.
+ */
+extern JS_PUBLIC_API(SavedFrameResult)
+GetSavedFrameColumn(JSContext* cx, HandleObject savedFrame, uint32_t* columnp,
+ SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
+
+/**
+ * Given a SavedFrame JSObject, get its functionDisplayName string, or nullptr
+ * if SpiderMonkey was unable to infer a name for the captured frame's
+ * function. Defaults to nullptr.
+ */
+extern JS_PUBLIC_API(SavedFrameResult)
+GetSavedFrameFunctionDisplayName(JSContext* cx, HandleObject savedFrame, MutableHandleString namep,
+ SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
+
+/**
+ * Given a SavedFrame JSObject, get its asyncCause string. Defaults to nullptr.
+ */
+extern JS_PUBLIC_API(SavedFrameResult)
+GetSavedFrameAsyncCause(JSContext* cx, HandleObject savedFrame, MutableHandleString asyncCausep,
+ SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
+
+/**
+ * Given a SavedFrame JSObject, get its asyncParent SavedFrame object or nullptr
+ * if there is no asyncParent. The `asyncParentp` out parameter is _NOT_
+ * guaranteed to be in the cx's compartment. Defaults to nullptr.
+ */
+extern JS_PUBLIC_API(SavedFrameResult)
+GetSavedFrameAsyncParent(JSContext* cx, HandleObject savedFrame, MutableHandleObject asyncParentp,
+ SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
+
+/**
+ * Given a SavedFrame JSObject, get its parent SavedFrame object or nullptr if
+ * it is the oldest frame in the stack. The `parentp` out parameter is _NOT_
+ * guaranteed to be in the cx's compartment. Defaults to nullptr.
+ */
+extern JS_PUBLIC_API(SavedFrameResult)
+GetSavedFrameParent(JSContext* cx, HandleObject savedFrame, MutableHandleObject parentp,
+ SavedFrameSelfHosted selfHosted = SavedFrameSelfHosted::Include);
+
+/**
+ * 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.
+ *
+ * Optional indent parameter specifies the number of white spaces to indent
+ * each line.
+ */
+extern JS_PUBLIC_API(bool)
+BuildStackString(JSContext* cx, 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)
+IsSavedFrame(JSObject* obj);
+
+} /* namespace JS */
+
+
+/* Stopwatch-based performance monitoring. */
+
+namespace js {
+
+class AutoStopwatch;
+
+/**
+ * Abstract base class for a representation of the performance of a
+ * component. Embeddings interested in performance monitoring should
+ * provide a concrete implementation of this class, as well as the
+ * relevant callbacks (see below).
+ */
+struct JS_PUBLIC_API(PerformanceGroup) {
+ PerformanceGroup();
+
+ // The current iteration of the event loop.
+ uint64_t iteration() const;
+
+ // `true` if an instance of `AutoStopwatch` is already monitoring
+ // the performance of this performance group for this iteration
+ // of the event loop, `false` otherwise.
+ bool isAcquired(uint64_t it) const;
+
+ // `true` if a specific instance of `AutoStopwatch` is already monitoring
+ // the performance of this performance group for this iteration
+ // of the event loop, `false` otherwise.
+ bool isAcquired(uint64_t it, const AutoStopwatch* owner) const;
+
+ // Mark that an instance of `AutoStopwatch` is monitoring
+ // the performance of this group for a given iteration.
+ void acquire(uint64_t it, const AutoStopwatch* owner);
+
+ // Mark that no `AutoStopwatch` is monitoring the
+ // performance of this group for the iteration.
+ void release(uint64_t it, const AutoStopwatch* owner);
+
+ // The number of cycles spent in this group during this iteration
+ // of the event loop. Note that cycles are not a reliable measure,
+ // especially over short intervals. See Stopwatch.* for a more
+ // complete discussion on the imprecision of cycle measurement.
+ uint64_t recentCycles(uint64_t iteration) const;
+ void addRecentCycles(uint64_t iteration, uint64_t cycles);
+
+ // The number of times this group has been activated during this
+ // iteration of the event loop.
+ uint64_t recentTicks(uint64_t iteration) const;
+ void addRecentTicks(uint64_t iteration, uint64_t ticks);
+
+ // The number of microseconds spent doing CPOW during this
+ // iteration of the event loop.
+ uint64_t recentCPOW(uint64_t iteration) const;
+ void addRecentCPOW(uint64_t iteration, uint64_t CPOW);
+
+ // Get rid of any data that pretends to be recent.
+ void resetRecentData();
+
+ // `true` if new measures should be added to this group, `false`
+ // otherwise.
+ bool isActive() const;
+ void setIsActive(bool);
+
+ // `true` if this group has been used in the current iteration,
+ // `false` otherwise.
+ bool isUsedInThisIteration() const;
+ void setIsUsedInThisIteration(bool);
+ protected:
+ // An implementation of `delete` for this object. Must be provided
+ // by the embedding.
+ virtual void Delete() = 0;
+
+ private:
+ // The number of cycles spent in this group during this iteration
+ // of the event loop. Note that cycles are not a reliable measure,
+ // especially over short intervals. See Runtime.cpp for a more
+ // complete discussion on the imprecision of cycle measurement.
+ uint64_t recentCycles_;
+
+ // The number of times this group has been activated during this
+ // iteration of the event loop.
+ uint64_t recentTicks_;
+
+ // The number of microseconds spent doing CPOW during this
+ // iteration of the event loop.
+ uint64_t recentCPOW_;
+
+ // The current iteration of the event loop. If necessary,
+ // may safely overflow.
+ uint64_t iteration_;
+
+ // `true` if new measures should be added to this group, `false`
+ // otherwise.
+ bool isActive_;
+
+ // `true` if this group has been used in the current iteration,
+ // `false` otherwise.
+ bool isUsedInThisIteration_;
+
+ // The stopwatch currently monitoring the group,
+ // or `nullptr` if none. Used ony for comparison.
+ const AutoStopwatch* owner_;
+
+ public:
+ // Compatibility with RefPtr<>
+ void AddRef();
+ void Release();
+ uint64_t refCount_;
+};
+
+using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 0, SystemAllocPolicy>;
+
+/**
+ * Commit any Performance Monitoring data.
+ *
+ * Until `FlushMonitoring` has been called, all PerformanceMonitoring data is invisible
+ * to the outside world and can cancelled with a call to `ResetMonitoring`.
+ */
+extern JS_PUBLIC_API(bool)
+FlushPerformanceMonitoring(JSContext*);
+
+/**
+ * Cancel any measurement that hasn't been committed.
+ */
+extern JS_PUBLIC_API(void)
+ResetPerformanceMonitoring(JSContext*);
+
+/**
+ * Cleanup any memory used by performance monitoring.
+ */
+extern JS_PUBLIC_API(void)
+DisposePerformanceMonitoring(JSContext*);
+
+/**
+ * Turn on/off stopwatch-based CPU monitoring.
+ *
+ * `SetStopwatchIsMonitoringCPOW` or `SetStopwatchIsMonitoringJank`
+ * may return `false` if monitoring could not be activated, which may
+ * happen if we are out of memory.
+ */
+extern JS_PUBLIC_API(bool)
+SetStopwatchIsMonitoringCPOW(JSContext*, bool);
+extern JS_PUBLIC_API(bool)
+GetStopwatchIsMonitoringCPOW(JSContext*);
+extern JS_PUBLIC_API(bool)
+SetStopwatchIsMonitoringJank(JSContext*, bool);
+extern JS_PUBLIC_API(bool)
+GetStopwatchIsMonitoringJank(JSContext*);
+
+// Extract the CPU rescheduling data.
+extern JS_PUBLIC_API(void)
+GetPerfMonitoringTestCpuRescheduling(JSContext*, uint64_t* stayed, uint64_t* moved);
+
+
+/**
+ * Add a number of microseconds to the time spent waiting on CPOWs
+ * since process start.
+ */
+extern JS_PUBLIC_API(void)
+AddCPOWPerformanceDelta(JSContext*, uint64_t delta);
+
+typedef bool
+(*StopwatchStartCallback)(uint64_t, void*);
+extern JS_PUBLIC_API(bool)
+SetStopwatchStartCallback(JSContext*, StopwatchStartCallback, void*);
+
+typedef bool
+(*StopwatchCommitCallback)(uint64_t, PerformanceGroupVector&, void*);
+extern JS_PUBLIC_API(bool)
+SetStopwatchCommitCallback(JSContext*, StopwatchCommitCallback, void*);
+
+typedef bool
+(*GetGroupsCallback)(JSContext*, PerformanceGroupVector&, void*);
+extern JS_PUBLIC_API(bool)
+SetGetPerformanceGroupsCallback(JSContext*, GetGroupsCallback, void*);
+
+} /* namespace js */
+
+
+#endif /* jsapi_h */