| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
| * vim: set ts=8 sts=4 et sw=4 tw=99: |
| * This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| /* JavaScript API. */ |
| |
| #ifndef jsapi_h |
| #define jsapi_h |
| |
| #include "mozilla/FloatingPoint.h" |
| #include "mozilla/RangedPtr.h" |
| #include "mozilla/StandardInteger.h" |
| #include "mozilla/ThreadLocal.h" |
| #include "mozilla/TypeTraits.h" |
| |
| #include <stdarg.h> |
| #include <stddef.h> |
| #include <stdio.h> |
| |
| #include "js-config.h" |
| #include "jsalloc.h" |
| #include "jspubtd.h" |
| |
| #include "js/CallArgs.h" |
| #include "js/CharacterEncoding.h" |
| #include "js/HashTable.h" |
| #include "js/RootingAPI.h" |
| #include "js/Utility.h" |
| #include "js/Value.h" |
| #include "js/Vector.h" |
| |
| #include "starboard/file.h" |
| #include "nb/memory_scope.h" |
| |
| /************************************************************************/ |
| |
| namespace JS { |
| |
| typedef mozilla::RangedPtr<const jschar> CharPtr; |
| |
| class StableCharPtr : public CharPtr { |
| public: |
| StableCharPtr(const StableCharPtr &s) : CharPtr(s) {} |
| StableCharPtr(const mozilla::RangedPtr<const jschar> &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) |
| {} |
| }; |
| |
| #if defined JS_THREADSAFE && defined JS_DEBUG |
| |
| class JS_PUBLIC_API(AutoCheckRequestDepth) |
| { |
| JSContext *cx; |
| public: |
| AutoCheckRequestDepth(JSContext *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, const Value &v); |
| #else |
| inline void AssertArgumentsAreSane(JSContext *cx, const Value &v) { |
| /* Do nothing */ |
| } |
| #endif /* JS_DEBUG */ |
| |
| class JS_PUBLIC_API(AutoGCRooter) { |
| public: |
| AutoGCRooter(JSContext *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 */ |
| DESCRIPTOR = -11, /* js::AutoPropertyDescriptorRooter */ |
| 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 */ |
| }; |
| |
| 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 = NULL |
| 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 *array; |
| |
| 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]); |
| } |
| |
| friend void AutoGCRooter::trace(JSTracer *trc); |
| |
| private: |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| |
| js::SkipRoot skip; |
| }; |
| |
| template<class T> |
| class AutoVectorRooter : protected AutoGCRooter |
| { |
| 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; |
| } |
| |
| typedef T ElementType; |
| |
| size_t length() const { return vector.length(); } |
| bool empty() const { return vector.empty(); } |
| |
| bool append(const T &v) { return vector.append(v); } |
| bool append(const AutoVectorRooter<T> &other) { |
| return vector.append(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) { |
| TRACK_MEMORY_SCOPE("Javascript"); |
| 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<T> handleAt(size_t i) { return JS::MutableHandle<T>::fromMarkedLocation(&vector[i]); } |
| JS::Handle<T> handleAt(size_t i) const { return JS::Handle<T>::fromMarkedLocation(&vector[i]); } |
| |
| const T *begin() const { return vector.begin(); } |
| T *begin() { return vector.begin(); } |
| |
| const T *end() const { return vector.end(); } |
| T *end() { return vector.end(); } |
| |
| 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)); |
| } |
| |
| typedef js::Vector<T, 8> VectorImpl; |
| VectorImpl vector; |
| |
| /* Prevent overwriting of inline elements in vector. */ |
| js::SkipRoot vectorRoot; |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| template<class Key, class Value> |
| class AutoHashMapRooter : protected AutoGCRooter |
| { |
| private: |
| typedef js::HashMap<Key, Value> HashMapImpl; |
| |
| public: |
| explicit AutoHashMapRooter(JSContext *cx, ptrdiff_t tag |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, tag), map(cx) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| typedef Key KeyType; |
| typedef Value ValueType; |
| typedef typename HashMapImpl::Lookup Lookup; |
| typedef typename HashMapImpl::Ptr Ptr; |
| typedef typename HashMapImpl::AddPtr AddPtr; |
| |
| bool init(uint32_t len = 16) { |
| return map.init(len); |
| } |
| bool initialized() const { |
| return map.initialized(); |
| } |
| Ptr lookup(const Lookup &l) const { |
| return map.lookup(l); |
| } |
| void remove(Ptr p) { |
| map.remove(p); |
| } |
| AddPtr lookupForAdd(const Lookup &l) const { |
| return map.lookupForAdd(l); |
| } |
| |
| template<typename KeyInput, typename ValueInput> |
| bool add(AddPtr &p, const KeyInput &k, const ValueInput &v) { |
| return map.add(p, k, v); |
| } |
| |
| bool add(AddPtr &p, const Key &k) { |
| return map.add(p, k); |
| } |
| |
| template<typename KeyInput, typename ValueInput> |
| bool relookupOrAdd(AddPtr &p, const KeyInput &k, const ValueInput &v) { |
| return map.relookupOrAdd(p, k, v); |
| } |
| |
| typedef typename HashMapImpl::Range Range; |
| Range all() const { |
| return map.all(); |
| } |
| |
| typedef typename HashMapImpl::Enum Enum; |
| |
| void clear() { |
| map.clear(); |
| } |
| |
| void finish() { |
| map.finish(); |
| } |
| |
| bool empty() const { |
| return map.empty(); |
| } |
| |
| uint32_t count() const { |
| return map.count(); |
| } |
| |
| size_t capacity() const { |
| return map.capacity(); |
| } |
| |
| size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const { |
| return map.sizeOfExcludingThis(mallocSizeOf); |
| } |
| size_t sizeOfIncludingThis(JSMallocSizeOfFun 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<typename KeyInput, typename ValueInput> |
| bool put(const KeyInput &k, const ValueInput &v) { |
| return map.put(k, v); |
| } |
| |
| template<typename KeyInput, typename ValueInput> |
| bool putNew(const KeyInput &k, const ValueInput &v) { |
| return map.putNew(k, v); |
| } |
| |
| Ptr lookupWithDefault(const Key &k, const Value &defaultValue) { |
| return map.lookupWithDefault(k, defaultValue); |
| } |
| |
| void remove(const Lookup &l) { |
| map.remove(l); |
| } |
| |
| friend void AutoGCRooter::trace(JSTracer *trc); |
| |
| private: |
| AutoHashMapRooter(const AutoHashMapRooter &hmr) MOZ_DELETE; |
| AutoHashMapRooter &operator=(const AutoHashMapRooter &hmr) MOZ_DELETE; |
| |
| HashMapImpl map; |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| template<class T> |
| class AutoHashSetRooter : protected AutoGCRooter |
| { |
| private: |
| typedef js::HashSet<T> HashSetImpl; |
| |
| public: |
| explicit AutoHashSetRooter(JSContext *cx, ptrdiff_t tag |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, tag), set(cx) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| typedef typename HashSetImpl::Lookup Lookup; |
| typedef typename HashSetImpl::Ptr Ptr; |
| typedef typename HashSetImpl::AddPtr AddPtr; |
| |
| bool init(uint32_t len = 16) { |
| return set.init(len); |
| } |
| bool initialized() const { |
| return set.initialized(); |
| } |
| Ptr lookup(const Lookup &l) const { |
| return set.lookup(l); |
| } |
| void remove(Ptr p) { |
| set.remove(p); |
| } |
| AddPtr lookupForAdd(const Lookup &l) const { |
| return set.lookupForAdd(l); |
| } |
| |
| bool add(AddPtr &p, const T &t) { |
| return set.add(p, t); |
| } |
| |
| bool relookupOrAdd(AddPtr &p, const Lookup &l, const T &t) { |
| return set.relookupOrAdd(p, l, t); |
| } |
| |
| typedef typename HashSetImpl::Range Range; |
| Range all() const { |
| return set.all(); |
| } |
| |
| typedef typename HashSetImpl::Enum Enum; |
| |
| void clear() { |
| set.clear(); |
| } |
| |
| void finish() { |
| set.finish(); |
| } |
| |
| bool empty() const { |
| return set.empty(); |
| } |
| |
| uint32_t count() const { |
| return set.count(); |
| } |
| |
| size_t capacity() const { |
| return set.capacity(); |
| } |
| |
| size_t sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf) const { |
| return set.sizeOfExcludingThis(mallocSizeOf); |
| } |
| size_t sizeOfIncludingThis(JSMallocSizeOfFun 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<Value> |
| { |
| public: |
| explicit AutoValueVector(JSContext *cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoVectorRooter<Value>(cx, VALVECTOR) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| class AutoIdVector : public AutoVectorRooter<jsid> |
| { |
| public: |
| explicit AutoIdVector(JSContext *cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoVectorRooter<jsid>(cx, IDVECTOR) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| class AutoObjectVector : public AutoVectorRooter<JSObject *> |
| { |
| public: |
| explicit AutoObjectVector(JSContext *cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoVectorRooter<JSObject *>(cx, OBJVECTOR) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| class AutoScriptVector : public AutoVectorRooter<JSScript *> |
| { |
| public: |
| explicit AutoScriptVector(JSContext *cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoVectorRooter<JSScript *>(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: |
| explicit CustomAutoRooter(JSContext *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 |
| }; |
| |
| /* Returns true if |v| is considered an acceptable this-value. */ |
| typedef bool (*IsAcceptableThis)(const Value &v); |
| |
| /* |
| * Implements the guts of a method; guaranteed to be provided an acceptable |
| * this-value, as determined by a corresponding IsAcceptableThis method. |
| */ |
| typedef bool (*NativeImpl)(JSContext *cx, CallArgs args); |
| |
| namespace detail { |
| |
| /* DON'T CALL THIS DIRECTLY. It's for use only by CallNonGenericMethod! */ |
| extern JS_PUBLIC_API(bool) |
| CallMethodIfWrapped(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args); |
| |
| } /* namespace detail */ |
| |
| /* |
| * Methods usually act upon |this| objects only from a single global object and |
| * compartment. Sometimes, however, a method must act upon |this| values from |
| * multiple global objects or compartments. In such cases the |this| value a |
| * method might see will be wrapped, such that various access to the object -- |
| * to its class, its private data, its reserved slots, and so on -- will not |
| * work properly without entering that object's compartment. This method |
| * implements a solution to this problem. |
| * |
| * To implement a method that accepts |this| values from multiple compartments, |
| * define two functions. The first function matches the IsAcceptableThis type |
| * and indicates whether the provided value is an acceptable |this| for the |
| * method; it must be a pure function only of its argument. |
| * |
| * static JSClass AnswerClass = { ... }; |
| * |
| * static bool |
| * IsAnswerObject(const Value &v) |
| * { |
| * if (!v.isObject()) |
| * return false; |
| * return JS_GetClass(&v.toObject()) == &AnswerClass; |
| * } |
| * |
| * The second function implements the NativeImpl signature and defines the |
| * behavior of the method when it is provided an acceptable |this| value. |
| * Aside from some typing niceties -- see the CallArgs interface for details -- |
| * its interface is the same as that of JSNative. |
| * |
| * static bool |
| * answer_getAnswer_impl(JSContext *cx, JS::CallArgs args) |
| * { |
| * args.rval().setInt32(42); |
| * return true; |
| * } |
| * |
| * The implementation function is guaranteed to be called *only* with a |this| |
| * value which is considered acceptable. |
| * |
| * Now to implement the actual method, write a JSNative that calls the method |
| * declared below, passing the appropriate template and runtime arguments. |
| * |
| * static JSBool |
| * answer_getAnswer(JSContext *cx, unsigned argc, JS::Value *vp) |
| * { |
| * JS::CallArgs args = JS::CallArgsFromVp(argc, vp); |
| * return JS::CallNonGenericMethod<IsAnswerObject, answer_getAnswer_impl>(cx, args); |
| * } |
| * |
| * Note that, because they are used as template arguments, the predicate |
| * and implementation functions must have external linkage. (This is |
| * unfortunate, but GCC wasn't inlining things as one would hope when we |
| * passed them as function arguments.) |
| * |
| * JS::CallNonGenericMethod will test whether |args.thisv()| is acceptable. If |
| * it is, it will call the provided implementation function, which will return |
| * a value and indicate success. If it is not, it will attempt to unwrap |
| * |this| and call the implementation function on the unwrapped |this|. If |
| * that succeeds, all well and good. If it doesn't succeed, a TypeError will |
| * be thrown. |
| * |
| * Note: JS::CallNonGenericMethod will only work correctly if it's called in |
| * tail position in a JSNative. Do not call it from any other place. |
| */ |
| template<IsAcceptableThis Test, NativeImpl Impl> |
| JS_ALWAYS_INLINE bool |
| CallNonGenericMethod(JSContext *cx, CallArgs args) |
| { |
| const Value &thisv = args.thisv(); |
| if (Test(thisv)) |
| return Impl(cx, args); |
| |
| return detail::CallMethodIfWrapped(cx, Test, Impl, args); |
| } |
| |
| JS_ALWAYS_INLINE bool |
| CallNonGenericMethod(JSContext *cx, IsAcceptableThis Test, NativeImpl Impl, CallArgs args) |
| { |
| TRACK_MEMORY_SCOPE("Javascript"); |
| const Value &thisv = args.thisv(); |
| if (Test(thisv)) |
| return Impl(cx, args); |
| |
| return detail::CallMethodIfWrapped(cx, Test, Impl, args); |
| } |
| |
| } /* namespace JS */ |
| |
| /************************************************************************/ |
| |
| /* JSClass operation signatures. */ |
| |
| /* |
| * Add or get a property named by id in obj. Note the jsid id type -- id may |
| * be a string (Unicode property identifier) or an int (element index). The |
| * *vp out parameter, on success, is the new property value after the action. |
| */ |
| typedef JSBool |
| (* JSPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp); |
| |
| /* |
| * Set a property named by id in obj, treating the assignment as strict |
| * mode code if strict is true. Note the jsid id type -- id may be a string |
| * (Unicode property identifier) or an int (element index). The *vp out |
| * parameter, on success, is the new property value after the |
| * set. |
| */ |
| typedef JSBool |
| (* JSStrictPropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool strict, JS::MutableHandle<JS::Value> vp); |
| |
| /* |
| * Delete a property named by id in obj. |
| * |
| * If an error occurred, return false as per normal JSAPI error practice. |
| * |
| * If no error occurred, but the deletion attempt wasn't allowed (perhaps |
| * because the property was non-configurable), set *succeeded to false and |
| * return true. This will cause |delete obj[id]| to evaluate to false in |
| * non-strict mode code, and to throw a TypeError in strict mode code. |
| * |
| * If no error occurred and the deletion wasn't disallowed (this is *not* the |
| * same as saying that a deletion actually occurred -- deleting a non-existent |
| * property, or an inherited property, is allowed -- it's just pointless), |
| * set *succeeded to true and return true. |
| */ |
| typedef JSBool |
| (* JSDeletePropertyOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool *succeeded); |
| |
| /* |
| * This function type is used for callbacks that enumerate the properties of |
| * a JSObject. The behavior depends on the value of enum_op: |
| * |
| * JSENUMERATE_INIT |
| * A new, opaque iterator state should be allocated and stored in *statep. |
| * (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored). |
| * |
| * The number of properties that will be enumerated should be returned as |
| * an integer jsval in *idp, if idp is non-null, and provided the number of |
| * enumerable properties is known. If idp is non-null and the number of |
| * enumerable properties can't be computed in advance, *idp should be set |
| * to JSVAL_ZERO. |
| * |
| * JSENUMERATE_INIT_ALL |
| * Used identically to JSENUMERATE_INIT, but exposes all properties of the |
| * object regardless of enumerability. |
| * |
| * JSENUMERATE_NEXT |
| * A previously allocated opaque iterator state is passed in via statep. |
| * Return the next jsid in the iteration using *idp. The opaque iterator |
| * state pointed at by statep is destroyed and *statep is set to JSVAL_NULL |
| * if there are no properties left to enumerate. |
| * |
| * JSENUMERATE_DESTROY |
| * Destroy the opaque iterator state previously allocated in *statep by a |
| * call to this function when enum_op was JSENUMERATE_INIT or |
| * JSENUMERATE_INIT_ALL. |
| * |
| * The return value is used to indicate success, with a value of JS_FALSE |
| * indicating failure. |
| */ |
| typedef JSBool |
| (* JSNewEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSIterateOp enum_op, |
| JS::MutableHandle<JS::Value> statep, JS::MutableHandleId idp); |
| |
| /* |
| * The old-style JSClass.enumerate op should define all lazy properties not |
| * yet reflected in obj. |
| */ |
| typedef JSBool |
| (* JSEnumerateOp)(JSContext *cx, JS::Handle<JSObject*> obj); |
| |
| /* |
| * Resolve a lazy property named by id in obj by defining it directly in obj. |
| * Lazy properties are those reflected from some peer native property space |
| * (e.g., the DOM attributes for a given node reflected as obj) on demand. |
| * |
| * JS looks for a property in an object, and if not found, tries to resolve |
| * the given id. If resolve succeeds, the engine looks again in case resolve |
| * defined obj[id]. If no such property exists directly in obj, the process |
| * is repeated with obj's prototype, etc. |
| * |
| * NB: JSNewResolveOp provides a cheaper way to resolve lazy properties. |
| */ |
| typedef JSBool |
| (* JSResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id); |
| |
| /* |
| * Like JSResolveOp, but flags provide contextual information as follows: |
| * |
| * JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment |
| * |
| * The *objp out parameter, on success, should be null to indicate that id |
| * was not resolved; and non-null, referring to obj or one of its prototypes, |
| * if id was resolved. The hook may assume *objp is null on entry. |
| * |
| * This hook instead of JSResolveOp is called via the JSClass.resolve member |
| * if JSCLASS_NEW_RESOLVE is set in JSClass.flags. |
| */ |
| typedef JSBool |
| (* JSNewResolveOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, unsigned flags, |
| JS::MutableHandleObject objp); |
| |
| /* |
| * Convert obj to the given type, returning true with the resulting value in |
| * *vp on success, and returning false on error or exception. |
| */ |
| typedef JSBool |
| (* JSConvertOp)(JSContext *cx, JS::Handle<JSObject*> obj, JSType type, |
| JS::MutableHandle<JS::Value> vp); |
| |
| typedef struct JSFreeOp JSFreeOp; |
| |
| struct JSFreeOp { |
| private: |
| JSRuntime *runtime_; |
| |
| protected: |
| JSFreeOp(JSRuntime *rt) |
| : runtime_(rt) { } |
| |
| public: |
| JSRuntime *runtime() const { |
| return runtime_; |
| } |
| }; |
| |
| /* |
| * Finalize obj, which the garbage collector has determined to be unreachable |
| * from other live objects or from GC roots. Obviously, finalizers must never |
| * store a reference to obj. |
| */ |
| typedef void |
| (* JSFinalizeOp)(JSFreeOp *fop, JSObject *obj); |
| |
| /* |
| * Finalizes external strings created by JS_NewExternalString. |
| */ |
| typedef struct JSStringFinalizer JSStringFinalizer; |
| |
| struct JSStringFinalizer { |
| void (*finalize)(const JSStringFinalizer *fin, jschar *chars); |
| }; |
| |
| /* |
| * JSClass.checkAccess type: check whether obj[id] may be accessed per mode, |
| * returning false on error/exception, true on success with obj[id]'s last-got |
| * value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id |
| * is either a string or an int jsval. |
| */ |
| typedef JSBool |
| (* JSCheckAccessOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, |
| JSAccessMode mode, JS::MutableHandle<JS::Value> vp); |
| |
| /* |
| * Check whether v is an instance of obj. Return false on error or exception, |
| * true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in |
| * *bp otherwise. |
| */ |
| typedef JSBool |
| (* JSHasInstanceOp)(JSContext *cx, JS::Handle<JSObject*> obj, JS::MutableHandle<JS::Value> vp, |
| JSBool *bp); |
| |
| /* |
| * Function type for trace operation of the class called to enumerate all |
| * traceable things reachable from obj's private data structure. For each such |
| * thing, a trace implementation must call one of the JS_Call*Tracer variants |
| * on the thing. |
| * |
| * JSTraceOp implementation can assume that no other threads mutates object |
| * state. It must not change state of the object or corresponding native |
| * structures. The only exception for this rule is the case when the embedding |
| * needs a tight integration with GC. In that case the embedding can check if |
| * the traversal is a part of the marking phase through calling |
| * JS_IsGCMarkingTracer and apply a special code like emptying caches or |
| * marking its native structures. |
| */ |
| typedef void |
| (* JSTraceOp)(JSTracer *trc, JSObject *obj); |
| |
| /* |
| * Callback that JSTraceOp implementation can provide to return a string |
| * describing the reference traced with JS_CallTracer. |
| */ |
| typedef void |
| (* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize); |
| |
| typedef JSObject * |
| (* JSWeakmapKeyDelegateOp)(JSObject *obj); |
| |
| /* 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 JSBool |
| (* JSContextCallback)(JSContext *cx, unsigned contextOp); |
| |
| typedef enum JSGCStatus { |
| JSGC_BEGIN, |
| JSGC_END |
| } JSGCStatus; |
| |
| typedef void |
| (* JSGCCallback)(JSRuntime *rt, JSGCStatus status); |
| |
| 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, JSBool isCompartment); |
| |
| /* |
| * Generic trace operation that calls JS_CallTracer on each traceable thing |
| * stored in data. |
| */ |
| typedef void |
| (* JSTraceDataOp)(JSTracer *trc, void *data); |
| |
| typedef JSBool |
| (* 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 JSBool |
| (* JSLocaleToUpperCase)(JSContext *cx, JS::Handle<JSString*> src, |
| JS::MutableHandle<JS::Value> rval); |
| |
| typedef JSBool |
| (* JSLocaleToLowerCase)(JSContext *cx, JS::Handle<JSString*> src, |
| JS::MutableHandle<JS::Value> rval); |
| |
| typedef JSBool |
| (* JSLocaleCompare)(JSContext *cx, JS::Handle<JSString*> src1, JS::Handle<JSString*> src2, |
| JS::MutableHandle<JS::Value> rval); |
| |
| typedef JSBool |
| (* JSLocaleToUnicode)(JSContext *cx, const char *src, JS::MutableHandle<JS::Value> 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 JSBool |
| (* 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-NULL, 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); |
| |
| 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); |
| |
| /* |
| * Read structured data from the reader r. This hook is used to read a value |
| * previously serialized by a call to the WriteStructuredCloneOp hook. |
| * |
| * tag and data are the pair of uint32_t values from the header. The callback |
| * may use the JS_Read* APIs to read any other relevant parts of the object |
| * from the reader r. closure is any value passed to the JS_ReadStructuredClone |
| * function. Return the new object on success, NULL on error/exception. |
| */ |
| typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r, |
| uint32_t tag, uint32_t data, void *closure); |
| |
| /* |
| * Structured data serialization hook. The engine can write primitive values, |
| * Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other |
| * type of object requires application support. This callback must first use |
| * the JS_WriteUint32Pair API to write an object header, passing a value |
| * greater than JS_SCTAG_USER to the tag parameter. Then it can use the |
| * JS_Write* APIs to write any other relevant parts of the value v to the |
| * writer w. closure is any value passed to the JS_WriteStructuredCLone function. |
| * |
| * Return true on success, false on error/exception. |
| */ |
| typedef JSBool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w, |
| JS::Handle<JSObject*> obj, void *closure); |
| |
| /* |
| * This is called when JS_WriteStructuredClone is given an invalid transferable. |
| * To follow HTML5, the application must throw a DATA_CLONE_ERR DOMException |
| * with error set to one of the JS_SCERR_* values. |
| */ |
| typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32_t errorid); |
| |
| /************************************************************************/ |
| |
| /* |
| * JS constants. For efficiency, prefer predicates (e.g. v.isNull()) and |
| * constructing values from scratch (e.g. Int32Value(0)). These constants are |
| * stored in memory and initialized at startup, so testing against them and |
| * using them requires memory loads and will be correspondingly slow. |
| */ |
| extern JS_PUBLIC_DATA(const jsval) JSVAL_NULL; |
| extern JS_PUBLIC_DATA(const jsval) JSVAL_ZERO; |
| extern JS_PUBLIC_DATA(const jsval) JSVAL_ONE; |
| extern JS_PUBLIC_DATA(const jsval) JSVAL_FALSE; |
| extern JS_PUBLIC_DATA(const jsval) JSVAL_TRUE; |
| extern JS_PUBLIC_DATA(const jsval) JSVAL_VOID; |
| |
| static JS_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); |
| } |
| |
| /************************************************************************/ |
| |
| /* |
| * A jsid is an identifier for a property or method of an object which is |
| * either a 31-bit signed integer, interned string or object. Also, there is |
| * an additional jsid value, JSID_VOID, which does not occur in JS scripts but |
| * may be used to indicate the absence of a valid jsid. |
| * |
| * A jsid is not implicitly convertible to or from a jsval; JS_ValueToId or |
| * JS_IdToValue must be used instead. |
| */ |
| |
| #define JSID_TYPE_STRING 0x0 |
| #define JSID_TYPE_INT 0x1 |
| #define JSID_TYPE_VOID 0x2 |
| #define JSID_TYPE_OBJECT 0x4 |
| #define JSID_TYPE_MASK 0x7 |
| |
| /* |
| * Avoid using canonical 'id' for jsid parameters since this is a magic word in |
| * Objective-C++ which, apparently, wants to be able to #include jsapi.h. |
| */ |
| #define id iden |
| |
| static JS_ALWAYS_INLINE JSBool |
| JSID_IS_STRING(jsid id) |
| { |
| return (JSID_BITS(id) & JSID_TYPE_MASK) == 0; |
| } |
| |
| static JS_ALWAYS_INLINE JSString * |
| JSID_TO_STRING(jsid id) |
| { |
| JS_ASSERT(JSID_IS_STRING(id)); |
| return (JSString *)JSID_BITS(id); |
| } |
| |
| static JS_ALWAYS_INLINE JSBool |
| JSID_IS_ZERO(jsid id) |
| { |
| return JSID_BITS(id) == 0; |
| } |
| |
| JS_PUBLIC_API(JSBool) |
| 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); |
| |
| static JS_ALWAYS_INLINE JSBool |
| JSID_IS_INT(jsid id) |
| { |
| return !!(JSID_BITS(id) & JSID_TYPE_INT); |
| } |
| |
| static JS_ALWAYS_INLINE int32_t |
| JSID_TO_INT(jsid id) |
| { |
| JS_ASSERT(JSID_IS_INT(id)); |
| return ((uint32_t)JSID_BITS(id)) >> 1; |
| } |
| |
| #define JSID_INT_MIN 0 |
| #define JSID_INT_MAX INT32_MAX |
| |
| static JS_ALWAYS_INLINE JSBool |
| INT_FITS_IN_JSID(int32_t i) |
| { |
| return i >= 0; |
| } |
| |
| static JS_ALWAYS_INLINE jsid |
| INT_TO_JSID(int32_t i) |
| { |
| jsid id; |
| JS_ASSERT(INT_FITS_IN_JSID(i)); |
| JSID_BITS(id) = ((i << 1) | JSID_TYPE_INT); |
| return id; |
| } |
| |
| static JS_ALWAYS_INLINE JSBool |
| JSID_IS_OBJECT(jsid id) |
| { |
| return (JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_OBJECT && |
| (size_t)JSID_BITS(id) != JSID_TYPE_OBJECT; |
| } |
| |
| static JS_ALWAYS_INLINE JSObject * |
| JSID_TO_OBJECT(jsid id) |
| { |
| JS_ASSERT(JSID_IS_OBJECT(id)); |
| return (JSObject *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK); |
| } |
| |
| static JS_ALWAYS_INLINE jsid |
| OBJECT_TO_JSID(JSObject *obj) |
| { |
| jsid id; |
| JS_ASSERT(obj != NULL); |
| JS_ASSERT(((size_t)obj & JSID_TYPE_MASK) == 0); |
| JSID_BITS(id) = ((size_t)obj | JSID_TYPE_OBJECT); |
| return id; |
| } |
| |
| static JS_ALWAYS_INLINE JSBool |
| JSID_IS_GCTHING(jsid id) |
| { |
| return JSID_IS_STRING(id) || JSID_IS_OBJECT(id); |
| } |
| |
| static JS_ALWAYS_INLINE void * |
| JSID_TO_GCTHING(jsid id) |
| { |
| return (void *)(JSID_BITS(id) & ~(size_t)JSID_TYPE_MASK); |
| } |
| |
| /* |
| * A void jsid is not a valid id and only arises as an exceptional API return |
| * value, such as in JS_NextProperty. Embeddings must not pass JSID_VOID into |
| * JSAPI entry points expecting a jsid and do not need to handle JSID_VOID in |
| * hooks receiving a jsid except when explicitly noted in the API contract. |
| */ |
| |
| static JS_ALWAYS_INLINE JSBool |
| JSID_IS_VOID(const jsid id) |
| { |
| JS_ASSERT_IF(((size_t)JSID_BITS(id) & JSID_TYPE_MASK) == JSID_TYPE_VOID, |
| JSID_BITS(id) == JSID_TYPE_VOID); |
| return ((size_t)JSID_BITS(id) == JSID_TYPE_VOID); |
| } |
| |
| static JS_ALWAYS_INLINE JSBool |
| JSID_IS_EMPTY(const jsid id) |
| { |
| return ((size_t)JSID_BITS(id) == JSID_TYPE_OBJECT); |
| } |
| |
| #undef id |
| |
| #ifdef JS_USE_JSID_STRUCT_TYPES |
| extern JS_PUBLIC_DATA(const jsid) JSID_VOID; |
| extern JS_PUBLIC_DATA(const jsid) JSID_EMPTY; |
| #else |
| # define JSID_VOID ((jsid)JSID_TYPE_VOID) |
| # define JSID_EMPTY ((jsid)JSID_TYPE_OBJECT) |
| #endif |
| |
| /* |
| * Returns true iff the given jsval is immune to GC and can be used across |
| * multiple JSRuntimes without requiring any conversion API. |
| */ |
| static JS_ALWAYS_INLINE JSBool |
| 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(JSBool) |
| 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 JSBool Boolean |
| * c uint16_t/jschar ECMA uint16_t, Unicode char |
| * i int32_t ECMA int32_t |
| * u uint32_t ECMA uint32_t |
| * j int32_t Rounded int32_t (coordinate) |
| * 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(JSBool) |
| JS_ConvertArguments(JSContext *cx, unsigned argc, jsval *argv, const char *format, |
| ...); |
| |
| #ifdef va_start |
| extern JS_PUBLIC_API(JSBool) |
| JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, |
| const char *format, va_list ap); |
| #endif |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp); |
| |
| extern JS_PUBLIC_API(JSFunction *) |
| JS_ValueToFunction(JSContext *cx, jsval v); |
| |
| extern JS_PUBLIC_API(JSFunction *) |
| JS_ValueToConstructor(JSContext *cx, jsval v); |
| |
| extern JS_PUBLIC_API(JSString *) |
| JS_ValueToString(JSContext *cx, jsval v); |
| |
| extern JS_PUBLIC_API(JSString *) |
| JS_ValueToSource(JSContext *cx, jsval v); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToNumber(JSContext *cx, jsval v, double *dp); |
| |
| 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(const JS::Value &v); |
| } /* namespace js */ |
| |
| namespace JS { |
| |
| /* ES5 9.3 ToNumber. */ |
| JS_ALWAYS_INLINE bool |
| ToNumber(JSContext *cx, const Value &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); |
| } |
| |
| JS_ALWAYS_INLINE bool |
| ToBoolean(const Value &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); |
| } |
| |
| } /* namespace JS */ |
| |
| extern JS_PUBLIC_API(JSBool) |
| 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); |
| |
| /* |
| * Convert a value to a number, then to an int32_t, according to the ECMA rules |
| * for ToInt32. |
| */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToECMAInt32(JSContext *cx, jsval v, int32_t *ip); |
| |
| /* |
| * Convert a value to a number, then to an int64_t, according to the WebIDL |
| * rules for ToInt64: http://dev.w3.org/2006/webapi/WebIDL/#es-long-long |
| */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToInt64(JSContext *cx, jsval v, int64_t *ip); |
| |
| /* |
| * Convert a value to a number, then to an uint64_t, according to the WebIDL |
| * rules for ToUint64: http://dev.w3.org/2006/webapi/WebIDL/#es-unsigned-long-long |
| */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToUint64(JSContext *cx, jsval v, uint64_t *ip); |
| |
| namespace js { |
| /* DO NOT CALL THIS. Use JS::ToInt16. */ |
| extern JS_PUBLIC_API(bool) |
| ToUint16Slow(JSContext *cx, const JS::Value &v, uint16_t *out); |
| |
| /* DO NOT CALL THIS. Use JS::ToInt32. */ |
| extern JS_PUBLIC_API(bool) |
| ToInt32Slow(JSContext *cx, const JS::Value &v, int32_t *out); |
| |
| /* DO NOT CALL THIS. Use JS::ToUint32. */ |
| extern JS_PUBLIC_API(bool) |
| ToUint32Slow(JSContext *cx, const JS::Value &v, uint32_t *out); |
| |
| /* DO NOT CALL THIS. Use JS::ToInt64. */ |
| extern JS_PUBLIC_API(bool) |
| ToInt64Slow(JSContext *cx, const JS::Value &v, int64_t *out); |
| |
| /* DO NOT CALL THIS. Use JS::ToUint64. */ |
| extern JS_PUBLIC_API(bool) |
| ToUint64Slow(JSContext *cx, const JS::Value &v, uint64_t *out); |
| } /* namespace js */ |
| |
| namespace JS { |
| |
| JS_ALWAYS_INLINE bool |
| ToUint16(JSContext *cx, const JS::Value &v, uint16_t *out) |
| { |
| AssertArgumentsAreSane(cx, v); |
| { |
| js::SkipRoot skip(cx, &v); |
| js::MaybeCheckStackRoots(cx); |
| } |
| |
| if (v.isInt32()) { |
| *out = uint16_t(v.toInt32()); |
| return true; |
| } |
| return js::ToUint16Slow(cx, v, out); |
| } |
| |
| JS_ALWAYS_INLINE bool |
| ToInt32(JSContext *cx, const JS::Value &v, int32_t *out) |
| { |
| AssertArgumentsAreSane(cx, v); |
| { |
| js::SkipRoot root(cx, &v); |
| js::MaybeCheckStackRoots(cx); |
| } |
| |
| if (v.isInt32()) { |
| *out = v.toInt32(); |
| return true; |
| } |
| return js::ToInt32Slow(cx, v, out); |
| } |
| |
| JS_ALWAYS_INLINE bool |
| ToUint32(JSContext *cx, const JS::Value &v, uint32_t *out) |
| { |
| AssertArgumentsAreSane(cx, v); |
| { |
| js::SkipRoot root(cx, &v); |
| js::MaybeCheckStackRoots(cx); |
| } |
| |
| if (v.isInt32()) { |
| *out = uint32_t(v.toInt32()); |
| return true; |
| } |
| return js::ToUint32Slow(cx, v, out); |
| } |
| |
| JS_ALWAYS_INLINE bool |
| ToInt64(JSContext *cx, const JS::Value &v, int64_t *out) |
| { |
| AssertArgumentsAreSane(cx, v); |
| { |
| js::SkipRoot skip(cx, &v); |
| js::MaybeCheckStackRoots(cx); |
| } |
| |
| if (v.isInt32()) { |
| *out = int64_t(v.toInt32()); |
| return true; |
| } |
| |
| return js::ToInt64Slow(cx, v, out); |
| } |
| |
| JS_ALWAYS_INLINE bool |
| ToUint64(JSContext *cx, const JS::Value &v, uint64_t *out) |
| { |
| AssertArgumentsAreSane(cx, v); |
| { |
| js::SkipRoot skip(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 */ |
| |
| /* |
| * Convert a value to a number, then to a uint32_t, according to the ECMA rules |
| * for ToUint32. |
| */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToECMAUint32(JSContext *cx, jsval v, uint32_t *ip); |
| |
| /* |
| * Convert a value to a number, then to an int32_t if it fits by rounding to |
| * nearest; but failing with an error report if the double is out of range |
| * or unordered. |
| */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToInt32(JSContext *cx, jsval v, int32_t *ip); |
| |
| /* |
| * ECMA ToUint16, for mapping a jsval to a Unicode point. |
| */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToUint16(JSContext *cx, jsval v, uint16_t *ip); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp); |
| |
| extern JS_PUBLIC_API(JSType) |
| JS_TypeOfValue(JSContext *cx, jsval v); |
| |
| extern JS_PUBLIC_API(const char *) |
| JS_GetTypeName(JSContext *cx, JSType type); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_StrictlyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_LooselyEqual(JSContext *cx, jsval v1, jsval v2, JSBool *equal); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_SameValue(JSContext *cx, jsval v1, jsval v2, JSBool *same); |
| |
| /* True iff fun is the global eval function. */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_IsBuiltinEvalFunction(JSFunction *fun); |
| |
| /* True iff fun is the Function constructor. */ |
| extern JS_PUBLIC_API(JSBool) |
| 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; |
| |
| extern JS_PUBLIC_API(JSRuntime *) |
| JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads); |
| |
| extern JS_PUBLIC_API(void) |
| JS_DestroyRuntime(JSRuntime *rt); |
| |
| extern JS_PUBLIC_API(void) |
| JS_ShutDown(void); |
| |
| 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(JSBool) |
| JS_IsInRequest(JSRuntime *rt); |
| |
| namespace JS { |
| |
| inline bool |
| IsPoisonedId(jsid iden) |
| { |
| if (JSID_IS_STRING(iden)) |
| return JS::IsPoisonedPtr(JSID_TO_STRING(iden)); |
| if (JSID_IS_OBJECT(iden)) |
| return JS::IsPoisonedPtr(JSID_TO_OBJECT(iden)); |
| return false; |
| } |
| |
| } /* namespace JS */ |
| |
| namespace js { |
| |
| template <> struct GCMethods<jsid> |
| { |
| static jsid initial() { return JSID_VOID; } |
| static ThingRootKind kind() { return THING_ROOT_ID; } |
| static bool poisoned(jsid id) { return JS::IsPoisonedId(id); } |
| static bool needsPostBarrier(jsid id) { return false; } |
| #ifdef JSGC_GENERATIONAL |
| static void postBarrier(jsid *idp) {} |
| static void relocate(jsid *idp) {} |
| #endif |
| }; |
| |
| } /* 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(JSContextCallback) |
| JS_SetContextCallback(JSRuntime *rt, JSContextCallback cxCallback); |
| |
| 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); |
| |
| /* |
| * JS options are orthogonal to version, and may be freely composed with one |
| * another as well as with version. |
| * |
| * JSOPTION_VAROBJFIX is recommended -- see the comments associated with the |
| * prototypes for JS_ExecuteScript, JS_EvaluateScript, etc. |
| */ |
| #define JSOPTION_EXTRA_WARNINGS JS_BIT(0) /* warn on dubious practices */ |
| #define JSOPTION_WERROR JS_BIT(1) /* convert warning to error */ |
| #define JSOPTION_VAROBJFIX JS_BIT(2) /* make JS_EvaluateScript use |
| the last object on its 'obj' |
| param's scope chain as the |
| ECMA 'variables object' */ |
| #define JSOPTION_PRIVATE_IS_NSISUPPORTS \ |
| JS_BIT(3) /* context private data points |
| to an nsISupports subclass */ |
| #define JSOPTION_COMPILE_N_GO JS_BIT(4) /* caller of JS_Compile*Script |
| promises to execute compiled |
| script once only; enables |
| compile-time scope chain |
| resolution of consts. */ |
| |
| /* JS_BIT(5) is currently unused. */ |
| |
| /* JS_BIT(6) is currently unused. */ |
| |
| /* JS_BIT(7) is currently unused. */ |
| |
| #define JSOPTION_DONT_REPORT_UNCAUGHT \ |
| JS_BIT(8) /* When returning from the |
| outermost API call, prevent |
| uncaught exceptions from |
| being converted to error |
| reports */ |
| |
| /* JS_BIT(9) is currently unused. */ |
| |
| /* JS_BIT(10) is currently unused. */ |
| |
| /* JS_BIT(11) is currently unused. */ |
| |
| #define JSOPTION_NO_SCRIPT_RVAL JS_BIT(12) /* A promise to the compiler |
| that a null rval out-param |
| will be passed to each call |
| to JS_ExecuteScript. */ |
| #define JSOPTION_UNROOTED_GLOBAL JS_BIT(13) /* The GC will not root the |
| contexts' default compartment |
| object, leaving that up to the |
| embedding. */ |
| |
| #define JSOPTION_BASELINE JS_BIT(14) /* Baseline compiler. */ |
| |
| #define JSOPTION_PCCOUNT JS_BIT(15) /* Collect per-op execution counts */ |
| |
| #define JSOPTION_TYPE_INFERENCE JS_BIT(16) /* Perform type inference. */ |
| #define JSOPTION_STRICT_MODE JS_BIT(17) /* Provides a way to force |
| strict mode for all code |
| without requiring |
| "use strict" annotations. */ |
| |
| #define JSOPTION_ION JS_BIT(18) /* IonMonkey */ |
| |
| #define JSOPTION_ASMJS JS_BIT(19) /* optimizingasm.js compiler */ |
| |
| #define JSOPTION_MASK JS_BITMASK(20) |
| |
| extern JS_PUBLIC_API(uint32_t) |
| JS_GetOptions(JSContext *cx); |
| |
| extern JS_PUBLIC_API(uint32_t) |
| JS_SetOptions(JSContext *cx, uint32_t options); |
| |
| extern JS_PUBLIC_API(uint32_t) |
| JS_ToggleOptions(JSContext *cx, uint32_t options); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetJitHardening(JSRuntime *rt, JSBool enabled); |
| |
| 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(JSWrapObjectCallback) |
| JS_SetWrapObjectCallbacks(JSRuntime *rt, |
| JSWrapObjectCallback callback, |
| JSSameCompartmentWrapObjectCallback sccallback, |
| JSPreWrapCallback precallback); |
| |
| 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(JSBool) |
| JS_WrapObject(JSContext *cx, JSObject **objp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_WrapValue(JSContext *cx, jsval *vp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| 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(JSBool) |
| JS_RefreshCrossCompartmentWrappers(JSContext *cx, JSObject *ob); |
| |
| /* |
| * At any time, a JSContext has a current (possibly-NULL) 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 NULL 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); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetGlobalObject(JSContext *cx, JSObject *obj); |
| |
| /* |
| * 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(JSBool) |
| JS_InitStandardClasses(JSContext *cx, JSObject *obj); |
| |
| /* |
| * Resolve id, which must contain either a string or an int, to a standard |
| * class name in obj if possible, defining the class's constructor and/or |
| * prototype and storing true in *resolved. If id does not name a standard |
| * class or a top-level property induced by initializing a standard class, |
| * store false in *resolved and just return true. Return false on error, |
| * as usual for JSBool 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(JSBool) |
| JS_ResolveStandardClass(JSContext *cx, JS::HandleObject obj, JS::HandleId id, |
| JSBool *resolved); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_EnumerateStandardClasses(JSContext *cx, JS::HandleObject obj); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key, JSObject **objp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_GetClassPrototype(JSContext *cx, JSProtoKey key, JSObject **objp); |
| |
| extern JS_PUBLIC_API(JSProtoKey) |
| JS_IdentifyClassPrototype(JSContext *cx, JSObject *obj); |
| |
| /* |
| * 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, JSObject *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, JSObject *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, JSObject *forObj); |
| |
| extern JS_PUBLIC_API(JSObject *) |
| JS_GetGlobalForObject(JSContext *cx, JSObject *obj); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_IsGlobalObject(JSObject *obj); |
| |
| /* |
| * May return NULL, 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); |
| |
| extern JS_PUBLIC_API(JSObject *) |
| JS_GetGlobalForScopeChain(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, JSObject *global); |
| |
| #ifdef JS_HAS_CTYPES |
| /* |
| * Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes' |
| * object will be sealed. |
| */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_InitCTypesClass(JSContext *cx, JSObject *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 NULL 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 JSBool |
| (* 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 NULL. |
| */ |
| 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(JSBool) |
| JS_AddValueRoot(JSContext *cx, jsval *vp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_AddStringRoot(JSContext *cx, JSString **rp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_AddObjectRoot(JSContext *cx, JSObject **rp); |
| |
| #ifdef NAME_ALL_GC_ROOTS |
| #define JS_DEFINE_TO_TOKEN(def) #def |
| #define JS_DEFINE_TO_STRING(def) JS_DEFINE_TO_TOKEN(def) |
| #define JS_AddValueRoot(cx,vp) JS_AddNamedValueRoot((cx), (vp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__)) |
| #define JS_AddStringRoot(cx,rp) JS_AddNamedStringRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__)) |
| #define JS_AddObjectRoot(cx,rp) JS_AddNamedObjectRoot((cx), (rp), (__FILE__ ":" JS_TOKEN_TO_STRING(__LINE__)) |
| #endif |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_AddNamedValueRoot(JSContext *cx, jsval *vp, const char *name); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_AddNamedValueRootRT(JSRuntime *rt, jsval *vp, const char *name); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name); |
| |
| extern JS_PUBLIC_API(JSBool) |
| 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); |
| |
| /* TODO: remove these APIs */ |
| |
| extern JS_FRIEND_API(void) |
| js_RemoveRoot(JSRuntime *rt, void *rp); |
| |
| /* |
| * C-compatible version of the Anchor class. It should be called after the last |
| * use of the variable it protects. |
| */ |
| extern JS_NEVER_INLINE JS_PUBLIC_API(void) |
| JS_AnchorPtr(void *p); |
| |
| /* |
| * 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(JSBool) |
| 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 JS_ALWAYS_INLINE JSBool |
| JSVAL_IS_TRACEABLE(jsval v) |
| { |
| return JSVAL_IS_TRACEABLE_IMPL(JSVAL_TO_IMPL(v)); |
| } |
| |
| static JS_ALWAYS_INLINE void * |
| JSVAL_TO_TRACEABLE(jsval v) |
| { |
| return JSVAL_TO_GCTHING(v); |
| } |
| |
| static JS_ALWAYS_INLINE JSGCTraceKind |
| JSVAL_TRACE_KIND(jsval v) |
| { |
| JS_ASSERT(JSVAL_IS_GCTHING(v)); |
| return (JSGCTraceKind) JSVAL_TRACE_KIND_IMPL(JSVAL_TO_IMPL(v)); |
| } |
| |
| /* |
| * Tracer callback, called for each traceable thing directly referenced by a |
| * particular object or runtime structure. It is the callback responsibility |
| * to ensure the traversal of the full object graph via calling eventually |
| * JS_TraceChildren on the passed thing. In this case the callback must be |
| * prepared to deal with cycles in the traversal graph. |
| * |
| * kind argument is one of JSTRACE_OBJECT, JSTRACE_STRING or a tag denoting |
| * internal implementation-specific traversal kind. In the latter case the only |
| * operations on thing that the callback can do is to call JS_TraceChildren or |
| * JS_GetTraceThingInfo. |
| * |
| * If eagerlyTraceWeakMaps is true, when we trace a WeakMap visit all |
| * of its mappings. This should be used in cases where the tracer |
| * wants to use the existing liveness of entries. |
| */ |
| typedef void |
| (* JSTraceCallback)(JSTracer *trc, void **thingp, JSGCTraceKind kind); |
| |
| enum WeakMapTraceKind { |
| DoNotTraceWeakMaps = 0, |
| TraceWeakMapValues = 1, |
| TraceWeakMapKeysValues = 2 |
| }; |
| |
| struct JSTracer { |
| JSRuntime *runtime; |
| JSTraceCallback callback; |
| JSTraceNamePrinter debugPrinter; |
| const void *debugPrintArg; |
| size_t debugPrintIndex; |
| WeakMapTraceKind eagerlyTraceWeakMaps; |
| #ifdef JS_GC_ZEAL |
| void *realLocation; |
| #endif |
| }; |
| |
| /* |
| * Set debugging information about a reference to a traceable thing to prepare |
| * for the following call to JS_CallTracer. |
| * |
| * When printer is null, arg must be const char * or char * C string naming |
| * the reference and index must be either (size_t)-1 indicating that the name |
| * alone describes the reference or it must be an index into some array vector |
| * that stores the reference. |
| * |
| * When printer callback is not null, the arg and index arguments are |
| * available to the callback as debugPrintArg and debugPrintIndex fields |
| * of JSTracer. |
| * |
| * The storage for name or callback's arguments needs to live only until |
| * the following call to JS_CallTracer returns. |
| */ |
| # define JS_SET_TRACING_DETAILS(trc, printer, arg, index) \ |
| JS_BEGIN_MACRO \ |
| (trc)->debugPrinter = (printer); \ |
| (trc)->debugPrintArg = (arg); \ |
| (trc)->debugPrintIndex = (index); \ |
| JS_END_MACRO |
| |
| /* |
| * Sets the real location for a marked reference, when passing the address |
| * directly is not feasable. |
| * |
| * FIXME: This is currently overcomplicated by our need to nest calls for Values |
| * stored as keys in hash tables, but will get simplified once we can rekey |
| * in-place. |
| */ |
| #ifdef JS_GC_ZEAL |
| # define JS_SET_TRACING_LOCATION(trc, location) \ |
| JS_BEGIN_MACRO \ |
| if (!(trc)->realLocation || !(location)) \ |
| (trc)->realLocation = (location); \ |
| JS_END_MACRO |
| # define JS_UNSET_TRACING_LOCATION(trc) \ |
| JS_BEGIN_MACRO \ |
| (trc)->realLocation = NULL; \ |
| JS_END_MACRO |
| #else |
| # define JS_SET_TRACING_LOCATION(trc, location) \ |
| JS_BEGIN_MACRO \ |
| JS_END_MACRO |
| # define JS_UNSET_TRACING_LOCATION(trc) \ |
| JS_BEGIN_MACRO \ |
| JS_END_MACRO |
| #endif |
| |
| |
| /* |
| * Convenience macro to describe the argument of JS_CallTracer using C string |
| * and index. |
| */ |
| # define JS_SET_TRACING_INDEX(trc, name, index) \ |
| JS_SET_TRACING_DETAILS(trc, NULL, name, index) |
| |
| /* |
| * Convenience macro to describe the argument of JS_CallTracer using C string. |
| */ |
| # define JS_SET_TRACING_NAME(trc, name) \ |
| JS_SET_TRACING_DETAILS(trc, NULL, name, (size_t)-1) |
| |
| /* |
| * The JS_Call*Tracer family of functions traces the given GC thing reference. |
| * This performs the tracing action configured on the given JSTracer: |
| * typically calling the JSTracer::callback or marking the thing as live. |
| * |
| * The argument to JS_Call*Tracer is an in-out param: when the function |
| * returns, the garbage collector might have moved the GC thing. In this case, |
| * the reference passed to JS_Call*Tracer 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(void) |
| JS_CallValueTracer(JSTracer *trc, JS::Value *valuep, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallIdTracer(JSTracer *trc, jsid *idp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallObjectTracer(JSTracer *trc, JSObject **objp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallStringTracer(JSTracer *trc, JSString **strp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallScriptTracer(JSTracer *trc, JSScript **scriptp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallHeapValueTracer(JSTracer *trc, JS::Heap<JS::Value> *valuep, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallHeapIdTracer(JSTracer *trc, JS::Heap<jsid> *idp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallHeapObjectTracer(JSTracer *trc, JS::Heap<JSObject *> *objp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallHeapStringTracer(JSTracer *trc, JS::Heap<JSString *> *strp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallHeapScriptTracer(JSTracer *trc, JS::Heap<JSScript *> *scriptp, const char *name); |
| |
| extern JS_PUBLIC_API(void) |
| JS_CallGenericTracer(JSTracer *trc, void *gcthing, const char *name); |
| |
| template <typename HashSetEnum> |
| inline void |
| JS_CallHashSetObjectTracer(JSTracer *trc, HashSetEnum &e, JSObject *const &key, const char *name) |
| { |
| JSObject *updated = key; |
| JS_SET_TRACING_LOCATION(trc, reinterpret_cast<void *>(&const_cast<JSObject *&>(key))); |
| JS_CallObjectTracer(trc, &updated, name); |
| if (updated != key) |
| e.rekeyFront(key, updated); |
| } |
| |
| /* |
| * The JS_CallMaskedObjectTracer variant traces a JSObject* that is stored |
| * with flags embedded in the low bits of the word. The flagMask parameter |
| * expects |*objp & flagMask| to yield the flags with the pointer value |
| * stripped and |*objp & ~flagMask| to yield a valid GC pointer. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_CallMaskedObjectTracer(JSTracer *trc, uintptr_t *objp, uintptr_t flagMask, const char *name); |
| |
| /* |
| * API for JSTraceCallback implementations. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_TracerInit(JSTracer *trc, JSRuntime *rt, JSTraceCallback callback); |
| |
| extern JS_PUBLIC_API(void) |
| JS_TraceChildren(JSTracer *trc, void *thing, JSGCTraceKind kind); |
| |
| extern JS_PUBLIC_API(void) |
| JS_TraceRuntime(JSTracer *trc); |
| |
| extern JS_PUBLIC_API(void) |
| JS_GetTraceThingInfo(char *buf, size_t bufsize, JSTracer *trc, |
| void *thing, JSGCTraceKind kind, JSBool includeDetails); |
| |
| extern JS_PUBLIC_API(const char *) |
| JS_GetTraceEdgeName(JSTracer *trc, char *buffer, int bufferSize); |
| |
| #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(JSBool) |
| 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); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetFinalizeCallback(JSRuntime *rt, JSFinalizeCallback cb); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_IsGCMarkingTracer(JSTracer *trc); |
| |
| /* |
| * 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(JSBool) |
| JS_IsAboutToBeFinalized(JSObject **obj); |
| |
| 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, |
| |
| /* Number of megabytes of analysis data to allocate before purging. */ |
| JSGC_ANALYSIS_PURGE_TRIGGER = 19, |
| |
| /* Lower limit after which we limit the heap growth. */ |
| JSGC_ALLOCATION_THRESHOLD = 20, |
| |
| /* |
| * 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 = 21 |
| } 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); |
| |
| /* |
| * 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(JSBool) |
| JS_IsExternalString(JSString *str); |
| |
| /* |
| * Return the 'closure' arg passed to JS_NewExternalStringWithClosure or NULL |
| * 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. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_SetNativeStackQuota(JSRuntime *cx, size_t stackSize); |
| |
| /************************************************************************/ |
| |
| /* |
| * Classes, objects, and properties. |
| */ |
| typedef void (*JSClassInternal)(); |
| |
| struct JSClass { |
| const char *name; |
| uint32_t flags; |
| |
| /* Mandatory non-null function pointer members. */ |
| JSPropertyOp addProperty; |
| JSDeletePropertyOp delProperty; |
| JSPropertyOp getProperty; |
| JSStrictPropertyOp setProperty; |
| JSEnumerateOp enumerate; |
| JSResolveOp resolve; |
| JSConvertOp convert; |
| JSFinalizeOp finalize; |
| |
| /* Optionally non-null members start here. */ |
| JSCheckAccessOp checkAccess; |
| JSNative call; |
| JSHasInstanceOp hasInstance; |
| JSNative construct; |
| JSTraceOp trace; |
| |
| void *reserved[40]; |
| }; |
| |
| #define JSCLASS_HAS_PRIVATE (1<<0) /* objects have private slot */ |
| #define JSCLASS_NEW_ENUMERATE (1<<1) /* has JSNewEnumerateOp hook */ |
| #define JSCLASS_NEW_RESOLVE (1<<2) /* has JSNewResolveOp hook */ |
| #define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) /* private is (nsISupports *) */ |
| #define JSCLASS_IS_DOMJSCLASS (1<<4) /* objects are DOM */ |
| #define JSCLASS_IMPLEMENTS_BARRIERS (1<<5) /* Correctly implements GC read |
| and write barriers */ |
| #define JSCLASS_EMULATES_UNDEFINED (1<<6) /* objects of this class act |
| like the value undefined, |
| in some contexts */ |
| #define JSCLASS_USERBIT1 (1<<7) /* Reserved for embeddings. */ |
| |
| /* |
| * To reserve slots fetched and stored via JS_Get/SetReservedSlot, bitwise-or |
| * JSCLASS_HAS_RESERVED_SLOTS(n) into the initializer for JSClass.flags, where |
| * n is a constant in [1, 255]. Reserved slots are indexed from 0 to n-1. |
| */ |
| #define JSCLASS_RESERVED_SLOTS_SHIFT 8 /* room for 8 flags below */ |
| #define JSCLASS_RESERVED_SLOTS_WIDTH 8 /* and 16 above this field */ |
| #define JSCLASS_RESERVED_SLOTS_MASK JS_BITMASK(JSCLASS_RESERVED_SLOTS_WIDTH) |
| #define JSCLASS_HAS_RESERVED_SLOTS(n) (((n) & JSCLASS_RESERVED_SLOTS_MASK) \ |
| << JSCLASS_RESERVED_SLOTS_SHIFT) |
| #define JSCLASS_RESERVED_SLOTS(clasp) (((clasp)->flags \ |
| >> JSCLASS_RESERVED_SLOTS_SHIFT) \ |
| & JSCLASS_RESERVED_SLOTS_MASK) |
| |
| #define JSCLASS_HIGH_FLAGS_SHIFT (JSCLASS_RESERVED_SLOTS_SHIFT + \ |
| JSCLASS_RESERVED_SLOTS_WIDTH) |
| |
| #define JSCLASS_IS_ANONYMOUS (1<<(JSCLASS_HIGH_FLAGS_SHIFT+0)) |
| #define JSCLASS_IS_GLOBAL (1<<(JSCLASS_HIGH_FLAGS_SHIFT+1)) |
| #define JSCLASS_INTERNAL_FLAG2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+2)) |
| #define JSCLASS_INTERNAL_FLAG3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+3)) |
| |
| /* Indicate whether the proto or ctor should be frozen. */ |
| #define JSCLASS_FREEZE_PROTO (1<<(JSCLASS_HIGH_FLAGS_SHIFT+4)) |
| #define JSCLASS_FREEZE_CTOR (1<<(JSCLASS_HIGH_FLAGS_SHIFT+5)) |
| |
| /* Reserved for embeddings. */ |
| #define JSCLASS_USERBIT2 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+6)) |
| #define JSCLASS_USERBIT3 (1<<(JSCLASS_HIGH_FLAGS_SHIFT+7)) |
| |
| #define JSCLASS_BACKGROUND_FINALIZE (1<<(JSCLASS_HIGH_FLAGS_SHIFT+8)) |
| |
| /* |
| * Bits 26 through 31 are reserved for the CACHED_PROTO_KEY mechanism, see |
| * below. |
| */ |
| |
| /* Global flags. */ |
| #define JSGLOBAL_FLAGS_CLEARED 0x1 |
| |
| /* |
| * ECMA-262 requires that most constructors used internally create objects |
| * with "the original Foo.prototype value" as their [[Prototype]] (__proto__) |
| * member initial value. The "original ... value" verbiage is there because |
| * in ECMA-262, global properties naming class objects are read/write and |
| * deleteable, for the most part. |
| * |
| * Implementing this efficiently requires that global objects have classes |
| * with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was |
| * prevously allowed, but is now an ES5 violation and thus unsupported. |
| */ |
| #define JSCLASS_GLOBAL_SLOT_COUNT (JSProto_LIMIT * 3 + 25) |
| #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \ |
| (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n))) |
| #define JSCLASS_GLOBAL_FLAGS \ |
| JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0) |
| #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp) \ |
| (((clasp)->flags & JSCLASS_IS_GLOBAL) \ |
| && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT) |
| |
| /* Fast access to the original value of each standard class's prototype. */ |
| #define JSCLASS_CACHED_PROTO_SHIFT (JSCLASS_HIGH_FLAGS_SHIFT + 10) |
| #define JSCLASS_CACHED_PROTO_WIDTH 6 |
| #define JSCLASS_CACHED_PROTO_MASK JS_BITMASK(JSCLASS_CACHED_PROTO_WIDTH) |
| #define JSCLASS_HAS_CACHED_PROTO(key) (uint32_t(key) << JSCLASS_CACHED_PROTO_SHIFT) |
| #define JSCLASS_CACHED_PROTO_KEY(clasp) ((JSProtoKey) \ |
| (((clasp)->flags \ |
| >> JSCLASS_CACHED_PROTO_SHIFT) \ |
| & JSCLASS_CACHED_PROTO_MASK)) |
| |
| /* Initializer for unused members of statically initialized JSClass structs. */ |
| #define JSCLASS_NO_INTERNAL_MEMBERS {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} |
| #define JSCLASS_NO_OPTIONAL_MEMBERS 0,0,0,0,0,JSCLASS_NO_INTERNAL_MEMBERS |
| |
| 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); |
| JS_ASSERT(i < length()); |
| 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 = NULL; |
| 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(JSBool) |
| JS_ValueToId(JSContext *cx, jsval v, jsid *idp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_IdToValue(JSContext *cx, jsid id, jsval *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(JSBool) |
| JS_DefaultValue(JSContext *cx, JSObject *obj, JSType hint, jsval *vp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_PropertyStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, |
| JS::MutableHandle<JS::Value> vp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_StrictPropertyStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSBool strict, |
| JS::MutableHandle<JS::Value> vp); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_DeletePropertyStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, |
| JSBool *succeeded); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_EnumerateStub(JSContext *cx, JS::Handle<JSObject*> obj); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_ResolveStub(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_ConvertStub(JSContext *cx, JS::Handle<JSObject*> obj, JSType type, |
| JS::MutableHandle<JS::Value> vp); |
| |
| struct JSConstDoubleSpec { |
| double dval; |
| const char *name; |
| uint8_t flags; |
| uint8_t spare[3]; |
| }; |
| |
| typedef struct JSJitInfo 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, NULL} |
| #define JSOP_NULLWRAPPER JSOP_WRAPPER(NULL) |
| |
| /* |
| * 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 { |
| const char *name; |
| int8_t tinyid; |
| uint8_t flags; |
| JSPropertyOpWrapper getter; |
| JSStrictPropertyOpWrapper setter; |
| }; |
| |
| namespace JS { |
| namespace detail { |
| |
| /* NEVER DEFINED, DON'T USE. For use by JS_CAST_NATIVE_TO only. */ |
| inline int CheckIsNative(JSNative native); |
| |
| } // namespace detail |
| } // namespace JS |
| |
| #define JS_CAST_NATIVE_TO(v, To) \ |
| (static_cast<void>(sizeof(JS::detail::CheckIsNative(v))), \ |
| reinterpret_cast<To>(v)) |
| |
| /* |
| * JSPropertySpec uses JSAPI JSPropertyOp and JSStrictPropertyOp in function |
| * signatures, but with JSPROP_NATIVE_ACCESSORS the actual values must be |
| * JSNatives. To avoid widespread casting, have JS_PSG and JS_PSGS perform |
| * type-safe casts. |
| */ |
| #define JS_PSG(name, getter, flags) \ |
| {name, 0, (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, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS, \ |
| JSOP_WRAPPER(JS_CAST_NATIVE_TO(getter, JSPropertyOp)), \ |
| JSOP_WRAPPER(JS_CAST_NATIVE_TO(setter, JSStrictPropertyOp))} |
| #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(NULL,NULL,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. |
| */ |
| #define JS_FS(name,call,nargs,flags) \ |
| {name, JSOP_WRAPPER(call), nargs, flags} |
| #define JS_FN(name,call,nargs,flags) \ |
| {name, JSOP_WRAPPER(call), nargs, (flags) | JSFUN_STUB_GSOPS} |
| #define JS_FNINFO(name,call,info,nargs,flags) \ |
| {name,{call,info},nargs,flags} |
| |
| extern JS_PUBLIC_API(JSObject *) |
| JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, |
| 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(JSBool) |
| JS_LinkConstructorAndPrototype(JSContext *cx, JSObject *ctor, JSObject *proto); |
| |
| extern JS_PUBLIC_API(JSClass *) |
| JS_GetClass(JSObject *obj); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *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, JSObject *obj, JSClass *clasp, |
| jsval *argv); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_GetPrototype(JSContext *cx, JSObject *obj, JSObject **protop); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto); |
| |
| extern JS_PUBLIC_API(JSObject *) |
| JS_GetParent(JSObject *obj); |
| |
| extern JS_PUBLIC_API(JSBool) |
| JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent); |
| |
| extern JS_PUBLIC_API(JSObject *) |
| JS_GetConstructor(JSContext *cx, JSObject *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(JSBool) |
| JS_GetObjectId(JSContext *cx, JSObject *obj, jsid *idp); |
| |
| namespace JS { |
| |
| enum { |
| FreshZone, |
| SystemZone, |
| SpecificZones |
| }; |
| |
| typedef uintptr_t ZoneSpecifier; |
| |
| inline ZoneSpecifier |
| SameZoneAs(JSObject *obj) |
| { |
| JS_ASSERT(uintptr_t(obj) > SpecificZones); |
| return ZoneSpecifier(obj); |
| } |
| |
| struct JS_PUBLIC_API(CompartmentOptions) { |
| ZoneSpecifier zoneSpec; |
| bool hasVersion; |
| JSVersion version; |
| |
| explicit CompartmentOptions() : zoneSpec(JS::FreshZone) |
| , hasVersion(false) |
| , version(JSVERSION_UNKNOWN) |
| {} |
| |
| CompartmentOptions &setZone(ZoneSpecifier spec) { zoneSpec = spec; return *this; } |
| CompartmentOptions &setVersion(JSVersion version_) { hasVersion = true; version = version_; return *this; } |
| }; |
| |
| } /* namespace JS */ |
| |
| extern JS_PUBLIC_API(JSObject *) |
| JS_NewGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals, |
| const JS::CompartmentOptions &options = JS::CompartmentOptions()); |
| |
| extern JS_PUBLIC_API(JSObject *) |
| JS_NewObject(JSContext *cx, JSClass *clasp, JSObject *proto, JSObject *parent); |
| |
| /* Queries the [[Extensible]] property of the object. */ |
| extern JS_PUBLIC_API(JSBool) |
| JS_IsExtensible(JSObject *obj); |
| |
| extern JS_PUBLIC_API(JSBool) |
| 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, JSClass *clasp, JSObject *proto, |
| JSObject *parent); |
| |
| /* |
| * Freeze obj, and all objects it refers to, recursively. This will not recurse |
|