123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * 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/. */
- #ifndef jsobj_h
- #define jsobj_h
- /*
- * JS object definitions.
- *
- * A JS object consists of a possibly-shared object descriptor containing
- * ordered property names, called the map; and a dense vector of property
- * values, called slots. The map/slot pointer pair is GC'ed, while the map
- * is reference counted and the slot vector is malloc'ed.
- */
- #include "mozilla/MemoryReporting.h"
- #include "gc/Barrier.h"
- #include "gc/Marking.h"
- #include "js/Conversions.h"
- #include "js/GCAPI.h"
- #include "js/GCVector.h"
- #include "js/HeapAPI.h"
- #include "vm/Shape.h"
- #include "vm/String.h"
- #include "vm/Xdr.h"
- namespace JS {
- struct ClassInfo;
- } // namespace JS
- namespace js {
- using PropertyDescriptorVector = JS::GCVector<JS::PropertyDescriptor>;
- class GCMarker;
- class Nursery;
- namespace gc {
- class RelocationOverlay;
- } // namespace gc
- inline JSObject*
- CastAsObject(GetterOp op)
- {
- return JS_FUNC_TO_DATA_PTR(JSObject*, op);
- }
- inline JSObject*
- CastAsObject(SetterOp op)
- {
- return JS_FUNC_TO_DATA_PTR(JSObject*, op);
- }
- inline Value
- CastAsObjectJsval(GetterOp op)
- {
- return ObjectOrNullValue(CastAsObject(op));
- }
- inline Value
- CastAsObjectJsval(SetterOp op)
- {
- return ObjectOrNullValue(CastAsObject(op));
- }
- /******************************************************************************/
- extern const Class IntlClass;
- extern const Class JSONClass;
- extern const Class MathClass;
- class GlobalObject;
- class NewObjectCache;
- enum class IntegrityLevel {
- Sealed,
- Frozen
- };
- // Forward declarations, required for later friend declarations.
- bool PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result, IntegrityLevel level = IntegrityLevel::Sealed);
- bool SetImmutablePrototype(js::ExclusiveContext* cx, JS::HandleObject obj, bool* succeeded);
- } /* namespace js */
- /*
- * A JavaScript object. The members common to all objects are as follows:
- *
- * - The |group_| member stores the group of the object, which contains its
- * prototype object, its class and the possible types of its properties.
- *
- * Subclasses of JSObject --- mainly NativeObject and JSFunction --- add more
- * members. Notable among these is the object's shape, which stores flags and
- * some other state, and, for native objects, the layout of all its properties.
- * The second word of a JSObject generally stores its shape; if the second word
- * stores anything else, the value stored cannot be a valid Shape* pointer, so
- * that shape guards can be performed on objects without regard to the specific
- * layout in use.
- */
- class JSObject : public js::gc::Cell
- {
- protected:
- js::GCPtrObjectGroup group_;
- private:
- friend class js::Shape;
- friend class js::GCMarker;
- friend class js::NewObjectCache;
- friend class js::Nursery;
- friend class js::gc::RelocationOverlay;
- friend bool js::PreventExtensions(JSContext* cx, JS::HandleObject obj, JS::ObjectOpResult& result, js::IntegrityLevel level);
- friend bool js::SetImmutablePrototype(js::ExclusiveContext* cx, JS::HandleObject obj,
- bool* succeeded);
- // Make a new group to use for a singleton object.
- static js::ObjectGroup* makeLazyGroup(JSContext* cx, js::HandleObject obj);
- public:
- bool isNative() const {
- return getClass()->isNative();
- }
- const js::Class* getClass() const {
- return group_->clasp();
- }
- const JSClass* getJSClass() const {
- return Jsvalify(getClass());
- }
- bool hasClass(const js::Class* c) const {
- return getClass() == c;
- }
- js::LookupPropertyOp getOpsLookupProperty() const { return getClass()->getOpsLookupProperty(); }
- js::DefinePropertyOp getOpsDefineProperty() const { return getClass()->getOpsDefineProperty(); }
- js::HasPropertyOp getOpsHasProperty() const { return getClass()->getOpsHasProperty(); }
- js::GetPropertyOp getOpsGetProperty() const { return getClass()->getOpsGetProperty(); }
- js::SetPropertyOp getOpsSetProperty() const { return getClass()->getOpsSetProperty(); }
- js::GetOwnPropertyOp getOpsGetOwnPropertyDescriptor()
- const { return getClass()->getOpsGetOwnPropertyDescriptor(); }
- js::DeletePropertyOp getOpsDeleteProperty() const { return getClass()->getOpsDeleteProperty(); }
- js::GetElementsOp getOpsGetElements() const { return getClass()->getOpsGetElements(); }
- JSNewEnumerateOp getOpsEnumerate() const { return getClass()->getOpsEnumerate(); }
- JSFunToStringOp getOpsFunToString() const { return getClass()->getOpsFunToString(); }
- js::ObjectGroup* group() const {
- MOZ_ASSERT(!hasLazyGroup());
- return groupRaw();
- }
- js::ObjectGroup* groupRaw() const {
- return group_;
- }
- /*
- * Whether this is the only object which has its specified group. This
- * object will have its group constructed lazily as needed by analysis.
- */
- bool isSingleton() const {
- return group_->singleton();
- }
- /*
- * Whether the object's group has not been constructed yet. If an object
- * might have a lazy group, use getGroup() below, otherwise group().
- */
- bool hasLazyGroup() const {
- return group_->lazy();
- }
- JSCompartment* compartment() const { return group_->compartment(); }
- JSCompartment* maybeCompartment() const { return compartment(); }
- inline js::Shape* maybeShape() const;
- inline js::Shape* ensureShape(js::ExclusiveContext* cx);
- /*
- * Make a non-array object with the specified initial state. This method
- * takes ownership of any extantSlots it is passed.
- */
- static inline JSObject* create(js::ExclusiveContext* cx,
- js::gc::AllocKind kind,
- js::gc::InitialHeap heap,
- js::HandleShape shape,
- js::HandleObjectGroup group);
- // Set the initial slots and elements of an object. These pointers are only
- // valid for native objects, but during initialization are set for all
- // objects. For non-native objects, these must not be dynamically allocated
- // pointers which leak when the non-native object finishes initialization.
- inline void setInitialSlotsMaybeNonNative(js::HeapSlot* slots);
- inline void setInitialElementsMaybeNonNative(js::HeapSlot* elements);
- enum GenerateShape {
- GENERATE_NONE,
- GENERATE_SHAPE
- };
- static bool setFlags(js::ExclusiveContext* cx, JS::HandleObject obj, js::BaseShape::Flag flags,
- GenerateShape generateShape = GENERATE_NONE);
- inline bool hasAllFlags(js::BaseShape::Flag flags) const;
- /*
- * An object is a delegate if it is on another object's prototype or scope
- * chain, and therefore the delegate might be asked implicitly to get or
- * set a property on behalf of another object. Delegates may be accessed
- * directly too, as may any object, but only those objects linked after the
- * head of any prototype or scope chain are flagged as delegates. This
- * definition helps to optimize shape-based property cache invalidation
- * (see Purge{Scope,Proto}Chain in jsobj.cpp).
- */
- inline bool isDelegate() const;
- static bool setDelegate(js::ExclusiveContext* cx, JS::HandleObject obj) {
- return setFlags(cx, obj, js::BaseShape::DELEGATE, GENERATE_SHAPE);
- }
- inline bool isBoundFunction() const;
- inline bool hasSpecialEquality() const;
- // A "qualified" varobj is the object on which "qualified" variable
- // declarations (i.e., those defined with "var") are kept.
- //
- // Conceptually, when a var binding is defined, it is defined on the
- // innermost qualified varobj on the scope chain.
- //
- // Function scopes (CallObjects) are qualified varobjs, and there can be
- // no other qualified varobj that is more inner for var bindings in that
- // function. As such, all references to local var bindings in a function
- // may be statically bound to the function scope. This is subject to
- // further optimization. Unaliased bindings inside functions reside
- // entirely on the frame, not in CallObjects.
- //
- // Global scopes are also qualified varobjs. It is possible to statically
- // know, for a given script, that are no more inner qualified varobjs, so
- // free variable references can be statically bound to the global.
- //
- // Finally, there are non-syntactic qualified varobjs used by embedders
- // (e.g., Gecko and XPConnect), as they often wish to run scripts under a
- // scope that captures var bindings.
- inline bool isQualifiedVarObj() const;
- static bool setQualifiedVarObj(js::ExclusiveContext* cx, JS::HandleObject obj) {
- return setFlags(cx, obj, js::BaseShape::QUALIFIED_VAROBJ);
- }
- // An "unqualified" varobj is the object on which "unqualified"
- // assignments (i.e., bareword assignments for which the LHS does not
- // exist on the scope chain) are kept.
- inline bool isUnqualifiedVarObj() const;
- // Objects with an uncacheable proto can have their prototype mutated
- // without inducing a shape change on the object. JIT inline caches should
- // do an explicit group guard to guard against this. Singletons always
- // generate a new shape when their prototype changes, regardless of this
- // hasUncacheableProto flag.
- inline bool hasUncacheableProto() const;
- static bool setUncacheableProto(js::ExclusiveContext* cx, JS::HandleObject obj) {
- MOZ_ASSERT(obj->hasStaticPrototype(),
- "uncacheability as a concept is only applicable to static "
- "(not dynamically-computed) prototypes");
- return setFlags(cx, obj, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
- }
- /*
- * Whether SETLELEM was used to access this object. See also the comment near
- * PropertyTree::MAX_HEIGHT.
- */
- inline bool hadElementsAccess() const;
- static bool setHadElementsAccess(js::ExclusiveContext* cx, JS::HandleObject obj) {
- return setFlags(cx, obj, js::BaseShape::HAD_ELEMENTS_ACCESS);
- }
- /*
- * Whether there may be indexed properties on this object, excluding any in
- * the object's elements.
- */
- inline bool isIndexed() const;
- /*
- * If this object was instantiated with `new Ctor`, return the constructor's
- * display atom. Otherwise, return nullptr.
- */
- static bool constructorDisplayAtom(JSContext* cx, js::HandleObject obj,
- js::MutableHandleAtom name);
- /*
- * The same as constructorDisplayAtom above, however if this object has a
- * lazy group, nullptr is returned. This allows for use in situations that
- * cannot GC and where having some information, even if it is inconsistently
- * available, is better than no information.
- */
- JSAtom* maybeConstructorDisplayAtom() const;
- /* GC support. */
- void traceChildren(JSTracer* trc);
- void fixupAfterMovingGC();
- static const JS::TraceKind TraceKind = JS::TraceKind::Object;
- static const size_t MaxTagBits = 3;
- static bool isNullLike(const JSObject* obj) { return uintptr_t(obj) < (1 << MaxTagBits); }
- MOZ_ALWAYS_INLINE JS::Zone* zone() const {
- return group_->zone();
- }
- MOZ_ALWAYS_INLINE JS::shadow::Zone* shadowZone() const {
- return JS::shadow::Zone::asShadowZone(zone());
- }
- MOZ_ALWAYS_INLINE JS::Zone* zoneFromAnyThread() const {
- return group_->zoneFromAnyThread();
- }
- MOZ_ALWAYS_INLINE JS::shadow::Zone* shadowZoneFromAnyThread() const {
- return JS::shadow::Zone::asShadowZone(zoneFromAnyThread());
- }
- static MOZ_ALWAYS_INLINE void readBarrier(JSObject* obj);
- static MOZ_ALWAYS_INLINE void writeBarrierPre(JSObject* obj);
- static MOZ_ALWAYS_INLINE void writeBarrierPost(void* cellp, JSObject* prev, JSObject* next);
- /* Return the allocKind we would use if we were to tenure this object. */
- js::gc::AllocKind allocKindForTenure(const js::Nursery& nursery) const;
- size_t tenuredSizeOfThis() const {
- MOZ_ASSERT(isTenured());
- return js::gc::Arena::thingSize(asTenured().getAllocKind());
- }
- void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassInfo* info);
- // We can only use addSizeOfExcludingThis on tenured objects: it assumes it
- // can apply mallocSizeOf to bits and pieces of the object, whereas objects
- // in the nursery may have those bits and pieces allocated in the nursery
- // along with them, and are not each their own malloc blocks.
- size_t sizeOfIncludingThisInNursery() const;
- // Marks this object as having a singleton group, and leave the group lazy.
- // Constructs a new, unique shape for the object. This should only be
- // called for an object that was just created.
- static inline bool setSingleton(js::ExclusiveContext* cx, js::HandleObject obj);
- // Change an existing object to have a singleton group.
- static bool changeToSingleton(JSContext* cx, js::HandleObject obj);
- static inline js::ObjectGroup* getGroup(JSContext* cx, js::HandleObject obj);
- const js::GCPtrObjectGroup& groupFromGC() const {
- /* Direct field access for use by GC. */
- return group_;
- }
- /*
- * We permit proxies to dynamically compute their prototype if desired.
- * (Not all proxies will so desire: in particular, most DOM proxies can
- * track their prototype with a single, nullable JSObject*.) If a proxy
- * so desires, we store (JSObject*)0x1 in the proto field of the object's
- * group.
- *
- * We offer three ways to get an object's prototype:
- *
- * 1. obj->staticPrototype() returns the prototype, but it asserts if obj
- * is a proxy, and the proxy has opted to dynamically compute its
- * prototype using a getPrototype() handler.
- * 2. obj->taggedProto() returns a TaggedProto, which can be tested to
- * check if the proto is an object, nullptr, or lazily computed.
- * 3. js::GetPrototype(cx, obj, &proto) computes the proto of an object.
- * If obj is a proxy with dynamically-computed prototype, this code may
- * perform arbitrary behavior (allocation, GC, run JS) while computing
- * the proto.
- */
- js::TaggedProto taggedProto() const {
- return group_->proto();
- }
- bool hasTenuredProto() const;
- bool uninlinedIsProxy() const;
- JSObject* staticPrototype() const {
- MOZ_ASSERT(hasStaticPrototype());
- return taggedProto().toObjectOrNull();
- }
- // Normal objects and a subset of proxies have an uninteresting, static
- // (albeit perhaps mutable) [[Prototype]]. For such objects the
- // [[Prototype]] is just a value returned when needed for accesses, or
- // modified in response to requests. These objects store the
- // [[Prototype]] directly within |obj->group_|.
- bool hasStaticPrototype() const {
- return !hasDynamicPrototype();
- }
- // The remaining proxies have a [[Prototype]] requiring dynamic computation
- // for every access, going through the proxy handler {get,set}Prototype and
- // setImmutablePrototype methods. (Wrappers particularly use this to keep
- // the wrapper/wrappee [[Prototype]]s consistent.)
- bool hasDynamicPrototype() const {
- bool dynamic = taggedProto().isDynamic();
- MOZ_ASSERT_IF(dynamic, uninlinedIsProxy());
- MOZ_ASSERT_IF(dynamic, !isNative());
- return dynamic;
- }
- // True iff this object's [[Prototype]] is immutable. Must be called only
- // on objects with a static [[Prototype]]!
- inline bool staticPrototypeIsImmutable() const;
- inline void setGroup(js::ObjectGroup* group);
- /*
- * Mark an object that has been iterated over and is a singleton. We need
- * to recover this information in the object's type information after it
- * is purged on GC.
- */
- inline bool isIteratedSingleton() const;
- static bool setIteratedSingleton(js::ExclusiveContext* cx, JS::HandleObject obj) {
- return setFlags(cx, obj, js::BaseShape::ITERATED_SINGLETON);
- }
- /*
- * Mark an object as requiring its default 'new' type to have unknown
- * properties.
- */
- inline bool isNewGroupUnknown() const;
- static bool setNewGroupUnknown(JSContext* cx, const js::Class* clasp, JS::HandleObject obj);
- // Mark an object as having its 'new' script information cleared.
- inline bool wasNewScriptCleared() const;
- static bool setNewScriptCleared(js::ExclusiveContext* cx, JS::HandleObject obj) {
- return setFlags(cx, obj, js::BaseShape::NEW_SCRIPT_CLEARED);
- }
- /* Set a new prototype for an object with a singleton type. */
- static bool splicePrototype(JSContext* cx, js::HandleObject obj, const js::Class* clasp,
- js::Handle<js::TaggedProto> proto);
- /*
- * For bootstrapping, whether to splice a prototype for Function.prototype
- * or the global object.
- */
- bool shouldSplicePrototype();
- /*
- * Environment chains.
- *
- * The environment chain of an object is the link in the search path when
- * a script does a name lookup on an environment object. For JS internal
- * environment objects --- Call, LexicalEnvironment, and WithEnvironment
- * --- the chain is stored in the first fixed slot of the object. For
- * other environment objects, the chain goes directly to the global.
- *
- * In code which is not marked hasNonSyntacticScope, environment chains
- * can contain only syntactic environment objects (see
- * IsSyntacticEnvironment) with a global object at the root as the
- * environment of the outermost non-function script. In
- * hasNonSyntacticScope code, the environment of the outermost
- * non-function script might not be a global object, and can have a mix of
- * other objects above it before the global object is reached.
- */
- /*
- * Get the enclosing environment of an object. When called on a
- * non-EnvironmentObject, this will just be the global (the name
- * "enclosing environment" still applies in this situation because
- * non-EnvironmentObjects can be on the environment chain).
- */
- inline JSObject* enclosingEnvironment() const;
- inline js::GlobalObject& global() const;
- // In some rare cases the global object's compartment's global may not be
- // the same global object. For this reason, we need to take extra care when
- // tracing.
- //
- // These cases are:
- // 1) The off-thread parsing task uses a dummy global since it cannot
- // share with the actual global being used concurrently on the main
- // thread.
- // 2) A GC may occur when creating the GlobalObject, in which case the
- // compartment global pointer may not yet be set. In this case there is
- // nothing interesting to trace in the compartment.
- inline bool isOwnGlobal(JSTracer*) const;
- inline js::GlobalObject* globalForTracing(JSTracer*) const;
- /*
- * ES5 meta-object properties and operations.
- */
- public:
- // Indicates whether a non-proxy is extensible. Don't call on proxies!
- // This method really shouldn't exist -- but there are a few internal
- // places that want it (JITs and the like), and it'd be a pain to mark them
- // all as friends.
- inline bool nonProxyIsExtensible() const;
- public:
- /*
- * Iterator-specific getters and setters.
- */
- static const uint32_t ITER_CLASS_NFIXED_SLOTS = 1;
- /*
- * Back to generic stuff.
- */
- bool isCallable() const;
- bool isConstructor() const;
- JSNative callHook() const;
- JSNative constructHook() const;
- MOZ_ALWAYS_INLINE void finalize(js::FreeOp* fop);
- public:
- static bool reportReadOnly(JSContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
- static bool reportNotConfigurable(JSContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
- static bool reportNotExtensible(JSContext* cx, js::HandleObject obj,
- unsigned report = JSREPORT_ERROR);
- static bool nonNativeSetProperty(JSContext* cx, js::HandleObject obj, js::HandleId id,
- js::HandleValue v, js::HandleValue receiver,
- JS::ObjectOpResult& result);
- static bool nonNativeSetElement(JSContext* cx, js::HandleObject obj, uint32_t index,
- js::HandleValue v, js::HandleValue receiver,
- JS::ObjectOpResult& result);
- static bool swap(JSContext* cx, JS::HandleObject a, JS::HandleObject b);
- private:
- void fixDictionaryShapeAfterSwap();
- public:
- inline void initArrayClass();
- /*
- * In addition to the generic object interface provided by JSObject,
- * specific types of objects may provide additional operations. To access,
- * these addition operations, callers should use the pattern:
- *
- * if (obj.is<XObject>()) {
- * XObject& x = obj.as<XObject>();
- * x.foo();
- * }
- *
- * These XObject classes form a hierarchy. For example, for a cloned block
- * object, the following predicates are true: is<ClonedBlockObject>,
- * is<NestedScopeObject> and is<ScopeObject>. Each of these has a
- * respective class that derives and adds operations.
- *
- * A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file
- * triplet (along with any class YObject that derives XObject).
- *
- * Note that X represents a low-level representation and does not query the
- * [[Class]] property of object defined by the spec (for this, see
- * js::GetBuiltinClass).
- */
- template <class T>
- inline bool is() const { return getClass() == &T::class_; }
- template <class T>
- T& as() {
- MOZ_ASSERT(this->is<T>());
- return *static_cast<T*>(this);
- }
- template <class T>
- const T& as() const {
- MOZ_ASSERT(this->is<T>());
- return *static_cast<const T*>(this);
- }
- #ifdef DEBUG
- void dump(FILE* fp) const;
- void dump() const;
- #endif
- /* JIT Accessors */
- static size_t offsetOfGroup() { return offsetof(JSObject, group_); }
- // Maximum size in bytes of a JSObject.
- static const size_t MAX_BYTE_SIZE = 4 * sizeof(void*) + 16 * sizeof(JS::Value);
- private:
- JSObject() = delete;
- JSObject(const JSObject& other) = delete;
- void operator=(const JSObject& other) = delete;
- };
- template <class U>
- MOZ_ALWAYS_INLINE JS::Handle<U*>
- js::RootedBase<JSObject*>::as() const
- {
- const JS::Rooted<JSObject*>& self = *static_cast<const JS::Rooted<JSObject*>*>(this);
- MOZ_ASSERT(self->is<U>());
- return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
- }
- template <class U>
- MOZ_ALWAYS_INLINE JS::Handle<U*>
- js::HandleBase<JSObject*>::as() const
- {
- const JS::Handle<JSObject*>& self = *static_cast<const JS::Handle<JSObject*>*>(this);
- MOZ_ASSERT(self->is<U>());
- return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
- }
- /*
- * The only sensible way to compare JSObject with == is by identity. We use
- * const& instead of * as a syntactic way to assert non-null. This leads to an
- * abundance of address-of operators to identity. Hence this overload.
- */
- static MOZ_ALWAYS_INLINE bool
- operator==(const JSObject& lhs, const JSObject& rhs)
- {
- return &lhs == &rhs;
- }
- static MOZ_ALWAYS_INLINE bool
- operator!=(const JSObject& lhs, const JSObject& rhs)
- {
- return &lhs != &rhs;
- }
- // Size of the various GC thing allocation sizes used for objects.
- struct JSObject_Slots0 : JSObject { void* data[3]; };
- struct JSObject_Slots2 : JSObject { void* data[3]; js::Value fslots[2]; };
- struct JSObject_Slots4 : JSObject { void* data[3]; js::Value fslots[4]; };
- struct JSObject_Slots8 : JSObject { void* data[3]; js::Value fslots[8]; };
- struct JSObject_Slots12 : JSObject { void* data[3]; js::Value fslots[12]; };
- struct JSObject_Slots16 : JSObject { void* data[3]; js::Value fslots[16]; };
- /* static */ MOZ_ALWAYS_INLINE void
- JSObject::readBarrier(JSObject* obj)
- {
- MOZ_ASSERT_IF(obj, !isNullLike(obj));
- if (obj && obj->isTenured())
- obj->asTenured().readBarrier(&obj->asTenured());
- }
- /* static */ MOZ_ALWAYS_INLINE void
- JSObject::writeBarrierPre(JSObject* obj)
- {
- MOZ_ASSERT_IF(obj, !isNullLike(obj));
- if (obj && obj->isTenured())
- obj->asTenured().writeBarrierPre(&obj->asTenured());
- }
- /* static */ MOZ_ALWAYS_INLINE void
- JSObject::writeBarrierPost(void* cellp, JSObject* prev, JSObject* next)
- {
- MOZ_ASSERT(cellp);
- MOZ_ASSERT_IF(next, !IsNullTaggedPointer(next));
- MOZ_ASSERT_IF(prev, !IsNullTaggedPointer(prev));
- // If the target needs an entry, add it.
- js::gc::StoreBuffer* buffer;
- if (next && (buffer = next->storeBuffer())) {
- // If we know that the prev has already inserted an entry, we can skip
- // doing the lookup to add the new entry. Note that we cannot safely
- // assert the presence of the entry because it may have been added
- // via a different store buffer.
- if (prev && prev->storeBuffer())
- return;
- buffer->putCell(static_cast<js::gc::Cell**>(cellp));
- return;
- }
- // Remove the prev entry if the new value does not need it.
- if (prev && (buffer = prev->storeBuffer()))
- buffer->unputCell(static_cast<js::gc::Cell**>(cellp));
- }
- namespace js {
- inline bool
- IsCallable(const Value& v)
- {
- return v.isObject() && v.toObject().isCallable();
- }
- // ES6 rev 24 (2014 April 27) 7.2.5 IsConstructor
- inline bool
- IsConstructor(const Value& v)
- {
- return v.isObject() && v.toObject().isConstructor();
- }
- } /* namespace js */
- class JSValueArray {
- public:
- const js::Value* array;
- size_t length;
- JSValueArray(const js::Value* v, size_t c) : array(v), length(c) {}
- };
- class ValueArray {
- public:
- js::Value* array;
- size_t length;
- ValueArray(js::Value* v, size_t c) : array(v), length(c) {}
- };
- namespace js {
- /*** Standard internal methods ********************************************************************
- *
- * The functions below are the fundamental operations on objects. See the
- * comment about "Standard internal methods" in jsapi.h.
- */
- /*
- * ES6 [[GetPrototypeOf]]. Get obj's prototype, storing it in protop.
- *
- * If obj is definitely not a proxy, the infallible obj->getProto() can be used
- * instead. See the comment on JSObject::getTaggedProto().
- */
- inline bool
- GetPrototype(JSContext* cx, HandleObject obj, MutableHandleObject protop);
- /*
- * ES6 [[SetPrototypeOf]]. Change obj's prototype to proto.
- *
- * Returns false on error, success of operation in *result. For example, if
- * obj is not extensible, its prototype is fixed. js::SetPrototype will return
- * true, because no exception is thrown for this; but *result will be false.
- */
- extern bool
- SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto,
- ObjectOpResult& result);
- /* Convenience function: like the above, but throw on failure. */
- extern bool
- SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto);
- /*
- * ES6 [[IsExtensible]]. Extensible objects can have new properties defined on
- * them. Inextensible objects can't, and their [[Prototype]] slot is fixed as
- * well.
- */
- inline bool
- IsExtensible(ExclusiveContext* cx, HandleObject obj, bool* extensible);
- /*
- * ES6 [[PreventExtensions]]. Attempt to change the [[Extensible]] bit on |obj|
- * to false. Indicate success or failure through the |result| outparam, or
- * actual error through the return value.
- *
- * The `level` argument is SM-specific. `obj` should have an integrity level of
- * at least `level`.
- */
- extern bool
- PreventExtensions(JSContext* cx, HandleObject obj, ObjectOpResult& result, IntegrityLevel level);
- /* Convenience function. As above, but throw on failure. */
- extern bool
- PreventExtensions(JSContext* cx, HandleObject obj, IntegrityLevel level = IntegrityLevel::Sealed);
- /*
- * ES6 [[GetOwnProperty]]. 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.
- */
- extern bool
- GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
- MutableHandle<JS::PropertyDescriptor> desc);
- /* ES6 [[DefineOwnProperty]]. Define a property on obj. */
- extern bool
- DefineProperty(JSContext* cx, HandleObject obj, HandleId id,
- Handle<JS::PropertyDescriptor> desc, ObjectOpResult& result);
- extern bool
- DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
- JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult& result);
- extern bool
- DefineProperty(ExclusiveContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
- JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult& result);
- extern bool
- DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, HandleValue value,
- JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult& result);
- /*
- * When the 'result' out-param is omitted, the behavior is the same as above, except
- * that any failure results in a TypeError.
- */
- extern bool
- DefineProperty(JSContext* cx, HandleObject obj, HandleId id, Handle<JS::PropertyDescriptor> desc);
- extern bool
- DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
- JSGetterOp getter = nullptr,
- JSSetterOp setter = nullptr,
- unsigned attrs = JSPROP_ENUMERATE);
- extern bool
- DefineProperty(ExclusiveContext* cx, HandleObject obj, PropertyName* name, HandleValue value,
- JSGetterOp getter = nullptr,
- JSSetterOp setter = nullptr,
- unsigned attrs = JSPROP_ENUMERATE);
- extern bool
- DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, HandleValue value,
- JSGetterOp getter = nullptr,
- JSSetterOp setter = nullptr,
- unsigned attrs = JSPROP_ENUMERATE);
- /*
- * ES6 [[Has]]. Set *foundp to true if `id in obj` (that is, if obj has an own
- * or inherited property obj[id]), false otherwise.
- */
- inline bool
- HasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
- inline bool
- HasProperty(JSContext* cx, HandleObject obj, PropertyName* name, bool* foundp);
- /*
- * ES6 [[Get]]. Get the value of the property `obj[id]`, or undefined if no
- * such property exists.
- *
- * Typically obj == receiver; if obj != receiver then the caller is most likely
- * a proxy using GetProperty to finish a property get that started out as
- * `receiver[id]`, and we've already searched the prototype chain up to `obj`.
- */
- inline bool
- GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
- MutableHandleValue vp);
- inline bool
- GetProperty(JSContext* cx, HandleObject obj, HandleValue receiver, PropertyName* name,
- MutableHandleValue vp)
- {
- RootedId id(cx, NameToId(name));
- return GetProperty(cx, obj, receiver, id, vp);
- }
- inline bool
- GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
- MutableHandleValue vp)
- {
- RootedValue receiverValue(cx, ObjectValue(*receiver));
- return GetProperty(cx, obj, receiverValue, id, vp);
- }
- inline bool
- GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, PropertyName* name,
- MutableHandleValue vp)
- {
- RootedValue receiverValue(cx, ObjectValue(*receiver));
- return GetProperty(cx, obj, receiverValue, name, vp);
- }
- inline bool
- GetElement(JSContext* cx, HandleObject obj, HandleValue receiver, uint32_t index,
- MutableHandleValue vp);
- inline bool
- GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
- MutableHandleValue vp);
- inline bool
- GetPropertyNoGC(JSContext* cx, JSObject* obj, const Value& receiver, jsid id, Value* vp);
- inline bool
- GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, jsid id, Value* vp)
- {
- return GetPropertyNoGC(cx, obj, ObjectValue(*receiver), id, vp);
- }
- inline bool
- GetPropertyNoGC(JSContext* cx, JSObject* obj, const Value& receiver, PropertyName* name, Value* vp)
- {
- return GetPropertyNoGC(cx, obj, receiver, NameToId(name), vp);
- }
- inline bool
- GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, PropertyName* name, Value* vp)
- {
- return GetPropertyNoGC(cx, obj, ObjectValue(*receiver), name, vp);
- }
- inline bool
- GetElementNoGC(JSContext* cx, JSObject* obj, const Value& receiver, uint32_t index, Value* vp);
- inline bool
- GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index, Value* vp);
- /*
- * ES6 [[Set]]. Carry out the assignment `obj[id] = v`.
- *
- * The `receiver` argument has to do with how [[Set]] interacts with the
- * prototype chain and proxies. It's hard to explain and ES6 doesn't really
- * try. Long story short, if you just want bog-standard assignment, pass
- * `ObjectValue(*obj)` as receiver. Or better, use one of the signatures that
- * doesn't have a receiver parameter.
- *
- * Callers pass obj != receiver e.g. when a proxy is involved, obj is the
- * proxy's target, and the proxy is using SetProperty to finish an assignment
- * that started out as `receiver[id] = v`, by delegating it to obj.
- */
- inline bool
- SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
- HandleValue receiver, ObjectOpResult& result);
- inline bool
- SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
- {
- RootedValue receiver(cx, ObjectValue(*obj));
- ObjectOpResult result;
- return SetProperty(cx, obj, id, v, receiver, result) &&
- result.checkStrict(cx, obj, id);
- }
- inline bool
- SetProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue v,
- HandleValue receiver, ObjectOpResult& result)
- {
- RootedId id(cx, NameToId(name));
- return SetProperty(cx, obj, id, v, receiver, result);
- }
- inline bool
- SetProperty(JSContext* cx, HandleObject obj, PropertyName* name, HandleValue v)
- {
- RootedId id(cx, NameToId(name));
- RootedValue receiver(cx, ObjectValue(*obj));
- ObjectOpResult result;
- return SetProperty(cx, obj, id, v, receiver, result) &&
- result.checkStrict(cx, obj, id);
- }
- inline bool
- SetElement(JSContext* cx, HandleObject obj, uint32_t index, HandleValue v,
- HandleValue receiver, ObjectOpResult& result);
- /*
- * ES6 draft rev 31 (15 Jan 2015) 7.3.3 Put (O, P, V, Throw), except that on
- * success, the spec says this is supposed to return a boolean value, which we
- * don't bother doing.
- */
- inline bool
- PutProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v, bool strict)
- {
- RootedValue receiver(cx, ObjectValue(*obj));
- ObjectOpResult result;
- return SetProperty(cx, obj, id, v, receiver, result) &&
- result.checkStrictErrorOrWarning(cx, obj, id, strict);
- }
- /*
- * ES6 [[Delete]]. Equivalent to the JS code `delete obj[id]`.
- */
- inline bool
- DeleteProperty(JSContext* cx, HandleObject obj, HandleId id, ObjectOpResult& result);
- inline bool
- DeleteElement(JSContext* cx, HandleObject obj, uint32_t index, ObjectOpResult& result);
- /*** SpiderMonkey nonstandard internal methods ***************************************************/
- /**
- * If |obj| (underneath any functionally-transparent wrapper proxies) has as
- * its [[GetPrototypeOf]] trap the ordinary [[GetPrototypeOf]] behavior defined
- * for ordinary objects, set |*isOrdinary = true| and store |obj|'s prototype
- * in |result|. Otherwise set |*isOrdinary = false|. In case of error, both
- * outparams have unspecified value.
- */
- extern bool
- GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary,
- MutableHandleObject protop);
- /*
- * Attempt to make |obj|'s [[Prototype]] immutable, such that subsequently
- * trying to change it will not work. If an internal error occurred,
- * returns false. Otherwise, |*succeeded| is set to true iff |obj|'s
- * [[Prototype]] is now immutable.
- */
- extern bool
- SetImmutablePrototype(js::ExclusiveContext* cx, JS::HandleObject obj, bool* succeeded);
- extern bool
- GetPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
- MutableHandle<JS::PropertyDescriptor> desc);
- /*
- * Deprecated. A version of HasProperty that also returns the object on which
- * the property was found (but that information is unreliable for proxies), and
- * the Shape of the property, if native.
- */
- extern bool
- LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
- MutableHandleObject objp, MutableHandleShape propp);
- inline bool
- LookupProperty(JSContext* cx, HandleObject obj, PropertyName* name,
- MutableHandleObject objp, MutableHandleShape propp)
- {
- RootedId id(cx, NameToId(name));
- return LookupProperty(cx, obj, id, objp, propp);
- }
- /* Set *result to tell whether obj has an own property with the given id. */
- extern bool
- HasOwnProperty(JSContext* cx, HandleObject obj, HandleId id, bool* result);
- /**
- * This enum is used to select whether the defined functions should be marked as
- * builtin native instrinsics for self-hosted code.
- */
- enum DefineAsIntrinsic {
- NotIntrinsic,
- AsIntrinsic
- };
- extern bool
- DefineFunctions(JSContext* cx, HandleObject obj, const JSFunctionSpec* fs,
- DefineAsIntrinsic intrinsic);
- /* ES6 draft rev 36 (2015 March 17) 7.1.1 ToPrimitive(vp[, preferredType]) */
- extern bool
- ToPrimitiveSlow(JSContext* cx, JSType hint, MutableHandleValue vp);
- inline bool
- ToPrimitive(JSContext* cx, MutableHandleValue vp)
- {
- if (vp.isPrimitive())
- return true;
- return ToPrimitiveSlow(cx, JSTYPE_VOID, vp);
- }
- inline bool
- ToPrimitive(JSContext* cx, JSType preferredType, MutableHandleValue vp)
- {
- if (vp.isPrimitive())
- return true;
- return ToPrimitiveSlow(cx, preferredType, vp);
- }
- /*
- * toString support. (This isn't called GetClassName because there's a macro in
- * <windows.h> with that name.)
- */
- extern const char*
- GetObjectClassName(JSContext* cx, HandleObject obj);
- /*
- * Return an object that may be used as `this` in place of obj. For most
- * objects this just returns obj.
- *
- * Some JSObjects shouldn't be exposed directly to script. This includes (at
- * least) WithEnvironmentObjects and Window objects. However, since both of
- * those can be on scope chains, we sometimes would expose those as `this` if
- * we were not so vigilant about calling GetThisValue where appropriate.
- *
- * See comments at ComputeImplicitThis.
- */
- Value
- GetThisValue(JSObject* obj);
- /* * */
- typedef JSObject* (*ClassInitializerOp)(JSContext* cx, JS::HandleObject obj);
- /* Fast access to builtin constructors and prototypes. */
- bool
- GetBuiltinConstructor(ExclusiveContext* cx, JSProtoKey key, MutableHandleObject objp);
- bool
- GetBuiltinPrototype(ExclusiveContext* cx, JSProtoKey key, MutableHandleObject objp);
- JSObject*
- GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
- extern bool
- SetClassAndProto(JSContext* cx, HandleObject obj,
- const Class* clasp, Handle<TaggedProto> proto);
- extern bool
- IsStandardPrototype(JSObject* obj, JSProtoKey key);
- } /* namespace js */
- /*
- * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
- */
- extern const char js_watch_str[];
- extern const char js_unwatch_str[];
- extern const char js_hasOwnProperty_str[];
- extern const char js_isPrototypeOf_str[];
- extern const char js_propertyIsEnumerable_str[];
- #ifdef JS_OLD_GETTER_SETTER_METHODS
- extern const char js_defineGetter_str[];
- extern const char js_defineSetter_str[];
- extern const char js_lookupGetter_str[];
- extern const char js_lookupSetter_str[];
- #endif
- namespace js {
- inline gc::InitialHeap
- GetInitialHeap(NewObjectKind newKind, const Class* clasp)
- {
- if (newKind == NurseryAllocatedProxy) {
- MOZ_ASSERT(clasp->isProxy());
- MOZ_ASSERT(clasp->hasFinalize());
- MOZ_ASSERT(!CanNurseryAllocateFinalizedClass(clasp));
- return gc::DefaultHeap;
- }
- if (newKind != GenericObject)
- return gc::TenuredHeap;
- if (clasp->hasFinalize() && !CanNurseryAllocateFinalizedClass(clasp))
- return gc::TenuredHeap;
- return gc::DefaultHeap;
- }
- bool
- NewObjectWithTaggedProtoIsCachable(ExclusiveContext* cxArg, Handle<TaggedProto> proto,
- NewObjectKind newKind, const Class* clasp);
- // ES6 9.1.15 GetPrototypeFromConstructor.
- extern bool
- GetPrototypeFromConstructor(JSContext* cx, js::HandleObject newTarget, js::MutableHandleObject proto);
- extern bool
- GetPrototypeFromCallableConstructor(JSContext* cx, const CallArgs& args, js::MutableHandleObject proto);
- // Specialized call for constructing |this| with a known function callee,
- // and a known prototype.
- extern JSObject*
- CreateThisForFunctionWithProto(JSContext* cx, js::HandleObject callee, HandleObject newTarget,
- HandleObject proto, NewObjectKind newKind = GenericObject);
- // Specialized call for constructing |this| with a known function callee.
- extern JSObject*
- CreateThisForFunction(JSContext* cx, js::HandleObject callee, js::HandleObject newTarget,
- NewObjectKind newKind);
- // Generic call for constructing |this|.
- extern JSObject*
- CreateThis(JSContext* cx, const js::Class* clasp, js::HandleObject callee);
- extern JSObject*
- CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto);
- extern JSObject*
- DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKind = GenericObject);
- inline JSGetterOp
- CastAsGetterOp(JSObject* object)
- {
- return JS_DATA_TO_FUNC_PTR(JSGetterOp, object);
- }
- inline JSSetterOp
- CastAsSetterOp(JSObject* object)
- {
- return JS_DATA_TO_FUNC_PTR(JSSetterOp, object);
- }
- /* ES6 draft rev 32 (2015 Feb 2) 6.2.4.5 ToPropertyDescriptor(Obj) */
- bool
- ToPropertyDescriptor(JSContext* cx, HandleValue descval, bool checkAccessors,
- MutableHandle<JS::PropertyDescriptor> desc);
- /*
- * Throw a TypeError if desc.getterObject() or setterObject() is not
- * callable. This performs exactly the checks omitted by ToPropertyDescriptor
- * when checkAccessors is false.
- */
- bool
- CheckPropertyDescriptorAccessors(JSContext* cx, Handle<JS::PropertyDescriptor> desc);
- void
- CompletePropertyDescriptor(MutableHandle<JS::PropertyDescriptor> desc);
- /*
- * Read property descriptors from props, as for Object.defineProperties. See
- * ES5 15.2.3.7 steps 3-5.
- */
- extern bool
- ReadPropertyDescriptors(JSContext* cx, HandleObject props, bool checkAccessors,
- AutoIdVector* ids, MutableHandle<PropertyDescriptorVector> descs);
- /* Read the name using a dynamic lookup on the scopeChain. */
- extern bool
- LookupName(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
- MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp);
- extern bool
- LookupNameNoGC(JSContext* cx, PropertyName* name, JSObject* scopeChain,
- JSObject** objp, JSObject** pobjp, Shape** propp);
- /*
- * Like LookupName except returns the global object if 'name' is not found in
- * any preceding scope.
- *
- * Additionally, pobjp and propp are not needed by callers so they are not
- * returned.
- */
- extern bool
- LookupNameWithGlobalDefault(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
- MutableHandleObject objp);
- /*
- * Like LookupName except returns the unqualified var object if 'name' is not
- * found in any preceding scope. Normally the unqualified var object is the
- * global. If the value for the name in the looked-up scope is an
- * uninitialized lexical, an UninitializedLexicalObject is returned.
- *
- * Additionally, pobjp is not needed by callers so it is not returned.
- */
- extern bool
- LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
- MutableHandleObject objp);
- } // namespace js
- namespace js {
- extern JSObject*
- FindVariableScope(JSContext* cx, JSFunction** funp);
- bool
- LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject** objp,
- Shape** propp);
- bool
- LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape** propp,
- bool* isTypedArrayOutOfRange = nullptr);
- bool
- GetPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Value* vp);
- bool
- GetGetterPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSFunction** fp);
- bool
- GetOwnGetterPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSFunction** fp);
- bool
- GetOwnNativeGetterPure(JSContext* cx, JSObject* obj, jsid id, JSNative* native);
- bool
- HasOwnDataPropertyPure(JSContext* cx, JSObject* obj, jsid id, bool* result);
- bool
- GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
- MutableHandle<JS::PropertyDescriptor> desc);
- bool
- GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp);
- /*
- * Like JS::FromPropertyDescriptor, but ignore desc.object() and always set vp
- * to an object on success.
- *
- * Use JS::FromPropertyDescriptor for getOwnPropertyDescriptor, since desc.object()
- * is used to indicate whether a result was found or not. Use this instead for
- * defineProperty: it would be senseless to define a "missing" property.
- */
- extern bool
- FromPropertyDescriptorToObject(JSContext* cx, Handle<JS::PropertyDescriptor> desc,
- MutableHandleValue vp);
- extern bool
- IsDelegate(JSContext* cx, HandleObject obj, const Value& v, bool* result);
- // obj is a JSObject*, but we root it immediately up front. We do it
- // that way because we need a Rooted temporary in this method anyway.
- extern bool
- IsDelegateOfObject(JSContext* cx, HandleObject protoObj, JSObject* obj, bool* result);
- /* Wrap boolean, number or string as Boolean, Number or String object. */
- extern JSObject*
- PrimitiveToObject(JSContext* cx, const Value& v);
- } /* namespace js */
- namespace js {
- /* For converting stack values to objects. */
- MOZ_ALWAYS_INLINE JSObject*
- ToObjectFromStack(JSContext* cx, HandleValue vp)
- {
- if (vp.isObject())
- return &vp.toObject();
- return js::ToObjectSlow(cx, vp, true);
- }
- template<XDRMode mode>
- bool
- XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj);
- /*
- * Report a TypeError: "so-and-so is not an object".
- * Using NotNullObject is usually less code.
- */
- extern void
- ReportNotObject(JSContext* cx, const Value& v);
- inline JSObject*
- NonNullObject(JSContext* cx, const Value& v)
- {
- if (v.isObject())
- return &v.toObject();
- ReportNotObject(cx, v);
- return nullptr;
- }
- extern bool
- GetFirstArgumentAsObject(JSContext* cx, const CallArgs& args, const char* method,
- MutableHandleObject objp);
- /* Helpers for throwing. These always return false. */
- extern bool
- Throw(JSContext* cx, jsid id, unsigned errorNumber);
- extern bool
- Throw(JSContext* cx, JSObject* obj, unsigned errorNumber);
- /*
- * ES6 rev 29 (6 Dec 2014) 7.3.13. Mark obj as non-extensible, and adjust each
- * of obj's own properties' attributes appropriately: each property becomes
- * non-configurable, and if level == Frozen, data properties become
- * non-writable as well.
- */
- extern bool
- SetIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level);
- inline bool
- FreezeObject(JSContext* cx, HandleObject obj)
- {
- return SetIntegrityLevel(cx, obj, IntegrityLevel::Frozen);
- }
- /*
- * ES6 rev 29 (6 Dec 2014) 7.3.14. Code shared by Object.isSealed and
- * Object.isFrozen.
- */
- extern bool
- TestIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level, bool* resultp);
- extern bool
- SpeciesConstructor(JSContext* cx, HandleObject obj, HandleValue defaultCtor, MutableHandleValue pctor);
- extern bool
- SpeciesConstructor(JSContext* cx, HandleObject obj, JSProtoKey ctorKey, MutableHandleValue pctor);
- extern bool
- GetObjectFromIncumbentGlobal(JSContext* cx, MutableHandleObject obj);
- } /* namespace js */
- #endif /* jsobj_h */
|