| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
| * vim: set ts=8 sts=4 et sw=4 tw=99: |
| * This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| /* JavaScript API. */ |
| |
| #ifndef jsapi_h |
| #define jsapi_h |
| |
| #include "mozilla/AlreadyAddRefed.h" |
| #include "mozilla/FloatingPoint.h" |
| #include "mozilla/MemoryReporting.h" |
| #include "mozilla/Range.h" |
| #include "mozilla/RangedPtr.h" |
| #include "mozilla/RefPtr.h" |
| |
| #include <stdarg.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| |
| #include "jsalloc.h" |
| #include "jspubtd.h" |
| |
| #include "js/CallArgs.h" |
| #include "js/Class.h" |
| #include "js/HashTable.h" |
| #include "js/Id.h" |
| #include "js/Principals.h" |
| #include "js/RootingAPI.h" |
| #include "js/TraceableVector.h" |
| #include "js/TracingAPI.h" |
| #include "js/Utility.h" |
| #include "js/Value.h" |
| #include "js/Vector.h" |
| |
| /************************************************************************/ |
| |
| namespace JS { |
| |
| class TwoByteChars; |
| |
| #ifdef JS_DEBUG |
| |
| class JS_PUBLIC_API(AutoCheckRequestDepth) |
| { |
| JSContext* cx; |
| public: |
| explicit AutoCheckRequestDepth(JSContext* cx); |
| explicit AutoCheckRequestDepth(js::ContextFriendFields* cx); |
| ~AutoCheckRequestDepth(); |
| }; |
| |
| # define CHECK_REQUEST(cx) \ |
| JS::AutoCheckRequestDepth _autoCheckRequestDepth(cx) |
| |
| #else |
| |
| # define CHECK_REQUEST(cx) \ |
| ((void) 0) |
| |
| #endif /* JS_DEBUG */ |
| |
| /** AutoValueArray roots an internal fixed-size array of Values. */ |
| template <size_t N> |
| class MOZ_RAII AutoValueArray : public AutoGCRooter |
| { |
| const size_t length_; |
| Value elements_[N]; |
| |
| public: |
| explicit AutoValueArray(JSContext* cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, VALARRAY), length_(N) |
| { |
| /* Always initialize in case we GC before assignment. */ |
| mozilla::PodArrayZero(elements_); |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| unsigned length() const { return length_; } |
| const Value* begin() const { return elements_; } |
| Value* begin() { return elements_; } |
| |
| HandleValue operator[](unsigned i) const { |
| MOZ_ASSERT(i < N); |
| return HandleValue::fromMarkedLocation(&elements_[i]); |
| } |
| MutableHandleValue operator[](unsigned i) { |
| MOZ_ASSERT(i < N); |
| return MutableHandleValue::fromMarkedLocation(&elements_[i]); |
| } |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| template<class T> |
| class MOZ_RAII AutoVectorRooterBase : protected AutoGCRooter |
| { |
| typedef js::Vector<T, 8> VectorImpl; |
| VectorImpl vector; |
| |
| public: |
| explicit AutoVectorRooterBase(JSContext* cx, ptrdiff_t tag |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, tag), vector(cx) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| explicit AutoVectorRooterBase(js::ContextFriendFields* cx, ptrdiff_t tag |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, tag), vector(cx) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| typedef T ElementType; |
| typedef typename VectorImpl::Range Range; |
| |
| size_t length() const { return vector.length(); } |
| bool empty() const { return vector.empty(); } |
| |
| bool append(const T& v) { return vector.append(v); } |
| bool appendN(const T& v, size_t len) { return vector.appendN(v, len); } |
| bool append(const T* ptr, size_t len) { return vector.append(ptr, len); } |
| bool appendAll(const AutoVectorRooterBase<T>& other) { |
| return vector.appendAll(other.vector); |
| } |
| |
| bool insert(T* p, const T& val) { return vector.insert(p, val); } |
| |
| /* For use when space has already been reserved. */ |
| void infallibleAppend(const T& v) { vector.infallibleAppend(v); } |
| |
| void popBack() { vector.popBack(); } |
| T popCopy() { return vector.popCopy(); } |
| |
| bool growBy(size_t inc) { |
| size_t oldLength = vector.length(); |
| if (!vector.growByUninitialized(inc)) |
| return false; |
| makeRangeGCSafe(oldLength); |
| return true; |
| } |
| |
| bool resize(size_t newLength) { |
| size_t oldLength = vector.length(); |
| if (newLength <= oldLength) { |
| vector.shrinkBy(oldLength - newLength); |
| return true; |
| } |
| if (!vector.growByUninitialized(newLength - oldLength)) |
| return false; |
| makeRangeGCSafe(oldLength); |
| return true; |
| } |
| |
| void clear() { vector.clear(); } |
| |
| bool reserve(size_t newLength) { |
| return vector.reserve(newLength); |
| } |
| |
| JS::MutableHandle<T> operator[](size_t i) { |
| return JS::MutableHandle<T>::fromMarkedLocation(&vector[i]); |
| } |
| JS::Handle<T> operator[](size_t i) const { |
| return JS::Handle<T>::fromMarkedLocation(&vector[i]); |
| } |
| |
| const T* begin() const { return vector.begin(); } |
| T* begin() { return vector.begin(); } |
| |
| const T* end() const { return vector.end(); } |
| T* end() { return vector.end(); } |
| |
| Range all() { return vector.all(); } |
| |
| const T& back() const { return vector.back(); } |
| |
| friend void AutoGCRooter::trace(JSTracer* trc); |
| |
| private: |
| void makeRangeGCSafe(size_t oldLength) { |
| T* t = vector.begin() + oldLength; |
| for (size_t i = oldLength; i < vector.length(); ++i, ++t) |
| memset(t, 0, sizeof(T)); |
| } |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| template <typename T> |
| class MOZ_RAII AutoVectorRooter : public AutoVectorRooterBase<T> |
| { |
| public: |
| explicit AutoVectorRooter(JSContext* cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoVectorRooterBase<T>(cx, this->GetTag(T())) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| explicit AutoVectorRooter(js::ContextFriendFields* cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoVectorRooterBase<T>(cx, this->GetTag(T())) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| typedef AutoVectorRooter<Value> AutoValueVector; |
| typedef AutoVectorRooter<jsid> AutoIdVector; |
| typedef AutoVectorRooter<JSObject*> AutoObjectVector; |
| |
| using ValueVector = js::TraceableVector<JS::Value>; |
| using IdVector = js::TraceableVector<jsid>; |
| using ScriptVector = js::TraceableVector<JSScript*>; |
| |
| template<class Key, class Value> |
| class MOZ_RAII AutoHashMapRooter : protected AutoGCRooter |
| { |
| private: |
| typedef js::HashMap<Key, Value> HashMapImpl; |
| |
| public: |
| explicit AutoHashMapRooter(JSContext* cx, ptrdiff_t tag |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, tag), map(cx) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| typedef Key KeyType; |
| typedef Value ValueType; |
| typedef typename HashMapImpl::Entry Entry; |
| typedef typename HashMapImpl::Lookup Lookup; |
| typedef typename HashMapImpl::Ptr Ptr; |
| typedef typename HashMapImpl::AddPtr AddPtr; |
| |
| bool init(uint32_t len = 16) { |
| return map.init(len); |
| } |
| bool initialized() const { |
| return map.initialized(); |
| } |
| Ptr lookup(const Lookup& l) const { |
| return map.lookup(l); |
| } |
| void remove(Ptr p) { |
| map.remove(p); |
| } |
| AddPtr lookupForAdd(const Lookup& l) const { |
| return map.lookupForAdd(l); |
| } |
| |
| template<typename KeyInput, typename ValueInput> |
| bool add(AddPtr& p, const KeyInput& k, const ValueInput& v) { |
| return map.add(p, k, v); |
| } |
| |
| bool add(AddPtr& p, const Key& k) { |
| return map.add(p, k); |
| } |
| |
| template<typename KeyInput, typename ValueInput> |
| bool relookupOrAdd(AddPtr& p, const KeyInput& k, const ValueInput& v) { |
| return map.relookupOrAdd(p, k, v); |
| } |
| |
| typedef typename HashMapImpl::Range Range; |
| Range all() const { |
| return map.all(); |
| } |
| |
| typedef typename HashMapImpl::Enum Enum; |
| |
| void clear() { |
| map.clear(); |
| } |
| |
| void finish() { |
| map.finish(); |
| } |
| |
| bool empty() const { |
| return map.empty(); |
| } |
| |
| uint32_t count() const { |
| return map.count(); |
| } |
| |
| size_t capacity() const { |
| return map.capacity(); |
| } |
| |
| size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { |
| return map.sizeOfExcludingThis(mallocSizeOf); |
| } |
| size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { |
| return map.sizeOfIncludingThis(mallocSizeOf); |
| } |
| |
| /************************************************** Shorthand operations */ |
| |
| bool has(const Lookup& l) const { |
| return map.has(l); |
| } |
| |
| template<typename KeyInput, typename ValueInput> |
| bool put(const KeyInput& k, const ValueInput& v) { |
| return map.put(k, v); |
| } |
| |
| template<typename KeyInput, typename ValueInput> |
| bool putNew(const KeyInput& k, const ValueInput& v) { |
| return map.putNew(k, v); |
| } |
| |
| Ptr lookupWithDefault(const Key& k, const Value& defaultValue) { |
| return map.lookupWithDefault(k, defaultValue); |
| } |
| |
| void remove(const Lookup& l) { |
| map.remove(l); |
| } |
| |
| friend void AutoGCRooter::trace(JSTracer* trc); |
| |
| private: |
| AutoHashMapRooter(const AutoHashMapRooter& hmr) = delete; |
| AutoHashMapRooter& operator=(const AutoHashMapRooter& hmr) = delete; |
| |
| HashMapImpl map; |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| template<class T> |
| class MOZ_RAII AutoHashSetRooter : protected AutoGCRooter |
| { |
| private: |
| typedef js::HashSet<T> HashSetImpl; |
| |
| public: |
| explicit AutoHashSetRooter(JSContext* cx, ptrdiff_t tag |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, tag), set(cx) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| typedef typename HashSetImpl::Lookup Lookup; |
| typedef typename HashSetImpl::Ptr Ptr; |
| typedef typename HashSetImpl::AddPtr AddPtr; |
| |
| bool init(uint32_t len = 16) { |
| return set.init(len); |
| } |
| bool initialized() const { |
| return set.initialized(); |
| } |
| Ptr lookup(const Lookup& l) const { |
| return set.lookup(l); |
| } |
| void remove(Ptr p) { |
| set.remove(p); |
| } |
| AddPtr lookupForAdd(const Lookup& l) const { |
| return set.lookupForAdd(l); |
| } |
| |
| bool add(AddPtr& p, const T& t) { |
| return set.add(p, t); |
| } |
| |
| bool relookupOrAdd(AddPtr& p, const Lookup& l, const T& t) { |
| return set.relookupOrAdd(p, l, t); |
| } |
| |
| typedef typename HashSetImpl::Range Range; |
| Range all() const { |
| return set.all(); |
| } |
| |
| typedef typename HashSetImpl::Enum Enum; |
| |
| void clear() { |
| set.clear(); |
| } |
| |
| void finish() { |
| set.finish(); |
| } |
| |
| bool empty() const { |
| return set.empty(); |
| } |
| |
| uint32_t count() const { |
| return set.count(); |
| } |
| |
| size_t capacity() const { |
| return set.capacity(); |
| } |
| |
| size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const { |
| return set.sizeOfExcludingThis(mallocSizeOf); |
| } |
| size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const { |
| return set.sizeOfIncludingThis(mallocSizeOf); |
| } |
| |
| /************************************************** Shorthand operations */ |
| |
| bool has(const Lookup& l) const { |
| return set.has(l); |
| } |
| |
| bool put(const T& t) { |
| return set.put(t); |
| } |
| |
| bool putNew(const T& t) { |
| return set.putNew(t); |
| } |
| |
| void remove(const Lookup& l) { |
| set.remove(l); |
| } |
| |
| friend void AutoGCRooter::trace(JSTracer* trc); |
| |
| private: |
| AutoHashSetRooter(const AutoHashSetRooter& hmr) = delete; |
| AutoHashSetRooter& operator=(const AutoHashSetRooter& hmr) = delete; |
| |
| HashSetImpl set; |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| /** |
| * Custom rooting behavior for internal and external clients. |
| */ |
| class MOZ_RAII JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter |
| { |
| public: |
| template <typename CX> |
| explicit CustomAutoRooter(CX* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : AutoGCRooter(cx, CUSTOM) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| } |
| |
| friend void AutoGCRooter::trace(JSTracer* trc); |
| |
| protected: |
| /** Supplied by derived class to trace roots. */ |
| virtual void trace(JSTracer* trc) = 0; |
| |
| private: |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| /** A handle to an array of rooted values. */ |
| class HandleValueArray |
| { |
| const size_t length_; |
| const Value * const elements_; |
| |
| HandleValueArray(size_t len, const Value* elements) : length_(len), elements_(elements) {} |
| |
| public: |
| explicit HandleValueArray(const RootedValue& value) : length_(1), elements_(value.address()) {} |
| |
| MOZ_IMPLICIT HandleValueArray(const AutoValueVector& values) |
| : length_(values.length()), elements_(values.begin()) {} |
| |
| template <size_t N> |
| MOZ_IMPLICIT HandleValueArray(const AutoValueArray<N>& values) : length_(N), elements_(values.begin()) {} |
| |
| /** CallArgs must already be rooted somewhere up the stack. */ |
| MOZ_IMPLICIT HandleValueArray(const JS::CallArgs& args) : length_(args.length()), elements_(args.array()) {} |
| |
| /** Use with care! Only call this if the data is guaranteed to be marked. */ |
| static HandleValueArray fromMarkedLocation(size_t len, const Value* elements) { |
| return HandleValueArray(len, elements); |
| } |
| |
| static HandleValueArray subarray(const HandleValueArray& values, size_t startIndex, size_t len) { |
| MOZ_ASSERT(startIndex + len <= values.length()); |
| return HandleValueArray(len, values.begin() + startIndex); |
| } |
| |
| static HandleValueArray empty() { |
| return HandleValueArray(0, nullptr); |
| } |
| |
| size_t length() const { return length_; } |
| const Value* begin() const { return elements_; } |
| |
| HandleValue operator[](size_t i) const { |
| MOZ_ASSERT(i < length_); |
| return HandleValue::fromMarkedLocation(&elements_[i]); |
| } |
| }; |
| |
| } /* namespace JS */ |
| |
| /************************************************************************/ |
| |
| struct JSFreeOp { |
| private: |
| JSRuntime* runtime_; |
| |
| protected: |
| explicit JSFreeOp(JSRuntime* rt) |
| : runtime_(rt) { } |
| |
| public: |
| JSRuntime* runtime() const { |
| return runtime_; |
| } |
| }; |
| |
| /* Callbacks and their arguments. */ |
| |
| /************************************************************************/ |
| |
| typedef enum JSContextOp { |
| JSCONTEXT_NEW, |
| JSCONTEXT_DESTROY |
| } JSContextOp; |
| |
| /** |
| * The possible values for contextOp when the runtime calls the callback are: |
| * JSCONTEXT_NEW JS_NewContext successfully created a new JSContext |
| * instance. The callback can initialize the instance as |
| * required. If the callback returns false, the instance |
| * will be destroyed and JS_NewContext returns null. In |
| * this case the callback is not called again. |
| * JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The |
| * callback may perform its own cleanup and must always |
| * return true. |
| * Any other value For future compatibility the callback must do nothing |
| * and return true in this case. |
| */ |
| typedef bool |
| (* JSContextCallback)(JSContext* cx, unsigned contextOp, void* data); |
| |
| typedef enum JSGCStatus { |
| JSGC_BEGIN, |
| JSGC_END |
| } JSGCStatus; |
| |
| typedef void |
| (* JSGCCallback)(JSRuntime* rt, JSGCStatus status, void* data); |
| |
| typedef enum JSFinalizeStatus { |
| /** |
| * Called when preparing to sweep a group of compartments, before anything |
| * has been swept. The collector will not yield to the mutator before |
| * calling the callback with JSFINALIZE_GROUP_END status. |
| */ |
| JSFINALIZE_GROUP_START, |
| |
| /** |
| * Called when preparing to sweep a group of compartments. Weak references |
| * to unmarked things have been removed and things that are not swept |
| * incrementally have been finalized at this point. The collector may yield |
| * to the mutator after this point. |
| */ |
| JSFINALIZE_GROUP_END, |
| |
| /** |
| * Called at the end of collection when everything has been swept. |
| */ |
| JSFINALIZE_COLLECTION_END |
| } JSFinalizeStatus; |
| |
| typedef void |
| (* JSFinalizeCallback)(JSFreeOp* fop, JSFinalizeStatus status, bool isCompartment, void* data); |
| |
| typedef void |
| (* JSWeakPointerZoneGroupCallback)(JSRuntime* rt, void* data); |
| |
| typedef void |
| (* JSWeakPointerCompartmentCallback)(JSRuntime* rt, JSCompartment* comp, void* data); |
| |
| typedef bool |
| (* JSInterruptCallback)(JSContext* cx); |
| |
| typedef void |
| (* JSErrorReporter)(JSContext* cx, const char* message, JSErrorReport* report); |
| |
| /** |
| * 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 unsigned errorNumber); |
| |
| typedef bool |
| (* JSLocaleToUpperCase)(JSContext* cx, JS::HandleString src, JS::MutableHandleValue rval); |
| |
| typedef bool |
| (* JSLocaleToLowerCase)(JSContext* cx, JS::HandleString src, JS::MutableHandleValue rval); |
| |
| typedef bool |
| (* JSLocaleCompare)(JSContext* cx, JS::HandleString src1, JS::HandleString src2, |
| JS::MutableHandleValue rval); |
| |
| typedef bool |
| (* JSLocaleToUnicode)(JSContext* cx, const char* src, JS::MutableHandleValue rval); |
| |
| /** |
| * Callback used to ask the embedding for the cross compartment wrapper handler |
| * that implements the desired prolicy for this kind of object in the |
| * destination compartment. |obj| is the object to be wrapped. If |existing| is |
| * non-nullptr, it will point to an existing wrapper object that should be |
| * re-used if possible. |existing| is guaranteed to be a cross-compartment |
| * wrapper with a lazily-defined prototype and the correct global. It is |
| * guaranteed not to wrap a function. |
| */ |
| typedef JSObject* |
| (* JSWrapObjectCallback)(JSContext* cx, JS::HandleObject existing, JS::HandleObject obj); |
| |
| /** |
| * Callback used by the wrap hook to ask the embedding to prepare an object |
| * for wrapping in a context. This might include unwrapping other wrappers |
| * or even finding a more suitable object for the new compartment. |
| */ |
| typedef JSObject* |
| (* JSPreWrapCallback)(JSContext* cx, JS::HandleObject scope, JS::HandleObject obj, |
| JS::HandleObject objectPassedToWrap); |
| |
| struct JSWrapObjectCallbacks |
| { |
| JSWrapObjectCallback wrap; |
| JSPreWrapCallback preWrap; |
| }; |
| |
| typedef void |
| (* JSDestroyCompartmentCallback)(JSFreeOp* fop, JSCompartment* compartment); |
| |
| typedef void |
| (* JSZoneCallback)(JS::Zone* zone); |
| |
| typedef void |
| (* JSCompartmentNameCallback)(JSRuntime* rt, JSCompartment* compartment, |
| char* buf, size_t bufsize); |
| |
| /************************************************************************/ |
| |
| static MOZ_ALWAYS_INLINE JS::Value |
| JS_NumberValue(double d) |
| { |
| int32_t i; |
| d = JS::CanonicalizeNaN(d); |
| if (mozilla::NumberIsInt32(d, &i)) |
| return JS::Int32Value(i); |
| return JS::DoubleValue(d); |
| } |
| |
| /************************************************************************/ |
| |
| JS_PUBLIC_API(bool) |
| JS_StringHasBeenPinned(JSContext* cx, JSString* str); |
| |
| namespace JS { |
| |
| /** |
| * Container class for passing in script source buffers to the JS engine. This |
| * not only groups the buffer and length values, it also provides a way to |
| * optionally pass ownership of the buffer to the JS engine without copying. |
| * Rules for use: |
| * |
| * 1) The data array must be allocated with js_malloc() or js_realloc() if |
| * ownership is being granted to the SourceBufferHolder. |
| * 2) If ownership is not given to the SourceBufferHolder, then the memory |
| * must be kept alive until the JS compilation is complete. |
| * 3) Any code calling SourceBufferHolder::take() must guarantee to keep the |
| * memory alive until JS compilation completes. Normally only the JS |
| * engine should be calling take(). |
| * |
| * Example use: |
| * |
| * size_t length = 512; |
| * char16_t* chars = static_cast<char16_t*>(js_malloc(sizeof(char16_t) * length)); |
| * JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership); |
| * JS::Compile(cx, options, srcBuf); |
| */ |
| class MOZ_STACK_CLASS SourceBufferHolder final |
| { |
| public: |
| enum Ownership { |
| NoOwnership, |
| GiveOwnership |
| }; |
| |
| SourceBufferHolder(const char16_t* data, size_t dataLength, Ownership ownership) |
| : data_(data), |
| length_(dataLength), |
| ownsChars_(ownership == GiveOwnership) |
| { |
| // Ensure that null buffers properly return an unowned, empty, |
| // null-terminated string. |
| static const char16_t NullChar_ = 0; |
| if (!get()) { |
| data_ = &NullChar_; |
| length_ = 0; |
| ownsChars_ = false; |
| } |
| } |
| |
| ~SourceBufferHolder() { |
| if (ownsChars_) |
| js_free(const_cast<char16_t*>(data_)); |
| } |
| |
| // Access the underlying source buffer without affecting ownership. |
| const char16_t* get() const { return data_; } |
| |
| // Length of the source buffer in char16_t code units (not bytes) |
| size_t length() const { return length_; } |
| |
| // Returns true if the SourceBufferHolder owns the buffer and will free |
| // it upon destruction. If true, it is legal to call take(). |
| bool ownsChars() const { return ownsChars_; } |
| |
| // Retrieve and take ownership of the underlying data buffer. The caller |
| // is now responsible for calling js_free() on the returned value, *but only |
| // after JS script compilation has completed*. |
| // |
| // After the buffer has been taken the SourceBufferHolder functions as if |
| // it had been constructed on an unowned buffer; get() and length() still |
| // work. In order for this to be safe the taken buffer must be kept alive |
| // until after JS script compilation completes as noted above. |
| // |
| // Note, it's the caller's responsibility to check ownsChars() before taking |
| // the buffer. Taking and then free'ing an unowned buffer will have dire |
| // consequences. |
| char16_t* take() { |
| MOZ_ASSERT(ownsChars_); |
| ownsChars_ = false; |
| return const_cast<char16_t*>(data_); |
| } |
| |
| private: |
| SourceBufferHolder(SourceBufferHolder&) = delete; |
| SourceBufferHolder& operator=(SourceBufferHolder&) = delete; |
| |
| const char16_t* data_; |
| size_t length_; |
| bool ownsChars_; |
| }; |
| |
| } /* namespace JS */ |
| |
| /************************************************************************/ |
| |
| /* Property attributes, set in JSPropertySpec and passed to API functions. |
| * |
| * NB: The data structure in which some of these values are stored only uses |
| * a uint8_t to store the relevant information. Proceed with caution if |
| * trying to reorder or change the the first byte worth of flags. |
| */ |
| #define JSPROP_ENUMERATE 0x01 /* property is visible to for/in loop */ |
| #define JSPROP_READONLY 0x02 /* not settable: assignment is no-op. |
| This flag is only valid when neither |
| JSPROP_GETTER nor JSPROP_SETTER is |
| set. */ |
| #define JSPROP_PERMANENT 0x04 /* property cannot be deleted */ |
| #define JSPROP_PROPOP_ACCESSORS 0x08 /* Passed to JS_Define(UC)Property* and |
| JS_DefineElement if getters/setters |
| are JSGetterOp/JSSetterOp */ |
| #define JSPROP_GETTER 0x10 /* property holds getter function */ |
| #define JSPROP_SETTER 0x20 /* property holds setter function */ |
| #define JSPROP_SHARED 0x40 /* don't allocate a value slot for this |
| property; don't copy the property on |
| set of the same-named property in an |
| object that delegates to a prototype |
| containing this property */ |
| #define JSPROP_INTERNAL_USE_BIT 0x80 /* internal JS engine use only */ |
| #define JSPROP_DEFINE_LATE 0x100 /* Don't define property when initially creating |
| the constructor. Some objects like Function/Object |
| have self-hosted functions that can only be defined |
| after the initialization is already finished. */ |
| #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 */ |
| |
| /* |
| * If set, will allow redefining a non-configurable property, but only on a |
| * non-DOM global. This is a temporary hack that will need to go away in bug |
| * 1105518. |
| */ |
| #define JSPROP_REDEFINE_NONCONFIGURABLE 0x1000 |
| |
| /* |
| * Resolve hooks and enumerate hooks must pass this flag when calling |
| * JS_Define* APIs to reify lazily-defined properties. |
| * |
| * JSPROP_RESOLVING is used only with property-defining APIs. It tells the |
| * engine to skip the resolve hook when performing the lookup at the beginning |
| * of property definition. This keeps the resolve hook from accidentally |
| * triggering itself: unchecked recursion. |
| * |
| * For enumerate hooks, triggering the resolve hook would be merely silly, not |
| * fatal, except in some cases involving non-configurable properties. |
| */ |
| #define JSPROP_RESOLVING 0x2000 |
| |
| #define JSPROP_IGNORE_ENUMERATE 0x4000 /* ignore the value in JSPROP_ENUMERATE. |
| This flag only valid when defining over |
| an existing property. */ |
| #define JSPROP_IGNORE_READONLY 0x8000 /* ignore the value in JSPROP_READONLY. |
| This flag only valid when defining over |
| an existing property. */ |
| #define JSPROP_IGNORE_PERMANENT 0x10000 /* ignore the value in JSPROP_PERMANENT. |
| This flag only valid when defining over |
| an existing property. */ |
| #define JSPROP_IGNORE_VALUE 0x20000 /* ignore the Value in the descriptor. Nothing was |
| specified when passed to Object.defineProperty |
| from script. */ |
| |
| /** |
| * The first call to JS_CallOnce by any thread in a process will call 'func'. |
| * Later calls to JS_CallOnce with the same JSCallOnceType object will be |
| * suppressed. |
| * |
| * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce |
| * to invoke its JSInitCallback. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_CallOnce(JSCallOnceType* once, JSInitCallback func); |
| |
| /** Microseconds since the epoch, midnight, January 1, 1970 UTC. */ |
| extern JS_PUBLIC_API(int64_t) |
| JS_Now(void); |
| |
| /** Don't want to export data, so provide accessors for non-inline Values. */ |
| extern JS_PUBLIC_API(JS::Value) |
| JS_GetNaNValue(JSContext* cx); |
| |
| extern JS_PUBLIC_API(JS::Value) |
| JS_GetNegativeInfinityValue(JSContext* cx); |
| |
| extern JS_PUBLIC_API(JS::Value) |
| JS_GetPositiveInfinityValue(JSContext* cx); |
| |
| extern JS_PUBLIC_API(JS::Value) |
| JS_GetEmptyStringValue(JSContext* cx); |
| |
| extern JS_PUBLIC_API(JSString*) |
| JS_GetEmptyString(JSRuntime* rt); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_ValueToObject(JSContext* cx, JS::HandleValue v, JS::MutableHandleObject objp); |
| |
| extern JS_PUBLIC_API(JSFunction*) |
| JS_ValueToFunction(JSContext* cx, JS::HandleValue v); |
| |
| extern JS_PUBLIC_API(JSFunction*) |
| JS_ValueToConstructor(JSContext* cx, JS::HandleValue v); |
| |
| extern JS_PUBLIC_API(JSString*) |
| JS_ValueToSource(JSContext* cx, JS::Handle<JS::Value> v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DoubleIsInt32(double d, int32_t* ip); |
| |
| extern JS_PUBLIC_API(JSType) |
| JS_TypeOfValue(JSContext* cx, JS::Handle<JS::Value> v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_StrictlyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_LooselyEqual(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* equal); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SameValue(JSContext* cx, JS::Handle<JS::Value> v1, JS::Handle<JS::Value> v2, bool* same); |
| |
| /** True iff fun is the global eval function. */ |
| extern JS_PUBLIC_API(bool) |
| JS_IsBuiltinEvalFunction(JSFunction* fun); |
| |
| /** True iff fun is the Function constructor. */ |
| extern JS_PUBLIC_API(bool) |
| JS_IsBuiltinFunctionConstructor(JSFunction* fun); |
| |
| /************************************************************************/ |
| |
| /* |
| * Locking, contexts, and memory allocation. |
| * |
| * It is important that SpiderMonkey be initialized, and the first 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 |
| */ |
| |
| extern JS_PUBLIC_API(JSRuntime*) |
| JS_NewRuntime(uint32_t maxbytes, |
| uint32_t maxNurseryBytes = JS::DefaultNurseryBytes, |
| JSRuntime* parentRuntime = nullptr); |
| |
| extern JS_PUBLIC_API(void) |
| JS_DestroyRuntime(JSRuntime* rt); |
| |
| typedef double (*JS_CurrentEmbedderTimeFunction)(); |
| |
| /** |
| * The embedding can specify a time function that will be used in some |
| * situations. The function can return the time however it likes; but |
| * the norm is to return times in units of milliseconds since an |
| * arbitrary, but consistent, epoch. If the time function is not set, |
| * a built-in default will be used. |
| */ |
| JS_PUBLIC_API(void) |
| JS_SetCurrentEmbedderTimeFunction(JS_CurrentEmbedderTimeFunction timeFn); |
| |
| /** |
| * Return the time as computed using the current time function, or a |
| * suitable default if one has not been set. |
| */ |
| JS_PUBLIC_API(double) |
| JS_GetCurrentEmbedderTime(); |
| |
| JS_PUBLIC_API(void*) |
| JS_GetRuntimePrivate(JSRuntime* rt); |
| |
| extern JS_PUBLIC_API(JSRuntime*) |
| JS_GetRuntime(JSContext* cx); |
| |
| extern JS_PUBLIC_API(JSRuntime*) |
| JS_GetParentRuntime(JSContext* cx); |
| |
| JS_PUBLIC_API(void) |
| JS_SetRuntimePrivate(JSRuntime* rt, void* data); |
| |
| extern JS_PUBLIC_API(void) |
| JS_BeginRequest(JSContext* cx); |
| |
| extern JS_PUBLIC_API(void) |
| JS_EndRequest(JSContext* cx); |
| |
| namespace js { |
| |
| void |
| AssertHeapIsIdle(JSRuntime* rt); |
| |
| void |
| AssertHeapIsIdle(JSContext* cx); |
| |
| } /* namespace js */ |
| |
| class MOZ_RAII JSAutoRequest |
| { |
| public: |
| explicit JSAutoRequest(JSContext* cx |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM) |
| : mContext(cx) |
| { |
| MOZ_GUARD_OBJECT_NOTIFIER_INIT; |
| JS_BeginRequest(mContext); |
| } |
| ~JSAutoRequest() { |
| JS_EndRequest(mContext); |
| } |
| |
| protected: |
| JSContext* mContext; |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| |
| #if 0 |
| private: |
| static void* operator new(size_t) CPP_THROW_NEW { return 0; } |
| static void operator delete(void*, size_t) { } |
| #endif |
| }; |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetContextCallback(JSRuntime* rt, JSContextCallback cxCallback, void* data); |
| |
| extern JS_PUBLIC_API(JSContext*) |
| JS_NewContext(JSRuntime* rt, size_t stackChunkSize); |
| |
| extern JS_PUBLIC_API(void) |
| JS_DestroyContext(JSContext* cx); |
| |
| extern JS_PUBLIC_API(void) |
| JS_DestroyContextNoGC(JSContext* cx); |
| |
| extern JS_PUBLIC_API(void*) |
| JS_GetContextPrivate(JSContext* cx); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetContextPrivate(JSContext* cx, void* data); |
| |
| extern JS_PUBLIC_API(void*) |
| JS_GetSecondContextPrivate(JSContext* cx); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetSecondContextPrivate(JSContext* cx, void* data); |
| |
| extern JS_PUBLIC_API(JSRuntime*) |
| JS_GetRuntime(JSContext* cx); |
| |
| extern JS_PUBLIC_API(JSContext*) |
| JS_ContextIterator(JSRuntime* rt, JSContext** iterp); |
| |
| extern JS_PUBLIC_API(JSVersion) |
| JS_GetVersion(JSContext* cx); |
| |
| /** |
| * Mutate the version on the compartment. This is generally discouraged, but |
| * necessary to support the version mutation in the js and xpc shell command |
| * set. |
| * |
| * It would be nice to put this in jsfriendapi, but the linkage requirements |
| * of the shells make that impossible. |
| */ |
| JS_PUBLIC_API(void) |
| JS_SetVersionForCompartment(JSCompartment* compartment, JSVersion version); |
| |
| extern JS_PUBLIC_API(const char*) |
| JS_VersionToString(JSVersion version); |
| |
| extern JS_PUBLIC_API(JSVersion) |
| JS_StringToVersion(const char* string); |
| |
| namespace JS { |
| |
| class JS_PUBLIC_API(RuntimeOptions) { |
| public: |
| RuntimeOptions() |
| : |
| #if defined(COBALT_DISABLE_JIT) |
| baseline_(false), |
| ion_(false), |
| asmJS_(false), |
| #else |
| baseline_(true), |
| ion_(true), |
| asmJS_(true), |
| #endif |
| throwOnAsmJSValidationFailure_(false), |
| #if defined(COBALT_DISABLE_JIT) |
| nativeRegExp_(false), |
| #else |
| nativeRegExp_(true), |
| #endif |
| unboxedArrays_(false), |
| asyncStack_(true), |
| werror_(false), |
| strictMode_(false), |
| extraWarnings_(false) |
| { |
| } |
| |
| bool baseline() const { return baseline_; } |
| RuntimeOptions& setBaseline(bool flag) { |
| baseline_ = flag; |
| return *this; |
| } |
| RuntimeOptions& toggleBaseline() { |
| baseline_ = !baseline_; |
| return *this; |
| } |
| |
| bool ion() const { return ion_; } |
| RuntimeOptions& setIon(bool flag) { |
| ion_ = flag; |
| return *this; |
| } |
| RuntimeOptions& toggleIon() { |
| ion_ = !ion_; |
| return *this; |
| } |
| |
| bool asmJS() const { return asmJS_; } |
| RuntimeOptions& setAsmJS(bool flag) { |
| asmJS_ = flag; |
| return *this; |
| } |
| RuntimeOptions& toggleAsmJS() { |
| asmJS_ = !asmJS_; |
| return *this; |
| } |
| |
| bool throwOnAsmJSValidationFailure() const { return throwOnAsmJSValidationFailure_; } |
| RuntimeOptions& setThrowOnAsmJSValidationFailure(bool flag) { |
| throwOnAsmJSValidationFailure_ = flag; |
| return *this; |
| } |
| RuntimeOptions& toggleThrowOnAsmJSValidationFailure() { |
| throwOnAsmJSValidationFailure_ = !throwOnAsmJSValidationFailure_; |
| return *this; |
| } |
| |
| bool nativeRegExp() const { return nativeRegExp_; } |
| RuntimeOptions& setNativeRegExp(bool flag) { |
| nativeRegExp_ = flag; |
| return *this; |
| } |
| |
| bool unboxedArrays() const { return unboxedArrays_; } |
| RuntimeOptions& setUnboxedArrays(bool flag) { |
| unboxedArrays_ = flag; |
| return *this; |
| } |
| |
| bool asyncStack() const { return asyncStack_; } |
| RuntimeOptions& setAsyncStack(bool flag) { |
| asyncStack_ = flag; |
| return *this; |
| } |
| |
| bool werror() const { return werror_; } |
| RuntimeOptions& setWerror(bool flag) { |
| werror_ = flag; |
| return *this; |
| } |
| RuntimeOptions& toggleWerror() { |
| werror_ = !werror_; |
| return *this; |
| } |
| |
| bool strictMode() const { return strictMode_; } |
| RuntimeOptions& setStrictMode(bool flag) { |
| strictMode_ = flag; |
| return *this; |
| } |
| RuntimeOptions& toggleStrictMode() { |
| strictMode_ = !strictMode_; |
| return *this; |
| } |
| |
| bool extraWarnings() const { return extraWarnings_; } |
| RuntimeOptions& setExtraWarnings(bool flag) { |
| extraWarnings_ = flag; |
| return *this; |
| } |
| RuntimeOptions& toggleExtraWarnings() { |
| extraWarnings_ = !extraWarnings_; |
| return *this; |
| } |
| |
| private: |
| bool baseline_ : 1; |
| bool ion_ : 1; |
| bool asmJS_ : 1; |
| bool throwOnAsmJSValidationFailure_ : 1; |
| bool nativeRegExp_ : 1; |
| bool unboxedArrays_ : 1; |
| bool asyncStack_ : 1; |
| bool werror_ : 1; |
| bool strictMode_ : 1; |
| bool extraWarnings_ : 1; |
| }; |
| |
| JS_PUBLIC_API(RuntimeOptions&) |
| RuntimeOptionsRef(JSRuntime* rt); |
| |
| JS_PUBLIC_API(RuntimeOptions&) |
| RuntimeOptionsRef(JSContext* cx); |
| |
| class JS_PUBLIC_API(ContextOptions) { |
| public: |
| ContextOptions() |
| : privateIsNSISupports_(false), |
| dontReportUncaught_(false), |
| autoJSAPIOwnsErrorReporting_(false) |
| { |
| } |
| |
| bool privateIsNSISupports() const { return privateIsNSISupports_; } |
| ContextOptions& setPrivateIsNSISupports(bool flag) { |
| privateIsNSISupports_ = flag; |
| return *this; |
| } |
| ContextOptions& togglePrivateIsNSISupports() { |
| privateIsNSISupports_ = !privateIsNSISupports_; |
| return *this; |
| } |
| |
| bool dontReportUncaught() const { return dontReportUncaught_; } |
| ContextOptions& setDontReportUncaught(bool flag) { |
| dontReportUncaught_ = flag; |
| return *this; |
| } |
| ContextOptions& toggleDontReportUncaught() { |
| dontReportUncaught_ = !dontReportUncaught_; |
| return *this; |
| } |
| |
| bool autoJSAPIOwnsErrorReporting() const { return autoJSAPIOwnsErrorReporting_; } |
| ContextOptions& setAutoJSAPIOwnsErrorReporting(bool flag) { |
| autoJSAPIOwnsErrorReporting_ = flag; |
| return *this; |
| } |
| ContextOptions& toggleAutoJSAPIOwnsErrorReporting() { |
| autoJSAPIOwnsErrorReporting_ = !autoJSAPIOwnsErrorReporting_; |
| return *this; |
| } |
| |
| |
| private: |
| bool privateIsNSISupports_ : 1; |
| bool dontReportUncaught_ : 1; |
| // dontReportUncaught isn't respected by all JSAPI codepaths, particularly the |
| // JS_ReportError* functions that eventually report the error even when dontReportUncaught is |
| // set, if script is not running. We want a way to indicate that the embedder will always |
| // handle any exceptions, and that SpiderMonkey should just leave them on the context. This is |
| // the way we want to do all future error handling in Gecko - stealing the exception explicitly |
| // from the context and handling it as per the situation. This will eventually become the |
| // default and these 2 flags should go away. |
| bool autoJSAPIOwnsErrorReporting_ : 1; |
| }; |
| |
| JS_PUBLIC_API(ContextOptions&) |
| ContextOptionsRef(JSContext* cx); |
| |
| class JS_PUBLIC_API(AutoSaveContextOptions) { |
| public: |
| explicit AutoSaveContextOptions(JSContext* cx) |
| : cx_(cx), |
| oldOptions_(ContextOptionsRef(cx_)) |
| { |
| } |
| |
| ~AutoSaveContextOptions() |
| { |
| ContextOptionsRef(cx_) = oldOptions_; |
| } |
| |
| private: |
| JSContext* cx_; |
| JS::ContextOptions oldOptions_; |
| }; |
| |
| } /* namespace JS */ |
| |
| extern JS_PUBLIC_API(const char*) |
| JS_GetImplementationVersion(void); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetDestroyCompartmentCallback(JSRuntime* rt, JSDestroyCompartmentCallback callback); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetDestroyZoneCallback(JSRuntime* rt, JSZoneCallback callback); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetSweepZoneCallback(JSRuntime* rt, JSZoneCallback callback); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetCompartmentNameCallback(JSRuntime* rt, JSCompartmentNameCallback callback); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetWrapObjectCallbacks(JSRuntime* rt, const JSWrapObjectCallbacks* callbacks); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetCompartmentPrivate(JSCompartment* compartment, void* data); |
| |
| extern JS_PUBLIC_API(void*) |
| JS_GetCompartmentPrivate(JSCompartment* compartment); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetZoneUserData(JS::Zone* zone, void* data); |
| |
| extern JS_PUBLIC_API(void*) |
| JS_GetZoneUserData(JS::Zone* zone); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_WrapObject(JSContext* cx, JS::MutableHandleObject objp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_WrapValue(JSContext* cx, JS::MutableHandleValue vp); |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_TransplantObject(JSContext* cx, JS::HandleObject origobj, JS::HandleObject target); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_RefreshCrossCompartmentWrappers(JSContext* cx, JS::Handle<JSObject*> obj); |
| |
| /* |
| * At any time, a JSContext has a current (possibly-nullptr) compartment. |
| * Compartments are described in: |
| * |
| * developer.mozilla.org/en-US/docs/SpiderMonkey/SpiderMonkey_compartments |
| * |
| * The current compartment of a context may be changed. The preferred way to do |
| * this is with JSAutoCompartment: |
| * |
| * void foo(JSContext* cx, JSObject* obj) { |
| * // in some compartment 'c' |
| * { |
| * JSAutoCompartment ac(cx, obj); // constructor enters |
| * // in the compartment of 'obj' |
| * } // destructor leaves |
| * // back in compartment 'c' |
| * } |
| * |
| * For more complicated uses that don't neatly fit in a C++ stack frame, the |
| * compartment can entered and left using separate function calls: |
| * |
| * void foo(JSContext* cx, JSObject* obj) { |
| * // in 'oldCompartment' |
| * JSCompartment* oldCompartment = JS_EnterCompartment(cx, obj); |
| * // in the compartment of 'obj' |
| * JS_LeaveCompartment(cx, oldCompartment); |
| * // back in 'oldCompartment' |
| * } |
| * |
| * Note: these calls must still execute in a LIFO manner w.r.t all other |
| * enter/leave calls on the context. Furthermore, only the return value of a |
| * JS_EnterCompartment call may be passed as the 'oldCompartment' argument of |
| * the corresponding JS_LeaveCompartment call. |
| */ |
| |
| class MOZ_RAII JS_PUBLIC_API(JSAutoCompartment) |
| { |
| JSContext* cx_; |
| JSCompartment* oldCompartment_; |
| public: |
| JSAutoCompartment(JSContext* cx, JSObject* target |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM); |
| JSAutoCompartment(JSContext* cx, JSScript* target |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM); |
| ~JSAutoCompartment(); |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| class MOZ_RAII JS_PUBLIC_API(JSAutoNullableCompartment) |
| { |
| JSContext* cx_; |
| JSCompartment* oldCompartment_; |
| public: |
| explicit JSAutoNullableCompartment(JSContext* cx, JSObject* targetOrNull |
| MOZ_GUARD_OBJECT_NOTIFIER_PARAM); |
| ~JSAutoNullableCompartment(); |
| |
| MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER |
| }; |
| |
| /** NB: This API is infallible; a nullptr return value does not indicate error. */ |
| extern JS_PUBLIC_API(JSCompartment*) |
| JS_EnterCompartment(JSContext* cx, JSObject* target); |
| |
| extern JS_PUBLIC_API(void) |
| JS_LeaveCompartment(JSContext* cx, JSCompartment* oldCompartment); |
| |
| typedef void (*JSIterateCompartmentCallback)(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. Also, barriers are disabled via the TraceSession. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_IterateCompartments(JSRuntime* rt, void* data, |
| JSIterateCompartmentCallback compartmentCallback); |
| |
| /** |
| * Initialize standard JS class constructors, prototypes, and any top-level |
| * functions and constants associated with the standard classes (e.g. isNaN |
| * for Number). |
| * |
| * NB: This sets cx's global object to obj if it was null. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_InitStandardClasses(JSContext* cx, JS::Handle<JSObject*> obj); |
| |
| /** |
| * Resolve id, which must contain either a string or an int, to a standard |
| * class name in obj if possible, defining the class's constructor and/or |
| * prototype and storing true in *resolved. If id does not name a standard |
| * class or a top-level property induced by initializing a standard class, |
| * store false in *resolved and just return true. Return false on error, |
| * as usual for bool result-typed API entry points. |
| * |
| * This API can be called directly from a global object class's resolve op, |
| * to define standard classes lazily. The class's enumerate op should call |
| * JS_EnumerateStandardClasses(cx, obj), to define eagerly during for..in |
| * loops any classes not yet resolved lazily. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_ResolveStandardClass(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolved); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_EnumerateStandardClasses(JSContext* cx, JS::HandleObject obj); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetClassObject(JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetClassPrototype(JSContext* cx, JSProtoKey key, JS::MutableHandle<JSObject*> objp); |
| |
| namespace JS { |
| |
| /* |
| * Determine if the given object is an instance/prototype/constructor for a standard |
| * class. If so, return the associated JSProtoKey. If not, return JSProto_Null. |
| */ |
| |
| extern JS_PUBLIC_API(JSProtoKey) |
| IdentifyStandardInstance(JSObject* obj); |
| |
| extern JS_PUBLIC_API(JSProtoKey) |
| IdentifyStandardPrototype(JSObject* obj); |
| |
| extern JS_PUBLIC_API(JSProtoKey) |
| IdentifyStandardInstanceOrPrototype(JSObject* obj); |
| |
| extern JS_PUBLIC_API(JSProtoKey) |
| IdentifyStandardConstructor(JSObject* obj); |
| |
| extern JS_PUBLIC_API(void) |
| ProtoKeyToId(JSContext* cx, JSProtoKey key, JS::MutableHandleId idp); |
| |
| } /* namespace JS */ |
| |
| extern JS_PUBLIC_API(JSProtoKey) |
| JS_IdToProtoKey(JSContext* cx, JS::HandleId id); |
| |
| /** |
| * Returns the original value of |Function.prototype| from the global object in |
| * which |forObj| was created. |
| */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetFunctionPrototype(JSContext* cx, JS::HandleObject forObj); |
| |
| /** |
| * Returns the original value of |Object.prototype| from the global object in |
| * which |forObj| was created. |
| */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetObjectPrototype(JSContext* cx, JS::HandleObject forObj); |
| |
| /** |
| * Returns the original value of |Array.prototype| from the global object in |
| * which |forObj| was created. |
| */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetArrayPrototype(JSContext* cx, JS::HandleObject forObj); |
| |
| /** |
| * Returns the original value of |Error.prototype| from the global |
| * object of the current compartment of cx. |
| */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetErrorPrototype(JSContext* cx); |
| |
| /** |
| * Returns the %IteratorPrototype% object that all built-in iterator prototype |
| * chains go through for the global object of the current compartment of cx. |
| */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetIteratorPrototype(JSContext* cx); |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetGlobalForObject(JSContext* cx, JSObject* obj); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_IsGlobalObject(JSObject* obj); |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GlobalLexicalScope(JSObject* obj); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_HasExtensibleLexicalScope(JSObject* obj); |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_ExtensibleLexicalScope(JSObject* obj); |
| |
| /** |
| * May return nullptr, if |c| never had a global (e.g. the atoms compartment), |
| * or if |c|'s global has been collected. |
| */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetGlobalForCompartmentOrNull(JSContext* cx, JSCompartment* c); |
| |
| namespace JS { |
| |
| extern JS_PUBLIC_API(JSObject*) |
| CurrentGlobalOrNull(JSContext* cx); |
| |
| } // namespace JS |
| |
| /** |
| * Add 'Reflect.parse', a SpiderMonkey extension, to the Reflect object on the |
| * given global. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_InitReflectParse(JSContext* cx, JS::HandleObject global); |
| |
| /** |
| * Add various profiling-related functions as properties of the given object. |
| * Defined in builtin/Profilers.cpp. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_DefineProfilingFunctions(JSContext* cx, JS::HandleObject obj); |
| |
| /* Defined in vm/Debugger.cpp. */ |
| extern JS_PUBLIC_API(bool) |
| JS_DefineDebuggerObject(JSContext* cx, JS::HandleObject obj); |
| |
| #ifdef JS_HAS_CTYPES |
| /** |
| * Initialize the 'ctypes' object on a global variable 'obj'. The 'ctypes' |
| * object will be sealed. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_InitCTypesClass(JSContext* cx, JS::HandleObject global); |
| |
| /** |
| * Convert a unicode string 'source' of length 'slen' to the platform native |
| * charset, returning a null-terminated string allocated with JS_malloc. On |
| * failure, this function should report an error. |
| */ |
| typedef char* |
| (* JSCTypesUnicodeToNativeFun)(JSContext* cx, const char16_t* source, size_t slen); |
| |
| /** |
| * Set of function pointers that ctypes can use for various internal functions. |
| * See JS_SetCTypesCallbacks below. Providing nullptr for a function is safe, |
| * and will result in the applicable ctypes functionality not being available. |
| */ |
| struct JSCTypesCallbacks { |
| JSCTypesUnicodeToNativeFun unicodeToNative; |
| }; |
| |
| typedef struct JSCTypesCallbacks JSCTypesCallbacks; |
| |
| /** |
| * Set the callbacks on the provided 'ctypesObj' object. 'callbacks' should be a |
| * pointer to static data that exists for the lifetime of 'ctypesObj', but it |
| * may safely be altered after calling this function and without having |
| * to call this function again. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_SetCTypesCallbacks(JSObject* ctypesObj, const JSCTypesCallbacks* callbacks); |
| #endif |
| |
| extern JS_PUBLIC_API(void*) |
| JS_malloc(JSContext* cx, size_t nbytes); |
| |
| extern JS_PUBLIC_API(void*) |
| JS_realloc(JSContext* cx, void* p, size_t oldBytes, size_t newBytes); |
| |
| /** |
| * A wrapper for js_free(p) that may delay js_free(p) invocation as a |
| * performance optimization. |
| * cx may be nullptr. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_free(JSContext* cx, void* p); |
| |
| /** |
| * A wrapper for js_free(p) that may delay js_free(p) invocation as a |
| * performance optimization as specified by the given JSFreeOp instance. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_freeop(JSFreeOp* fop, void* p); |
| |
| extern JS_PUBLIC_API(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); |
| |
| /** |
| * Register externally maintained GC roots. |
| * |
| * traceOp: the trace operation. For each root the implementation should call |
| * JS_CallTracer whenever the root contains a traceable thing. |
| * data: the data argument to pass to each invocation of traceOp. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_AddExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data); |
| |
| /** Undo a call to JS_AddExtraGCRootsTracer. */ |
| extern JS_PUBLIC_API(void) |
| JS_RemoveExtraGCRootsTracer(JSRuntime* rt, JSTraceDataOp traceOp, void* data); |
| |
| /* |
| * Garbage collector API. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_GC(JSRuntime* rt); |
| |
| extern JS_PUBLIC_API(void) |
| JS_MaybeGC(JSContext* cx); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetGCCallback(JSRuntime* rt, JSGCCallback cb, void* data); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_AddFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb, void* data); |
| |
| extern JS_PUBLIC_API(void) |
| JS_RemoveFinalizeCallback(JSRuntime* rt, JSFinalizeCallback cb); |
| |
| /* |
| * Weak pointers and garbage collection |
| * |
| * Weak pointers are by their nature not marked as part of garbage collection, |
| * but they may need to be updated in two cases after a GC: |
| * |
| * 1) Their referent was found not to be live and is about to be finalized |
| * 2) Their referent has been moved by a compacting GC |
| * |
| * To handle this, any part of the system that maintain weak pointers to |
| * JavaScript GC things must register a callback with |
| * JS_(Add,Remove)WeakPointer{ZoneGroup,Compartment}Callback(). This callback |
| * must then call JS_UpdateWeakPointerAfterGC() on all weak pointers it knows |
| * about. |
| * |
| * Since sweeping is incremental, we have several callbacks to avoid repeatedly |
| * having to visit all embedder structures. The WeakPointerZoneGroupCallback is |
| * called once for each strongly connected group of zones, whereas the |
| * WeakPointerCompartmentCallback is called once for each compartment that is |
| * visited while sweeping. Structures that cannot contain references in more |
| * than one compartment should sweep the relevant per-compartment structures |
| * using the latter callback to minimizer per-slice overhead. |
| * |
| * The argument to JS_UpdateWeakPointerAfterGC() is an in-out param. If the |
| * referent is about to be finalized the pointer will be set to null. If the |
| * referent has been moved then the pointer will be updated to point to the new |
| * location. |
| * |
| * Callers of this method are responsible for updating any state that is |
| * dependent on the object's address. For example, if the object's address is |
| * used as a key in a hashtable, then the object must be removed and |
| * re-inserted with the correct hash. |
| */ |
| |
| extern JS_PUBLIC_API(bool) |
| JS_AddWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb, void* data); |
| |
| extern JS_PUBLIC_API(void) |
| JS_RemoveWeakPointerZoneGroupCallback(JSRuntime* rt, JSWeakPointerZoneGroupCallback cb); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_AddWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb, |
| void* data); |
| |
| extern JS_PUBLIC_API(void) |
| JS_RemoveWeakPointerCompartmentCallback(JSRuntime* rt, JSWeakPointerCompartmentCallback cb); |
| |
| extern JS_PUBLIC_API(void) |
| JS_UpdateWeakPointerAfterGC(JS::Heap<JSObject*>* objp); |
| |
| extern JS_PUBLIC_API(void) |
| JS_UpdateWeakPointerAfterGCUnbarriered(JSObject** objp); |
| |
| typedef enum JSGCParamKey { |
| /** Maximum nominal heap before last ditch GC. */ |
| JSGC_MAX_BYTES = 0, |
| |
| /** Number of JS_malloc bytes before last ditch GC. */ |
| JSGC_MAX_MALLOC_BYTES = 1, |
| |
| /** Amount of bytes allocated by the GC. */ |
| JSGC_BYTES = 3, |
| |
| /** Number of times GC has been invoked. Includes both major and minor GC. */ |
| JSGC_NUMBER = 4, |
| |
| /** Max size of the code cache in bytes. */ |
| JSGC_MAX_CODE_CACHE_BYTES = 5, |
| |
| /** Select GC mode. */ |
| JSGC_MODE = 6, |
| |
| /** Number of cached empty GC chunks. */ |
| JSGC_UNUSED_CHUNKS = 7, |
| |
| /** Total number of allocated GC chunks. */ |
| JSGC_TOTAL_CHUNKS = 8, |
| |
| /** Max milliseconds to spend in an incremental GC slice. */ |
| JSGC_SLICE_TIME_BUDGET = 9, |
| |
| /** Maximum size the GC mark stack can grow to. */ |
| JSGC_MARK_STACK_LIMIT = 10, |
| |
| /** |
| * GCs less than this far apart in time will be considered 'high-frequency GCs'. |
| * See setGCLastBytes in jsgc.cpp. |
| */ |
| JSGC_HIGH_FREQUENCY_TIME_LIMIT = 11, |
| |
| /** Start of dynamic heap growth. */ |
| JSGC_HIGH_FREQUENCY_LOW_LIMIT = 12, |
| |
| /** End of dynamic heap growth. */ |
| JSGC_HIGH_FREQUENCY_HIGH_LIMIT = 13, |
| |
| /** Upper bound of heap growth. */ |
| JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX = 14, |
| |
| /** Lower bound of heap growth. */ |
| JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN = 15, |
| |
| /** Heap growth for low frequency GCs. */ |
| JSGC_LOW_FREQUENCY_HEAP_GROWTH = 16, |
| |
| /** |
| * If false, the heap growth factor is fixed at 3. If true, it is determined |
| * based on whether GCs are high- or low- frequency. |
| */ |
| JSGC_DYNAMIC_HEAP_GROWTH = 17, |
| |
| /** If true, high-frequency GCs will use a longer mark slice. */ |
| JSGC_DYNAMIC_MARK_SLICE = 18, |
| |
| /** Lower limit after which we limit the heap growth. */ |
| JSGC_ALLOCATION_THRESHOLD = 19, |
| |
| /** |
| * We decommit memory lazily. If more than this number of megabytes is |
| * available to be decommitted, then JS_MaybeGC will trigger a shrinking GC |
| * to decommit it. |
| */ |
| JSGC_DECOMMIT_THRESHOLD = 20, |
| |
| /** |
| * We try to keep at least this many unused chunks in the free chunk pool at |
| * all times, even after a shrinking GC. |
| */ |
| JSGC_MIN_EMPTY_CHUNK_COUNT = 21, |
| |
| /** We never keep more than this many unused chunks in the free chunk pool. */ |
| JSGC_MAX_EMPTY_CHUNK_COUNT = 22, |
| |
| /** Whether compacting GC is enabled. */ |
| JSGC_COMPACTING_ENABLED = 23 |
| } JSGCParamKey; |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetGCParameter(JSRuntime* rt, JSGCParamKey key, uint32_t value); |
| |
| extern JS_PUBLIC_API(uint32_t) |
| JS_GetGCParameter(JSRuntime* rt, JSGCParamKey key); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetGCParameterForThread(JSContext* cx, JSGCParamKey key, uint32_t value); |
| |
| extern JS_PUBLIC_API(uint32_t) |
| JS_GetGCParameterForThread(JSContext* cx, JSGCParamKey key); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetGCParametersBasedOnAvailableMemory(JSRuntime* rt, uint32_t availMem); |
| |
| /** |
| * Create a new JSString whose chars member refers to external memory, i.e., |
| * memory requiring application-specific finalization. |
| */ |
| extern JS_PUBLIC_API(JSString*) |
| JS_NewExternalString(JSContext* cx, const char16_t* chars, size_t length, |
| const JSStringFinalizer* fin); |
| |
| /** |
| * Return whether 'str' was created with JS_NewExternalString or |
| * JS_NewExternalStringWithClosure. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_IsExternalString(JSString* str); |
| |
| /** |
| * Return the 'fin' arg passed to JS_NewExternalString. |
| */ |
| extern JS_PUBLIC_API(const JSStringFinalizer*) |
| JS_GetExternalStringFinalizer(JSString* str); |
| |
| /** |
| * Set the size of the native stack that should not be exceed. To disable |
| * stack size checking pass 0. |
| * |
| * SpiderMonkey allows for a distinction between system code (such as GCs, which |
| * may incidentally be triggered by script but are not strictly performed on |
| * behalf of such script), trusted script (as determined by JS_SetTrustedPrincipals), |
| * and untrusted script. Each kind of code may have a different stack quota, |
| * allowing embedders to keep higher-priority machinery running in the face of |
| * scripted stack exhaustion by something else. |
| * |
| * The stack quotas for each kind of code should be monotonically descending, |
| * and may be specified with this function. If 0 is passed for a given kind |
| * of code, it defaults to the value of the next-highest-priority kind. |
| * |
| * This function may only be called immediately after the runtime is initialized |
| * and before any code is executed and/or interrupts requested. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_SetNativeStackQuota(JSRuntime* cx, size_t systemCodeStackSize, |
| size_t trustedScriptStackSize = 0, |
| size_t untrustedScriptStackSize = 0); |
| |
| /************************************************************************/ |
| |
| extern JS_PUBLIC_API(bool) |
| JS_ValueToId(JSContext* cx, JS::HandleValue v, JS::MutableHandleId idp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_StringToId(JSContext* cx, JS::HandleString s, JS::MutableHandleId idp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_IdToValue(JSContext* cx, jsid id, JS::MutableHandle<JS::Value> vp); |
| |
| namespace JS { |
| |
| /** |
| * Convert obj to a primitive value. On success, store the result in vp and |
| * return true. |
| * |
| * The hint argument must be JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID (no |
| * hint). |
| * |
| * Implements: ES6 7.1.1 ToPrimitive(input, [PreferredType]). |
| */ |
| extern JS_PUBLIC_API(bool) |
| ToPrimitive(JSContext* cx, JS::HandleObject obj, JSType hint, JS::MutableHandleValue vp); |
| |
| /** |
| * If args.get(0) is one of the strings "string", "number", or "default", set |
| * *result to JSTYPE_STRING, JSTYPE_NUMBER, or JSTYPE_VOID accordingly and |
| * return true. Otherwise, return false with a TypeError pending. |
| * |
| * This can be useful in implementing a @@toPrimitive method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| GetFirstArgumentAsTypeHint(JSContext* cx, CallArgs args, JSType *result); |
| |
| } /* namespace JS */ |
| |
| extern JS_PUBLIC_API(bool) |
| JS_PropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::MutableHandleValue vp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_StrictPropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::MutableHandleValue vp, JS::ObjectOpResult& result); |
| |
| template<typename T> |
| struct JSConstScalarSpec { |
| const char* name; |
| T val; |
| }; |
| |
| typedef JSConstScalarSpec<double> JSConstDoubleSpec; |
| typedef JSConstScalarSpec<int32_t> JSConstIntegerSpec; |
| |
| struct JSJitInfo; |
| |
| /** |
| * Wrapper to relace JSNative for JSPropertySpecs and JSFunctionSpecs. This will |
| * allow us to pass one JSJitInfo per function with the property/function spec, |
| * without additional field overhead. |
| */ |
| typedef struct JSNativeWrapper { |
| JSNative op; |
| const JSJitInfo* info; |
| } JSNativeWrapper; |
| |
| /* |
| * Macro static initializers which make it easy to pass no JSJitInfo as part of a |
| * JSPropertySpec or JSFunctionSpec. |
| */ |
| #define JSNATIVE_WRAPPER(native) { {native, nullptr} } |
| |
| /** |
| * Description of a property. JS_DefineProperties and JS_InitClass take arrays |
| * of these and define many properties at once. JS_PSG, JS_PSGS and JS_PS_END |
| * are helper macros for defining such arrays. |
| */ |
| struct JSPropertySpec { |
| struct SelfHostedWrapper { |
| void* unused; |
| const char* funname; |
| }; |
| |
| const char* name; |
| uint8_t flags; |
| union { |
| JSNativeWrapper native; |
| SelfHostedWrapper selfHosted; |
| } getter; |
| union { |
| JSNativeWrapper native; |
| SelfHostedWrapper selfHosted; |
| } setter; |
| |
| bool isSelfHosted() const { |
| #ifdef DEBUG |
| // Verify that our accessors match our JSPROP_GETTER flag. |
| if (flags & JSPROP_GETTER) |
| checkAccessorsAreSelfHosted(); |
| else |
| checkAccessorsAreNative(); |
| #endif |
| return (flags & JSPROP_GETTER); |
| } |
| |
| static_assert(sizeof(SelfHostedWrapper) == sizeof(JSNativeWrapper), |
| "JSPropertySpec::getter/setter must be compact"); |
| static_assert(offsetof(SelfHostedWrapper, funname) == offsetof(JSNativeWrapper, info), |
| "JS_SELF_HOSTED* macros below require that " |
| "SelfHostedWrapper::funname overlay " |
| "JSNativeWrapper::info"); |
| private: |
| void checkAccessorsAreNative() const { |
| MOZ_ASSERT(getter.native.op); |
| // We may not have a setter at all. So all we can assert here, for the |
| // native case is that if we have a jitinfo for the setter then we have |
| // a setter op too. This is good enough to make sure we don't have a |
| // SelfHostedWrapper for the setter. |
| MOZ_ASSERT_IF(setter.native.info, setter.native.op); |
| } |
| |
| void checkAccessorsAreSelfHosted() const { |
| MOZ_ASSERT(!getter.selfHosted.unused); |
| MOZ_ASSERT(!setter.selfHosted.unused); |
| } |
| }; |
| |
| namespace JS { |
| namespace detail { |
| |
| /* NEVER DEFINED, DON'T USE. For use by JS_CAST_NATIVE_TO only. */ |
| inline int CheckIsNative(JSNative native); |
| |
| /* NEVER DEFINED, DON'T USE. For use by JS_CAST_STRING_TO only. */ |
| template<size_t N> |
| inline int |
| CheckIsCharacterLiteral(const char (&arr)[N]); |
| |
| /* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_GETTER only. */ |
| inline int CheckIsGetterOp(JSGetterOp op); |
| |
| /* NEVER DEFINED, DON'T USE. For use by JS_PROPERTYOP_SETTER only. */ |
| inline int CheckIsSetterOp(JSSetterOp op); |
| |
| |
| } // namespace detail |
| } // namespace JS |
| |
| #define JS_CAST_NATIVE_TO(v, To) \ |
| (static_cast<void>(sizeof(JS::detail::CheckIsNative(v))), \ |
| reinterpret_cast<To>(v)) |
| |
| #define JS_CAST_STRING_TO(s, To) \ |
| (static_cast<void>(sizeof(JS::detail::CheckIsCharacterLiteral(s))), \ |
| reinterpret_cast<To>(s)) |
| |
| #define JS_CHECK_ACCESSOR_FLAGS(flags) \ |
| (static_cast<mozilla::EnableIf<((flags) & ~(JSPROP_ENUMERATE | JSPROP_PERMANENT)) == 0>::Type>(0), \ |
| (flags)) |
| |
| #define JS_PROPERTYOP_GETTER(v) \ |
| (static_cast<void>(sizeof(JS::detail::CheckIsGetterOp(v))), \ |
| reinterpret_cast<JSNative>(v)) |
| |
| #define JS_PROPERTYOP_SETTER(v) \ |
| (static_cast<void>(sizeof(JS::detail::CheckIsSetterOp(v))), \ |
| reinterpret_cast<JSNative>(v)) |
| |
| #define JS_STUBGETTER JS_PROPERTYOP_GETTER(JS_PropertyStub) |
| |
| #define JS_STUBSETTER JS_PROPERTYOP_SETTER(JS_StrictPropertyStub) |
| |
| /* |
| * JSPropertySpec uses JSNativeWrapper. These macros encapsulate the definition |
| * of JSNative-backed JSPropertySpecs, by defining the JSNativeWrappers for |
| * them. |
| */ |
| #define JS_PSG(name, getter, flags) \ |
| {name, \ |
| uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \ |
| JSNATIVE_WRAPPER(getter), \ |
| JSNATIVE_WRAPPER(nullptr)} |
| #define JS_PSGS(name, getter, setter, flags) \ |
| {name, \ |
| uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED), \ |
| JSNATIVE_WRAPPER(getter), \ |
| JSNATIVE_WRAPPER(setter)} |
| #define JS_SELF_HOSTED_GET(name, getterName, flags) \ |
| {name, \ |
| uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \ |
| { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \ |
| JSNATIVE_WRAPPER(nullptr) } |
| #define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \ |
| {name, \ |
| uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER), \ |
| { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) }, \ |
| { nullptr, JS_CAST_STRING_TO(setterName, const JSJitInfo*) } } |
| #define JS_PS_END { nullptr, 0, JSNATIVE_WRAPPER(nullptr), JSNATIVE_WRAPPER(nullptr) } |
| #define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \ |
| {reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \ |
| uint8_t(JS_CHECK_ACCESSOR_FLAGS(flags) | JSPROP_SHARED | JSPROP_GETTER), \ |
| { { nullptr, JS_CAST_STRING_TO(getterName, const JSJitInfo*) } }, \ |
| JSNATIVE_WRAPPER(nullptr) } |
| |
| /** |
| * To define a native function, set call to a JSNativeWrapper. To define a |
| * self-hosted function, set selfHostedName to the name of a function |
| * compiled during JSRuntime::initSelfHosting. |
| */ |
| struct JSFunctionSpec { |
| const char* name; |
| JSNativeWrapper call; |
| uint16_t nargs; |
| uint16_t flags; |
| const char* selfHostedName; |
| }; |
| |
| /* |
| * Terminating sentinel initializer to put at the end of a JSFunctionSpec array |
| * that's passed to JS_DefineFunctions or JS_InitClass. |
| */ |
| #define JS_FS_END JS_FS(nullptr,nullptr,0,0) |
| |
| /* |
| * Initializer macros for a JSFunctionSpec array element. JS_FN (whose name pays |
| * homage to the old JSNative/JSFastNative split) simply adds the flag |
| * JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of |
| * JSJitInfos. JS_SELF_HOSTED_FN declares a self-hosted function. |
| * JS_INLINABLE_FN allows specifying an InlinableNative enum value for natives |
| * inlined or specialized by the JIT. Finally JS_FNSPEC has slots for all the |
| * fields. |
| * |
| * The _SYM variants allow defining a function with a symbol key rather than a |
| * string key. For example, use JS_SYM_FN(iterator, ...) to define an |
| * @@iterator method. |
| */ |
| #define JS_FS(name,call,nargs,flags) \ |
| JS_FNSPEC(name, call, nullptr, nargs, flags, nullptr) |
| #define JS_FN(name,call,nargs,flags) \ |
| JS_FNSPEC(name, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr) |
| #define JS_INLINABLE_FN(name,call,nargs,flags,native) \ |
| JS_FNSPEC(name, call, &js::jit::JitInfo_##native, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr) |
| #define JS_SYM_FN(symbol,call,nargs,flags) \ |
| JS_SYM_FNSPEC(symbol, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr) |
| #define JS_FNINFO(name,call,info,nargs,flags) \ |
| JS_FNSPEC(name, call, info, nargs, flags, nullptr) |
| #define JS_SELF_HOSTED_FN(name,selfHostedName,nargs,flags) \ |
| JS_FNSPEC(name, nullptr, nullptr, nargs, flags, selfHostedName) |
| #define JS_SELF_HOSTED_SYM_FN(symbol, selfHostedName, nargs, flags) \ |
| JS_SYM_FNSPEC(symbol, nullptr, nullptr, nargs, flags, selfHostedName) |
| #define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \ |
| JS_FNSPEC(reinterpret_cast<const char*>( \ |
| uint32_t(::JS::SymbolCode::symbol) + 1), \ |
| call, info, nargs, flags, selfHostedName) |
| #define JS_FNSPEC(name,call,info,nargs,flags,selfHostedName) \ |
| {name, {call, info}, nargs, flags, selfHostedName} |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_InitClass(JSContext* cx, JS::HandleObject obj, JS::HandleObject parent_proto, |
| const JSClass* clasp, JSNative constructor, unsigned nargs, |
| const JSPropertySpec* ps, const JSFunctionSpec* fs, |
| const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs); |
| |
| /** |
| * Set up ctor.prototype = proto and proto.constructor = ctor with the |
| * right property flags. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_LinkConstructorAndPrototype(JSContext* cx, JS::Handle<JSObject*> ctor, |
| JS::Handle<JSObject*> proto); |
| |
| extern JS_PUBLIC_API(const JSClass*) |
| JS_GetClass(JSObject* obj); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_InstanceOf(JSContext* cx, JS::Handle<JSObject*> obj, const JSClass* clasp, JS::CallArgs* args); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_HasInstance(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> v, bool* bp); |
| |
| extern JS_PUBLIC_API(void*) |
| JS_GetPrivate(JSObject* obj); |
| |
| extern JS_PUBLIC_API(void) |
| JS_SetPrivate(JSObject* obj, void* data); |
| |
| extern JS_PUBLIC_API(void*) |
| JS_GetInstancePrivate(JSContext* cx, JS::Handle<JSObject*> obj, const JSClass* clasp, |
| JS::CallArgs* args); |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_GetConstructor(JSContext* cx, JS::Handle<JSObject*> proto); |
| |
| namespace JS { |
| |
| enum ZoneSpecifier { |
| FreshZone = 0, |
| SystemZone = 1 |
| }; |
| |
| class JS_PUBLIC_API(CompartmentOptions) |
| { |
| public: |
| class Override { |
| public: |
| Override() : mode_(Default) {} |
| |
| bool get(bool defaultValue) const { |
| if (mode_ == Default) |
| return defaultValue; |
| return mode_ == ForceTrue; |
| } |
| |
| void set(bool overrideValue) { |
| mode_ = overrideValue ? ForceTrue : ForceFalse; |
| } |
| |
| void reset() { |
| mode_ = Default; |
| } |
| |
| private: |
| enum Mode { |
| Default, |
| ForceTrue, |
| ForceFalse |
| }; |
| |
| Mode mode_; |
| }; |
| |
| explicit CompartmentOptions() |
| : version_(JSVERSION_UNKNOWN) |
| , invisibleToDebugger_(false) |
| , mergeable_(false) |
| , discardSource_(false) |
| , disableLazyParsing_(false) |
| , cloneSingletons_(false) |
| , traceGlobal_(nullptr) |
| , singletonsAsTemplates_(true) |
| , addonId_(nullptr) |
| , preserveJitCode_(false) |
| { |
| zone_.spec = JS::FreshZone; |
| } |
| |
| JSVersion version() const { return version_; } |
| CompartmentOptions& setVersion(JSVersion aVersion) { |
| MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN); |
| version_ = aVersion; |
| return *this; |
| } |
| |
| // Certain scopes (i.e. XBL compilation scopes) are implementation details |
| // of the embedding, and references to them should never leak out to script. |
| // This flag causes the this compartment to skip firing onNewGlobalObject |
| // and makes addDebuggee a no-op for this global. |
| bool invisibleToDebugger() const { return invisibleToDebugger_; } |
| CompartmentOptions& setInvisibleToDebugger(bool flag) { |
| invisibleToDebugger_ = flag; |
| return *this; |
| } |
| |
| // Compartments used for off-thread compilation have their contents merged |
| // into a target compartment when the compilation is finished. This is only |
| // allowed if this flag is set. The invisibleToDebugger flag must also be |
| // set for such compartments. |
| bool mergeable() const { return mergeable_; } |
| CompartmentOptions& setMergeable(bool flag) { |
| mergeable_ = flag; |
| return *this; |
| } |
| |
| // For certain globals, we know enough about the code that will run in them |
| // that we can discard script source entirely. |
| bool discardSource() const { return discardSource_; } |
| CompartmentOptions& setDiscardSource(bool flag) { |
| discardSource_ = flag; |
| return *this; |
| } |
| |
| bool disableLazyParsing() const { return disableLazyParsing_; } |
| CompartmentOptions& setDisableLazyParsing(bool flag) { |
| disableLazyParsing_ = flag; |
| return *this; |
| } |
| |
| bool cloneSingletons() const { return cloneSingletons_; } |
| CompartmentOptions& setCloneSingletons(bool flag) { |
| cloneSingletons_ = flag; |
| return *this; |
| } |
| |
| bool extraWarnings(JSRuntime* rt) const; |
| bool extraWarnings(JSContext* cx) const; |
| Override& extraWarningsOverride() { return extraWarningsOverride_; } |
| |
| void* zonePointer() const { |
| MOZ_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone)); |
| return zone_.pointer; |
| } |
| ZoneSpecifier zoneSpecifier() const { return zone_.spec; } |
| CompartmentOptions& setZone(ZoneSpecifier spec); |
| CompartmentOptions& setSameZoneAs(JSObject* obj); |
| |
| void setSingletonsAsValues() { |
| singletonsAsTemplates_ = false; |
| } |
| bool getSingletonsAsTemplates() const { |
| return singletonsAsTemplates_; |
| } |
| |
| // A null add-on ID means that the compartment is not associated with an |
| // add-on. |
| JSAddonId* addonIdOrNull() const { return addonId_; } |
| CompartmentOptions& setAddonId(JSAddonId* id) { |
| addonId_ = id; |
| return *this; |
| } |
| |
| CompartmentOptions& setTrace(JSTraceOp op) { |
| traceGlobal_ = op; |
| return *this; |
| } |
| JSTraceOp getTrace() const { |
| return traceGlobal_; |
| } |
| |
| bool preserveJitCode() const { return preserveJitCode_; } |
| CompartmentOptions& setPreserveJitCode(bool flag) { |
| preserveJitCode_ = flag; |
| return *this; |
| } |
| |
| private: |
| JSVersion version_; |
| bool invisibleToDebugger_; |
| bool mergeable_; |
| bool discardSource_; |
| bool disableLazyParsing_; |
| bool cloneSingletons_; |
| Override extraWarningsOverride_; |
| union { |
| ZoneSpecifier spec; |
| void* pointer; // js::Zone* is not exposed in the API. |
| } zone_; |
| JSTraceOp traceGlobal_; |
| |
| // To XDR singletons, we need to ensure that all singletons are all used as |
| // templates, by making JSOP_OBJECT return a clone of the JSScript |
| // singleton, instead of returning the value which is baked in the JSScript. |
| bool singletonsAsTemplates_; |
| |
| JSAddonId* addonId_; |
| bool preserveJitCode_; |
| }; |
| |
| JS_PUBLIC_API(CompartmentOptions&) |
| CompartmentOptionsRef(JSCompartment* compartment); |
| |
| JS_PUBLIC_API(CompartmentOptions&) |
| CompartmentOptionsRef(JSObject* obj); |
| |
| JS_PUBLIC_API(CompartmentOptions&) |
| CompartmentOptionsRef(JSContext* cx); |
| |
| /** |
| * During global creation, we fire notifications to callbacks registered |
| * via the Debugger API. These callbacks are arbitrary script, and can touch |
| * the global in arbitrary ways. When that happens, the global should not be |
| * in a half-baked state. But this creates a problem for consumers that need |
| * to set slots on the global to put it in a consistent state. |
| * |
| * This API provides a way for consumers to set slots atomically (immediately |
| * after the global is created), before any debugger hooks are fired. It's |
| * unfortunately on the clunky side, but that's the way the cookie crumbles. |
| * |
| * If callers have no additional state on the global to set up, they may pass |
| * |FireOnNewGlobalHook| to JS_NewGlobalObject, which causes that function to |
| * fire the hook as its final act before returning. Otherwise, callers should |
| * pass |DontFireOnNewGlobalHook|, which means that they are responsible for |
| * invoking JS_FireOnNewGlobalObject upon successfully creating the global. If |
| * an error occurs and the operation aborts, callers should skip firing the |
| * hook. But otherwise, callers must take care to fire the hook exactly once |
| * before compiling any script in the global's scope (we have assertions in |
| * place to enforce this). This lets us be sure that debugger clients never miss |
| * breakpoints. |
| */ |
| enum OnNewGlobalHookOption { |
| FireOnNewGlobalHook, |
| DontFireOnNewGlobalHook |
| }; |
| |
| } /* namespace JS */ |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_NewGlobalObject(JSContext* cx, const JSClass* clasp, JSPrincipals* principals, |
| JS::OnNewGlobalHookOption hookOption, |
| const JS::CompartmentOptions& options = JS::CompartmentOptions()); |
| /** |
| * Spidermonkey does not have a good way of keeping track of what compartments should be marked on |
| * their own. We can mark the roots unconditionally, but marking GC things only relevant in live |
| * compartments is hard. To mitigate this, we create a static trace hook, installed on each global |
| * object, from which we can be sure the compartment is relevant, and mark it. |
| * |
| * It is still possible to specify custom trace hooks for global object classes. They can be |
| * provided via the CompartmentOptions passed to JS_NewGlobalObject. |
| */ |
| extern JS_PUBLIC_API(void) |
| JS_GlobalObjectTraceHook(JSTracer* trc, JSObject* global); |
| |
| extern JS_PUBLIC_API(void) |
| JS_FireOnNewGlobalObject(JSContext* cx, JS::HandleObject global); |
| |
| extern JS_PUBLIC_API(JSObject*) |
| JS_NewObject(JSContext* cx, const JSClass* clasp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_IsNative(JSObject* obj); |
| |
| extern JS_PUBLIC_API(JSRuntime*) |
| JS_GetObjectRuntime(JSObject* obj); |
| |
| /** |
| * Unlike JS_NewObject, JS_NewObjectWithGivenProto does not compute a default |
| * proto. If proto is nullptr, the JS object will have `null` as [[Prototype]]. |
| */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_NewObjectWithGivenProto(JSContext* cx, const JSClass* clasp, JS::Handle<JSObject*> proto); |
| |
| /** Creates a new plain object, like `new Object()`, with Object.prototype as [[Prototype]]. */ |
| extern JS_PUBLIC_API(JSObject*) |
| JS_NewPlainObject(JSContext* cx); |
| |
| /** |
| * Freeze obj, and all objects it refers to, recursively. This will not recurse |
| * through non-extensible objects, on the assumption that those are already |
| * deep-frozen. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_DeepFreezeObject(JSContext* cx, JS::Handle<JSObject*> obj); |
| |
| /** |
| * Freezes an object; see ES5's Object.freeze(obj) method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_FreezeObject(JSContext* cx, JS::Handle<JSObject*> obj); |
| |
| |
| /*** Property descriptors ************************************************************************/ |
| |
| struct JSPropertyDescriptor : public JS::Traceable { |
| JSObject* obj; |
| unsigned attrs; |
| JSGetterOp getter; |
| JSSetterOp setter; |
| JS::Value value; |
| |
| JSPropertyDescriptor() |
| : obj(nullptr), attrs(0), getter(nullptr), setter(nullptr), value(JS::UndefinedValue()) |
| {} |
| |
| static void trace(JSPropertyDescriptor* self, JSTracer* trc) { self->trace(trc); } |
| void trace(JSTracer* trc); |
| }; |
| |
| namespace JS { |
| |
| template <typename Outer> |
| class PropertyDescriptorOperations |
| { |
| const JSPropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); } |
| |
| bool has(unsigned bit) const { |
| MOZ_ASSERT(bit != 0); |
| MOZ_ASSERT((bit & (bit - 1)) == 0); // only a single bit |
| return (desc().attrs & bit) != 0; |
| } |
| |
| bool hasAny(unsigned bits) const { |
| return (desc().attrs & bits) != 0; |
| } |
| |
| bool hasAll(unsigned bits) const { |
| return (desc().attrs & bits) == bits; |
| } |
| |
| // Non-API attributes bit used internally for arguments objects. |
| enum { SHADOWABLE = JSPROP_INTERNAL_USE_BIT }; |
| |
| public: |
| // Descriptors with JSGetterOp/JSSetterOp are considered data |
| // descriptors. It's complicated. |
| bool isAccessorDescriptor() const { return hasAny(JSPROP_GETTER | JSPROP_SETTER); } |
| bool isGenericDescriptor() const { |
| return (desc().attrs& |
| (JSPROP_GETTER | JSPROP_SETTER | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE)) == |
| (JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE); |
| } |
| bool isDataDescriptor() const { return !isAccessorDescriptor() && !isGenericDescriptor(); } |
| |
| bool hasConfigurable() const { return !has(JSPROP_IGNORE_PERMANENT); } |
| bool configurable() const { MOZ_ASSERT(hasConfigurable()); return !has(JSPROP_PERMANENT); } |
| |
| bool hasEnumerable() const { return !has(JSPROP_IGNORE_ENUMERATE); } |
| bool enumerable() const { MOZ_ASSERT(hasEnumerable()); return has(JSPROP_ENUMERATE); } |
| |
| bool hasValue() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_VALUE); } |
| JS::HandleValue value() const { |
| return JS::HandleValue::fromMarkedLocation(&desc().value); |
| } |
| |
| bool hasWritable() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_READONLY); } |
| bool writable() const { MOZ_ASSERT(hasWritable()); return !has(JSPROP_READONLY); } |
| |
| bool hasGetterObject() const { return has(JSPROP_GETTER); } |
| JS::HandleObject getterObject() const { |
| MOZ_ASSERT(hasGetterObject()); |
| return JS::HandleObject::fromMarkedLocation( |
| reinterpret_cast<JSObject* const*>(&desc().getter)); |
| } |
| bool hasSetterObject() const { return has(JSPROP_SETTER); } |
| JS::HandleObject setterObject() const { |
| MOZ_ASSERT(hasSetterObject()); |
| return JS::HandleObject::fromMarkedLocation( |
| reinterpret_cast<JSObject* const*>(&desc().setter)); |
| } |
| |
| bool hasGetterOrSetter() const { return desc().getter || desc().setter; } |
| bool isShared() const { return has(JSPROP_SHARED); } |
| |
| JS::HandleObject object() const { |
| return JS::HandleObject::fromMarkedLocation(&desc().obj); |
| } |
| unsigned attributes() const { return desc().attrs; } |
| JSGetterOp getter() const { return desc().getter; } |
| JSSetterOp setter() const { return desc().setter; } |
| |
| void assertValid() const { |
| #ifdef DEBUG |
| MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE | JSPROP_IGNORE_ENUMERATE | |
| JSPROP_PERMANENT | JSPROP_IGNORE_PERMANENT | |
| JSPROP_READONLY | JSPROP_IGNORE_READONLY | |
| JSPROP_IGNORE_VALUE | |
| JSPROP_GETTER | |
| JSPROP_SETTER | |
| JSPROP_SHARED | |
| JSPROP_REDEFINE_NONCONFIGURABLE | |
| JSPROP_RESOLVING | |
| SHADOWABLE)) == 0); |
| MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)); |
| MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)); |
| if (isAccessorDescriptor()) { |
| MOZ_ASSERT(has(JSPROP_SHARED)); |
| MOZ_ASSERT(!has(JSPROP_READONLY)); |
| MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY)); |
| MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE)); |
| MOZ_ASSERT(!has(SHADOWABLE)); |
| MOZ_ASSERT(value().isUndefined()); |
| MOZ_ASSERT_IF(!has(JSPROP_GETTER), !getter()); |
| MOZ_ASSERT_IF(!has(JSPROP_SETTER), !setter()); |
| } else { |
| MOZ_ASSERT(!hasAll(JSPROP_IGNORE_READONLY | JSPROP_READONLY)); |
| MOZ_ASSERT_IF(has(JSPROP_IGNORE_VALUE), value().isUndefined()); |
| } |
| MOZ_ASSERT(getter() != JS_PropertyStub); |
| MOZ_ASSERT(setter() != JS_StrictPropertyStub); |
| |
| MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_ENUMERATE)); |
| MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_PERMANENT)); |
| MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_READONLY)); |
| MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_IGNORE_VALUE)); |
| MOZ_ASSERT_IF(has(JSPROP_RESOLVING), !has(JSPROP_REDEFINE_NONCONFIGURABLE)); |
| #endif |
| } |
| |
| void assertComplete() const { |
| #ifdef DEBUG |
| assertValid(); |
| MOZ_ASSERT((attributes() & ~(JSPROP_ENUMERATE | |
| JSPROP_PERMANENT | |
| JSPROP_READONLY | |
| JSPROP_GETTER | |
| JSPROP_SETTER | |
| JSPROP_SHARED | |
| JSPROP_REDEFINE_NONCONFIGURABLE | |
| JSPROP_RESOLVING | |
| SHADOWABLE)) == 0); |
| MOZ_ASSERT_IF(isAccessorDescriptor(), has(JSPROP_GETTER) && has(JSPROP_SETTER)); |
| #endif |
| } |
| |
| void assertCompleteIfFound() const { |
| #ifdef DEBUG |
| if (object()) |
| assertComplete(); |
| #endif |
| } |
| }; |
| |
| template <typename Outer> |
| class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer> |
| { |
| JSPropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); } |
| |
| public: |
| void clear() { |
| object().set(nullptr); |
| setAttributes(0); |
| setGetter(nullptr); |
| setSetter(nullptr); |
| value().setUndefined(); |
| } |
| |
| void initFields(HandleObject obj, HandleValue v, unsigned attrs, |
| JSGetterOp getterOp, JSSetterOp setterOp) { |
| MOZ_ASSERT(getterOp != JS_PropertyStub); |
| MOZ_ASSERT(setterOp != JS_StrictPropertyStub); |
| |
| object().set(obj); |
| value().set(v); |
| setAttributes(attrs); |
| setGetter(getterOp); |
| setSetter(setterOp); |
| } |
| |
| void assign(JSPropertyDescriptor& other) { |
| object().set(other.obj); |
| setAttributes(other.attrs); |
| setGetter(other.getter); |
| setSetter(other.setter); |
| value().set(other.value); |
| } |
| |
| void setDataDescriptor(HandleValue v, unsigned attrs) { |
| MOZ_ASSERT((attrs & ~(JSPROP_ENUMERATE | |
| JSPROP_PERMANENT | |
| JSPROP_READONLY | |
| JSPROP_IGNORE_ENUMERATE | |
| JSPROP_IGNORE_PERMANENT | |
| JSPROP_IGNORE_READONLY)) == 0); |
| object().set(nullptr); |
| setAttributes(attrs); |
| setGetter(nullptr); |
| setSetter(nullptr); |
| value().set(v); |
| } |
| |
| JS::MutableHandleObject object() { |
| return JS::MutableHandleObject::fromMarkedLocation(&desc().obj); |
| } |
| unsigned& attributesRef() { return desc().attrs; } |
| JSGetterOp& getter() { return desc().getter; } |
| JSSetterOp& setter() { return desc().setter; } |
| JS::MutableHandleValue value() { |
| return JS::MutableHandleValue::fromMarkedLocation(&desc().value); |
| } |
| void setValue(JS::HandleValue v) { |
| MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER))); |
| attributesRef() &= ~JSPROP_IGNORE_VALUE; |
| value().set(v); |
| } |
| |
| void setConfigurable(bool configurable) { |
| setAttributes((desc().attrs & ~(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)) | |
| (configurable ? 0 : JSPROP_PERMANENT)); |
| } |
| void setEnumerable(bool enumerable) { |
| setAttributes((desc().attrs & ~(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)) | |
| (enumerable ? JSPROP_ENUMERATE : 0)); |
| } |
| void setWritable(bool writable) { |
| MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER))); |
| setAttributes((desc().attrs & ~(JSPROP_IGNORE_READONLY | JSPROP_READONLY)) | |
| (writable ? 0 : JSPROP_READONLY)); |
| } |
| void setAttributes(unsigned attrs) { desc().attrs = attrs; } |
| |
| void setGetter(JSGetterOp op) { |
| MOZ_ASSERT(op != JS_PropertyStub); |
| desc().getter = op; |
| } |
| void setSetter(JSSetterOp op) { |
| MOZ_ASSERT(op != JS_StrictPropertyStub); |
| desc().setter = op; |
| } |
| void setGetterObject(JSObject* obj) { |
| desc().getter = reinterpret_cast<JSGetterOp>(obj); |
| desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY); |
| desc().attrs |= JSPROP_GETTER | JSPROP_SHARED; |
| } |
| void setSetterObject(JSObject* obj) { |
| desc().setter = reinterpret_cast<JSSetterOp>(obj); |
| desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY); |
| desc().attrs |= JSPROP_SETTER | JSPROP_SHARED; |
| } |
| |
| JS::MutableHandleObject getterObject() { |
| MOZ_ASSERT(this->hasGetterObject()); |
| return JS::MutableHandleObject::fromMarkedLocation( |
| reinterpret_cast<JSObject**>(&desc().getter)); |
| } |
| JS::MutableHandleObject setterObject() { |
| MOZ_ASSERT(this->hasSetterObject()); |
| return JS::MutableHandleObject::fromMarkedLocation( |
| reinterpret_cast<JSObject**>(&desc().setter)); |
| } |
| }; |
| |
| } /* namespace JS */ |
| |
| namespace js { |
| |
| template <> |
| class RootedBase<JSPropertyDescriptor> |
| : public JS::MutablePropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor>> |
| {}; |
| |
| template <> |
| class HandleBase<JSPropertyDescriptor> |
| : public JS::PropertyDescriptorOperations<JS::Handle<JSPropertyDescriptor>> |
| {}; |
| |
| template <> |
| class MutableHandleBase<JSPropertyDescriptor> |
| : public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor>> |
| {}; |
| |
| } /* namespace js */ |
| |
| namespace JS { |
| |
| extern JS_PUBLIC_API(bool) |
| ObjectToCompletePropertyDescriptor(JSContext* cx, |
| JS::HandleObject obj, |
| JS::HandleValue descriptor, |
| JS::MutableHandle<JSPropertyDescriptor> desc); |
| |
| } // namespace JS |
| |
| |
| /*** Standard internal methods ******************************************************************** |
| * |
| * The functions below are the fundamental operations on objects. |
| * |
| * ES6 specifies 14 internal methods that define how objects behave. The |
| * standard is actually quite good on this topic, though you may have to read |
| * it a few times. See ES6 sections 6.1.7.2 and 6.1.7.3. |
| * |
| * When 'obj' is an ordinary object, these functions have boring standard |
| * behavior as specified by ES6 section 9.1; see the section about internal |
| * methods in js/src/vm/NativeObject.h. |
| * |
| * Proxies override the behavior of internal methods. So when 'obj' is a proxy, |
| * any one of the functions below could do just about anything. See |
| * js/public/Proxy.h. |
| */ |
| |
| /** |
| * Get the prototype of obj, storing it in result. |
| * |
| * Implements: ES6 [[GetPrototypeOf]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_GetPrototype(JSContext* cx, JS::HandleObject obj, JS::MutableHandleObject result); |
| |
| /** |
| * Change the prototype of obj. |
| * |
| * Implements: ES6 [[SetPrototypeOf]] internal method. |
| * |
| * In cases where ES6 [[SetPrototypeOf]] returns false without an exception, |
| * JS_SetPrototype throws a TypeError and returns false. |
| * |
| * Performance warning: JS_SetPrototype is very bad for performance. It may |
| * cause compiled jit-code to be invalidated. It also causes not only obj but |
| * all other objects in the same "group" as obj to be permanently deoptimized. |
| * It's better to create the object with the right prototype from the start. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_SetPrototype(JSContext* cx, JS::HandleObject obj, JS::HandleObject proto); |
| |
| /** |
| * Determine whether obj is extensible. Extensible objects can have new |
| * properties defined on them. Inextensible objects can't, and their |
| * [[Prototype]] slot is fixed as well. |
| * |
| * Implements: ES6 [[IsExtensible]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_IsExtensible(JSContext* cx, JS::HandleObject obj, bool* extensible); |
| |
| /** |
| * Attempt to make |obj| non-extensible. |
| * |
| * Not all failures are treated as errors. See the comment on |
| * JS::ObjectOpResult in js/public/Class.h. |
| * |
| * Implements: ES6 [[PreventExtensions]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result); |
| |
| /** |
| * Attempt to make the [[Prototype]] of |obj| immutable, such that any attempt |
| * to modify it will fail. If an error occurs during the attempt, return false |
| * (with a pending exception set, depending upon the nature of the error). If |
| * no error occurs, return true with |*succeeded| set to indicate whether the |
| * attempt successfully made the [[Prototype]] immutable. |
| * |
| * This is a nonstandard internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_SetImmutablePrototype(JSContext* cx, JS::HandleObject obj, bool* succeeded); |
| |
| /** |
| * Get a description of one of obj's own properties. If no such property exists |
| * on obj, return true with desc.object() set to null. |
| * |
| * Implements: ES6 [[GetOwnProperty]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_GetOwnPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::MutableHandle<JSPropertyDescriptor> desc); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name, |
| JS::MutableHandle<JSPropertyDescriptor> desc); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetOwnUCPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char16_t* name, |
| JS::MutableHandle<JSPropertyDescriptor> desc); |
| |
| /** |
| * Like JS_GetOwnPropertyDescriptorById, but also searches the prototype chain |
| * if no own property is found directly on obj. The object on which the |
| * property is found is returned in desc.object(). If the property is not found |
| * on the prototype chain, this returns true with desc.object() set to null. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_GetPropertyDescriptorById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::MutableHandle<JSPropertyDescriptor> desc); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetPropertyDescriptor(JSContext* cx, JS::HandleObject obj, const char* name, |
| JS::MutableHandle<JSPropertyDescriptor> desc); |
| |
| /** |
| * Define a property on obj. |
| * |
| * This function uses JS::ObjectOpResult to indicate conditions that ES6 |
| * specifies as non-error failures. This is inconvenient at best, so use this |
| * function only if you are implementing a proxy handler's defineProperty() |
| * method. For all other purposes, use one of the many DefineProperty functions |
| * below that throw an exception in all failure cases. |
| * |
| * Implements: ES6 [[DefineOwnProperty]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::Handle<JSPropertyDescriptor> desc, |
| JS::ObjectOpResult& result); |
| |
| /** |
| * Define a property on obj, throwing a TypeError if the attempt fails. |
| * This is the C++ equivalent of `Object.defineProperty(obj, id, desc)`. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::Handle<JSPropertyDescriptor> desc); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, int32_t value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, uint32_t value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefinePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, double value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleObject value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleString value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, int32_t value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, uint32_t value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineProperty(JSContext* cx, JS::HandleObject obj, const char* name, double value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::Handle<JSPropertyDescriptor> desc, |
| JS::ObjectOpResult& result); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::Handle<JSPropertyDescriptor> desc); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::HandleValue value, unsigned attrs, |
| JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::HandleObject value, unsigned attrs, |
| JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::HandleString value, unsigned attrs, |
| JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| int32_t value, unsigned attrs, |
| JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| uint32_t value, unsigned attrs, |
| JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| double value, unsigned attrs, |
| JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DefineElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double value, |
| unsigned attrs, JSNative getter = nullptr, JSNative setter = nullptr); |
| |
| /** |
| * Compute the expression `id in obj`. |
| * |
| * If obj has an own or inherited property obj[id], set *foundp = true and |
| * return true. If not, set *foundp = false and return true. On error, return |
| * false with an exception pending. |
| * |
| * Implements: ES6 [[Has]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_HasPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_HasProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_HasUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| bool* vp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_HasElement(JSContext* cx, JS::HandleObject obj, uint32_t index, bool* foundp); |
| |
| /** |
| * Determine whether obj has an own property with the key `id`. |
| * |
| * Implements: ES6 7.3.11 HasOwnProperty(O, P). |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_HasOwnPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_HasOwnProperty(JSContext* cx, JS::HandleObject obj, const char* name, bool* foundp); |
| |
| /** |
| * Get the value of the property `obj[id]`, or undefined if no such property |
| * exists. This is the C++ equivalent of `vp = Reflect.get(obj, id, receiver)`. |
| * |
| * Most callers don't need the `receiver` argument. Consider using |
| * JS_GetProperty instead. (But if you're implementing a proxy handler's set() |
| * method, it's often correct to call this function and pass the receiver |
| * through.) |
| * |
| * Implements: ES6 [[Get]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_ForwardGetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::HandleValue receiver, JS::MutableHandleValue vp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_ForwardGetElementTo(JSContext* cx, JS::HandleObject obj, uint32_t index, |
| JS::HandleObject receiver, JS::MutableHandleValue vp); |
| |
| /** |
| * Get the value of the property `obj[id]`, or undefined if no such property |
| * exists. The result is stored in vp. |
| * |
| * Implements: ES6 7.3.1 Get(O, P). |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_GetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::MutableHandleValue vp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::MutableHandleValue vp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::MutableHandleValue vp); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_GetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::MutableHandleValue vp); |
| |
| /** |
| * Perform the same property assignment as `Reflect.set(obj, id, v, receiver)`. |
| * |
| * This function has a `receiver` argument that most callers don't need. |
| * Consider using JS_SetProperty instead. |
| * |
| * Implements: ES6 [[Set]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v, |
| JS::HandleValue receiver, JS::ObjectOpResult& result); |
| |
| /** |
| * Perform the assignment `obj[id] = v`. |
| * |
| * This function performs non-strict assignment, so if the property is |
| * read-only, nothing happens and no error is thrown. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_SetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetProperty(JSContext* cx, JS::HandleObject obj, const char* name, JS::HandleValue v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::HandleValue v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleValue v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleObject v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, JS::HandleString v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, int32_t v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, uint32_t v); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_SetElement(JSContext* cx, JS::HandleObject obj, uint32_t index, double v); |
| |
| /** |
| * Delete a property. This is the C++ equivalent of |
| * `result = Reflect.deleteProperty(obj, id)`. |
| * |
| * This function has a `result` out parameter that most callers don't need. |
| * Unless you can pass through an ObjectOpResult provided by your caller, it's |
| * probably best to use the JS_DeletePropertyById signature with just 3 |
| * arguments. |
| * |
| * Implements: ES6 [[Delete]] internal method. |
| */ |
| extern JS_PUBLIC_API(bool) |
| JS_DeletePropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, |
| JS::ObjectOpResult& result); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name, |
| JS::ObjectOpResult& result); |
| |
| extern JS_PUBLIC_API(bool) |
| JS_DeleteUCProperty(JSContext* cx, JS::HandleObject obj, const char16_t* name, size_t namelen, |
| JS::ObjectOpResult& result); |
| |