/* -*- 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/Atomics.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/RootingAPI.h" #include "js/Utility.h" #include "js/Value.h" #include "js/Vector.h" /************************************************************************/ struct JSTracer; namespace JS { class Latin1CharsZ; class TwoByteChars; typedef mozilla::RangedPtr CharPtr; class StableCharPtr : public CharPtr { public: StableCharPtr(const StableCharPtr &s) : CharPtr(s) {} StableCharPtr(const mozilla::RangedPtr &s) : CharPtr(s) {} StableCharPtr(const jschar *s, size_t len) : CharPtr(s, len) {} StableCharPtr(const jschar *pos, const jschar *start, size_t len) : CharPtr(pos, start, len) {} using CharPtr::operator=; }; #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 */ STRING = -12, /* js::AutoStringRooter */ 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; }; class AutoStringRooter : private AutoGCRooter { public: AutoStringRooter(JSContext *cx, JSString *str = nullptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, STRING), str_(str) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; } void setString(JSString *str) { str_ = str; } JSString * string() const { return str_; } JSString ** addr() { return &str_; } JSString * const * addr() const { return &str_; } friend void AutoGCRooter::trace(JSTracer *trc); private: JSString *str_; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; class AutoArrayRooter : private AutoGCRooter { public: AutoArrayRooter(JSContext *cx, size_t len, Value *vec MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, len), array(vec), skip(cx, array, len) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; JS_ASSERT(tag_ >= 0); } void changeLength(size_t newLength) { tag_ = ptrdiff_t(newLength); JS_ASSERT(tag_ >= 0); } void changeArray(Value *newArray, size_t newLength) { changeLength(newLength); array = newArray; } Value *start() { return array; } size_t length() { JS_ASSERT(tag_ >= 0); return size_t(tag_); } MutableHandleValue handleAt(size_t i) { JS_ASSERT(i < size_t(tag_)); return MutableHandleValue::fromMarkedLocation(&array[i]); } HandleValue handleAt(size_t i) const { JS_ASSERT(i < size_t(tag_)); return HandleValue::fromMarkedLocation(&array[i]); } MutableHandleValue operator[](size_t i) { JS_ASSERT(i < size_t(tag_)); return MutableHandleValue::fromMarkedLocation(&array[i]); } HandleValue operator[](size_t i) const { JS_ASSERT(i < size_t(tag_)); return HandleValue::fromMarkedLocation(&array[i]); } friend void AutoGCRooter::trace(JSTracer *trc); private: Value *array; js::SkipRoot skip; MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER }; template class AutoVectorRooter : protected AutoGCRooter { typedef js::Vector VectorImpl; VectorImpl vector; /* Prevent overwriting of inline elements in vector. */ js::SkipRoot vectorRoot; public: explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, tag), vector(cx), vectorRoot(cx, &vector) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; } explicit AutoVectorRooter(js::ContextFriendFields *cx, ptrdiff_t tag MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : AutoGCRooter(cx, tag), vector(cx), vectorRoot(cx, &vector) { 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 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 }; } /* 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 (* JSOperationCallback)(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); /* * Security protocol types. */ typedef void (* JSDestroyPrincipalsOp)(JSPrincipals *principals); /* * Used to check if a CSP instance wants to disable eval() and friends. * See js_CheckCSPPermitsJSAction() in jsobj. */ typedef bool (* JSCSPEvalChecker)(JSContext *cx); /* * 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); /* * Callback used when wrapping determines that the underlying object is already * in the compartment for which it is being wrapped. This allows consumers to * maintain same-compartment wrapping invariants. * * |obj| is guaranteed to be same-compartment as |cx|, but it may (or may not) * be a security or cross-compartment wrapper. This is an unfortunate contract, * but is important for to avoid unnecessarily recomputing every cross- * compartment wrapper that gets passed to wrap. */ typedef JSObject * (* JSSameCompartmentWrapObjectCallback)(JSContext *cx, JS::HandleObject obj); struct JSWrapObjectCallbacks { JSWrapObjectCallback wrap; JSSameCompartmentWrapObjectCallback sameCompartmentWrap; 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::DoubleIsInt32(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 }; } /* 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 JSPROP_SHORTID 0x100 /* set in JS_DefineProperty attrs if getters/setters use a shortid */ #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, unsigned argc, jsval *argv, const char *format, ...); #ifdef va_start extern JS_PUBLIC_API(bool) JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, 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); { js::SkipRoot root(cx, &v); js::MaybeCheckStackRoots(cx); } 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); js::MaybeCheckStackRoots(cx); 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); js::MaybeCheckStackRoots(cx); 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); js::MaybeCheckStackRoots(cx); 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); js::MaybeCheckStackRoots(cx); 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); js::MaybeCheckStackRoots(cx); 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); 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); 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(ContextOptions) { public: ContextOptions() : extraWarnings_(false), werror_(false), varObjFix_(false), privateIsNSISupports_(false), dontReportUncaught_(false), noDefaultCompartmentObject_(false), noScriptRval_(false), strictMode_(false), baseline_(false), typeInference_(false), ion_(false), asmJS_(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 baseline() const { return baseline_; } ContextOptions &setBaseline(bool flag) { baseline_ = flag; return *this; } ContextOptions &toggleBaseline() { baseline_ = !baseline_; return *this; } bool typeInference() const { return typeInference_; } ContextOptions &setTypeInference(bool flag) { typeInference_ = flag; return *this; } ContextOptions &toggleTypeInference() { typeInference_ = !typeInference_; return *this; } bool ion() const { return ion_; } ContextOptions &setIon(bool flag) { ion_ = flag; return *this; } ContextOptions &toggleIon() { ion_ = !ion_; return *this; } bool asmJS() const { return asmJS_; } ContextOptions &setAsmJS(bool flag) { asmJS_ = flag; return *this; } ContextOptions &toggleAsmJS() { asmJS_ = !asmJS_; return *this; } bool 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 baseline_ : 1; bool typeInference_ : 1; bool ion_ : 1; bool asmJS_ : 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, jsid *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(); }; /* 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); extern JS_PUBLIC_API(JSProtoKey) JS_IdentifyClassPrototype(JSObject *obj); 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); } /* * This method returns the global corresponding to the most recent scripted * frame, which may not match the cx's current compartment. This is extremely * dangerous, because it can bypass compartment security invariants in subtle * ways. To use it safely, the caller must perform a subsequent security * check. There is currently only one consumer of this function in Gecko, and * it should probably stay that way. If you'd like to use it, please consult * the XPConnect module owner first. */ extern JS_PUBLIC_API(JSObject *) JS_GetScriptedGlobal(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); /* * 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) JS_AddValueRoot(JSContext *cx, jsval *vp); extern JS_PUBLIC_API(bool) JS_AddStringRoot(JSContext *cx, JSString **rp); extern JS_PUBLIC_API(bool) JS_AddObjectRoot(JSContext *cx, JSObject **rp); extern JS_PUBLIC_API(bool) JS_AddNamedValueRoot(JSContext *cx, jsval *vp, const char *name); extern JS_PUBLIC_API(bool) JS_AddNamedValueRootRT(JSRuntime *rt, jsval *vp, const char *name); extern JS_PUBLIC_API(bool) JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name); extern JS_PUBLIC_API(bool) JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name); extern JS_PUBLIC_API(bool) JS_AddNamedScriptRoot(JSContext *cx, JSScript **rp, const char *name); extern JS_PUBLIC_API(void) JS_RemoveValueRoot(JSContext *cx, jsval *vp); extern JS_PUBLIC_API(void) JS_RemoveStringRoot(JSContext *cx, JSString **rp); extern JS_PUBLIC_API(void) JS_RemoveObjectRoot(JSContext *cx, JSObject **rp); extern JS_PUBLIC_API(void) JS_RemoveScriptRoot(JSContext *cx, JSScript **rp); extern JS_PUBLIC_API(void) JS_RemoveValueRootRT(JSRuntime *rt, jsval *vp); extern JS_PUBLIC_API(void) JS_RemoveStringRootRT(JSRuntime *rt, JSString **rp); extern JS_PUBLIC_API(void) JS_RemoveObjectRootRT(JSRuntime *rt, JSObject **rp); extern JS_PUBLIC_API(void) JS_RemoveScriptRootRT(JSRuntime *rt, JSScript **rp); /* * 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); /* * JS_CallTracer API and related macros for implementors of JSTraceOp, to * enumerate all references to traceable things reachable via a property or * other strong ref identified for debugging purposes by name or index or * a naming callback. * * See the JSTraceOp typedef. */ /* * Use the following macros to check if a particular jsval is a traceable * thing and to extract the thing and its kind to pass to JS_CallTracer. */ static MOZ_ALWAYS_INLINE bool JSVAL_IS_TRACEABLE(jsval v) { return JSVAL_IS_TRACEABLE_IMPL(JSVAL_TO_IMPL(v)); } static MOZ_ALWAYS_INLINE void * JSVAL_TO_TRACEABLE(jsval v) { return JSVAL_TO_GCTHING(v); } static MOZ_ALWAYS_INLINE JSGCTraceKind JSVAL_TRACE_KIND(jsval v) { JS_ASSERT(JSVAL_IS_GCTHING(v)); return (JSGCTraceKind) JSVAL_TRACE_KIND_IMPL(JSVAL_TO_IMPL(v)); } #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; typedef enum JSGCMode { /* Perform only global GCs. */ JSGC_MODE_GLOBAL = 0, /* Perform per-compartment GCs until too much garbage has accumulated. */ JSGC_MODE_COMPARTMENT = 1, /* * Collect in short time slices rather than all at once. Implies * JSGC_MODE_COMPARTMENT. */ JSGC_MODE_INCREMENTAL = 2 } JSGCMode; 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, jsval v, JS::MutableHandle idp); extern JS_PUBLIC_API(bool) JS_IdToValue(JSContext *cx, jsid id, JS::MutableHandle vp); /* * JSNewResolveOp flag bits. */ #define JSRESOLVE_ASSIGNING 0x01 /* resolve on the left of assignment */ /* * 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; int8_t tinyid; 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, 0, \ 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, 0, \ 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, 0, \ 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, 0, \ 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 {0, 0, 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, jsval *argv); 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, jsval *argv); 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, JSObject *obj, JSObject *parent); extern JS_PUBLIC_API(JSObject *) JS_GetConstructor(JSContext *cx, JS::Handle proto); /* * Get a unique identifier for obj, good for the lifetime of obj (even if it * is moved by a copying GC). Return false on failure (likely out of memory), * and true with *idp containing the unique id on success. */ extern JS_PUBLIC_API(bool) JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp); 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) , 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; } bool baseline(JSContext *cx) const; Override &baselineOverride() { return baselineOverride_; } bool typeInference(const js::ExclusiveContext *cx) const; Override &typeInferenceOverride() { return typeInferenceOverride_; } bool ion(JSContext *cx) const; Override &ionOverride() { return ionOverride_; } bool asmJS(JSContext *cx) const; Override &asmJSOverride() { return asmJSOverride_; } 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_; }; private: JSVersion version_; bool invisibleToDebugger_; bool mergeable_; Override baselineOverride_; Override typeInferenceOverride_; Override ionOverride_; Override asmJSOverride_; Override cloneSingletonsOverride_; union { ZoneSpecifier spec; void *pointer; // js::Zone* is not exposed in the API. } zone_; // 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(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()); 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, JSObject *ctor, unsigned argc, jsval *argv); 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, JSObject *obj, const JSConstDoubleSpec *cds); extern JS_PUBLIC_API(bool) JS_DefineProperties(JSContext *cx, JSObject *obj, const JSPropertySpec *ps); extern JS_PUBLIC_API(bool) JS_DefineProperty(JSContext *cx, JSObject *obj, const char *name, jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); 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, JSObject *obj, jsid id, jsval descriptor, bool *bp); extern JS_PUBLIC_API(bool) JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name, int8_t tinyid, jsval value, JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); 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); extern JS_PUBLIC_API(bool) JS_LookupPropertyWithFlags(JSContext *cx, JS::HandleObject obj, const char *name, unsigned flags, JS::MutableHandleValue vp); extern JS_PUBLIC_API(bool) JS_LookupPropertyWithFlagsById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned flags, JS::MutableHandleObject objp, JS::MutableHandleValue vp); struct JSPropertyDescriptor { JSObject *obj; unsigned attrs; unsigned shortid; JSPropertyOp getter; JSStrictPropertyOp setter; JS::Value value; JSPropertyDescriptor() : obj(nullptr), attrs(0), shortid(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 hasShortId() const { return desc()->attrs & JSPROP_SHORTID; } 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; } unsigned shortid() const { return desc()->shortid; } 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); setShortId(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 setShortId(unsigned id) { desc()->shortid = id; } 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, JSObject *objArg, jsid id, unsigned flags, JS::MutableHandle desc); extern JS_PUBLIC_API(bool) JS_GetOwnPropertyDescriptor(JSContext *cx, JSObject *objArg, const char *name, unsigned flags, 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, JSObject *obj, jsid id, unsigned flags, JS::MutableHandle desc); extern JS_PUBLIC_API(bool) JS_GetPropertyDescriptor(JSContext *cx, JSObject *obj, const char *name, unsigned flags, 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_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj, const jschar *name, size_t namelen, int8_t tinyid, 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, int length, jsval *vector); 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, JSObject *obj, uint32_t index, JSObject *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, JSObject *objArg); /* * 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, which must have been * returned by JS_AllocateArrayBufferContents or JS_StealArrayBufferContents. * The new array buffer takes ownership. After calling this function, do not * free |contents| or use |contents| from another thread. */ extern JS_PUBLIC_API(JSObject *) JS_NewArrayBufferWithContents(JSContext *cx, 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 |*contents| and must free it or transfer ownership via * JS_NewArrayBufferWithContents when done using it. * To free |*contents|, call free(). * A pointer to the buffer's data is returned in |*data|. This pointer can * be used until |*contents| is freed or has its ownership transferred. */ extern JS_PUBLIC_API(bool) JS_StealArrayBufferContents(JSContext *cx, JS::HandleObject obj, void **contents, uint8_t **data); /* * Allocate memory that may be eventually passed to * JS_NewArrayBufferWithContents. |nbytes| is the number of payload bytes * required. The pointer to pass to JS_NewArrayBufferWithContents is returned * in |contents|. The pointer to the |nbytes| of usable memory is returned in * |data|. (*|contents| will contain a header before |data|.) The only legal * operations on *|contents| is to free it, or pass it to * JS_NewArrayBufferWithContents or JS_ReallocateArrayBufferContents. */ extern JS_PUBLIC_API(bool) JS_AllocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents, uint8_t **data); /* * Reallocate memory allocated by JS_AllocateArrayBufferContents, growing or * shrinking it as appropriate. The new data pointer will be returned in data. * If *contents is nullptr, behaves like JS_AllocateArrayBufferContents. */ extern JS_PUBLIC_API(bool) JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents, uint8_t **data); extern JS_PUBLIC_API(JSIdArray *) JS_Enumerate(JSContext *cx, JSObject *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); /************************************************************************/ /* * Security protocol. */ struct JSPrincipals { /* Don't call "destroy"; use reference counting macros below. */ #ifdef JS_THREADSAFE mozilla::Atomic refcount; #else int32_t refcount; #endif #ifdef JS_DEBUG /* A helper to facilitate principals debugging. */ uint32_t debugToken; #endif void setDebugToken(uint32_t token) { # ifdef JS_DEBUG debugToken = token; # endif } /* * This is not defined by the JS engine but should be provided by the * embedding. */ JS_PUBLIC_API(void) dump(); }; extern JS_PUBLIC_API(void) JS_HoldPrincipals(JSPrincipals *principals); extern JS_PUBLIC_API(void) JS_DropPrincipals(JSRuntime *rt, JSPrincipals *principals); struct JSSecurityCallbacks { JSCSPEvalChecker contentSecurityPolicyAllows; JSSubsumesOp subsumes; }; extern JS_PUBLIC_API(void) JS_SetSecurityCallbacks(JSRuntime *rt, const JSSecurityCallbacks *callbacks); extern JS_PUBLIC_API(const JSSecurityCallbacks *) JS_GetSecurityCallbacks(JSRuntime *rt); /* * Code running with "trusted" principals will be given a deeper stack * allocation than ordinary scripts. This allows trusted script to run after * untrusted script has exhausted the stack. This function sets the * runtime-wide trusted principal. * * This principals is not held (via JS_HoldPrincipals/JS_DropPrincipals) since * there is no available JSContext. Instead, the caller must ensure that the * given principals stays valid for as long as 'rt' may point to it. If the * principals would be destroyed before 'rt', JS_SetTrustedPrincipals must be * called again, passing nullptr for 'prin'. */ extern JS_PUBLIC_API(void) JS_SetTrustedPrincipals(JSRuntime *rt, const JSPrincipals *prin); /* * Initialize the callback that is called to destroy JSPrincipals instance * when its reference counter drops to zero. The initialization can be done * only once per JS runtime. */ extern JS_PUBLIC_API(void) JS_InitDestroyPrincipalsCallback(JSRuntime *rt, JSDestroyPrincipalsOp destroyPrincipals); /************************************************************************/ /* * 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) { protected: JSPrincipals *principals_; JSPrincipals *originPrincipals_; const char *filename_; 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() : principals_(nullptr), originPrincipals_(nullptr), filename_(nullptr), sourceMapURL_(nullptr), version(JSVERSION_UNKNOWN), versionSet(false), utf8(false), lineno(1), column(0), compileAndGo(false), forEval(false), noScriptRval(false), selfHostingMode(false), canLazilyParse(true), strictOption(false), extraWarningsOption(false), werrorOption(false), asmJSOption(false), forceAsync(false), sourcePolicy(SAVE_SOURCE) { } // 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 *principals() const { return principals_; } JSPrincipals *originPrincipals() const; const char *filename() const { return filename_; } const jschar *sourceMapURL() const { return sourceMapURL_; } virtual JSObject *element() const = 0; virtual JSString *elementAttributeName() const = 0; // POD options. JSVersion version; bool versionSet; bool utf8; unsigned lineno; unsigned column; bool compileAndGo; bool forEval; bool noScriptRval; bool selfHostingMode; bool canLazilyParse; bool strictOption; bool extraWarningsOption; bool werrorOption; bool asmJSOption; bool forceAsync; enum SourcePolicy { NO_SOURCE, LAZY_SOURCE, SAVE_SOURCE } sourcePolicy; // 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; 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; } // 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); /* 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 &setPrincipals(JSPrincipals *p) { if (p) JS_HoldPrincipals(p); if (principals_) JS_DropPrincipals(runtime, principals_); principals_ = p; 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 &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; } OwningCompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; } OwningCompileOptions &setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; } OwningCompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; } virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE; }; /* * 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; public: explicit CompileOptions(JSContext *cx, JSVersion version = JSVERSION_UNKNOWN); CompileOptions(js::ContextFriendFields *cx, const ReadOnlyCompileOptions &rhs) : ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx) { copyPODOptions(rhs); principals_ = rhs.principals(); originPrincipals_ = rhs.originPrincipals(); filename_ = rhs.filename(); sourceMapURL_ = rhs.sourceMapURL(); elementRoot = rhs.element(); elementAttributeNameRoot = rhs.elementAttributeName(); } JSObject *element() const MOZ_OVERRIDE { return elementRoot; } JSString *elementAttributeName() const MOZ_OVERRIDE { return elementAttributeNameRoot; } 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 &setPrincipals(JSPrincipals *p) { principals_ = p; 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 &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; } CompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; } CompileOptions &setCanLazilyParse(bool clp) { canLazilyParse = clp; return *this; } CompileOptions &setSourcePolicy(SourcePolicy sp) { sourcePolicy = sp; return *this; } virtual bool wrap(JSContext *cx, JSCompartment *compartment) MOZ_OVERRIDE; }; 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 specified, this method will also report * any error or warnings generated during the parse. * * 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, HandleObject obj, 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(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, JSObject *obj, JSScript *script, jsval *rval); extern JS_PUBLIC_API(bool) JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval, JSVersion version); /* * Execute either the function-defining prolog of a script, or the script's * main body, but not both. */ typedef enum JSExecPart { JSEXEC_PROLOG, JSEXEC_MAIN } JSExecPart; extern JS_PUBLIC_API(bool) JS_EvaluateScript(JSContext *cx, JSObject *obj, const char *bytes, unsigned length, const char *filename, unsigned lineno, jsval *rval); extern JS_PUBLIC_API(bool) JS_EvaluateScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals, const char *bytes, unsigned length, const char *filename, unsigned lineno, jsval *rval); extern JS_PUBLIC_API(bool) JS_EvaluateScriptForPrincipalsVersion(JSContext *cx, JSObject *obj, JSPrincipals *principals, const char *bytes, unsigned length, const char *filename, unsigned lineno, jsval *rval, JSVersion version); 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); extern JS_PUBLIC_API(bool) JS_EvaluateUCScriptForPrincipals(JSContext *cx, JS::Handle obj, JSPrincipals *principals, const jschar *chars, unsigned length, const char *filename, unsigned lineno, JS::MutableHandle rval); extern JS_PUBLIC_API(bool) JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JS::Handle obj, JSPrincipals *principals, const jschar *chars, unsigned length, const char *filename, unsigned lineno, JS::MutableHandle rval, JSVersion version); /* * JSAPI clients may optionally specify the 'originPrincipals' of a script. * A script's originPrincipals may be retrieved through the debug API (via * JS_GetScriptOriginPrincipals) and the originPrincipals are transitively * assigned to any nested scripts (including scripts dynamically created via * eval and the Function constructor). If originPrincipals is null, then the * value of principals is used as origin principals for the script. */ extern JS_PUBLIC_API(bool) JS_EvaluateUCScriptForPrincipalsVersionOrigin(JSContext *cx, JS::Handle obj, JSPrincipals *principals, JSPrincipals *originPrincipals, const jschar *chars, unsigned length, const char *filename, unsigned lineno, JS::MutableHandle rval, JSVersion version); namespace JS { extern JS_PUBLIC_API(bool) Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const jschar *chars, size_t length, jsval *rval); extern JS_PUBLIC_API(bool) Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *bytes, size_t length, jsval *rval); extern JS_PUBLIC_API(bool) Evaluate(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options, const char *filename, jsval *rval); } /* namespace JS */ extern JS_PUBLIC_API(bool) JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, unsigned argc, jsval *argv, jsval *rval); extern JS_PUBLIC_API(bool) JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, unsigned argc, jsval *argv, jsval *rval); extern JS_PUBLIC_API(bool) JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, unsigned argc, jsval *argv, jsval *rval); namespace JS { static inline bool Call(JSContext *cx, JSObject *thisObj, JSFunction *fun, unsigned argc, jsval *argv, MutableHandleValue rval) { return !!JS_CallFunction(cx, thisObj, fun, argc, argv, rval.address()); } static inline bool Call(JSContext *cx, JSObject *thisObj, const char *name, unsigned argc, jsval *argv, MutableHandleValue rval) { return !!JS_CallFunctionName(cx, thisObj, name, argc, argv, rval.address()); } static inline bool Call(JSContext *cx, JSObject *thisObj, jsval fun, unsigned argc, jsval *argv, MutableHandleValue rval) { return !!JS_CallFunctionValue(cx, thisObj, fun, argc, argv, rval.address()); } extern JS_PUBLIC_API(bool) Call(JSContext *cx, jsval thisv, jsval fun, unsigned argc, jsval *argv, MutableHandleValue rval); static inline bool Call(JSContext *cx, jsval thisv, JSObject *funObj, unsigned argc, jsval *argv, MutableHandleValue rval) { return Call(cx, thisv, OBJECT_TO_JSVAL(funObj), argc, argv, rval); } } /* namespace JS */ /* * These functions allow setting an operation callback that will be called * from the JS thread some time after any thread triggered the callback using * JS_TriggerOperationCallback(rt). * * To schedule the GC and for other activities the engine internally triggers * operation 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(JSOperationCallback) JS_SetOperationCallback(JSRuntime *rt, JSOperationCallback callback); extern JS_PUBLIC_API(JSOperationCallback) JS_GetOperationCallback(JSRuntime *rt); extern JS_PUBLIC_API(void) JS_TriggerOperationCallback(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 * trigger 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, JSString *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, JSString *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); /* * 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); } /* 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); /* * Save the current exception state. This takes a snapshot of cx's current * exception state without making any change to that state. * * The returned state pointer MUST be passed later to JS_RestoreExceptionState * (to restore that saved state, overriding any more recent state) or else to * JS_DropExceptionState (to free the state struct in case it is not correct * or desirable to restore it). Both Restore and Drop free the state struct, * so callers must stop using the pointer returned from Save after calling the * Release or Drop API. */ 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 jsval *vp); /************************************************************************/ #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(JSContext *cx, bool enabled); extern JS_PUBLIC_API(void) JS_SetParallelIonCompilationEnabled(JSContext *cx, 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") typedef enum JSJitCompilerOption { #define JIT_COMPILER_DECLARE(key, str) \ JSJITCOMPILER_ ## key, JIT_COMPILER_OPTIONS(JIT_COMPILER_DECLARE) #undef JIT_COMPILER_DECLARE JSJITCOMPILER_NOT_AN_OPTION } JSJitCompilerOption; extern JS_PUBLIC_API(void) JS_SetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt, uint32_t value); extern JS_PUBLIC_API(int) JS_GetGlobalJitCompilerOption(JSContext *cx, 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); /* * Return the current script 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) JS_DescribeScriptedCaller(JSContext *cx, JS::MutableHandleScript script, unsigned *lineno); namespace JS { /* * 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 JS_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 *principals, JSPrincipals *originPrincipals); extern JS_PUBLIC_API(JSObject *) JS_DecodeInterpretedFunction(JSContext *cx, const void *data, uint32_t length, JSPrincipals *principals, 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. */ typedef bool (* OpenAsmJSCacheEntryForWriteOp)(HandleObject global, 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_; JS::RootedObject iterator; ForOfIterator(const ForOfIterator &) MOZ_DELETE; ForOfIterator &operator=(const ForOfIterator &) MOZ_DELETE; public: ForOfIterator(JSContext *cx) : cx_(cx), iterator(cx) { } 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; } }; } /* namespace JS */ #endif /* jsapi_h */