diff -r 000000000000 -r 6474c204b198 js/src/jsapi.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/js/src/jsapi.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,5044 @@ +/* -*- 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/FloatingPoint.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/RangedPtr.h" + +#include +#include +#include +#include + +#include "jsalloc.h" +#include "jspubtd.h" + +#include "js/CallArgs.h" +#include "js/Class.h" +#include "js/HashTable.h" +#include "js/Id.h" +#include "js/Principals.h" +#include "js/RootingAPI.h" +#include "js/TracingAPI.h" +#include "js/Utility.h" +#include "js/Value.h" +#include "js/Vector.h" + +/************************************************************************/ + +namespace JS { + +class Latin1CharsZ; +class TwoByteChars; + +#if defined JS_THREADSAFE && defined JS_DEBUG + +class JS_PUBLIC_API(AutoCheckRequestDepth) +{ + JSContext *cx; + public: + AutoCheckRequestDepth(JSContext *cx); + AutoCheckRequestDepth(js::ContextFriendFields *cx); + ~AutoCheckRequestDepth(); +}; + +# define CHECK_REQUEST(cx) \ + JS::AutoCheckRequestDepth _autoCheckRequestDepth(cx) + +#else + +# define CHECK_REQUEST(cx) \ + ((void) 0) + +#endif /* JS_THREADSAFE && JS_DEBUG */ + +#ifdef JS_DEBUG +/* + * Assert that we're not doing GC on cx, that we're in a request as + * needed, and that the compartments for cx and v are correct. + * Also check that GC would be safe at this point. + */ +JS_PUBLIC_API(void) +AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v); +#else +inline void AssertArgumentsAreSane(JSContext *cx, JS::HandleValue v) { + /* Do nothing */ +} +#endif /* JS_DEBUG */ + +class JS_PUBLIC_API(AutoGCRooter) { + public: + AutoGCRooter(JSContext *cx, ptrdiff_t tag); + AutoGCRooter(js::ContextFriendFields *cx, ptrdiff_t tag); + + ~AutoGCRooter() { + JS_ASSERT(this == *stackTop); + *stackTop = down; + } + + /* Implemented in gc/RootMarking.cpp. */ + inline void trace(JSTracer *trc); + static void traceAll(JSTracer *trc); + static void traceAllWrappers(JSTracer *trc); + + protected: + AutoGCRooter * const down; + + /* + * Discriminates actual subclass of this being used. If non-negative, the + * subclass roots an array of values of the length stored in this field. + * If negative, meaning is indicated by the corresponding value in the enum + * below. Any other negative value indicates some deeper problem such as + * memory corruption. + */ + ptrdiff_t tag_; + + enum { + VALARRAY = -2, /* js::AutoValueArray */ + PARSER = -3, /* js::frontend::Parser */ + SHAPEVECTOR = -4, /* js::AutoShapeVector */ + IDARRAY = -6, /* js::AutoIdArray */ + DESCRIPTORS = -7, /* js::AutoPropDescArrayRooter */ + ID = -9, /* js::AutoIdRooter */ + VALVECTOR = -10, /* js::AutoValueVector */ + IDVECTOR = -13, /* js::AutoIdVector */ + OBJVECTOR = -14, /* js::AutoObjectVector */ + STRINGVECTOR =-15, /* js::AutoStringVector */ + SCRIPTVECTOR =-16, /* js::AutoScriptVector */ + NAMEVECTOR = -17, /* js::AutoNameVector */ + HASHABLEVALUE=-18, /* js::HashableValue */ + IONMASM = -19, /* js::jit::MacroAssembler */ + IONALLOC = -20, /* js::jit::AutoTempAllocatorRooter */ + WRAPVECTOR = -21, /* js::AutoWrapperVector */ + WRAPPER = -22, /* js::AutoWrapperRooter */ + OBJOBJHASHMAP=-23, /* js::AutoObjectObjectHashMap */ + OBJU32HASHMAP=-24, /* js::AutoObjectUnsigned32HashMap */ + OBJHASHSET = -25, /* js::AutoObjectHashSet */ + JSONPARSER = -26, /* js::JSONParser */ + CUSTOM = -27, /* js::CustomAutoRooter */ + FUNVECTOR = -28 /* js::AutoFunctionVector */ + }; + + private: + AutoGCRooter ** const stackTop; + + /* No copy or assignment semantics. */ + AutoGCRooter(AutoGCRooter &ida) MOZ_DELETE; + void operator=(AutoGCRooter &ida) MOZ_DELETE; +}; + +/* AutoValueArray roots an internal fixed-size array of Values. */ +template +class AutoValueArray : public AutoGCRooter +{ + const size_t length_; + Value elements_[N]; + + public: + 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 { + JS_ASSERT(i < N); + return HandleValue::fromMarkedLocation(&elements_[i]); + } + MutableHandleValue operator[](unsigned i) { + JS_ASSERT(i < N); + return MutableHandleValue::fromMarkedLocation(&elements_[i]); + } + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +template +class AutoVectorRooter : protected AutoGCRooter +{ + typedef js::Vector VectorImpl; + VectorImpl vector; + + public: + explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoGCRooter(cx, tag), vector(cx) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + explicit AutoVectorRooter(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(); } + + bool append(const T &v) { return vector.append(v); } + bool append(const T *ptr, size_t len) { return vector.append(ptr, len); } + bool appendAll(const AutoVectorRooter &other) { + return vector.appendAll(other.vector); + } + + 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(); } + + bool growBy(size_t inc) { + size_t oldLength = vector.length(); + if (!vector.growByUninitialized(inc)) + return false; + makeRangeGCSafe(oldLength); + return true; + } + + 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(); } + + bool reserve(size_t newLength) { + return vector.reserve(newLength); + } + + T &operator[](size_t i) { return vector[i]; } + const T &operator[](size_t i) const { return vector[i]; } + + JS::MutableHandle handleAt(size_t i) { + return JS::MutableHandle::fromMarkedLocation(&vector[i]); + } + JS::Handle handleAt(size_t i) const { + return JS::Handle::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 +class AutoHashMapRooter : protected AutoGCRooter +{ + private: + typedef js::HashMap 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 + 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 + 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); + } + + unsigned generation() const { + return map.generation(); + } + + /************************************************** Shorthand operations */ + + bool has(const Lookup &l) const { + return map.has(l); + } + + template + bool put(const KeyInput &k, const ValueInput &v) { + return map.put(k, v); + } + + template + 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) MOZ_DELETE; + AutoHashMapRooter &operator=(const AutoHashMapRooter &hmr) MOZ_DELETE; + + HashMapImpl map; + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +template +class AutoHashSetRooter : protected AutoGCRooter +{ + private: + typedef js::HashSet 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); + } + + unsigned generation() const { + return set.generation(); + } + + /************************************************** 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) MOZ_DELETE; + AutoHashSetRooter &operator=(const AutoHashSetRooter &hmr) MOZ_DELETE; + + HashSetImpl set; + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +class MOZ_STACK_CLASS AutoValueVector : public AutoVectorRooter +{ + public: + explicit AutoValueVector(JSContext *cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooter(cx, VALVECTOR) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +class AutoIdVector : public AutoVectorRooter +{ + public: + explicit AutoIdVector(JSContext *cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooter(cx, IDVECTOR) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +class AutoObjectVector : public AutoVectorRooter +{ + public: + explicit AutoObjectVector(JSContext *cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooter(cx, OBJVECTOR) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +class AutoFunctionVector : public AutoVectorRooter +{ + public: + explicit AutoFunctionVector(JSContext *cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooter(cx, FUNVECTOR) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + explicit AutoFunctionVector(js::ContextFriendFields *cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooter(cx, FUNVECTOR) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +class AutoScriptVector : public AutoVectorRooter +{ + public: + explicit AutoScriptVector(JSContext *cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoVectorRooter(cx, SCRIPTVECTOR) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +/* + * Cutsom rooting behavior for internal and external clients. + */ +class JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter +{ + public: + template + explicit CustomAutoRooter(CX *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoGCRooter(cx, CUSTOM) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + friend void AutoGCRooter::trace(JSTracer *trc); + + protected: + /* 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: + HandleValueArray(const RootedValue& value) : length_(1), elements_(value.address()) {} + + HandleValueArray(const AutoValueVector& values) + : length_(values.length()), elements_(values.begin()) {} + + template + HandleValueArray(const AutoValueArray& values) : length_(N), elements_(values.begin()) {} + + /* CallArgs must already be rooted somewhere up the stack. */ + 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) { + JS_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 { + JS_ASSERT(i < length_); + return HandleValue::fromMarkedLocation(&elements_[i]); + } +}; + +} /* namespace JS */ + +/************************************************************************/ + +struct JSFreeOp { + private: + JSRuntime *runtime_; + + protected: + JSFreeOp(JSRuntime *rt) + : runtime_(rt) { } + + public: + JSRuntime *runtime() const { + return runtime_; + } +}; + +/* Callbacks and their arguments. */ + +/************************************************************************/ + +typedef enum JSContextOp { + JSCONTEXT_NEW, + JSCONTEXT_DESTROY +} JSContextOp; + +/* + * The possible values for contextOp when the runtime calls the callback are: + * JSCONTEXT_NEW JS_NewContext successfully created a new JSContext + * instance. The callback can initialize the instance as + * required. If the callback returns false, the instance + * will be destroyed and JS_NewContext returns null. In + * this case the callback is not called again. + * JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The + * callback may perform its own cleanup and must always + * return true. + * Any other value For future compatibility the callback must do nothing + * and return true in this case. + */ +typedef bool +(* JSContextCallback)(JSContext *cx, unsigned contextOp, void *data); + +typedef enum JSGCStatus { + JSGC_BEGIN, + JSGC_END +} JSGCStatus; + +typedef void +(* JSGCCallback)(JSRuntime *rt, JSGCStatus status, void *data); + +typedef enum JSFinalizeStatus { + /* + * Called when preparing to sweep a group of compartments, 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 compartments. 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 isCompartment); + +typedef bool +(* JSInterruptCallback)(JSContext *cx); + +typedef void +(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report); + +#ifdef MOZ_TRACE_JSCALLS +typedef void +(* JSFunctionCallback)(const JSFunction *fun, + const JSScript *scr, + const JSContext *cx, + int entering); +#endif + +/* + * Possible exception types. These types are part of a JSErrorFormatString + * structure. They define which error to throw in case of a runtime error. + * JSEXN_NONE marks an unthrowable error. + */ +typedef enum JSExnType { + JSEXN_NONE = -1, + JSEXN_ERR, + JSEXN_INTERNALERR, + JSEXN_EVALERR, + JSEXN_RANGEERR, + JSEXN_REFERENCEERR, + JSEXN_SYNTAXERR, + JSEXN_TYPEERR, + JSEXN_URIERR, + JSEXN_LIMIT +} JSExnType; + +typedef struct JSErrorFormatString { + /* 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 char *locale, + 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, + JS::HandleObject proto, JS::HandleObject parent, + unsigned flags); + +/* + * 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 JSObject * +(* JSPreWrapCallback)(JSContext *cx, JS::HandleObject scope, JS::HandleObject obj, + unsigned flags); + +struct JSWrapObjectCallbacks +{ + JSWrapObjectCallback wrap; + JSPreWrapCallback preWrap; +}; + +typedef void +(* JSDestroyCompartmentCallback)(JSFreeOp *fop, JSCompartment *compartment); + +typedef void +(* JSZoneCallback)(JS::Zone *zone); + +typedef void +(* JSCompartmentNameCallback)(JSRuntime *rt, JSCompartment *compartment, + char *buf, size_t bufsize); + +/************************************************************************/ + +static MOZ_ALWAYS_INLINE jsval +JS_NumberValue(double d) +{ + int32_t i; + d = JS::CanonicalizeNaN(d); + if (mozilla::NumberIsInt32(d, &i)) + return INT_TO_JSVAL(i); + return DOUBLE_TO_JSVAL(d); +} + +/************************************************************************/ + +JS_PUBLIC_API(bool) +JS_StringHasBeenInterned(JSContext *cx, JSString *str); + +/* + * Only JSStrings that have been interned via the JSAPI can be turned into + * jsids by API clients. + * + * N.B. if a jsid is backed by a string which has not been interned, that + * string must be appropriately rooted to avoid being collected by the GC. + */ +JS_PUBLIC_API(jsid) +INTERNED_STRING_TO_JSID(JSContext *cx, JSString *str); + +/* + * Returns true iff the given jsval is immune to GC and can be used across + * multiple JSRuntimes without requiring any conversion API. + */ +static MOZ_ALWAYS_INLINE bool +JSVAL_IS_UNIVERSAL(jsval v) +{ + return !JSVAL_IS_GCTHING(v); +} + +namespace JS { + +class AutoIdRooter : private AutoGCRooter +{ + public: + explicit AutoIdRooter(JSContext *cx, jsid aId = INT_TO_JSID(0) + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoGCRooter(cx, ID), id_(aId) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + jsid id() { + return id_; + } + + jsid * addr() { + return &id_; + } + + friend void AutoGCRooter::trace(JSTracer *trc); + + private: + jsid id_; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +// 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; +// jschar* chars = static_cast(js_malloc(sizeof(jschar) * length)); +// JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership); +// JS::Compile(cx, obj, options, srcBuf); +// +class MOZ_STACK_CLASS SourceBufferHolder MOZ_FINAL +{ + public: + enum Ownership { + NoOwnership, + GiveOwnership + }; + + SourceBufferHolder(const jschar *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 jschar NullChar_ = 0; + if (!get()) { + data_ = &NullChar_; + length_ = 0; + ownsChars_ = false; + } + } + + ~SourceBufferHolder() { + if (ownsChars_) + js_free(const_cast(data_)); + } + + // Access the underlying source buffer without affecting ownership. + const jschar *get() const { return data_; } + + // Length of the source buffer in jschars (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. + jschar *take() { + JS_ASSERT(ownsChars_); + ownsChars_ = false; + return const_cast(data_); + } + + private: + SourceBufferHolder(SourceBufferHolder &) MOZ_DELETE; + SourceBufferHolder &operator=(SourceBufferHolder &) MOZ_DELETE; + + const jschar *data_; + size_t length_; + bool ownsChars_; +}; + +} /* namespace JS */ + +/************************************************************************/ + +/* Property attributes, set in JSPropertySpec and passed to API functions. */ +#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_NATIVE_ACCESSORS 0x08 /* set in JSPropertyDescriptor.flags + if getters/setters are JSNatives */ +#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_INDEX 0x80 /* name is actually (int) index */ + +#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 */ + + +/* + * Specify a generic native prototype methods, i.e., methods of a class + * prototype that are exposed as static methods taking an extra leading + * argument: the generic |this| parameter. + * + * If you set this flag in a JSFunctionSpec struct's flags initializer, then + * that struct must live at least as long as the native static method object + * created due to this flag by JS_DefineFunctions or JS_InitClass. Typically + * JSFunctionSpec structs are allocated in static arrays. + */ +#define JSFUN_GENERIC_NATIVE 0x800 + +#define JSFUN_FLAGS_MASK 0xe00 /* | of all the JSFUN_* flags */ + +/* + * The first call to JS_CallOnce by any thread in a process will call 'func'. + * Later calls to JS_CallOnce with the same JSCallOnceType object will be + * suppressed. + * + * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce + * to invoke its JSInitCallback. + */ +extern JS_PUBLIC_API(bool) +JS_CallOnce(JSCallOnceType *once, JSInitCallback func); + +/* 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 jsvals. */ +extern JS_PUBLIC_API(jsval) +JS_GetNaNValue(JSContext *cx); + +extern JS_PUBLIC_API(jsval) +JS_GetNegativeInfinityValue(JSContext *cx); + +extern JS_PUBLIC_API(jsval) +JS_GetPositiveInfinityValue(JSContext *cx); + +extern JS_PUBLIC_API(jsval) +JS_GetEmptyStringValue(JSContext *cx); + +extern JS_PUBLIC_API(JSString *) +JS_GetEmptyString(JSRuntime *rt); + +/* + * Format is a string of the following characters (spaces are insignificant), + * specifying the tabulated type conversions: + * + * b bool Boolean + * c uint16_t/jschar ECMA uint16_t, Unicode char + * i int32_t ECMA int32_t + * j int32_t ECMA int32_t (used to be different) + * u uint32_t ECMA uint32_t + * d double IEEE double + * I double Integral IEEE double + * S JSString * Unicode string, accessed by a JSString pointer + * W jschar * Unicode character vector, 0-terminated (W for wide) + * o JSObject * Object reference + * f JSFunction * Function private + * v jsval Argument value (no conversion) + * * N/A Skip this argument (no vararg) + * / N/A End of required arguments + * + * The variable argument list after format must consist of &b, &c, &s, e.g., + * where those variables have the types given above. For the pointer types + * char *, JSString *, and JSObject *, the pointed-at memory returned belongs + * to the JS runtime, not to the calling native code. The runtime promises + * to keep this memory valid so long as argv refers to allocated stack space + * (so long as the native function is active). + * + * Fewer arguments than format specifies may be passed only if there is a / + * in format after the last required argument specifier and argc is at least + * the number of required arguments. More arguments than format specifies + * may be passed without error; it is up to the caller to deal with trailing + * unconverted arguments. + */ +extern JS_PUBLIC_API(bool) +JS_ConvertArguments(JSContext *cx, const JS::CallArgs &args, const char *format, ...); + +#ifdef va_start +extern JS_PUBLIC_API(bool) +JS_ConvertArgumentsVA(JSContext *cx, const JS::CallArgs &args, const char *format, + va_list ap); +#endif + +extern JS_PUBLIC_API(bool) +JS_ConvertValue(JSContext *cx, JS::HandleValue v, JSType type, JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_ValueToObject(JSContext *cx, JS::HandleValue v, JS::MutableHandleObject objp); + +extern JS_PUBLIC_API(JSFunction *) +JS_ValueToFunction(JSContext *cx, JS::HandleValue v); + +extern JS_PUBLIC_API(JSFunction *) +JS_ValueToConstructor(JSContext *cx, JS::HandleValue v); + +extern JS_PUBLIC_API(JSString *) +JS_ValueToSource(JSContext *cx, JS::Handle v); + +namespace js { +/* + * DO NOT CALL THIS. Use JS::ToNumber + */ +extern JS_PUBLIC_API(bool) +ToNumberSlow(JSContext *cx, JS::Value v, double *dp); + +/* + * DO NOT CALL THIS. Use JS::ToBoolean + */ +extern JS_PUBLIC_API(bool) +ToBooleanSlow(JS::HandleValue v); + +/* + * DO NOT CALL THIS. Use JS::ToString + */ +extern JS_PUBLIC_API(JSString*) +ToStringSlow(JSContext *cx, JS::HandleValue v); +} /* namespace js */ + +namespace JS { + +/* ES5 9.3 ToNumber. */ +MOZ_ALWAYS_INLINE bool +ToNumber(JSContext *cx, HandleValue v, double *out) +{ + AssertArgumentsAreSane(cx, v); + + if (v.isNumber()) { + *out = v.toNumber(); + return true; + } + return js::ToNumberSlow(cx, v, out); +} + +MOZ_ALWAYS_INLINE bool +ToBoolean(HandleValue v) +{ + if (v.isBoolean()) + return v.toBoolean(); + if (v.isInt32()) + return v.toInt32() != 0; + if (v.isNullOrUndefined()) + return false; + if (v.isDouble()) { + double d = v.toDouble(); + return !mozilla::IsNaN(d) && d != 0; + } + + /* The slow path handles strings and objects. */ + return js::ToBooleanSlow(v); +} + +MOZ_ALWAYS_INLINE JSString* +ToString(JSContext *cx, HandleValue v) +{ + if (v.isString()) + return v.toString(); + return js::ToStringSlow(cx, v); +} + +} /* namespace JS */ + +extern JS_PUBLIC_API(bool) +JS_DoubleIsInt32(double d, int32_t *ip); + +extern JS_PUBLIC_API(int32_t) +JS_DoubleToInt32(double d); + +extern JS_PUBLIC_API(uint32_t) +JS_DoubleToUint32(double d); + + +namespace js { +/* DO NOT CALL THIS. Use JS::ToUint16. */ +extern JS_PUBLIC_API(bool) +ToUint16Slow(JSContext *cx, JS::HandleValue v, uint16_t *out); + +/* DO NOT CALL THIS. Use JS::ToInt32. */ +extern JS_PUBLIC_API(bool) +ToInt32Slow(JSContext *cx, JS::HandleValue v, int32_t *out); + +/* DO NOT CALL THIS. Use JS::ToUint32. */ +extern JS_PUBLIC_API(bool) +ToUint32Slow(JSContext *cx, JS::HandleValue v, uint32_t *out); + +/* DO NOT CALL THIS. Use JS::ToInt64. */ +extern JS_PUBLIC_API(bool) +ToInt64Slow(JSContext *cx, JS::HandleValue v, int64_t *out); + +/* DO NOT CALL THIS. Use JS::ToUint64. */ +extern JS_PUBLIC_API(bool) +ToUint64Slow(JSContext *cx, JS::HandleValue v, uint64_t *out); +} /* namespace js */ + +namespace JS { + +MOZ_ALWAYS_INLINE bool +ToUint16(JSContext *cx, JS::HandleValue v, uint16_t *out) +{ + AssertArgumentsAreSane(cx, v); + + if (v.isInt32()) { + *out = uint16_t(v.toInt32()); + return true; + } + return js::ToUint16Slow(cx, v, out); +} + +MOZ_ALWAYS_INLINE bool +ToInt32(JSContext *cx, JS::HandleValue v, int32_t *out) +{ + AssertArgumentsAreSane(cx, v); + + if (v.isInt32()) { + *out = v.toInt32(); + return true; + } + return js::ToInt32Slow(cx, v, out); +} + +MOZ_ALWAYS_INLINE bool +ToUint32(JSContext *cx, JS::HandleValue v, uint32_t *out) +{ + AssertArgumentsAreSane(cx, v); + + if (v.isInt32()) { + *out = uint32_t(v.toInt32()); + return true; + } + return js::ToUint32Slow(cx, v, out); +} + +MOZ_ALWAYS_INLINE bool +ToInt64(JSContext *cx, JS::HandleValue v, int64_t *out) +{ + AssertArgumentsAreSane(cx, v); + + if (v.isInt32()) { + *out = int64_t(v.toInt32()); + return true; + } + return js::ToInt64Slow(cx, v, out); +} + +MOZ_ALWAYS_INLINE bool +ToUint64(JSContext *cx, JS::HandleValue v, uint64_t *out) +{ + AssertArgumentsAreSane(cx, v); + + if (v.isInt32()) { + /* Account for sign extension of negatives into the longer 64bit space. */ + *out = uint64_t(int64_t(v.toInt32())); + return true; + } + return js::ToUint64Slow(cx, v, out); +} + + +} /* namespace JS */ + +extern JS_PUBLIC_API(JSType) +JS_TypeOfValue(JSContext *cx, JS::Handle v); + +extern JS_PUBLIC_API(const char *) +JS_GetTypeName(JSContext *cx, JSType type); + +extern JS_PUBLIC_API(bool) +JS_StrictlyEqual(JSContext *cx, jsval v1, jsval v2, bool *equal); + +extern JS_PUBLIC_API(bool) +JS_LooselyEqual(JSContext *cx, JS::Handle v1, JS::Handle v2, bool *equal); + +extern JS_PUBLIC_API(bool) +JS_SameValue(JSContext *cx, jsval v1, jsval 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); + +/************************************************************************/ + +/* + * Initialization, locking, contexts, and memory allocation. + * + * It is important that the first runtime and 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 + */ + +typedef enum JSUseHelperThreads +{ + JS_NO_HELPER_THREADS, + JS_USE_HELPER_THREADS +} JSUseHelperThreads; + +/** + * Initialize SpiderMonkey, returning true only if initialization succeeded. + * Once this method has succeeded, it is safe to call JS_NewRuntime and other + * JSAPI methods. + * + * This method must be called before any other JSAPI method is used on any + * thread. Once it has been used, it is safe to call any JSAPI method, and it + * remains safe to do so until JS_ShutDown is correctly called. + * + * It is currently not possible to initialize SpiderMonkey multiple times (that + * is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so + * again). This restriction may eventually be lifted. + */ +extern JS_PUBLIC_API(bool) +JS_Init(void); + +/** + * Destroy free-standing resources allocated by SpiderMonkey, not associated + * with any runtime, context, or other structure. + * + * This method should be called after all other JSAPI data has been properly + * cleaned up: every new runtime must have been destroyed, every new context + * must have been destroyed, and so on. Calling this method before all other + * resources have been destroyed has undefined behavior. + * + * Failure to call this method, at present, has no adverse effects other than + * leaking memory. This may not always be the case; it's recommended that all + * embedders call this method when all other JSAPI operations have completed. + * + * It is currently not possible to initialize SpiderMonkey multiple times (that + * is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so + * again). This restriction may eventually be lifted. + */ +extern JS_PUBLIC_API(void) +JS_ShutDown(void); + +extern JS_PUBLIC_API(JSRuntime *) +JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads, + JSRuntime *parentRuntime = nullptr); + +extern JS_PUBLIC_API(void) +JS_DestroyRuntime(JSRuntime *rt); + +// These are equivalent to ICU's |UMemAllocFn|, |UMemReallocFn|, and +// |UMemFreeFn| types. The first argument (called |context| in the ICU docs) +// will always be nullptr, and should be ignored. +typedef void *(*JS_ICUAllocFn)(const void *, size_t size); +typedef void *(*JS_ICUReallocFn)(const void *, void *p, size_t size); +typedef void (*JS_ICUFreeFn)(const void *, void *p); + +// This function can be used to track memory used by ICU. +// Do not use it unless you know what you are doing! +extern JS_PUBLIC_API(bool) +JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn); + +JS_PUBLIC_API(void *) +JS_GetRuntimePrivate(JSRuntime *rt); + +extern JS_PUBLIC_API(JSRuntime *) +JS_GetRuntime(JSContext *cx); + +extern JS_PUBLIC_API(JSRuntime *) +JS_GetParentRuntime(JSContext *cx); + +JS_PUBLIC_API(void) +JS_SetRuntimePrivate(JSRuntime *rt, void *data); + +extern JS_PUBLIC_API(void) +JS_BeginRequest(JSContext *cx); + +extern JS_PUBLIC_API(void) +JS_EndRequest(JSContext *cx); + +extern JS_PUBLIC_API(bool) +JS_IsInRequest(JSRuntime *rt); + +namespace js { + +void +AssertHeapIsIdle(JSRuntime *rt); + +void +AssertHeapIsIdle(JSContext *cx); + +} /* namespace js */ + +class JSAutoRequest +{ + public: + 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 +}; + +class JSAutoCheckRequest +{ + public: + JSAutoCheckRequest(JSContext *cx + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + { +#if defined JS_THREADSAFE && defined JS_DEBUG + mContext = cx; + JS_ASSERT(JS_IsInRequest(JS_GetRuntime(cx))); +#endif + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + ~JSAutoCheckRequest() { +#if defined JS_THREADSAFE && defined JS_DEBUG + JS_ASSERT(JS_IsInRequest(JS_GetRuntime(mContext))); +#endif + } + + + private: +#if defined JS_THREADSAFE && defined JS_DEBUG + JSContext *mContext; +#endif + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER +}; + +extern JS_PUBLIC_API(void) +JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback, void *data); + +extern JS_PUBLIC_API(JSContext *) +JS_NewContext(JSRuntime *rt, size_t stackChunkSize); + +extern JS_PUBLIC_API(void) +JS_DestroyContext(JSContext *cx); + +extern JS_PUBLIC_API(void) +JS_DestroyContextNoGC(JSContext *cx); + +extern JS_PUBLIC_API(void *) +JS_GetContextPrivate(JSContext *cx); + +extern JS_PUBLIC_API(void) +JS_SetContextPrivate(JSContext *cx, void *data); + +extern JS_PUBLIC_API(void *) +JS_GetSecondContextPrivate(JSContext *cx); + +extern JS_PUBLIC_API(void) +JS_SetSecondContextPrivate(JSContext *cx, void *data); + +extern JS_PUBLIC_API(JSRuntime *) +JS_GetRuntime(JSContext *cx); + +extern JS_PUBLIC_API(JSContext *) +JS_ContextIterator(JSRuntime *rt, JSContext **iterp); + +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(RuntimeOptions) { + public: + RuntimeOptions() + : baseline_(false), + ion_(false), + asmJS_(false) + { + } + + bool baseline() const { return baseline_; } + RuntimeOptions &setBaseline(bool flag) { + baseline_ = flag; + return *this; + } + RuntimeOptions &toggleBaseline() { + baseline_ = !baseline_; + return *this; + } + + bool ion() const { return ion_; } + RuntimeOptions &setIon(bool flag) { + ion_ = flag; + return *this; + } + RuntimeOptions &toggleIon() { + ion_ = !ion_; + return *this; + } + + bool asmJS() const { return asmJS_; } + RuntimeOptions &setAsmJS(bool flag) { + asmJS_ = flag; + return *this; + } + RuntimeOptions &toggleAsmJS() { + asmJS_ = !asmJS_; + return *this; + } + + private: + bool baseline_ : 1; + bool ion_ : 1; + bool asmJS_ : 1; +}; + +JS_PUBLIC_API(RuntimeOptions &) +RuntimeOptionsRef(JSRuntime *rt); + +JS_PUBLIC_API(RuntimeOptions &) +RuntimeOptionsRef(JSContext *cx); + +class JS_PUBLIC_API(ContextOptions) { + public: + ContextOptions() + : extraWarnings_(false), + werror_(false), + varObjFix_(false), + privateIsNSISupports_(false), + dontReportUncaught_(false), + noDefaultCompartmentObject_(false), + noScriptRval_(false), + strictMode_(false), + cloneSingletons_(false) + { + } + + bool extraWarnings() const { return extraWarnings_; } + ContextOptions &setExtraWarnings(bool flag) { + extraWarnings_ = flag; + return *this; + } + ContextOptions &toggleExtraWarnings() { + extraWarnings_ = !extraWarnings_; + return *this; + } + + bool werror() const { return werror_; } + ContextOptions &setWerror(bool flag) { + werror_ = flag; + return *this; + } + ContextOptions &toggleWerror() { + werror_ = !werror_; + return *this; + } + + bool varObjFix() const { return varObjFix_; } + ContextOptions &setVarObjFix(bool flag) { + varObjFix_ = flag; + return *this; + } + ContextOptions &toggleVarObjFix() { + varObjFix_ = !varObjFix_; + return *this; + } + + bool privateIsNSISupports() const { return privateIsNSISupports_; } + ContextOptions &setPrivateIsNSISupports(bool flag) { + privateIsNSISupports_ = flag; + return *this; + } + ContextOptions &togglePrivateIsNSISupports() { + privateIsNSISupports_ = !privateIsNSISupports_; + return *this; + } + + bool dontReportUncaught() const { return dontReportUncaught_; } + ContextOptions &setDontReportUncaught(bool flag) { + dontReportUncaught_ = flag; + return *this; + } + ContextOptions &toggleDontReportUncaught() { + dontReportUncaught_ = !dontReportUncaught_; + return *this; + } + + bool noDefaultCompartmentObject() const { return noDefaultCompartmentObject_; } + ContextOptions &setNoDefaultCompartmentObject(bool flag) { + noDefaultCompartmentObject_ = flag; + return *this; + } + ContextOptions &toggleNoDefaultCompartmentObject() { + noDefaultCompartmentObject_ = !noDefaultCompartmentObject_; + return *this; + } + + bool noScriptRval() const { return noScriptRval_; } + ContextOptions &setNoScriptRval(bool flag) { + noScriptRval_ = flag; + return *this; + } + ContextOptions &toggleNoScriptRval() { + noScriptRval_ = !noScriptRval_; + return *this; + } + + bool strictMode() const { return strictMode_; } + ContextOptions &setStrictMode(bool flag) { + strictMode_ = flag; + return *this; + } + ContextOptions &toggleStrictMode() { + strictMode_ = !strictMode_; + return *this; + } + + bool cloneSingletons() const { return cloneSingletons_; } + ContextOptions &setCloneSingletons(bool flag) { + cloneSingletons_ = flag; + return *this; + } + ContextOptions &toggleCloneSingletons() { + cloneSingletons_ = !cloneSingletons_; + return *this; + } + + private: + bool extraWarnings_ : 1; + bool werror_ : 1; + bool varObjFix_ : 1; + bool privateIsNSISupports_ : 1; + bool dontReportUncaught_ : 1; + bool noDefaultCompartmentObject_ : 1; + bool noScriptRval_ : 1; + bool strictMode_ : 1; + bool cloneSingletons_ : 1; +}; + +JS_PUBLIC_API(ContextOptions &) +ContextOptionsRef(JSContext *cx); + +class JS_PUBLIC_API(AutoSaveContextOptions) { + public: + AutoSaveContextOptions(JSContext *cx) + : cx_(cx), + oldOptions_(ContextOptionsRef(cx_)) + { + } + + ~AutoSaveContextOptions() + { + ContextOptionsRef(cx_) = oldOptions_; + } + + private: + JSContext *cx_; + JS::ContextOptions oldOptions_; +}; + +} /* namespace JS */ + +extern JS_PUBLIC_API(const char *) +JS_GetImplementationVersion(void); + +extern JS_PUBLIC_API(void) +JS_SetDestroyCompartmentCallback(JSRuntime *rt, JSDestroyCompartmentCallback callback); + +extern JS_PUBLIC_API(void) +JS_SetDestroyZoneCallback(JSRuntime *rt, JSZoneCallback callback); + +extern JS_PUBLIC_API(void) +JS_SetSweepZoneCallback(JSRuntime *rt, JSZoneCallback callback); + +extern JS_PUBLIC_API(void) +JS_SetCompartmentNameCallback(JSRuntime *rt, JSCompartmentNameCallback callback); + +extern JS_PUBLIC_API(void) +JS_SetWrapObjectCallbacks(JSRuntime *rt, 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(bool) +JS_WrapId(JSContext *cx, JS::MutableHandleId idp); + +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 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 JS_PUBLIC_API(JSAutoCompartment) +{ + JSContext *cx_; + JSCompartment *oldCompartment_; + public: + JSAutoCompartment(JSContext *cx, JSObject *target); + JSAutoCompartment(JSContext *cx, JSScript *target); + ~JSAutoCompartment(); +}; + +class JS_PUBLIC_API(JSAutoNullCompartment) +{ + JSContext *cx_; + JSCompartment *oldCompartment_; + public: + JSAutoNullCompartment(JSContext *cx); + ~JSAutoNullCompartment(); +}; + +/* 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)(JSRuntime *rt, 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. + */ +extern JS_PUBLIC_API(void) +JS_IterateCompartments(JSRuntime *rt, 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 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_EnumerateStandardClasses(JSContext *cx, JS::HandleObject obj); + +extern JS_PUBLIC_API(bool) +JS_GetClassObject(JSContext *cx, JSProtoKey key, JS::MutableHandle objp); + +extern JS_PUBLIC_API(bool) +JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JS::MutableHandle objp); + +namespace JS { + +/* + * Determine if the given object is an instance or prototype 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); + +} /* 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); + +extern JS_PUBLIC_API(JSObject *) +JS_GetGlobalForObject(JSContext *cx, JSObject *obj); + +extern JS_PUBLIC_API(bool) +JS_IsGlobalObject(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); + +} + +/* + * Initialize the 'Reflect' object on a global object. + */ +extern JS_PUBLIC_API(JSObject *) +JS_InitReflect(JSContext *cx, JS::HandleObject global); + +#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 jschar *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, JSCTypesCallbacks *callbacks); +#endif + +typedef bool +(* JSEnumerateDiagnosticMemoryCallback)(void *ptr, size_t length); + +/* + * Enumerate memory regions that contain diagnostic information + * intended to be included in crash report minidumps. + */ +extern JS_PUBLIC_API(void) +JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback); + +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 nbytes); + +/* + * 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(JSFreeOp *) +JS_GetDefaultFreeOp(JSRuntime *rt); + +extern JS_PUBLIC_API(void) +JS_updateMallocCounter(JSContext *cx, size_t nbytes); + +extern JS_PUBLIC_API(char *) +JS_strdup(JSContext *cx, const char *s); + +/* Duplicate a string. Does not report an error on failure. */ +extern JS_PUBLIC_API(char *) +JS_strdup(JSRuntime *rt, const char *s); + +namespace JS { + +/* + * A GC root is a pointer to a jsval, JSObject * or JSString * that itself + * points into the GC heap. JS_AddValueRoot takes a pointer to a jsval and + * JS_AddGCThingRoot takes a pointer to a JSObject * or JString *. + * + * Note that, since JS_Add*Root stores the address of a variable (of type + * jsval, JSString *, or JSObject *), that variable must live until + * JS_Remove*Root is called to remove that variable. For example, after: + * + * void some_function() { + * jsval v; + * JS_AddNamedValueRoot(cx, &v, "name"); + * + * the caller must perform + * + * JS_RemoveValueRoot(cx, &v); + * + * before some_function() returns. + * + * Also, use JS_AddNamed*Root(cx, &structPtr->memberObj, "structPtr->memberObj") + * in preference to JS_Add*Root(cx, &structPtr->memberObj), in order to identify + * roots by their source callsites. This way, you can find the callsite while + * debugging if you should fail to do JS_Remove*Root(cx, &structPtr->memberObj) + * before freeing structPtr's memory. + */ +extern JS_PUBLIC_API(bool) +AddValueRoot(JSContext *cx, JS::Heap *vp); + +extern JS_PUBLIC_API(bool) +AddStringRoot(JSContext *cx, JS::Heap *rp); + +extern JS_PUBLIC_API(bool) +AddObjectRoot(JSContext *cx, JS::Heap *rp); + +extern JS_PUBLIC_API(bool) +AddNamedValueRoot(JSContext *cx, JS::Heap *vp, const char *name); + +extern JS_PUBLIC_API(bool) +AddNamedValueRootRT(JSRuntime *rt, JS::Heap *vp, const char *name); + +extern JS_PUBLIC_API(bool) +AddNamedStringRoot(JSContext *cx, JS::Heap *rp, const char *name); + +extern JS_PUBLIC_API(bool) +AddNamedObjectRoot(JSContext *cx, JS::Heap *rp, const char *name); + +extern JS_PUBLIC_API(bool) +AddNamedScriptRoot(JSContext *cx, JS::Heap *rp, const char *name); + +extern JS_PUBLIC_API(void) +RemoveValueRoot(JSContext *cx, JS::Heap *vp); + +extern JS_PUBLIC_API(void) +RemoveStringRoot(JSContext *cx, JS::Heap *rp); + +extern JS_PUBLIC_API(void) +RemoveObjectRoot(JSContext *cx, JS::Heap *rp); + +extern JS_PUBLIC_API(void) +RemoveScriptRoot(JSContext *cx, JS::Heap *rp); + +extern JS_PUBLIC_API(void) +RemoveValueRootRT(JSRuntime *rt, JS::Heap *vp); + +extern JS_PUBLIC_API(void) +RemoveStringRootRT(JSRuntime *rt, JS::Heap *rp); + +extern JS_PUBLIC_API(void) +RemoveObjectRootRT(JSRuntime *rt, JS::Heap *rp); + +extern JS_PUBLIC_API(void) +RemoveScriptRootRT(JSRuntime *rt, JS::Heap *rp); + +} /* namespace JS */ + +/* + * Register externally maintained GC roots. + * + * traceOp: the trace operation. For each root the implementation should call + * JS_CallTracer 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(JSRuntime *rt, JSTraceDataOp traceOp, void *data); + +/* Undo a call to JS_AddExtraGCRootsTracer. */ +extern JS_PUBLIC_API(void) +JS_RemoveExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data); + +#ifdef JS_DEBUG + +/* + * Debug-only method to dump the object graph of heap-allocated things. + * + * fp: file for the dump output. + * start: when non-null, dump only things reachable from start + * thing. Otherwise dump all things reachable from the + * runtime roots. + * startKind: trace kind of start if start is not null. Must be + * JSTRACE_OBJECT when start is null. + * thingToFind: dump only paths in the object graph leading to thingToFind + * when non-null. + * maxDepth: the upper bound on the number of edges to descend from the + * graph roots. + * thingToIgnore: thing to ignore during the graph traversal when non-null. + */ +extern JS_PUBLIC_API(bool) +JS_DumpHeap(JSRuntime *rt, FILE *fp, void* startThing, JSGCTraceKind kind, + void *thingToFind, size_t maxDepth, void *thingToIgnore); + +#endif + +/* + * Garbage collector API. + */ +extern JS_PUBLIC_API(void) +JS_GC(JSRuntime *rt); + +extern JS_PUBLIC_API(void) +JS_MaybeGC(JSContext *cx); + +extern JS_PUBLIC_API(void) +JS_SetGCCallback(JSRuntime *rt, JSGCCallback cb, void *data); + +extern JS_PUBLIC_API(void) +JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb); + +extern JS_PUBLIC_API(bool) +JS_IsGCMarkingTracer(JSTracer *trc); + +/* For assertions only. */ +#ifdef JS_DEBUG +extern JS_PUBLIC_API(bool) +JS_IsMarkingGray(JSTracer *trc); +#endif + +/* + * JS_IsAboutToBeFinalized checks if the given object is going to be finalized + * at the end of the current GC. When called outside of the context of a GC, + * this function will return false. Typically this function is used on weak + * references, where the reference should be nulled out or destroyed if the + * given object is about to be finalized. + * + * The argument to JS_IsAboutToBeFinalized is an in-out param: when the + * function returns false, the object being referenced is still alive, but the + * garbage collector might have moved it. In this case, the reference passed + * to JS_IsAboutToBeFinalized will be updated to the object's 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_IsAboutToBeFinalized(JS::Heap *objp); + +extern JS_PUBLIC_API(bool) +JS_IsAboutToBeFinalizedUnbarriered(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 when GC was invoked. */ + JSGC_NUMBER = 4, + + /* Max size of the code cache in bytes. */ + JSGC_MAX_CODE_CACHE_BYTES = 5, + + /* 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 decommit memory lazily. If more than this number of megabytes is + * available to be decommitted, then JS_MaybeGC will trigger a shrinking GC + * to decommit it. + */ + JSGC_DECOMMIT_THRESHOLD = 20 +} JSGCParamKey; + +extern JS_PUBLIC_API(void) +JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value); + +extern JS_PUBLIC_API(uint32_t) +JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key); + +extern JS_PUBLIC_API(void) +JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value); + +extern JS_PUBLIC_API(uint32_t) +JS_GetGCParameterForThread(JSContext *cx, JSGCParamKey key); + +extern JS_PUBLIC_API(void) +JS_SetGCParametersBasedOnAvailableMemory(JSRuntime *rt, 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 jschar *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 'closure' arg passed to JS_NewExternalStringWithClosure or + * nullptr if the external string was created via 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. + */ +extern JS_PUBLIC_API(void) +JS_SetNativeStackQuota(JSRuntime *cx, size_t systemCodeStackSize, + size_t trustedScriptStackSize = 0, + size_t untrustedScriptStackSize = 0); + +/************************************************************************/ + +extern JS_PUBLIC_API(int) +JS_IdArrayLength(JSContext *cx, JSIdArray *ida); + +extern JS_PUBLIC_API(jsid) +JS_IdArrayGet(JSContext *cx, JSIdArray *ida, int index); + +extern JS_PUBLIC_API(void) +JS_DestroyIdArray(JSContext *cx, JSIdArray *ida); + +namespace JS { + +class AutoIdArray : private AutoGCRooter +{ + public: + AutoIdArray(JSContext *cx, JSIdArray *ida + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : AutoGCRooter(cx, IDARRAY), context(cx), idArray(ida) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + ~AutoIdArray() { + if (idArray) + JS_DestroyIdArray(context, idArray); + } + bool operator!() { + return !idArray; + } + jsid operator[](size_t i) const { + JS_ASSERT(idArray); + return JS_IdArrayGet(context, idArray, i); + } + size_t length() const { + return JS_IdArrayLength(context, idArray); + } + + friend void AutoGCRooter::trace(JSTracer *trc); + + JSIdArray *steal() { + JSIdArray *copy = idArray; + idArray = nullptr; + return copy; + } + + protected: + inline void trace(JSTracer *trc); + + private: + JSContext *context; + JSIdArray *idArray; + MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER + + /* No copy or assignment semantics. */ + AutoIdArray(AutoIdArray &ida) MOZ_DELETE; + void operator=(AutoIdArray &ida) MOZ_DELETE; +}; + +} /* namespace JS */ + +extern JS_PUBLIC_API(bool) +JS_ValueToId(JSContext *cx, JS::HandleValue v, JS::MutableHandleId idp); + +extern JS_PUBLIC_API(bool) +JS_StringToId(JSContext *cx, JS::HandleString s, JS::MutableHandleId idp); + +extern JS_PUBLIC_API(bool) +JS_IdToValue(JSContext *cx, jsid id, JS::MutableHandle vp); + +/* + * Invoke the [[DefaultValue]] hook (see ES5 8.6.2) with the provided hint on + * the specified object, computing a primitive default value for the object. + * The hint must be JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID (no hint). On + * success the resulting value is stored in *vp. + */ +extern JS_PUBLIC_API(bool) +JS_DefaultValue(JSContext *cx, JS::Handle obj, JSType hint, + JS::MutableHandle vp); + +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, bool strict, + JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_DeletePropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id, + bool *succeeded); + +extern JS_PUBLIC_API(bool) +JS_EnumerateStub(JSContext *cx, JS::HandleObject obj); + +extern JS_PUBLIC_API(bool) +JS_ResolveStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id); + +extern JS_PUBLIC_API(bool) +JS_ConvertStub(JSContext *cx, JS::HandleObject obj, JSType type, + JS::MutableHandleValue vp); + +struct JSConstDoubleSpec { + double dval; + const char *name; + uint8_t flags; + uint8_t spare[3]; +}; + +struct JSJitInfo; + +/* + * Wrappers to replace {Strict,}PropertyOp for JSPropertySpecs. This will allow + * us to pass one JSJitInfo per function with the property spec, without + * additional field overhead. + */ +typedef struct JSStrictPropertyOpWrapper { + JSStrictPropertyOp op; + const JSJitInfo *info; +} JSStrictPropertyOpWrapper; + +typedef struct JSPropertyOpWrapper { + JSPropertyOp op; + const JSJitInfo *info; +} JSPropertyOpWrapper; + +/* + * Wrapper to do as above, but for JSNatives for JSFunctionSpecs. + */ +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 JSOP_WRAPPER(op) { {op, nullptr} } +#define JSOP_NULLWRAPPER JSOP_WRAPPER(nullptr) + +/* + * To define an array element rather than a named property member, cast the + * element's index to (const char *) and initialize name with it, and set the + * JSPROP_INDEX bit in flags. + */ +struct JSPropertySpec { + struct SelfHostedWrapper { + void *unused; + const char *funname; + }; + + const char *name; + uint8_t flags; + union { + JSPropertyOpWrapper propertyOp; + SelfHostedWrapper selfHosted; + } getter; + union { + JSStrictPropertyOpWrapper propertyOp; + SelfHostedWrapper selfHosted; + } setter; + +private: + void StaticAsserts() { + JS_STATIC_ASSERT(sizeof(SelfHostedWrapper) == sizeof(JSPropertyOpWrapper)); + JS_STATIC_ASSERT(sizeof(SelfHostedWrapper) == sizeof(JSStrictPropertyOpWrapper)); + JS_STATIC_ASSERT(offsetof(SelfHostedWrapper, funname) == + offsetof(JSPropertyOpWrapper, info)); + } +}; + +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 +inline int +CheckIsCharacterLiteral(const char (&arr)[N]); + +} // namespace detail +} // namespace JS + +#define JS_CAST_NATIVE_TO(v, To) \ + (static_cast(sizeof(JS::detail::CheckIsNative(v))), \ + reinterpret_cast(v)) + +#define JS_CAST_STRING_TO(s, To) \ + (static_cast(sizeof(JS::detail::CheckIsCharacterLiteral(s))), \ + reinterpret_cast(s)) + +#define JS_CHECK_ACCESSOR_FLAGS(flags) \ + (static_cast::Type>(0), \ + (flags)) + +/* + * JSPropertySpec uses JSAPI JSPropertyOp and JSStrictPropertyOp in function + * signatures. These macros encapsulate the definition of JSNative-backed + * JSPropertySpecs, performing type-safe casts on the getter/setter functions + * and adding the necessary property flags to trigger interpretation as + * JSNatives. + */ +#define JS_PSG(name, getter, flags) \ + {name, \ + uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS), \ + JSOP_WRAPPER(JS_CAST_NATIVE_TO(getter, JSPropertyOp)), \ + JSOP_NULLWRAPPER} +#define JS_PSGS(name, getter, setter, flags) \ + {name, \ + uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS), \ + JSOP_WRAPPER(JS_CAST_NATIVE_TO(getter, JSPropertyOp)), \ + JSOP_WRAPPER(JS_CAST_NATIVE_TO(setter, JSStrictPropertyOp))} +#define JS_SELF_HOSTED_GET(name, getterName, flags) \ + {name, \ + uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \ + { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo *) }, \ + JSOP_NULLWRAPPER } +#define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \ + {name, \ + uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER), \ + { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo *) }, \ + { nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo *) } } +#define JS_PS_END { nullptr, 0, JSOP_NULLWRAPPER, JSOP_NULLWRAPPER } + +/* + * 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. Finally + * JS_FNSPEC has slots for all the fields. + */ +#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_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_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 ctor, + JS::Handle proto); + +extern JS_PUBLIC_API(const JSClass *) +JS_GetClass(JSObject *obj); + +extern JS_PUBLIC_API(bool) +JS_InstanceOf(JSContext *cx, JS::Handle obj, const JSClass *clasp, JS::CallArgs *args); + +extern JS_PUBLIC_API(bool) +JS_HasInstance(JSContext *cx, JS::Handle obj, JS::Handle v, bool *bp); + +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 obj, const JSClass *clasp, + JS::CallArgs *args); + +extern JS_PUBLIC_API(bool) +JS_GetPrototype(JSContext *cx, JS::HandleObject obj, JS::MutableHandleObject protop); + +extern JS_PUBLIC_API(bool) +JS_SetPrototype(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto); + +extern JS_PUBLIC_API(JSObject *) +JS_GetParent(JSObject *obj); + +extern JS_PUBLIC_API(bool) +JS_SetParent(JSContext *cx, JS::HandleObject obj, JS::HandleObject parent); + +extern JS_PUBLIC_API(JSObject *) +JS_GetConstructor(JSContext *cx, JS::Handle proto); + +namespace JS { + +enum ZoneSpecifier { + FreshZone = 0, + SystemZone = 1 +}; + +class JS_PUBLIC_API(CompartmentOptions) +{ + 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_; + }; + + explicit CompartmentOptions() + : version_(JSVERSION_UNKNOWN) + , invisibleToDebugger_(false) + , mergeable_(false) + , discardSource_(false) + , traceGlobal_(nullptr) + , singletonsAsTemplates_(true) + { + zone_.spec = JS::FreshZone; + } + + JSVersion version() const { return version_; } + CompartmentOptions &setVersion(JSVersion aVersion) { + MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN); + version_ = aVersion; + return *this; + } + + // 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_; } + CompartmentOptions &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_; } + CompartmentOptions &setMergeable(bool flag) { + mergeable_ = flag; + 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_; } + CompartmentOptions &setDiscardSource(bool flag) { + discardSource_ = flag; + return *this; + } + + + bool cloneSingletons(JSContext *cx) const; + Override &cloneSingletonsOverride() { return cloneSingletonsOverride_; } + + void *zonePointer() const { + JS_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone)); + return zone_.pointer; + } + ZoneSpecifier zoneSpecifier() const { return zone_.spec; } + CompartmentOptions &setZone(ZoneSpecifier spec); + CompartmentOptions &setSameZoneAs(JSObject *obj); + + void setSingletonsAsValues() { + singletonsAsTemplates_ = false; + } + bool getSingletonsAsTemplates() const { + return singletonsAsTemplates_; + }; + + CompartmentOptions &setTrace(JSTraceOp op) { + traceGlobal_ = op; + return *this; + } + JSTraceOp getTrace() const { + return traceGlobal_; + } + + private: + JSVersion version_; + bool invisibleToDebugger_; + bool mergeable_; + bool discardSource_; + Override cloneSingletonsOverride_; + union { + ZoneSpecifier spec; + void *pointer; // js::Zone* is not exposed in the API. + } zone_; + JSTraceOp traceGlobal_; + + // 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_; +}; + +JS_PUBLIC_API(CompartmentOptions &) +CompartmentOptionsRef(JSCompartment *compartment); + +JS_PUBLIC_API(CompartmentOptions &) +CompartmentOptionsRef(JSObject *obj); + +JS_PUBLIC_API(CompartmentOptions &) +CompartmentOptionsRef(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 = JS::CompartmentOptions()); +/* + * 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, JS::Handle proto, + JS::Handle parent); + +/* Queries the [[Extensible]] property of the object. */ +extern JS_PUBLIC_API(bool) +JS_IsExtensible(JSContext *cx, JS::HandleObject obj, bool *extensible); + +extern JS_PUBLIC_API(bool) +JS_IsNative(JSObject *obj); + +extern JS_PUBLIC_API(JSRuntime *) +JS_GetObjectRuntime(JSObject *obj); + +/* + * Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default + * proto if proto's actual parameter value is null. + */ +extern JS_PUBLIC_API(JSObject *) +JS_NewObjectWithGivenProto(JSContext *cx, const JSClass *clasp, JS::Handle proto, + JS::Handle parent); + +/* + * Freeze obj, and all objects it refers to, recursively. This will not recurse + * through non-extensible objects, on the assumption that those are already + * deep-frozen. + */ +extern JS_PUBLIC_API(bool) +JS_DeepFreezeObject(JSContext *cx, JS::Handle obj); + +/* + * Freezes an object; see ES5's Object.freeze(obj) method. + */ +extern JS_PUBLIC_API(bool) +JS_FreezeObject(JSContext *cx, JS::Handle obj); + +extern JS_PUBLIC_API(bool) +JS_PreventExtensions(JSContext *cx, JS::HandleObject obj); + +extern JS_PUBLIC_API(JSObject *) +JS_New(JSContext *cx, JS::HandleObject ctor, const JS::HandleValueArray& args); + +extern JS_PUBLIC_API(JSObject *) +JS_DefineObject(JSContext *cx, JSObject *obj, const char *name, const JSClass *clasp, + JSObject *proto, unsigned attrs); + +extern JS_PUBLIC_API(bool) +JS_DefineConstDoubles(JSContext *cx, JS::HandleObject obj, const JSConstDoubleSpec *cds); + +extern JS_PUBLIC_API(bool) +JS_DefineProperties(JSContext *cx, JS::HandleObject obj, const JSPropertySpec *ps); + +extern JS_PUBLIC_API(bool) +JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleValue value, + unsigned attrs, + JSPropertyOp getter = nullptr, JSStrictPropertyOp setter = nullptr); + +extern JS_PUBLIC_API(bool) +JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleObject value, + unsigned attrs, + JSPropertyOp getter = nullptr, JSStrictPropertyOp setter = nullptr); + +extern JS_PUBLIC_API(bool) +JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleString value, + unsigned attrs, + JSPropertyOp getter = nullptr, JSStrictPropertyOp setter = nullptr); + +extern JS_PUBLIC_API(bool) +JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, int32_t value, + unsigned attrs, + JSPropertyOp getter = nullptr, JSStrictPropertyOp setter = nullptr); + +extern JS_PUBLIC_API(bool) +JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, uint32_t value, + unsigned attrs, + JSPropertyOp getter = nullptr, JSStrictPropertyOp setter = nullptr); + +extern JS_PUBLIC_API(bool) +JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, double value, + unsigned attrs, + JSPropertyOp getter = nullptr, JSStrictPropertyOp setter = nullptr); + +extern JS_PUBLIC_API(bool) +JS_DefinePropertyById(JSContext *cx, JSObject *obj, jsid id, jsval value, + JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); + +extern JS_PUBLIC_API(bool) +JS_DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, + JS::HandleValue descriptor, bool *bp); + +extern JS_PUBLIC_API(bool) +JS_AlreadyHasOwnProperty(JSContext *cx, JS::HandleObject obj, const char *name, + bool *foundp); + +extern JS_PUBLIC_API(bool) +JS_AlreadyHasOwnPropertyById(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_HasPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp); + +extern JS_PUBLIC_API(bool) +JS_LookupProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_LookupPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, + JS::MutableHandleValue vp); + +struct JSPropertyDescriptor { + JSObject *obj; + unsigned attrs; + JSPropertyOp getter; + JSStrictPropertyOp setter; + JS::Value value; + + JSPropertyDescriptor() + : obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JSVAL_VOID) + {} + + void trace(JSTracer *trc); +}; + +namespace JS { + +template +class PropertyDescriptorOperations +{ + const JSPropertyDescriptor * desc() const { return static_cast(this)->extract(); } + + public: + bool isEnumerable() const { return desc()->attrs & JSPROP_ENUMERATE; } + bool isReadonly() const { return desc()->attrs & JSPROP_READONLY; } + bool isPermanent() const { return desc()->attrs & JSPROP_PERMANENT; } + bool hasNativeAccessors() const { return desc()->attrs & JSPROP_NATIVE_ACCESSORS; } + bool hasGetterObject() const { return desc()->attrs & JSPROP_GETTER; } + bool hasSetterObject() const { return desc()->attrs & JSPROP_SETTER; } + bool hasGetterOrSetterObject() const { return desc()->attrs & (JSPROP_GETTER | JSPROP_SETTER); } + bool isShared() const { return desc()->attrs & JSPROP_SHARED; } + bool isIndex() const { return desc()->attrs & JSPROP_INDEX; } + bool hasAttributes(unsigned attrs) const { return desc()->attrs & attrs; } + + JS::HandleObject object() const { + return JS::HandleObject::fromMarkedLocation(&desc()->obj); + } + unsigned attributes() const { return desc()->attrs; } + JSPropertyOp getter() const { return desc()->getter; } + JSStrictPropertyOp setter() const { return desc()->setter; } + JS::HandleObject getterObject() const { + MOZ_ASSERT(hasGetterObject()); + return JS::HandleObject::fromMarkedLocation( + reinterpret_cast(&desc()->getter)); + } + JS::HandleObject setterObject() const { + MOZ_ASSERT(hasSetterObject()); + return JS::HandleObject::fromMarkedLocation( + reinterpret_cast(&desc()->setter)); + } + JS::HandleValue value() const { + return JS::HandleValue::fromMarkedLocation(&desc()->value); + } +}; + +template +class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations +{ + JSPropertyDescriptor * desc() { return static_cast(this)->extractMutable(); } + + public: + + void clear() { + object().set(nullptr); + setAttributes(0); + setGetter(nullptr); + setSetter(nullptr); + value().setUndefined(); + } + + JS::MutableHandleObject object() { + return JS::MutableHandleObject::fromMarkedLocation(&desc()->obj); + } + unsigned &attributesRef() { return desc()->attrs; } + JSPropertyOp &getter() { return desc()->getter; } + JSStrictPropertyOp &setter() { return desc()->setter; } + JS::MutableHandleValue value() { + return JS::MutableHandleValue::fromMarkedLocation(&desc()->value); + } + + void setEnumerable() { desc()->attrs |= JSPROP_ENUMERATE; } + void setAttributes(unsigned attrs) { desc()->attrs = attrs; } + + void setGetter(JSPropertyOp op) { desc()->getter = op; } + void setSetter(JSStrictPropertyOp op) { desc()->setter = op; } + void setGetterObject(JSObject *obj) { desc()->getter = reinterpret_cast(obj); } + void setSetterObject(JSObject *obj) { desc()->setter = reinterpret_cast(obj); } +}; + +} /* namespace JS */ + +namespace js { + +template <> +struct GCMethods { + static JSPropertyDescriptor initial() { return JSPropertyDescriptor(); } + static ThingRootKind kind() { return THING_ROOT_PROPERTY_DESCRIPTOR; } + static bool poisoned(const JSPropertyDescriptor &desc) { + return (desc.obj && JS::IsPoisonedPtr(desc.obj)) || + (desc.attrs & JSPROP_GETTER && desc.getter && JS::IsPoisonedPtr(desc.getter)) || + (desc.attrs & JSPROP_SETTER && desc.setter && JS::IsPoisonedPtr(desc.setter)) || + (desc.value.isGCThing() && JS::IsPoisonedPtr(desc.value.toGCThing())); + } +}; + +template <> +class RootedBase + : public JS::MutablePropertyDescriptorOperations > +{ + friend class JS::PropertyDescriptorOperations >; + friend class JS::MutablePropertyDescriptorOperations >; + const JSPropertyDescriptor *extract() const { + return static_cast*>(this)->address(); + } + JSPropertyDescriptor *extractMutable() { + return static_cast*>(this)->address(); + } +}; + +template <> +class HandleBase + : public JS::PropertyDescriptorOperations > +{ + friend class JS::PropertyDescriptorOperations >; + const JSPropertyDescriptor *extract() const { + return static_cast*>(this)->address(); + } +}; + +template <> +class MutableHandleBase + : public JS::MutablePropertyDescriptorOperations > +{ + friend class JS::PropertyDescriptorOperations >; + friend class JS::MutablePropertyDescriptorOperations >; + const JSPropertyDescriptor *extract() const { + return static_cast*>(this)->address(); + } + JSPropertyDescriptor *extractMutable() { + return static_cast*>(this)->address(); + } +}; + +} /* namespace js */ + +extern JS_PUBLIC_API(bool) +JS_GetOwnPropertyDescriptorById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, + JS::MutableHandle desc); + +extern JS_PUBLIC_API(bool) +JS_GetOwnPropertyDescriptor(JSContext *cx, JS::HandleObject obj, const char *name, + JS::MutableHandle desc); + +/* + * Like JS_GetOwnPropertyDescriptorById but will return a property on + * an object on the prototype chain (returned in desc->obj). If desc->obj is null, + * then this property was not found on the prototype chain. + */ +extern JS_PUBLIC_API(bool) +JS_GetPropertyDescriptorById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, + JS::MutableHandle desc); + +extern JS_PUBLIC_API(bool) +JS_GetPropertyDescriptor(JSContext *cx, JS::HandleObject obj, const char *name, + JS::MutableHandle desc); + +extern JS_PUBLIC_API(bool) +JS_GetProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_GetPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_ForwardGetPropertyTo(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject onBehalfOf, + JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_SetProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleValue v); + +extern JS_PUBLIC_API(bool) +JS_SetPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v); + +extern JS_PUBLIC_API(bool) +JS_DeleteProperty(JSContext *cx, JS::HandleObject obj, const char *name); + +extern JS_PUBLIC_API(bool) +JS_DeleteProperty2(JSContext *cx, JS::HandleObject obj, const char *name, bool *succeeded); + +extern JS_PUBLIC_API(bool) +JS_DeletePropertyById(JSContext *cx, JS::HandleObject obj, jsid id); + +extern JS_PUBLIC_API(bool) +JS_DeletePropertyById2(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *succeeded); + +extern JS_PUBLIC_API(bool) +JS_DefineUCProperty(JSContext *cx, JSObject *obj, + const jschar *name, size_t namelen, jsval value, + JSPropertyOp getter, JSStrictPropertyOp setter, + unsigned attrs); + +extern JS_PUBLIC_API(bool) +JS_AlreadyHasOwnUCProperty(JSContext *cx, JS::HandleObject obj, const jschar *name, + size_t namelen, bool *foundp); + +extern JS_PUBLIC_API(bool) +JS_HasUCProperty(JSContext *cx, JS::HandleObject obj, + const jschar *name, size_t namelen, + bool *vp); + +extern JS_PUBLIC_API(bool) +JS_LookupUCProperty(JSContext *cx, JS::HandleObject obj, + const jschar *name, size_t namelen, + JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_GetUCProperty(JSContext *cx, JS::HandleObject obj, + const jschar *name, size_t namelen, + JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_SetUCProperty(JSContext *cx, JS::HandleObject obj, + const jschar *name, size_t namelen, + JS::HandleValue v); + +extern JS_PUBLIC_API(bool) +JS_DeleteUCProperty2(JSContext *cx, JS::HandleObject obj, const jschar *name, size_t namelen, + bool *succeeded); + +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); + +extern JS_PUBLIC_API(bool) +JS_IsArrayObject(JSContext *cx, JS::HandleValue value); + +extern JS_PUBLIC_API(bool) +JS_IsArrayObject(JSContext *cx, JS::HandleObject obj); + +extern JS_PUBLIC_API(bool) +JS_GetArrayLength(JSContext *cx, JS::Handle obj, uint32_t *lengthp); + +extern JS_PUBLIC_API(bool) +JS_SetArrayLength(JSContext *cx, JS::Handle obj, uint32_t length); + +extern JS_PUBLIC_API(bool) +JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value, + JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); + +extern JS_PUBLIC_API(bool) +JS_AlreadyHasOwnElement(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *foundp); + +extern JS_PUBLIC_API(bool) +JS_HasElement(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *foundp); + +extern JS_PUBLIC_API(bool) +JS_LookupElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_GetElement(JSContext *cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp); + +extern JS_PUBLIC_API(bool) +JS_ForwardGetElementTo(JSContext *cx, JS::HandleObject obj, uint32_t index, + JS::HandleObject onBehalfOf, JS::MutableHandleValue vp); + +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); + +extern JS_PUBLIC_API(bool) +JS_DeleteElement(JSContext *cx, JS::HandleObject obj, uint32_t index); + +extern JS_PUBLIC_API(bool) +JS_DeleteElement2(JSContext *cx, JS::HandleObject obj, uint32_t index, bool *succeeded); + +/* + * Remove all configurable properties from the given (non-global) object and + * assign undefined to all writable data properties. + */ +JS_PUBLIC_API(void) +JS_ClearNonGlobalObject(JSContext *cx, JS::HandleObject obj); + +/* + * 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. 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); + +/* + * 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); + +/* + * Allocate memory that may be eventually passed to + * JS_NewArrayBufferWithContents. |maybecx| is optional; if a non-nullptr cx is + * given, it will be used for memory accounting and OOM reporting. |nbytes| is + * the number of payload bytes required. + */ +extern JS_PUBLIC_API(void *) +JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes); + +/* + * Reallocate memory allocated by JS_AllocateArrayBufferContents, growing or + * shrinking it as appropriate. If oldContents is null then this behaves like + * JS_AllocateArrayBufferContents. + */ +extern JS_PUBLIC_API(void *) +JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void *oldContents, uint32_t oldNbytes); + +/* + * Create a new mapped array buffer with the given memory mapped contents. On success, + * the 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_NeuterArrayBuffer() 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(JSIdArray *) +JS_Enumerate(JSContext *cx, JS::HandleObject obj); + +/* + * Create an object to iterate over enumerable properties of obj, in arbitrary + * property definition order. NB: This differs from longstanding for..in loop + * order, which uses order of property definition in obj. + */ +extern JS_PUBLIC_API(JSObject *) +JS_NewPropertyIterator(JSContext *cx, JS::Handle obj); + +/* + * Return true on success with *idp containing the id of the next enumerable + * property to visit using iterobj, or JSID_IS_VOID if there is no such property + * left to visit. Return false on error. + */ +extern JS_PUBLIC_API(bool) +JS_NextProperty(JSContext *cx, JS::Handle iterobj, jsid *idp); + +extern JS_PUBLIC_API(jsval) +JS_GetReservedSlot(JSObject *obj, uint32_t index); + +extern JS_PUBLIC_API(void) +JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v); + +/************************************************************************/ + +/* + * Functions and scripts. + */ +extern JS_PUBLIC_API(JSFunction *) +JS_NewFunction(JSContext *cx, JSNative call, unsigned nargs, unsigned flags, + JS::Handle parent, const char *name); + +/* + * Create the function with the name given by the id. JSID_IS_STRING(id) must + * be true. + */ +extern JS_PUBLIC_API(JSFunction *) +JS_NewFunctionById(JSContext *cx, JSNative call, unsigned nargs, unsigned flags, + JS::Handle parent, JS::Handle id); + +namespace JS { + +extern JS_PUBLIC_API(JSFunction *) +GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, JS::Handle id, + unsigned nargs); + +} /* 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_ObjectIsCallable(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); + +/* + * Bind the given callable to use the given object as "this". + * + * If |callable| is not callable, will throw and return nullptr. + */ +extern JS_PUBLIC_API(JSObject*) +JS_BindCallable(JSContext *cx, JS::Handle callable, JS::Handle newThis); + +extern JS_PUBLIC_API(bool) +JS_DefineFunctions(JSContext *cx, JS::Handle obj, const JSFunctionSpec *fs); + +extern JS_PUBLIC_API(JSFunction *) +JS_DefineFunction(JSContext *cx, JS::Handle obj, const char *name, JSNative call, + unsigned nargs, unsigned attrs); + +extern JS_PUBLIC_API(JSFunction *) +JS_DefineUCFunction(JSContext *cx, JS::Handle obj, + const jschar *name, size_t namelen, JSNative call, + unsigned nargs, unsigned attrs); + +extern JS_PUBLIC_API(JSFunction *) +JS_DefineFunctionById(JSContext *cx, JS::Handle obj, JS::Handle id, JSNative call, + unsigned nargs, unsigned attrs); + +/* + * Clone a top-level function into a new scope. This function will dynamically + * fail if funobj was lexically nested inside some other function. + */ +extern JS_PUBLIC_API(JSObject *) +JS_CloneFunctionObject(JSContext *cx, JS::Handle funobj, JS::Handle parent); + +/* + * 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 obj, const char *utf8, + size_t length); + +extern JS_PUBLIC_API(JSScript *) +JS_CompileScript(JSContext *cx, JS::HandleObject obj, + const char *ascii, size_t length, + const JS::CompileOptions &options); + +extern JS_PUBLIC_API(JSScript *) +JS_CompileUCScript(JSContext *cx, JS::HandleObject obj, + const jschar *chars, size_t length, + const JS::CompileOptions &options); + +extern JS_PUBLIC_API(JSObject *) +JS_GetGlobalFromScript(JSScript *script); + +extern JS_PUBLIC_API(JSFunction *) +JS_CompileFunction(JSContext *cx, JS::HandleObject obj, const char *name, + unsigned nargs, const char *const *argnames, + const char *bytes, size_t length, + const JS::CompileOptions &options); + +extern JS_PUBLIC_API(JSFunction *) +JS_CompileUCFunction(JSContext *cx, JS::HandleObject obj, const char *name, + unsigned nargs, const char *const *argnames, + const jschar *chars, size_t length, + const JS::CompileOptions &options); + +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. + * + * So, we have a class hierarchy that reflects these three use cases: + * + * - ReadOnlyCompileOptions is the common base class. It can be used by code + * that simply needs to access options set elsewhere, like the compiler. + * + * - 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. + */ + +/* + * The common base class for the CompileOptions hierarchy. + * + * 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) +{ + friend class CompileOptions; + + protected: + JSPrincipals *originPrincipals_; + const char *filename_; + const char *introducerFilename_; + const jschar *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. + ReadOnlyCompileOptions() + : originPrincipals_(nullptr), + filename_(nullptr), + introducerFilename_(nullptr), + sourceMapURL_(nullptr), + version(JSVERSION_UNKNOWN), + versionSet(false), + utf8(false), + lineno(1), + column(0), + compileAndGo(false), + forEval(false), + defineOnScope(true), + noScriptRval(false), + selfHostingMode(false), + canLazilyParse(true), + strictOption(false), + extraWarningsOption(false), + werrorOption(false), + asmJSOption(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 copyPODOptions(const ReadOnlyCompileOptions &rhs); + + public: + // Read-only accessors for non-POD options. The proper way to set these + // depends on the derived type. + JSPrincipals *originPrincipals(js::ExclusiveContext *cx) const; + const char *filename() const { return filename_; } + const char *introducerFilename() const { return introducerFilename_; } + const jschar *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; + unsigned lineno; + unsigned column; + bool compileAndGo; + bool forEval; + bool defineOnScope; + bool noScriptRval; + bool selfHostingMode; + bool canLazilyParse; + bool strictOption; + bool extraWarningsOption; + bool werrorOption; + bool asmJSOption; + 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; + + // Wrap any compilation option values that need it as appropriate for + // use from |compartment|. + virtual bool wrap(JSContext *cx, JSCompartment *compartment) = 0; + + private: + static JSObject * const nullObjectPtr; + void operator=(const ReadOnlyCompileOptions &) MOZ_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 +{ + JSRuntime *runtime; + 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 MOZ_OVERRIDE { return elementRoot; } + JSString *elementAttributeName() const MOZ_OVERRIDE { return elementAttributeNameRoot; } + JSScript *introductionScript() const MOZ_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 jschar *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 &setOriginPrincipals(JSPrincipals *p) { + if (p) JS_HoldPrincipals(p); + if (originPrincipals_) JS_DropPrincipals(runtime, originPrincipals_); + originPrincipals_ = p; + 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 &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; } + OwningCompileOptions &setForEval(bool eval) { forEval = eval; return *this; } + OwningCompileOptions &setDefineOnScope(bool define) { defineOnScope = define; 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; + } + + virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE; + + private: + void operator=(const CompileOptions &rhs) MOZ_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) : 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); + + originPrincipals_ = rhs.originPrincipals_; + filename_ = rhs.filename(); + sourceMapURL_ = rhs.sourceMapURL(); + elementRoot = rhs.element(); + elementAttributeNameRoot = rhs.elementAttributeName(); + introductionScriptRoot = rhs.introductionScript(); + } + + JSObject *element() const MOZ_OVERRIDE { return elementRoot; } + JSString *elementAttributeName() const MOZ_OVERRIDE { return elementAttributeNameRoot; } + JSScript *introductionScript() const MOZ_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 jschar *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 &setOriginPrincipals(JSPrincipals *p) { + originPrincipals_ = p; + 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 &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; } + CompileOptions &setForEval(bool eval) { forEval = eval; return *this; } + CompileOptions &setDefineOnScope(bool define) { defineOnScope = define; 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; + } + + virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE; + + private: + void operator=(const CompileOptions &rhs) MOZ_DELETE; +}; + +/* + * |script| will always be set. On failure, it will be set to nullptr. + */ +extern JS_PUBLIC_API(bool) +Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + SourceBufferHolder &srcBuf, JS::MutableHandleScript script); + +extern JS_PUBLIC_API(JSScript *) +Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *bytes, size_t length); + +extern JS_PUBLIC_API(JSScript *) +Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const jschar *chars, size_t length); + +extern JS_PUBLIC_API(JSScript *) +Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, FILE *file); + +extern JS_PUBLIC_API(JSScript *) +Compile(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename); + +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, + * FinishOffThreadScript must be invoked on the main thread to get the result + * script or nullptr. If maybecx is not specified, the resources will be freed, + * but no script will be returned. + * + * 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 jschar *chars, size_t length, + OffThreadCompileCallback callback, void *callbackData); + +extern JS_PUBLIC_API(JSScript *) +FinishOffThreadScript(JSContext *maybecx, JSRuntime *rt, void *token); + +extern JS_PUBLIC_API(bool) +CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *name, unsigned nargs, const char *const *argnames, + SourceBufferHolder &srcBuf, JS::MutableHandleFunction fun); + +extern JS_PUBLIC_API(JSFunction *) +CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *name, unsigned nargs, const char *const *argnames, + const char *bytes, size_t length); + +extern JS_PUBLIC_API(JSFunction *) +CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *name, unsigned nargs, const char *const *argnames, + const jschar *chars, size_t length); + +} /* namespace JS */ + +extern JS_PUBLIC_API(JSString *) +JS_DecompileScript(JSContext *cx, JS::Handle script, const char *name, unsigned indent); + +/* + * API extension: OR this into indent to avoid pretty-printing the decompiled + * source resulting from JS_DecompileFunction{,Body}. + */ +#define JS_DONT_PRETTY_PRINT ((unsigned)0x8000) + +extern JS_PUBLIC_API(JSString *) +JS_DecompileFunction(JSContext *cx, JS::Handle fun, unsigned indent); + +extern JS_PUBLIC_API(JSString *) +JS_DecompileFunctionBody(JSContext *cx, JS::Handle fun, unsigned indent); + +/* + * NB: JS_ExecuteScript and the JS_Evaluate*Script* quadruplets use the obj + * parameter as the initial scope chain header, the 'this' keyword value, and + * the variables object (ECMA parlance for where 'var' and 'function' bind + * names) of the execution context for script. + * + * Using obj as the variables object is problematic if obj's parent (which is + * the scope chain link; see JS_SetParent and JS_NewObject) is not null: in + * this case, variables created by 'var x = 0', e.g., go in obj, but variables + * created by assignment to an unbound id, 'x = 0', go in the last object on + * the scope chain linked by parent. + * + * ECMA calls that last scoping object the "global object", but note that many + * embeddings have several such objects. ECMA requires that "global code" be + * executed with the variables object equal to this global object. But these + * JS API entry points provide freedom to execute code against a "sub-global", + * i.e., a parented or scoped object, in which case the variables object will + * differ from the last object on the scope chain, resulting in confusing and + * non-ECMA explicit vs. implicit variable creation. + * + * Caveat embedders: unless you already depend on this buggy variables object + * binding behavior, you should call ContextOptionsRef(cx).setVarObjFix(true) + * for each context in the application, if you pass parented objects as the obj + * parameter, or may ever pass such objects in the future. + * + * Why a runtime option? The alternative is to add six or so new API entry + * points with signatures matching the following six, 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 JS_SetOption call, + * 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_EvaluateScript, + * etc., entry points. + */ +extern JS_PUBLIC_API(bool) +JS_ExecuteScript(JSContext *cx, JS::HandleObject obj, JS::HandleScript script, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +JS_ExecuteScript(JSContext *cx, JS::HandleObject obj, 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 obj, JS::Handle script); + +} /* namespace JS */ + +extern JS_PUBLIC_API(bool) +JS_ExecuteScriptVersion(JSContext *cx, JS::HandleObject obj, JS::HandleScript script, + JS::MutableHandleValue rval, JSVersion version); + +extern JS_PUBLIC_API(bool) +JS_ExecuteScriptVersion(JSContext *cx, JS::HandleObject obj, JS::HandleScript script, + JSVersion version); + +extern JS_PUBLIC_API(bool) +JS_EvaluateScript(JSContext *cx, JS::HandleObject obj, + const char *bytes, unsigned length, + const char *filename, unsigned lineno, + JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +JS_EvaluateScript(JSContext *cx, JS::HandleObject obj, + const char *bytes, unsigned length, + const char *filename, unsigned lineno); + +extern JS_PUBLIC_API(bool) +JS_EvaluateUCScript(JSContext *cx, JS::Handle obj, + const jschar *chars, unsigned length, + const char *filename, unsigned lineno, + JS::MutableHandle rval); + +namespace JS { + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + SourceBufferHolder &srcBuf, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const jschar *chars, size_t length, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *bytes, size_t length, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *filename, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + SourceBufferHolder &srcBuf); + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const jschar *chars, size_t length); + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *bytes, size_t length); + +extern JS_PUBLIC_API(bool) +Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, + const char *filename); + +} /* namespace JS */ + +extern JS_PUBLIC_API(bool) +JS_CallFunction(JSContext *cx, JS::HandleObject obj, JS::HandleFunction fun, + const JS::HandleValueArray& args, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +JS_CallFunctionName(JSContext *cx, JS::HandleObject obj, const char *name, + const JS::HandleValueArray& args, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +JS_CallFunctionValue(JSContext *cx, JS::HandleObject obj, JS::HandleValue fval, + 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, const char *name, const JS::HandleValueArray& args, + MutableHandleValue rval) +{ + return !!JS_CallFunctionName(cx, thisObj, name, 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); +} + +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) +{ + JS_ASSERT(funObj); + JS::RootedValue fun(cx, JS::ObjectValue(*funObj)); + return Call(cx, thisv, fun, args, rval); +} + +} /* namespace JS */ + +/* + * 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(rt). + * + * 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(JSInterruptCallback) +JS_SetInterruptCallback(JSRuntime *rt, JSInterruptCallback callback); + +extern JS_PUBLIC_API(JSInterruptCallback) +JS_GetInterruptCallback(JSRuntime *rt); + +extern JS_PUBLIC_API(void) +JS_RequestInterruptCallback(JSRuntime *rt); + +extern JS_PUBLIC_API(bool) +JS_IsRunning(JSContext *cx); + +/* + * Saving and restoring frame chains. + * + * These two functions are used to set aside cx's call stack while that stack + * is inactive. After a call to JS_SaveFrameChain, it looks as if there is no + * code running on cx. Before calling JS_RestoreFrameChain, cx's call stack + * must be balanced and all nested calls to JS_SaveFrameChain must have had + * matching JS_RestoreFrameChain calls. + * + * JS_SaveFrameChain deals with cx not having any code running on it. + */ +extern JS_PUBLIC_API(bool) +JS_SaveFrameChain(JSContext *cx); + +extern JS_PUBLIC_API(void) +JS_RestoreFrameChain(JSContext *cx); + +#ifdef MOZ_TRACE_JSCALLS +/* + * The callback is expected to be quick and noninvasive. It should not + * request interrupts, turn on debugging, or produce uncaught JS + * exceptions. The state of the stack and registers in the context + * cannot be relied upon, since this callback may be invoked directly + * from either JIT. The 'entering' field means we are entering a + * function if it is positive, leaving a function if it is zero or + * negative. + */ +extern JS_PUBLIC_API(void) +JS_SetFunctionCallback(JSContext *cx, JSFunctionCallback fcb); + +extern JS_PUBLIC_API(JSFunctionCallback) +JS_GetFunctionCallback(JSContext *cx); +#endif /* MOZ_TRACE_JSCALLS */ + +/************************************************************************/ + +/* + * 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_InternJSString(JSContext *cx, JS::HandleString str); + +extern JS_PUBLIC_API(JSString *) +JS_InternStringN(JSContext *cx, const char *s, size_t length); + +extern JS_PUBLIC_API(JSString *) +JS_InternString(JSContext *cx, const char *s); + +extern JS_PUBLIC_API(JSString *) +JS_NewUCString(JSContext *cx, jschar *chars, size_t length); + +extern JS_PUBLIC_API(JSString *) +JS_NewUCStringCopyN(JSContext *cx, const jschar *s, size_t n); + +extern JS_PUBLIC_API(JSString *) +JS_NewUCStringCopyZ(JSContext *cx, const jschar *s); + +extern JS_PUBLIC_API(JSString *) +JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length); + +extern JS_PUBLIC_API(JSString *) +JS_InternUCString(JSContext *cx, const jschar *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 interned strings, i.e., strings from JS_InternString or + * JSID_TO_STRING(id), using JS_GetInternedStringChars*. + * + * 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 so only one needs to be rooted. 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; + * JS_ASSERT(fstr == JS_ASSERT_STRING_IS_FLAT(str)); + * + * // in an infallible context, for the same 'str' + * const jschar *chars = JS_GetFlatStringChars(fstr) + * JS_ASSERT(chars); + * + * The CharsZ APIs guarantee that the returned array has a null character at + * chars[length]. This can require additional copying so clients should prefer + * APIs without CharsZ if possible. The infallible functions also return + * null-terminated arrays. (There is no additional cost or non-Z alternative + * for the infallible functions, so 'Z' is left out of the identifier.) + */ + +extern JS_PUBLIC_API(size_t) +JS_GetStringLength(JSString *str); + +extern JS_PUBLIC_API(const jschar *) +JS_GetStringCharsAndLength(JSContext *cx, JSString *str, size_t *length); + +extern JS_PUBLIC_API(const jschar *) +JS_GetInternedStringChars(JSString *str); + +extern JS_PUBLIC_API(const jschar *) +JS_GetInternedStringCharsAndLength(JSString *str, size_t *length); + +extern JS_PUBLIC_API(const jschar *) +JS_GetStringCharsZ(JSContext *cx, JSString *str); + +extern JS_PUBLIC_API(const jschar *) +JS_GetStringCharsZAndLength(JSContext *cx, JSString *str, size_t *length); + +extern JS_PUBLIC_API(JSFlatString *) +JS_FlattenString(JSContext *cx, JSString *str); + +extern JS_PUBLIC_API(const jschar *) +JS_GetFlatStringChars(JSFlatString *str); + +static MOZ_ALWAYS_INLINE JSFlatString * +JSID_TO_FLAT_STRING(jsid id) +{ + JS_ASSERT(JSID_IS_STRING(id)); + return (JSFlatString *)(JSID_BITS(id)); +} + +static MOZ_ALWAYS_INLINE JSFlatString * +JS_ASSERT_STRING_IS_FLAT(JSString *str) +{ + JS_ASSERT(JS_GetFlatStringChars((JSFlatString *)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 jschars 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 jschar after the + * transcoded string. + */ +JS_PUBLIC_API(bool) +JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *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 JSAutoByteString +{ + public: + JSAutoByteString(JSContext *cx, JSString *str + MOZ_GUARD_OBJECT_NOTIFIER_PARAM) + : mBytes(JS_EncodeString(cx, str)) + { + JS_ASSERT(cx); + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + JSAutoByteString(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) + : mBytes(nullptr) + { + MOZ_GUARD_OBJECT_NOTIFIER_INIT; + } + + ~JSAutoByteString() { + js_free(mBytes); + } + + /* Take ownership of the given byte array. */ + void initBytes(char *bytes) { + JS_ASSERT(!mBytes); + mBytes = bytes; + } + + char *encodeLatin1(JSContext *cx, JSString *str) { + JS_ASSERT(!mBytes); + JS_ASSERT(cx); + mBytes = JS_EncodeString(cx, str); + return mBytes; + } + + char *encodeLatin1(js::ExclusiveContext *cx, JSString *str); + + char *encodeUtf8(JSContext *cx, JS::HandleString str) { + JS_ASSERT(!mBytes); + JS_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); +}; + +/************************************************************************/ +/* + * JSON functions + */ +typedef bool (* JSONWriteCallback)(const jschar *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); + +/* + * JSON.parse as specified by ES5. + */ +JS_PUBLIC_API(bool) +JS_ParseJSON(JSContext *cx, const jschar *chars, uint32_t len, JS::MutableHandleValue vp); + +JS_PUBLIC_API(bool) +JS_ParseJSONWithReviver(JSContext *cx, const jschar *chars, uint32_t len, 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(JSRuntime *rt, const char *locale); + +/* + * Returns 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. + */ +extern JS_PUBLIC_API(const char*) +JS_GetDefaultLocale(JSRuntime *rt); + +/* + * Reset the default locale to OS defaults. + */ +extern JS_PUBLIC_API(void) +JS_ResetDefaultLocale(JSRuntime *rt); + +/* + * Locale specific string conversion and error message callbacks. + */ +struct JSLocaleCallbacks { + JSLocaleToUpperCase localeToUpperCase; + JSLocaleToLowerCase localeToLowerCase; + JSLocaleCompare localeCompare; // not used #if EXPOSE_INTL_API + JSLocaleToUnicode localeToUnicode; + JSErrorCallback localeGetErrorMessage; +}; + +/* + * Establish locale callbacks. The pointer must persist as long as the + * JSRuntime. Passing nullptr restores the default behaviour. + */ +extern JS_PUBLIC_API(void) +JS_SetLocaleCallbacks(JSRuntime *rt, JSLocaleCallbacks *callbacks); + +/* + * Return the address of the current locale callbacks struct, which may + * be nullptr. + */ +extern JS_PUBLIC_API(JSLocaleCallbacks *) +JS_GetLocaleCallbacks(JSRuntime *rt); + +/************************************************************************/ + +/* + * Error reporting. + */ + +/* + * Report an exception represented by the sprintf-like conversion of format + * and its arguments. This exception message string is passed to a pre-set + * JSErrorReporter function (set by JS_SetErrorReporter). + */ +extern JS_PUBLIC_API(void) +JS_ReportError(JSContext *cx, const char *format, ...); + +/* + * Use an errorNumber to retrieve the format string, args are char * + */ +extern JS_PUBLIC_API(void) +JS_ReportErrorNumber(JSContext *cx, JSErrorCallback errorCallback, + void *userRef, const unsigned errorNumber, ...); + +#ifdef va_start +extern JS_PUBLIC_API(void) +JS_ReportErrorNumberVA(JSContext *cx, JSErrorCallback errorCallback, + void *userRef, const unsigned errorNumber, va_list ap); +#endif + +/* + * Use an errorNumber to retrieve the format string, args are jschar * + */ +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 jschar **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_ReportWarning(JSContext *cx, const char *format, ...); + +extern JS_PUBLIC_API(bool) +JS_ReportErrorFlagsAndNumber(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); + +struct JSErrorReport { + const char *filename; /* source file name, URL, etc., or null */ + JSPrincipals *originPrincipals; /* see 'originPrincipals' comment above */ + unsigned lineno; /* source line number */ + const char *linebuf; /* offending source line without final \n */ + const char *tokenptr; /* pointer to error token in linebuf */ + const jschar *uclinebuf; /* unicode (original) line buffer */ + const jschar *uctokenptr; /* unicode (original) token pointer */ + unsigned flags; /* error/warning, etc. */ + unsigned errorNumber; /* the error number, e.g. see js.msg */ + const jschar *ucmessage; /* the (default) error message */ + const jschar **messageArgs; /* arguments for the error message */ + int16_t exnType; /* One of the JSExnType constants */ + unsigned column; /* zero-based column index in line */ +}; + +/* + * 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 */ + +/* + * This condition is an error in strict mode code, a warning if + * JS_HAS_STRICT_OPTION(cx), and otherwise should not be reported at + * all. We check the strictness of the context's top frame's script; + * where that isn't appropriate, the caller should do the right checks + * itself instead of using this flag. + */ +#define JSREPORT_STRICT_MODE_ERROR 0x8 + +/* + * 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) +#define JSREPORT_IS_STRICT_MODE_ERROR(flags) (((flags) & \ + JSREPORT_STRICT_MODE_ERROR) != 0) +extern JS_PUBLIC_API(JSErrorReporter) +JS_GetErrorReporter(JSContext *cx); + +extern JS_PUBLIC_API(JSErrorReporter) +JS_SetErrorReporter(JSContext *cx, JSErrorReporter er); + +namespace JS { + +extern JS_PUBLIC_API(bool) +CreateTypeError(JSContext *cx, HandleString 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); + +} /* namespace JS */ + +/* + * Dates. + */ + +extern JS_PUBLIC_API(JSObject *) +JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec); + +extern JS_PUBLIC_API(JSObject *) +JS_NewDateObjectMsec(JSContext *cx, double msec); + +/* + * Infallible predicate to test whether obj is a date object. + */ +extern JS_PUBLIC_API(bool) +JS_ObjectIsDate(JSContext *cx, JS::HandleObject obj); + +/* + * Clears the cache of calculated local time from each Date object. + * Call to propagate a system timezone change. + */ +extern JS_PUBLIC_API(void) +JS_ClearDateCaches(JSContext *cx); + +/************************************************************************/ + +/* + * Regular Expressions. + */ +#define JSREG_FOLD 0x01 /* fold uppercase to lowercase */ +#define JSREG_GLOB 0x02 /* global exec, creates array of matches */ +#define JSREG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */ +#define JSREG_STICKY 0x08 /* only match starting at lastIndex */ + +extern JS_PUBLIC_API(JSObject *) +JS_NewRegExpObject(JSContext *cx, JS::HandleObject obj, char *bytes, size_t length, + unsigned flags); + +extern JS_PUBLIC_API(JSObject *) +JS_NewUCRegExpObject(JSContext *cx, JS::HandleObject obj, jschar *chars, size_t length, + unsigned flags); + +extern JS_PUBLIC_API(void) +JS_SetRegExpInput(JSContext *cx, JS::HandleObject obj, JS::HandleString input, + bool multiline); + +extern JS_PUBLIC_API(void) +JS_ClearRegExpStatics(JSContext *cx, JS::HandleObject obj); + +extern JS_PUBLIC_API(bool) +JS_ExecuteRegExp(JSContext *cx, JS::HandleObject obj, JS::HandleObject reobj, + jschar *chars, size_t length, size_t *indexp, bool test, + JS::MutableHandleValue rval); + +/* RegExp interface for clients without a global object. */ + +extern JS_PUBLIC_API(JSObject *) +JS_NewRegExpObjectNoStatics(JSContext *cx, char *bytes, size_t length, unsigned flags); + +extern JS_PUBLIC_API(JSObject *) +JS_NewUCRegExpObjectNoStatics(JSContext *cx, jschar *chars, size_t length, unsigned flags); + +extern JS_PUBLIC_API(bool) +JS_ExecuteRegExpNoStatics(JSContext *cx, JS::HandleObject reobj, jschar *chars, size_t length, + size_t *indexp, bool test, JS::MutableHandleValue rval); + +extern JS_PUBLIC_API(bool) +JS_ObjectIsRegExp(JSContext *cx, JS::HandleObject obj); + +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); + +extern JS_PUBLIC_API(bool) +JS_ReportPendingException(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_EvaluateScript(cx, ...); + * AutoSaveExceptionState savedExc(cx); + * ... cleanup that might re-enter JS ... + * return ok; + */ +class JS_PUBLIC_API(AutoSaveExceptionState) +{ + private: + JSContext *context; + 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() { + 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); + +/* + * Throws a StopIteration exception on cx. + */ +extern JS_PUBLIC_API(bool) +JS_ThrowStopIteration(JSContext *cx); + +extern JS_PUBLIC_API(bool) +JS_IsStopIteration(jsval v); + +extern JS_PUBLIC_API(intptr_t) +JS_GetCurrentThread(); + +/* + * A JS runtime always has an "owner thread". The owner thread is set when the + * runtime is created (to the current thread) and practically all entry points + * into the JS engine check that a runtime (or anything contained in the + * runtime: context, 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(JSRuntime *rt); + +/************************************************************************/ + +/* + * 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_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(JSRuntime *rt, bool enabled); + +extern JS_PUBLIC_API(void) +JS_SetParallelIonCompilationEnabled(JSRuntime *rt, bool enabled); + +#define JIT_COMPILER_OPTIONS(Register) \ + Register(BASELINE_USECOUNT_TRIGGER, "baseline.usecount.trigger") \ + Register(ION_USECOUNT_TRIGGER, "ion.usecount.trigger") \ + Register(ION_ENABLE, "ion.enable") \ + Register(BASELINE_ENABLE, "baseline.enable") \ + Register(PARALLEL_COMPILATION_ENABLE, "parallel-compilation.enable") + +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(JSRuntime *rt, JSJitCompilerOption opt, uint32_t value); +extern JS_PUBLIC_API(int) +JS_GetGlobalJitCompilerOption(JSRuntime *rt, JSJitCompilerOption opt); + +/* + * 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); + +namespace JS { + +/* + * AutoFilename encapsulates a pointer to a C-string and keeps the C-string + * alive for as long as the associated AutoFilename object is alive. + */ +class MOZ_STACK_CLASS JS_PUBLIC_API(AutoFilename) +{ + void *scriptSource_; + + AutoFilename(const AutoFilename &) MOZ_DELETE; + void operator=(const AutoFilename &) MOZ_DELETE; + + public: + AutoFilename() : scriptSource_(nullptr) {} + ~AutoFilename() { reset(nullptr); } + + const char *get() const; + + void reset(void *newScriptSource); +}; + +/* + * Return the current filename and line 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); + +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 AutoHideScriptedCaller +{ + public: + 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 +}; + +} /* namespace JS */ + +/* + * Encode/Decode interpreted scripts and functions to/from memory. + */ + +extern JS_PUBLIC_API(void *) +JS_EncodeScript(JSContext *cx, JS::HandleScript script, uint32_t *lengthp); + +extern JS_PUBLIC_API(void *) +JS_EncodeInterpretedFunction(JSContext *cx, JS::HandleObject funobj, uint32_t *lengthp); + +extern JS_PUBLIC_API(JSScript *) +JS_DecodeScript(JSContext *cx, const void *data, uint32_t length, JSPrincipals *originPrincipals); + +extern JS_PUBLIC_API(JSObject *) +JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length, + JSPrincipals *originPrincipals); + +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 jschar *begin, const jschar *limit, + size_t *size, const uint8_t **memory, intptr_t *handle); +typedef void +(* CloseAsmJSCacheEntryForReadOp)(HandleObject global, size_t size, const uint8_t *memory, + intptr_t handle); + +/* + * 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 bool +(* OpenAsmJSCacheEntryForWriteOp)(HandleObject global, bool installed, + const jschar *begin, const jschar *end, + size_t size, uint8_t **memory, intptr_t *handle); +typedef void +(* CloseAsmJSCacheEntryForWriteOp)(HandleObject global, size_t size, uint8_t *memory, + intptr_t handle); + +typedef js::Vector BuildIdCharVector; + +// 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 bool +(* BuildIdOp)(BuildIdCharVector *buildId); + +struct AsmJSCacheOps +{ + OpenAsmJSCacheEntryForReadOp openEntryForRead; + CloseAsmJSCacheEntryForReadOp closeEntryForRead; + OpenAsmJSCacheEntryForWriteOp openEntryForWrite; + CloseAsmJSCacheEntryForWriteOp closeEntryForWrite; + BuildIdOp buildId; +}; + +extern JS_PUBLIC_API(void) +SetAsmJSCacheOps(JSRuntime *rt, const AsmJSCacheOps *callbacks); + +/* + * 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 &) MOZ_DELETE; + ForOfIterator &operator=(const ForOfIterator &) MOZ_DELETE; + + public: + ForOfIterator(JSContext *cx) : cx_(cx), iterator(cx_), index(NOT_ARRAY) { } + + enum NonIterableBehavior { + ThrowOnNonIterable, + AllowNonIterable + }; + + /* + * Initialize the iterator. If AllowNonIterable is passed then if iterable + * does not have a callable @@iterator init() will just return true instead + * of throwing. Callers should 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, 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 so that the allocation will + * succeed if retried. After the callback returns, the JS engine will try to + * allocate again and may be succesful. + */ + +typedef void +(* LargeAllocationFailureCallback)(); + +extern JS_PUBLIC_API(void) +SetLargeAllocationFailureCallback(JSRuntime *rt, LargeAllocationFailureCallback afc); + +/* + * Unlike the error reporter, which is only called if the exception for an OOM + * bubbles up and is not caught, the OutOfMemoryCallback is called immediately + * at the OOM site to allow the embedding to capture the current state of heap + * allocation before anything is freed. If the large-allocation-failure callback + * is called at all (not all allocation sites call the large-allocation-failure + * callback on failure), it is called before the out-of-memory callback; the + * out-of-memory callback is only called if the allocation still fails after the + * large-allocation-failure callback has returned. + */ + +typedef void +(* OutOfMemoryCallback)(JSContext *cx); + +extern JS_PUBLIC_API(void) +SetOutOfMemoryCallback(JSRuntime *rt, OutOfMemoryCallback cb); + +} /* namespace JS */ + +#endif /* jsapi_h */