summaryrefslogtreecommitdiffstats
path: root/js/src/jsobj.h
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /js/src/jsobj.h
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'js/src/jsobj.h')
-rw-r--r--js/src/jsobj.h1387
1 files changed, 1387 insertions, 0 deletions
diff --git a/js/src/jsobj.h b/js/src/jsobj.h
new file mode 100644
index 000000000..fbf4e47be
--- /dev/null
+++ b/js/src/jsobj.h
@@ -0,0 +1,1387 @@
+/* -*- 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/. */
+
+#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::WatchOp getOpsWatch() const { return getClass()->getOpsWatch(); }
+ js::UnwatchOp getOpsUnwatch() const { return getClass()->getOpsUnwatch(); }
+ 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
+ };
+
+ bool setFlags(js::ExclusiveContext* cx, 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;
+ bool setDelegate(js::ExclusiveContext* cx) {
+ return setFlags(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
+ }
+
+ inline bool isBoundFunction() const;
+ inline bool hasSpecialEquality() const;
+
+ inline bool watched() const;
+ bool setWatched(js::ExclusiveContext* cx) {
+ return setFlags(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
+ }
+
+ // 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;
+ bool setQualifiedVarObj(js::ExclusiveContext* cx) {
+ return setFlags(cx, 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;
+ bool setUncacheableProto(js::ExclusiveContext* cx) {
+ MOZ_ASSERT(hasStaticPrototype(),
+ "uncacheability as a concept is only applicable to static "
+ "(not dynamically-computed) prototypes");
+ return setFlags(cx, 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;
+ bool setHadElementsAccess(js::ExclusiveContext* cx) {
+ return setFlags(cx, 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.
+ */
+ bool constructorDisplayAtom(JSContext* cx, 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);
+
+ inline js::ObjectGroup* getGroup(JSContext* cx);
+
+ 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;
+ bool setIteratedSingleton(js::ExclusiveContext* cx) {
+ return setFlags(cx, 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;
+ bool setNewScriptCleared(js::ExclusiveContext* cx) {
+ return setFlags(cx, js::BaseShape::NEW_SCRIPT_CLEARED);
+ }
+
+ /* Set a new prototype for an object with a singleton type. */
+ bool splicePrototype(JSContext* cx, 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(JSContext* cx);
+
+ /*
+ * 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);
+ bool reportNotConfigurable(JSContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
+ bool reportNotExtensible(JSContext* cx, 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);
+
+/*
+ * Set a watchpoint: a synchronous callback when the given property of the
+ * given object is set.
+ *
+ * Watchpoints are nonstandard and do not fit in well with the way ES6
+ * specifies [[Set]]. They are also insufficient for implementing
+ * Object.observe.
+ */
+extern bool
+WatchProperty(JSContext* cx, HandleObject obj, HandleId id, HandleObject callable);
+
+/* Clear a watchpoint. */
+extern bool
+UnwatchProperty(JSContext* cx, HandleObject obj, HandleId id);
+
+/* 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);
+
+extern bool
+ReportGetterOnlyAssignment(JSContext* cx, bool strict);
+
+/*
+ * 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 */