Bumping manifests a=b2g-bump
[gecko.git] / js / src / jsobj.h
blobc1d2f97ec582b456cda729085e037c1e516276ec
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef jsobj_h
8 #define jsobj_h
11 * JS object definitions.
13 * A JS object consists of a possibly-shared object descriptor containing
14 * ordered property names, called the map; and a dense vector of property
15 * values, called slots. The map/slot pointer pair is GC'ed, while the map
16 * is reference counted and the slot vector is malloc'ed.
19 #include "mozilla/MemoryReporting.h"
21 #include "gc/Barrier.h"
22 #include "gc/Marking.h"
23 #include "js/GCAPI.h"
24 #include "js/HeapAPI.h"
25 #include "vm/ObjectImpl.h"
26 #include "vm/Shape.h"
27 #include "vm/Xdr.h"
29 namespace JS {
30 struct ClassInfo;
33 namespace js {
35 class AutoPropDescVector;
36 class GCMarker;
37 struct NativeIterator;
38 class Nursery;
39 struct StackShape;
41 inline JSObject*
42 CastAsObject(PropertyOp op)
44 return JS_FUNC_TO_DATA_PTR(JSObject*, op);
47 inline JSObject*
48 CastAsObject(StrictPropertyOp op)
50 return JS_FUNC_TO_DATA_PTR(JSObject*, op);
53 inline Value
54 CastAsObjectJsval(PropertyOp op)
56 return ObjectOrNullValue(CastAsObject(op));
59 inline Value
60 CastAsObjectJsval(StrictPropertyOp op)
62 return ObjectOrNullValue(CastAsObject(op));
65 /******************************************************************************/
67 typedef Vector<PropDesc, 1> PropDescArray;
70 * The baseops namespace encapsulates the default behavior when performing
71 * various operations on an object, irrespective of hooks installed in the
72 * object's class. In general, instance methods on the object itself should be
73 * called instead of calling these methods directly.
75 namespace baseops {
78 * On success, and if id was found, return true with *objp non-null and with a
79 * property of *objp stored in *propp. If successful but id was not found,
80 * return true with both *objp and *propp null.
82 template <AllowGC allowGC>
83 extern bool
84 LookupProperty(ExclusiveContext* cx,
85 typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
86 typename MaybeRooted<jsid, allowGC>::HandleType id,
87 typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
88 typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
90 extern bool
91 LookupElement(JSContext* cx, HandleObject obj, uint32_t index,
92 MutableHandleObject objp, MutableHandleShape propp);
94 extern bool
95 DefineGeneric(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
96 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
98 extern bool
99 DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, HandleValue value,
100 JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
102 extern bool
103 GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp);
105 extern bool
106 GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, jsid id, Value* vp);
108 extern bool
109 GetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp);
111 inline bool
112 GetProperty(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
114 return GetProperty(cx, obj, obj, id, vp);
117 inline bool
118 GetElement(JSContext* cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
120 return GetElement(cx, obj, obj, index, vp);
124 * Indicates whether an assignment operation is qualified (`x.y = 0`) or
125 * unqualified (`y = 0`). In strict mode, the latter is an error if no such
126 * variable already exists.
128 * Used as an argument to baseops::SetPropertyHelper.
130 enum QualifiedBool {
131 Unqualified = 0,
132 Qualified = 1
135 template <ExecutionMode mode>
136 extern bool
137 SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cx, HandleObject obj,
138 HandleObject receiver, HandleId id, QualifiedBool qualified,
139 MutableHandleValue vp, bool strict);
141 extern bool
142 SetElementHelper(JSContext* cx, HandleObject obj, HandleObject Receiver, uint32_t index,
143 MutableHandleValue vp, bool strict);
145 extern bool
146 GetAttributes(JSContext* cx, HandleObject obj, HandleId id, unsigned* attrsp);
148 extern bool
149 SetAttributes(JSContext* cx, HandleObject obj, HandleId id, unsigned* attrsp);
151 extern bool
152 DeleteGeneric(JSContext* cx, HandleObject obj, HandleId id, bool* succeeded);
154 extern bool
155 Watch(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
157 extern bool
158 Unwatch(JSContext* cx, JS::HandleObject obj, JS::HandleId id);
160 } /* namespace js::baseops */
162 extern const Class IntlClass;
163 extern const Class JSONClass;
164 extern const Class MathClass;
166 class GlobalObject;
167 class MapObject;
168 class NewObjectCache;
169 class NormalArgumentsObject;
170 class SetObject;
171 class StrictArgumentsObject;
174 * NOTE: This is a placeholder for bug 619558.
176 * Run a post write barrier that encompasses multiple contiguous slots in a
177 * single step.
179 inline void
180 DenseRangeWriteBarrierPost(JSRuntime* rt, JSObject* obj, uint32_t start, uint32_t count)
182 #ifdef JSGC_GENERATIONAL
183 if (count > 0) {
184 JS::shadow::Runtime* shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt);
185 shadowRuntime->gcStoreBufferPtr()->putSlotFromAnyThread(obj, HeapSlot::Element, start, count);
187 #endif
190 namespace gc {
191 class ForkJoinNursery;
194 } /* namespace js */
197 * The public interface for an object.
199 * Implementation of the underlying structure occurs in ObjectImpl, from which
200 * this struct inherits. This inheritance is currently public, but it will
201 * eventually be made protected. For full details, see vm/ObjectImpl.{h,cpp}.
203 * The JSFunction struct is an extension of this struct allocated from a larger
204 * GC size-class.
206 class JSObject : public js::ObjectImpl
208 private:
209 friend class js::Shape;
210 friend class js::GCMarker;
211 friend class js::NewObjectCache;
212 friend class js::Nursery;
213 friend class js::gc::ForkJoinNursery;
215 /* Make the type object to use for LAZY_TYPE objects. */
216 static js::types::TypeObject* makeLazyType(JSContext* cx, js::HandleObject obj);
218 public:
219 static const js::Class class_;
222 * Update the last property, keeping the number of allocated slots in sync
223 * with the object's new slot span.
225 static bool setLastProperty(js::ThreadSafeContext* cx,
226 JS::HandleObject obj, js::HandleShape shape);
228 /* As above, but does not change the slot span. */
229 inline void setLastPropertyInfallible(js::Shape* shape);
232 * Make a non-array object with the specified initial state. This method
233 * takes ownership of any extantSlots it is passed.
235 static inline JSObject* create(js::ExclusiveContext* cx,
236 js::gc::AllocKind kind,
237 js::gc::InitialHeap heap,
238 js::HandleShape shape,
239 js::HandleTypeObject type);
241 /* Make an array object with the specified initial state. */
242 static inline js::ArrayObject* createArray(js::ExclusiveContext* cx,
243 js::gc::AllocKind kind,
244 js::gc::InitialHeap heap,
245 js::HandleShape shape,
246 js::HandleTypeObject type,
247 uint32_t length);
249 /* Make an array object with the specified initial state and elements. */
250 static inline js::ArrayObject* createArray(js::ExclusiveContext* cx,
251 js::gc::InitialHeap heap,
252 js::HandleShape shape,
253 js::HandleTypeObject type,
254 js::HeapSlot* elements);
256 private:
257 // Helper for the above two methods.
258 static inline JSObject*
259 createArrayInternal(js::ExclusiveContext* cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
260 js::HandleShape shape, js::HandleTypeObject type);
261 public:
264 * Remove the last property of an object, provided that it is safe to do so
265 * (the shape and previous shape do not carry conflicting information about
266 * the object itself).
268 inline void removeLastProperty(js::ExclusiveContext* cx);
269 inline bool canRemoveLastProperty();
272 * Update the slot span directly for a dictionary object, and allocate
273 * slots to cover the new span if necessary.
275 static bool setSlotSpan(js::ThreadSafeContext* cx, JS::HandleObject obj, uint32_t span);
277 /* Upper bound on the number of elements in an object. */
278 static const uint32_t NELEMENTS_LIMIT = JS_BIT(28);
280 public:
281 bool setDelegate(js::ExclusiveContext* cx) {
282 return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
285 bool isBoundFunction() const {
286 return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION);
289 inline bool hasSpecialEquality() const;
291 bool watched() const {
292 return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
294 bool setWatched(js::ExclusiveContext* cx) {
295 return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
298 /* See InterpreterFrame::varObj. */
299 inline bool isQualifiedVarObj();
300 bool setQualifiedVarObj(js::ExclusiveContext* cx) {
301 return setFlag(cx, js::BaseShape::QUALIFIED_VAROBJ);
304 inline bool isUnqualifiedVarObj();
305 bool setUnqualifiedVarObj(js::ExclusiveContext* cx) {
306 return setFlag(cx, js::BaseShape::UNQUALIFIED_VAROBJ);
310 * Objects with an uncacheable proto can have their prototype mutated
311 * without inducing a shape change on the object. Property cache entries
312 * and JIT inline caches should not be filled for lookups across prototype
313 * lookups on the object.
315 bool hasUncacheableProto() const {
316 return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
318 bool setUncacheableProto(js::ExclusiveContext* cx) {
319 return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
323 * Whether SETLELEM was used to access this object. See also the comment near
324 * PropertyTree::MAX_HEIGHT.
326 bool hadElementsAccess() const {
327 return lastProperty()->hasObjectFlag(js::BaseShape::HAD_ELEMENTS_ACCESS);
329 bool setHadElementsAccess(js::ExclusiveContext* cx) {
330 return setFlag(cx, js::BaseShape::HAD_ELEMENTS_ACCESS);
333 public:
334 bool nativeEmpty() const {
335 return lastProperty()->isEmptyShape();
338 bool shadowingShapeChange(js::ExclusiveContext* cx, const js::Shape& shape);
341 * Whether there may be indexed properties on this object, excluding any in
342 * the object's elements.
344 bool isIndexed() const {
345 return lastProperty()->hasObjectFlag(js::BaseShape::INDEXED);
348 uint32_t propertyCount() const {
349 return lastProperty()->entryCount();
352 bool hasShapeTable() const {
353 return lastProperty()->hasTable();
356 void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ClassInfo* info);
358 bool hasIdempotentProtoChain() const;
360 // MAX_FIXED_SLOTS is the biggest number of fixed slots our GC
361 // size classes will give an object.
362 static const uint32_t MAX_FIXED_SLOTS = 16;
364 public:
366 /* Accessors for properties. */
368 /* Whether a slot is at a fixed offset from this object. */
369 bool isFixedSlot(size_t slot) {
370 return slot < numFixedSlots();
373 /* Index into the dynamic slots array to use for a dynamic slot. */
374 size_t dynamicSlotIndex(size_t slot) {
375 JS_ASSERT(slot >= numFixedSlots());
376 return slot - numFixedSlots();
380 * Grow or shrink slots immediately before changing the slot span.
381 * The number of allocated slots is not stored explicitly, and changes to
382 * the slots must track changes in the slot span.
384 static bool growSlots(js::ThreadSafeContext* cx, js::HandleObject obj, uint32_t oldCount,
385 uint32_t newCount);
386 static void shrinkSlots(js::ThreadSafeContext* cx, js::HandleObject obj, uint32_t oldCount,
387 uint32_t newCount);
389 bool hasDynamicSlots() const { return !!slots; }
391 protected:
392 static inline bool updateSlotsForSpan(js::ThreadSafeContext* cx,
393 js::HandleObject obj, size_t oldSpan, size_t newSpan);
395 public:
397 * Trigger the write barrier on a range of slots that will no longer be
398 * reachable.
400 void prepareSlotRangeForOverwrite(size_t start, size_t end) {
401 for (size_t i = start; i < end; i++)
402 getSlotAddressUnchecked(i)->js::HeapSlot::~HeapSlot();
405 void prepareElementRangeForOverwrite(size_t start, size_t end) {
406 JS_ASSERT(end <= getDenseInitializedLength());
407 JS_ASSERT(!denseElementsAreCopyOnWrite());
408 for (size_t i = start; i < end; i++)
409 elements[i].js::HeapSlot::~HeapSlot();
412 static bool rollbackProperties(js::ExclusiveContext* cx, js::HandleObject obj,
413 uint32_t slotSpan);
415 void nativeSetSlot(uint32_t slot, const js::Value& value) {
416 JS_ASSERT(isNative());
417 JS_ASSERT(slot < slotSpan());
418 return setSlot(slot, value);
421 inline bool nativeSetSlotIfHasType(js::Shape* shape, const js::Value& value,
422 bool overwriting = true);
423 inline void nativeSetSlotWithType(js::ExclusiveContext* cx, js::Shape* shape,
424 const js::Value& value, bool overwriting = true);
426 inline const js::Value& getReservedSlot(uint32_t index) const {
427 JS_ASSERT(index < JSSLOT_FREE(getClass()));
428 return getSlot(index);
431 const js::HeapSlot& getReservedSlotRef(uint32_t index) const {
432 JS_ASSERT(index < JSSLOT_FREE(getClass()));
433 return getSlotRef(index);
436 js::HeapSlot& getReservedSlotRef(uint32_t index) {
437 JS_ASSERT(index < JSSLOT_FREE(getClass()));
438 return getSlotRef(index);
441 void initReservedSlot(uint32_t index, const js::Value& v) {
442 JS_ASSERT(index < JSSLOT_FREE(getClass()));
443 initSlot(index, v);
446 void setReservedSlot(uint32_t index, const js::Value& v) {
447 JS_ASSERT(index < JSSLOT_FREE(getClass()));
448 setSlot(index, v);
452 * Marks this object as having a singleton type, and leave the type lazy.
453 * Constructs a new, unique shape for the object.
455 static inline bool setSingletonType(js::ExclusiveContext* cx, js::HandleObject obj);
457 // uninlinedGetType() is the same as getType(), but not inlined.
458 inline js::types::TypeObject* getType(JSContext* cx);
459 js::types::TypeObject* uninlinedGetType(JSContext* cx);
461 const js::HeapPtrTypeObject& typeFromGC() const {
462 /* Direct field access for use by GC. */
463 return type_;
467 * We allow the prototype of an object to be lazily computed if the object
468 * is a proxy. In the lazy case, we store (JSObject*)0x1 in the proto field
469 * of the object's TypeObject. We offer three ways of getting the prototype:
471 * 1. obj->getProto() returns the prototype, but asserts if obj is a proxy.
472 * 2. obj->getTaggedProto() returns a TaggedProto, which can be tested to
473 * check if the proto is an object, nullptr, or lazily computed.
474 * 3. JSObject::getProto(cx, obj, &proto) computes the proto of an object.
475 * If obj is a proxy and the proto is lazy, this code may allocate or
476 * GC in order to compute the proto. Currently, it will not run JS code.
478 bool uninlinedIsProxy() const;
479 JSObject* getProto() const {
480 JS_ASSERT(!uninlinedIsProxy());
481 return getTaggedProto().toObjectOrNull();
483 static inline bool getProto(JSContext* cx, js::HandleObject obj,
484 js::MutableHandleObject protop);
485 // Returns false on error, success of operation in outparam.
486 static inline bool setProto(JSContext* cx, JS::HandleObject obj,
487 JS::HandleObject proto, bool* succeeded);
489 // uninlinedSetType() is the same as setType(), but not inlined.
490 inline void setType(js::types::TypeObject* newType);
491 void uninlinedSetType(js::types::TypeObject* newType);
493 #ifdef DEBUG
494 bool hasNewType(const js::Class* clasp, js::types::TypeObject* newType);
495 #endif
498 * Mark an object that has been iterated over and is a singleton. We need
499 * to recover this information in the object's type information after it
500 * is purged on GC.
502 bool isIteratedSingleton() const {
503 return lastProperty()->hasObjectFlag(js::BaseShape::ITERATED_SINGLETON);
505 bool setIteratedSingleton(js::ExclusiveContext* cx) {
506 return setFlag(cx, js::BaseShape::ITERATED_SINGLETON);
510 * Mark an object as requiring its default 'new' type to have unknown
511 * properties.
513 bool isNewTypeUnknown() const {
514 return lastProperty()->hasObjectFlag(js::BaseShape::NEW_TYPE_UNKNOWN);
516 static bool setNewTypeUnknown(JSContext* cx, const js::Class* clasp, JS::HandleObject obj);
518 /* Set a new prototype for an object with a singleton type. */
519 bool splicePrototype(JSContext* cx, const js::Class* clasp, js::Handle<js::TaggedProto> proto);
522 * For bootstrapping, whether to splice a prototype for Function.prototype
523 * or the global object.
525 bool shouldSplicePrototype(JSContext* cx);
528 * Parents and scope chains.
530 * All script-accessible objects with a nullptr parent are global objects,
531 * and all global objects have a nullptr parent. Some builtin objects
532 * which are not script-accessible also have a nullptr parent, such as
533 * parser created functions for non-compileAndGo scripts.
535 * Except for the non-script-accessible builtins, the global with which an
536 * object is associated can be reached by following parent links to that
537 * global (see global()).
539 * The scope chain of an object is the link in the search path when a
540 * script does a name lookup on a scope object. For JS internal scope
541 * objects --- Call, DeclEnv and Block --- the chain is stored in
542 * the first fixed slot of the object, and the object's parent is the
543 * associated global. For other scope objects, the chain is stored in the
544 * object's parent.
546 * In compileAndGo code, scope chains can contain only internal scope
547 * objects with a global object at the root as the scope of the outermost
548 * non-function script. In non-compileAndGo code, the scope of the
549 * outermost non-function script might not be a global object, and can have
550 * a mix of other objects above it before the global object is reached.
553 /* Access the parent link of an object. */
554 JSObject* getParent() const {
555 return lastProperty()->getObjectParent();
557 static bool setParent(JSContext* cx, js::HandleObject obj, js::HandleObject newParent);
560 * Get the enclosing scope of an object. When called on non-scope object,
561 * this will just be the global (the name "enclosing scope" still applies
562 * in this situation because non-scope objects can be on the scope chain).
564 inline JSObject* enclosingScope();
566 /* Access the metadata on an object. */
567 inline JSObject* getMetadata() const {
568 return lastProperty()->getObjectMetadata();
570 static bool setMetadata(JSContext* cx, js::HandleObject obj, js::HandleObject newMetadata);
572 inline js::GlobalObject& global() const;
573 inline bool isOwnGlobal() const;
575 /* Remove the type (and prototype) or parent from a new object. */
576 static inline bool clearType(JSContext* cx, js::HandleObject obj);
577 static bool clearParent(JSContext* cx, js::HandleObject obj);
580 * ES5 meta-object properties and operations.
583 private:
584 enum ImmutabilityType { SEAL, FREEZE };
587 * The guts of Object.seal (ES5 15.2.3.8) and Object.freeze (ES5 15.2.3.9): mark the
588 * object as non-extensible, and adjust each property's attributes appropriately: each
589 * property becomes non-configurable, and if |freeze|, data properties become
590 * read-only as well.
592 static bool sealOrFreeze(JSContext* cx, js::HandleObject obj, ImmutabilityType it);
594 static bool isSealedOrFrozen(JSContext* cx, js::HandleObject obj, ImmutabilityType it, bool* resultp);
596 static inline unsigned getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it);
598 public:
599 /* ES5 15.2.3.8: non-extensible, all props non-configurable */
600 static inline bool seal(JSContext* cx, js::HandleObject obj) { return sealOrFreeze(cx, obj, SEAL); }
601 /* ES5 15.2.3.9: non-extensible, all properties non-configurable, all data props read-only */
602 static inline bool freeze(JSContext* cx, js::HandleObject obj) { return sealOrFreeze(cx, obj, FREEZE); }
604 static inline bool isSealed(JSContext* cx, js::HandleObject obj, bool* resultp) {
605 return isSealedOrFrozen(cx, obj, SEAL, resultp);
607 static inline bool isFrozen(JSContext* cx, js::HandleObject obj, bool* resultp) {
608 return isSealedOrFrozen(cx, obj, FREEZE, resultp);
611 /* toString support. */
612 static const char* className(JSContext* cx, js::HandleObject obj);
614 /* Accessors for elements. */
615 bool ensureElements(js::ThreadSafeContext* cx, uint32_t capacity) {
616 JS_ASSERT(!denseElementsAreCopyOnWrite());
617 if (capacity > getDenseCapacity())
618 return growElements(cx, capacity);
619 return true;
622 static uint32_t goodAllocated(uint32_t n, uint32_t length);
623 bool growElements(js::ThreadSafeContext* cx, uint32_t newcap);
624 void shrinkElements(js::ThreadSafeContext* cx, uint32_t cap);
625 void setDynamicElements(js::ObjectElements* header) {
626 JS_ASSERT(!hasDynamicElements());
627 elements = header->elements();
628 JS_ASSERT(hasDynamicElements());
631 uint32_t getDenseCapacity() {
632 JS_ASSERT(isNative());
633 JS_ASSERT(getElementsHeader()->capacity >= getElementsHeader()->initializedLength);
634 return getElementsHeader()->capacity;
637 static bool CopyElementsForWrite(js::ThreadSafeContext* cx, JSObject* obj);
639 bool maybeCopyElementsForWrite(js::ThreadSafeContext* cx) {
640 if (denseElementsAreCopyOnWrite())
641 return CopyElementsForWrite(cx, this);
642 return true;
645 private:
646 inline void ensureDenseInitializedLengthNoPackedCheck(js::ThreadSafeContext* cx,
647 uint32_t index, uint32_t extra);
649 public:
650 void setDenseInitializedLength(uint32_t length) {
651 JS_ASSERT(isNative());
652 JS_ASSERT(length <= getDenseCapacity());
653 JS_ASSERT(!denseElementsAreCopyOnWrite());
654 prepareElementRangeForOverwrite(length, getElementsHeader()->initializedLength);
655 getElementsHeader()->initializedLength = length;
658 inline void ensureDenseInitializedLength(js::ExclusiveContext* cx,
659 uint32_t index, uint32_t extra);
660 inline void ensureDenseInitializedLengthPreservePackedFlag(js::ThreadSafeContext* cx,
661 uint32_t index, uint32_t extra);
662 void setDenseElement(uint32_t index, const js::Value& val) {
663 JS_ASSERT(isNative() && index < getDenseInitializedLength());
664 JS_ASSERT(!denseElementsAreCopyOnWrite());
665 elements[index].set(this, js::HeapSlot::Element, index, val);
668 void initDenseElement(uint32_t index, const js::Value& val) {
669 JS_ASSERT(isNative() && index < getDenseInitializedLength());
670 JS_ASSERT(!denseElementsAreCopyOnWrite());
671 elements[index].init(this, js::HeapSlot::Element, index, val);
674 void setDenseElementMaybeConvertDouble(uint32_t index, const js::Value& val) {
675 if (val.isInt32() && shouldConvertDoubleElements())
676 setDenseElement(index, js::DoubleValue(val.toInt32()));
677 else
678 setDenseElement(index, val);
681 inline bool setDenseElementIfHasType(uint32_t index, const js::Value& val);
682 inline void setDenseElementWithType(js::ExclusiveContext* cx, uint32_t index,
683 const js::Value& val);
684 inline void initDenseElementWithType(js::ExclusiveContext* cx, uint32_t index,
685 const js::Value& val);
686 inline void setDenseElementHole(js::ExclusiveContext* cx, uint32_t index);
687 static inline void removeDenseElementForSparseIndex(js::ExclusiveContext* cx,
688 js::HandleObject obj, uint32_t index);
690 inline js::Value getDenseOrTypedArrayElement(uint32_t idx);
692 void copyDenseElements(uint32_t dstStart, const js::Value* src, uint32_t count) {
693 JS_ASSERT(dstStart + count <= getDenseCapacity());
694 JS_ASSERT(!denseElementsAreCopyOnWrite());
695 JSRuntime* rt = runtimeFromMainThread();
696 if (JS::IsIncrementalBarrierNeeded(rt)) {
697 JS::Zone* zone = this->zone();
698 for (uint32_t i = 0; i < count; ++i)
699 elements[dstStart + i].set(zone, this, js::HeapSlot::Element, dstStart + i, src[i]);
700 } else {
701 memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot));
702 DenseRangeWriteBarrierPost(rt, this, dstStart, count);
706 void initDenseElements(uint32_t dstStart, const js::Value* src, uint32_t count) {
707 JS_ASSERT(dstStart + count <= getDenseCapacity());
708 JS_ASSERT(!denseElementsAreCopyOnWrite());
709 memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot));
710 DenseRangeWriteBarrierPost(runtimeFromMainThread(), this, dstStart, count);
713 void initDenseElementsUnbarriered(uint32_t dstStart, const js::Value* src, uint32_t count);
715 void moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count) {
716 JS_ASSERT(dstStart + count <= getDenseCapacity());
717 JS_ASSERT(srcStart + count <= getDenseInitializedLength());
718 JS_ASSERT(!denseElementsAreCopyOnWrite());
721 * Using memmove here would skip write barriers. Also, we need to consider
722 * an array containing [A, B, C], in the following situation:
724 * 1. Incremental GC marks slot 0 of array (i.e., A), then returns to JS code.
725 * 2. JS code moves slots 1..2 into slots 0..1, so it contains [B, C, C].
726 * 3. Incremental GC finishes by marking slots 1 and 2 (i.e., C).
728 * Since normal marking never happens on B, it is very important that the
729 * write barrier is invoked here on B, despite the fact that it exists in
730 * the array before and after the move.
732 JS::Zone* zone = this->zone();
733 JS::shadow::Zone* shadowZone = JS::shadow::Zone::asShadowZone(zone);
734 if (shadowZone->needsIncrementalBarrier()) {
735 if (dstStart < srcStart) {
736 js::HeapSlot* dst = elements + dstStart;
737 js::HeapSlot* src = elements + srcStart;
738 for (uint32_t i = 0; i < count; i++, dst++, src++)
739 dst->set(zone, this, js::HeapSlot::Element, dst - elements, *src);
740 } else {
741 js::HeapSlot* dst = elements + dstStart + count - 1;
742 js::HeapSlot* src = elements + srcStart + count - 1;
743 for (uint32_t i = 0; i < count; i++, dst--, src--)
744 dst->set(zone, this, js::HeapSlot::Element, dst - elements, *src);
746 } else {
747 memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot));
748 DenseRangeWriteBarrierPost(runtimeFromMainThread(), this, dstStart, count);
752 void moveDenseElementsNoPreBarrier(uint32_t dstStart, uint32_t srcStart, uint32_t count) {
753 JS_ASSERT(!shadowZone()->needsIncrementalBarrier());
755 JS_ASSERT(dstStart + count <= getDenseCapacity());
756 JS_ASSERT(srcStart + count <= getDenseCapacity());
757 JS_ASSERT(!denseElementsAreCopyOnWrite());
759 memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value));
760 DenseRangeWriteBarrierPost(runtimeFromMainThread(), this, dstStart, count);
763 bool shouldConvertDoubleElements() {
764 JS_ASSERT(getClass()->isNative());
765 return getElementsHeader()->shouldConvertDoubleElements();
768 inline void setShouldConvertDoubleElements();
769 inline void clearShouldConvertDoubleElements();
771 bool denseElementsAreCopyOnWrite() {
772 JS_ASSERT(isNative());
773 return getElementsHeader()->isCopyOnWrite();
776 /* Packed information for this object's elements. */
777 inline bool writeToIndexWouldMarkNotPacked(uint32_t index);
778 inline void markDenseElementsNotPacked(js::ExclusiveContext* cx);
781 * ensureDenseElements ensures that the object can hold at least
782 * index + extra elements. It returns ED_OK on success, ED_FAILED on
783 * failure to grow the array, ED_SPARSE when the object is too sparse to
784 * grow (this includes the case of index + extra overflow). In the last
785 * two cases the object is kept intact.
787 enum EnsureDenseResult { ED_OK, ED_FAILED, ED_SPARSE };
789 private:
790 inline EnsureDenseResult ensureDenseElementsNoPackedCheck(js::ThreadSafeContext* cx,
791 uint32_t index, uint32_t extra);
793 public:
794 inline EnsureDenseResult ensureDenseElements(js::ExclusiveContext* cx,
795 uint32_t index, uint32_t extra);
796 inline EnsureDenseResult ensureDenseElementsPreservePackedFlag(js::ThreadSafeContext* cx,
797 uint32_t index, uint32_t extra);
799 inline EnsureDenseResult extendDenseElements(js::ThreadSafeContext* cx,
800 uint32_t requiredCapacity, uint32_t extra);
802 /* Convert a single dense element to a sparse property. */
803 static bool sparsifyDenseElement(js::ExclusiveContext* cx,
804 js::HandleObject obj, uint32_t index);
806 /* Convert all dense elements to sparse properties. */
807 static bool sparsifyDenseElements(js::ExclusiveContext* cx, js::HandleObject obj);
809 /* Small objects are dense, no matter what. */
810 static const uint32_t MIN_SPARSE_INDEX = 1000;
813 * Element storage for an object will be sparse if fewer than 1/8 indexes
814 * are filled in.
816 static const unsigned SPARSE_DENSITY_RATIO = 8;
819 * Check if after growing the object's elements will be too sparse.
820 * newElementsHint is an estimated number of elements to be added.
822 bool willBeSparseElements(uint32_t requiredCapacity, uint32_t newElementsHint);
825 * After adding a sparse index to obj, see if it should be converted to use
826 * dense elements.
828 static EnsureDenseResult maybeDensifySparseElements(js::ExclusiveContext* cx, js::HandleObject obj);
830 public:
832 * Iterator-specific getters and setters.
835 static const uint32_t ITER_CLASS_NFIXED_SLOTS = 1;
838 * Back to generic stuff.
840 bool isCallable() {
841 return getClass()->isCallable();
843 bool isConstructor() const;
845 inline void finish(js::FreeOp* fop);
846 MOZ_ALWAYS_INLINE void finalize(js::FreeOp* fop);
848 static inline bool hasProperty(JSContext* cx, js::HandleObject obj,
849 js::HandleId id, bool* foundp);
852 * Allocate and free an object slot.
854 * FIXME: bug 593129 -- slot allocation should be done by object methods
855 * after calling object-parameter-free shape methods, avoiding coupling
856 * logic across the object vs. shape module wall.
858 static bool allocSlot(js::ThreadSafeContext* cx, JS::HandleObject obj, uint32_t* slotp);
859 void freeSlot(uint32_t slot);
861 public:
862 static bool reportReadOnly(js::ThreadSafeContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
863 bool reportNotConfigurable(js::ThreadSafeContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
864 bool reportNotExtensible(js::ThreadSafeContext* cx, unsigned report = JSREPORT_ERROR);
867 * Get the property with the given id, then call it as a function with the
868 * given arguments, providing this object as |this|. If the property isn't
869 * callable a TypeError will be thrown. On success the value returned by
870 * the call is stored in *vp.
872 bool callMethod(JSContext* cx, js::HandleId id, unsigned argc, js::Value* argv,
873 js::MutableHandleValue vp);
875 private:
876 static js::Shape* getChildPropertyOnDictionary(js::ThreadSafeContext* cx, JS::HandleObject obj,
877 js::HandleShape parent, js::StackShape& child);
878 static js::Shape* getChildProperty(js::ExclusiveContext* cx, JS::HandleObject obj,
879 js::HandleShape parent, js::StackShape& child);
880 template <js::ExecutionMode mode>
881 static inline js::Shape*
882 getOrLookupChildProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx,
883 JS::HandleObject obj, js::HandleShape parent, js::StackShape& child)
885 if (mode == js::ParallelExecution)
886 return lookupChildProperty(cx, obj, parent, child);
887 return getChildProperty(cx->asExclusiveContext(), obj, parent, child);
890 public:
892 * XXX: This should be private, but is public because it needs to be a
893 * friend of ThreadSafeContext to get to the propertyTree on cx->compartment_.
895 static js::Shape* lookupChildProperty(js::ThreadSafeContext* cx, JS::HandleObject obj,
896 js::HandleShape parent, js::StackShape& child);
899 protected:
901 * Internal helper that adds a shape not yet mapped by this object.
903 * Notes:
904 * 1. getter and setter must be normalized based on flags (see jsscope.cpp).
905 * 2. Checks for non-extensibility must be done by callers.
907 template <js::ExecutionMode mode>
908 static js::Shape*
909 addPropertyInternal(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx,
910 JS::HandleObject obj, JS::HandleId id,
911 JSPropertyOp getter, JSStrictPropertyOp setter,
912 uint32_t slot, unsigned attrs, unsigned flags, js::Shape** spp,
913 bool allowDictionary);
915 private:
916 struct TradeGutsReserved;
917 static bool ReserveForTradeGuts(JSContext* cx, JSObject* a, JSObject* b,
918 TradeGutsReserved& reserved);
920 static void TradeGuts(JSContext* cx, JSObject* a, JSObject* b,
921 TradeGutsReserved& reserved);
923 public:
924 /* Add a property whose id is not yet in this scope. */
925 static js::Shape* addProperty(js::ExclusiveContext* cx, JS::HandleObject, JS::HandleId id,
926 JSPropertyOp getter, JSStrictPropertyOp setter,
927 uint32_t slot, unsigned attrs, unsigned flags,
928 bool allowDictionary = true);
930 /* Add a data property whose id is not yet in this scope. */
931 js::Shape* addDataProperty(js::ExclusiveContext* cx,
932 jsid id_, uint32_t slot, unsigned attrs);
933 js::Shape* addDataProperty(js::ExclusiveContext* cx, js::HandlePropertyName name,
934 uint32_t slot, unsigned attrs);
936 /* Add or overwrite a property for id in this scope. */
937 template <js::ExecutionMode mode>
938 static js::Shape*
939 putProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx,
940 JS::HandleObject obj, JS::HandleId id,
941 JSPropertyOp getter, JSStrictPropertyOp setter,
942 uint32_t slot, unsigned attrs,
943 unsigned flags);
944 template <js::ExecutionMode mode>
945 static inline js::Shape*
946 putProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx,
947 JS::HandleObject obj, js::PropertyName* name,
948 JSPropertyOp getter, JSStrictPropertyOp setter,
949 uint32_t slot, unsigned attrs,
950 unsigned flags);
952 /* Change the given property into a sibling with the same id in this scope. */
953 template <js::ExecutionMode mode>
954 static js::Shape*
955 changeProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx,
956 js::HandleObject obj, js::HandleShape shape, unsigned attrs, unsigned mask,
957 JSPropertyOp getter, JSStrictPropertyOp setter);
959 static inline bool changePropertyAttributes(JSContext* cx, js::HandleObject obj,
960 js::HandleShape shape, unsigned attrs);
962 /* Remove the property named by id from this object. */
963 bool removeProperty(js::ExclusiveContext* cx, jsid id);
965 /* Clear the scope, making it empty. */
966 static void clear(JSContext* cx, js::HandleObject obj);
968 static bool lookupGeneric(JSContext* cx, js::HandleObject obj, js::HandleId id,
969 js::MutableHandleObject objp, js::MutableHandleShape propp);
971 static bool lookupProperty(JSContext* cx, js::HandleObject obj, js::PropertyName* name,
972 js::MutableHandleObject objp, js::MutableHandleShape propp)
974 JS::RootedId id(cx, js::NameToId(name));
975 return lookupGeneric(cx, obj, id, objp, propp);
978 static bool lookupElement(JSContext* cx, js::HandleObject obj, uint32_t index,
979 js::MutableHandleObject objp, js::MutableHandleShape propp)
981 js::LookupElementOp op = obj->getOps()->lookupElement;
982 return (op ? op : js::baseops::LookupElement)(cx, obj, index, objp, propp);
985 static bool defineGeneric(js::ExclusiveContext* cx, js::HandleObject obj,
986 js::HandleId id, js::HandleValue value,
987 JSPropertyOp getter = JS_PropertyStub,
988 JSStrictPropertyOp setter = JS_StrictPropertyStub,
989 unsigned attrs = JSPROP_ENUMERATE);
991 static bool defineProperty(js::ExclusiveContext* cx, js::HandleObject obj,
992 js::PropertyName* name, js::HandleValue value,
993 JSPropertyOp getter = JS_PropertyStub,
994 JSStrictPropertyOp setter = JS_StrictPropertyStub,
995 unsigned attrs = JSPROP_ENUMERATE);
997 static bool defineElement(js::ExclusiveContext* cx, js::HandleObject obj,
998 uint32_t index, js::HandleValue value,
999 JSPropertyOp getter = JS_PropertyStub,
1000 JSStrictPropertyOp setter = JS_StrictPropertyStub,
1001 unsigned attrs = JSPROP_ENUMERATE);
1003 static bool getGeneric(JSContext* cx, js::HandleObject obj, js::HandleObject receiver,
1004 js::HandleId id, js::MutableHandleValue vp)
1006 JS_ASSERT(!!obj->getOps()->getGeneric == !!obj->getOps()->getProperty);
1007 js::GenericIdOp op = obj->getOps()->getGeneric;
1008 if (op) {
1009 if (!op(cx, obj, receiver, id, vp))
1010 return false;
1011 } else {
1012 if (!js::baseops::GetProperty(cx, obj, receiver, id, vp))
1013 return false;
1015 return true;
1018 static bool getGenericNoGC(JSContext* cx, JSObject* obj, JSObject* receiver,
1019 jsid id, js::Value* vp)
1021 js::GenericIdOp op = obj->getOps()->getGeneric;
1022 if (op)
1023 return false;
1024 return js::baseops::GetPropertyNoGC(cx, obj, receiver, id, vp);
1027 static bool getProperty(JSContext* cx, js::HandleObject obj, js::HandleObject receiver,
1028 js::PropertyName* name, js::MutableHandleValue vp)
1030 JS::RootedId id(cx, js::NameToId(name));
1031 return getGeneric(cx, obj, receiver, id, vp);
1034 static bool getPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver,
1035 js::PropertyName* name, js::Value* vp)
1037 return getGenericNoGC(cx, obj, receiver, js::NameToId(name), vp);
1040 static inline bool getElement(JSContext* cx, js::HandleObject obj, js::HandleObject receiver,
1041 uint32_t index, js::MutableHandleValue vp);
1042 static inline bool getElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver,
1043 uint32_t index, js::Value* vp);
1045 static bool setGeneric(JSContext* cx, js::HandleObject obj, js::HandleObject receiver,
1046 js::HandleId id, js::MutableHandleValue vp, bool strict)
1048 if (obj->getOps()->setGeneric)
1049 return nonNativeSetProperty(cx, obj, id, vp, strict);
1050 return js::baseops::SetPropertyHelper<js::SequentialExecution>(
1051 cx, obj, receiver, id, js::baseops::Qualified, vp, strict);
1054 static bool setProperty(JSContext* cx, js::HandleObject obj, js::HandleObject receiver,
1055 js::PropertyName* name,
1056 js::MutableHandleValue vp, bool strict)
1058 JS::RootedId id(cx, js::NameToId(name));
1059 return setGeneric(cx, obj, receiver, id, vp, strict);
1062 static bool setElement(JSContext* cx, js::HandleObject obj, js::HandleObject receiver,
1063 uint32_t index, js::MutableHandleValue vp, bool strict)
1065 if (obj->getOps()->setElement)
1066 return nonNativeSetElement(cx, obj, index, vp, strict);
1067 return js::baseops::SetElementHelper(cx, obj, receiver, index, vp, strict);
1070 static bool nonNativeSetProperty(JSContext* cx, js::HandleObject obj,
1071 js::HandleId id, js::MutableHandleValue vp, bool strict);
1072 static bool nonNativeSetElement(JSContext* cx, js::HandleObject obj,
1073 uint32_t index, js::MutableHandleValue vp, bool strict);
1075 static bool getGenericAttributes(JSContext* cx, js::HandleObject obj,
1076 js::HandleId id, unsigned* attrsp)
1078 js::GenericAttributesOp op = obj->getOps()->getGenericAttributes;
1079 return (op ? op : js::baseops::GetAttributes)(cx, obj, id, attrsp);
1082 static inline bool setGenericAttributes(JSContext* cx, js::HandleObject obj,
1083 js::HandleId id, unsigned* attrsp);
1085 static inline bool deleteGeneric(JSContext* cx, js::HandleObject obj, js::HandleId id,
1086 bool* succeeded);
1087 static inline bool deleteElement(JSContext* cx, js::HandleObject obj, uint32_t index,
1088 bool* succeeded);
1090 static inline bool watch(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
1091 JS::HandleObject callable);
1092 static inline bool unwatch(JSContext* cx, JS::HandleObject obj, JS::HandleId id);
1094 static bool enumerate(JSContext* cx, JS::HandleObject obj, JSIterateOp iterop,
1095 JS::MutableHandleValue statep, JS::MutableHandleId idp)
1097 JSNewEnumerateOp op = obj->getOps()->enumerate;
1098 return (op ? op : JS_EnumerateState)(cx, obj, iterop, statep, idp);
1101 static bool defaultValue(JSContext* cx, js::HandleObject obj, JSType hint,
1102 js::MutableHandleValue vp)
1104 JSConvertOp op = obj->getClass()->convert;
1105 bool ok;
1106 if (op == JS_ConvertStub)
1107 ok = js::DefaultValue(cx, obj, hint, vp);
1108 else
1109 ok = op(cx, obj, hint, vp);
1110 JS_ASSERT_IF(ok, vp.isPrimitive());
1111 return ok;
1114 static JSObject* thisObject(JSContext* cx, js::HandleObject obj)
1116 if (js::ObjectOp op = obj->getOps()->thisObject)
1117 return op(cx, obj);
1118 return obj;
1121 static bool thisObject(JSContext* cx, const js::Value& v, js::Value* vp);
1123 static bool swap(JSContext* cx, JS::HandleObject a, JS::HandleObject b);
1125 inline void initArrayClass();
1128 * In addition to the generic object interface provided by JSObject,
1129 * specific types of objects may provide additional operations. To access,
1130 * these addition operations, callers should use the pattern:
1132 * if (obj.is<XObject>()) {
1133 * XObject& x = obj.as<XObject>();
1134 * x.foo();
1137 * These XObject classes form a hierarchy. For example, for a cloned block
1138 * object, the following predicates are true: is<ClonedBlockObject>,
1139 * is<BlockObject>, is<NestedScopeObject> and is<ScopeObject>. Each of
1140 * these has a respective class that derives and adds operations.
1142 * A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file
1143 * triplet (along with any class YObject that derives XObject).
1145 * Note that X represents a low-level representation and does not query the
1146 * [[Class]] property of object defined by the spec (for this, see
1147 * js::ObjectClassIs).
1150 template <class T>
1151 inline bool is() const { return getClass() == &T::class_; }
1153 template <class T>
1154 T& as() {
1155 JS_ASSERT(is<T>());
1156 return *static_cast<T*>(this);
1159 template <class T>
1160 const T& as() const {
1161 JS_ASSERT(is<T>());
1162 return *static_cast<const T*>(this);
1165 static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
1167 #ifdef DEBUG
1168 void dump();
1169 #endif
1171 private:
1172 static void staticAsserts() {
1173 static_assert(sizeof(JSObject) == sizeof(js::shadow::Object),
1174 "shadow interface must match actual interface");
1175 static_assert(sizeof(JSObject) == sizeof(js::ObjectImpl),
1176 "JSObject itself must not have any fields");
1177 static_assert(sizeof(JSObject) % sizeof(js::Value) == 0,
1178 "fixed slots after an object must be aligned");
1179 static_assert(js::shadow::Object::MAX_FIXED_SLOTS == MAX_FIXED_SLOTS,
1180 "We shouldn't be confused about our actual maximum "
1181 "number of fixed slots");
1184 JSObject() MOZ_DELETE;
1185 JSObject(const JSObject& other) MOZ_DELETE;
1186 void operator=(const JSObject& other) MOZ_DELETE;
1189 template <class U>
1190 MOZ_ALWAYS_INLINE JS::Handle<U*>
1191 js::RootedBase<JSObject*>::as() const
1193 const JS::Rooted<JSObject*>& self = *static_cast<const JS::Rooted<JSObject*>*>(this);
1194 JS_ASSERT(self->is<U>());
1195 return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address()));
1199 * The only sensible way to compare JSObject with == is by identity. We use
1200 * const& instead of * as a syntactic way to assert non-null. This leads to an
1201 * abundance of address-of operators to identity. Hence this overload.
1203 static MOZ_ALWAYS_INLINE bool
1204 operator==(const JSObject& lhs, const JSObject& rhs)
1206 return &lhs == &rhs;
1209 static MOZ_ALWAYS_INLINE bool
1210 operator!=(const JSObject& lhs, const JSObject& rhs)
1212 return &lhs != &rhs;
1215 struct JSObject_Slots2 : JSObject { js::Value fslots[2]; };
1216 struct JSObject_Slots4 : JSObject { js::Value fslots[4]; };
1217 struct JSObject_Slots8 : JSObject { js::Value fslots[8]; };
1218 struct JSObject_Slots12 : JSObject { js::Value fslots[12]; };
1219 struct JSObject_Slots16 : JSObject { js::Value fslots[16]; };
1221 namespace js {
1223 inline bool
1224 IsCallable(const Value& v)
1226 return v.isObject() && v.toObject().isCallable();
1229 // ES6 rev 24 (2014 April 27) 7.2.5 IsConstructor
1230 inline bool
1231 IsConstructor(const Value& v)
1233 return v.isObject() && v.toObject().isConstructor();
1236 inline JSObject*
1237 GetInnerObject(JSObject* obj)
1239 if (js::InnerObjectOp op = obj->getClass()->ext.innerObject) {
1240 JS::AutoSuppressGCAnalysis nogc;
1241 return op(obj);
1243 return obj;
1246 inline JSObject*
1247 GetOuterObject(JSContext* cx, js::HandleObject obj)
1249 if (js::ObjectOp op = obj->getClass()->ext.outerObject)
1250 return op(cx, obj);
1251 return obj;
1254 } /* namespace js */
1256 class JSValueArray {
1257 public:
1258 const jsval* array;
1259 size_t length;
1261 JSValueArray(const jsval* v, size_t c) : array(v), length(c) {}
1264 class ValueArray {
1265 public:
1266 js::Value* array;
1267 size_t length;
1269 ValueArray(js::Value* v, size_t c) : array(v), length(c) {}
1272 namespace js {
1274 /* Set *resultp to tell whether obj has an own property with the given id. */
1275 bool
1276 HasOwnProperty(JSContext* cx, HandleObject obj, HandleId id, bool* resultp);
1278 template <AllowGC allowGC>
1279 extern bool
1280 HasOwnProperty(JSContext* cx, LookupGenericOp lookup,
1281 typename MaybeRooted<JSObject*, allowGC>::HandleType obj,
1282 typename MaybeRooted<jsid, allowGC>::HandleType id,
1283 typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
1284 typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp);
1286 typedef JSObject* (*ClassInitializerOp)(JSContext* cx, JS::HandleObject obj);
1288 /* Fast access to builtin constructors and prototypes. */
1289 bool
1290 GetBuiltinConstructor(ExclusiveContext* cx, JSProtoKey key, MutableHandleObject objp);
1292 bool
1293 GetBuiltinPrototype(ExclusiveContext* cx, JSProtoKey key, MutableHandleObject objp);
1295 JSObject*
1296 GetBuiltinPrototypePure(GlobalObject* global, JSProtoKey protoKey);
1298 extern bool
1299 SetClassAndProto(JSContext* cx, HandleObject obj,
1300 const Class* clasp, Handle<TaggedProto> proto, bool* succeeded);
1303 * Property-lookup-based access to interface and prototype objects for classes.
1304 * If the class is built-in (hhas a non-null JSProtoKey), these forward to
1305 * GetClass{Object,Prototype}.
1308 bool
1309 FindClassObject(ExclusiveContext* cx, MutableHandleObject protop, const Class* clasp);
1311 extern bool
1312 FindClassPrototype(ExclusiveContext* cx, MutableHandleObject protop, const Class* clasp);
1314 } /* namespace js */
1317 * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
1319 extern const char js_watch_str[];
1320 extern const char js_unwatch_str[];
1321 extern const char js_hasOwnProperty_str[];
1322 extern const char js_isPrototypeOf_str[];
1323 extern const char js_propertyIsEnumerable_str[];
1325 #ifdef JS_OLD_GETTER_SETTER_METHODS
1326 extern const char js_defineGetter_str[];
1327 extern const char js_defineSetter_str[];
1328 extern const char js_lookupGetter_str[];
1329 extern const char js_lookupSetter_str[];
1330 #endif
1332 extern bool
1333 js_PopulateObject(JSContext* cx, js::HandleObject newborn, js::HandleObject props);
1336 namespace js {
1338 extern bool
1339 DefineOwnProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
1340 JS::HandleValue descriptor, bool* bp);
1342 extern bool
1343 DefineOwnProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
1344 JS::Handle<js::PropertyDescriptor> descriptor, bool* bp);
1347 * The NewObjectKind allows an allocation site to specify the type properties
1348 * and lifetime requirements that must be fixed at allocation time.
1350 enum NewObjectKind {
1351 /* This is the default. Most objects are generic. */
1352 GenericObject,
1355 * Singleton objects are treated specially by the type system. This flag
1356 * ensures that the new object is automatically set up correctly as a
1357 * singleton and is allocated in the correct heap.
1359 SingletonObject,
1362 * Objects which may be marked as a singleton after allocation must still
1363 * be allocated on the correct heap, but are not automatically setup as a
1364 * singleton after allocation.
1366 MaybeSingletonObject,
1369 * Objects which will not benefit from being allocated in the nursery
1370 * (e.g. because they are known to have a long lifetime) may be allocated
1371 * with this kind to place them immediately into the tenured generation.
1373 TenuredObject
1376 inline gc::InitialHeap
1377 GetInitialHeap(NewObjectKind newKind, const Class* clasp)
1379 if (clasp->finalize || newKind != GenericObject)
1380 return gc::TenuredHeap;
1381 return gc::DefaultHeap;
1384 // Specialized call for constructing |this| with a known function callee,
1385 // and a known prototype.
1386 extern JSObject*
1387 CreateThisForFunctionWithProto(JSContext* cx, js::HandleObject callee, JSObject* proto,
1388 NewObjectKind newKind = GenericObject);
1390 // Specialized call for constructing |this| with a known function callee.
1391 extern JSObject*
1392 CreateThisForFunction(JSContext* cx, js::HandleObject callee, NewObjectKind newKind);
1394 // Generic call for constructing |this|.
1395 extern JSObject*
1396 CreateThis(JSContext* cx, const js::Class* clasp, js::HandleObject callee);
1398 extern JSObject*
1399 CloneObject(JSContext* cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent);
1401 extern JSObject*
1402 DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKind = GenericObject);
1405 * Return successfully added or changed shape or nullptr on error.
1407 extern bool
1408 DefineNativeProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
1409 PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
1411 extern bool
1412 LookupNativeProperty(ExclusiveContext* cx, HandleObject obj, HandleId id,
1413 js::MutableHandleObject objp, js::MutableHandleShape propp);
1416 * Call the [[DefineOwnProperty]] internal method of obj.
1418 * If obj is an array, this follows ES5 15.4.5.1.
1419 * If obj is any other native object, this follows ES5 8.12.9.
1420 * If obj is a proxy, this calls the proxy handler's defineProperty method.
1421 * Otherwise, this reports an error and returns false.
1423 extern bool
1424 DefineProperty(JSContext* cx, js::HandleObject obj,
1425 js::HandleId id, const PropDesc& desc, bool throwError,
1426 bool* rval);
1428 bool
1429 DefineProperties(JSContext* cx, HandleObject obj, HandleObject props);
1432 * Read property descriptors from props, as for Object.defineProperties. See
1433 * ES5 15.2.3.7 steps 3-5.
1435 extern bool
1436 ReadPropertyDescriptors(JSContext* cx, HandleObject props, bool checkAccessors,
1437 AutoIdVector* ids, AutoPropDescVector* descs);
1439 /* Read the name using a dynamic lookup on the scopeChain. */
1440 extern bool
1441 LookupName(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
1442 MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp);
1444 extern bool
1445 LookupNameNoGC(JSContext* cx, PropertyName* name, JSObject* scopeChain,
1446 JSObject** objp, JSObject** pobjp, Shape** propp);
1449 * Like LookupName except returns the global object if 'name' is not found in
1450 * any preceding scope.
1452 * Additionally, pobjp and propp are not needed by callers so they are not
1453 * returned.
1455 extern bool
1456 LookupNameWithGlobalDefault(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
1457 MutableHandleObject objp);
1460 * Like LookupName except returns the unqualified var object if 'name' is not found in
1461 * any preceding scope. Normally the unqualified var object is the global.
1463 * Additionally, pobjp and propp are not needed by callers so they are not
1464 * returned.
1466 extern bool
1467 LookupNameUnqualified(JSContext* cx, HandlePropertyName name, HandleObject scopeChain,
1468 MutableHandleObject objp);
1472 extern JSObject*
1473 js_FindVariableScope(JSContext* cx, JSFunction** funp);
1476 namespace js {
1478 bool
1479 NativeGet(JSContext* cx, js::Handle<JSObject*> obj, js::Handle<JSObject*> pobj,
1480 js::Handle<js::Shape*> shape, js::MutableHandle<js::Value> vp);
1482 template <js::ExecutionMode mode>
1483 bool
1484 NativeSet(typename js::ExecutionModeTraits<mode>::ContextType cx,
1485 js::Handle<JSObject*> obj, js::Handle<JSObject*> receiver,
1486 js::Handle<js::Shape*> shape, bool strict, js::MutableHandleValue vp);
1488 bool
1489 LookupPropertyPure(JSObject* obj, jsid id, JSObject** objp, Shape** propp);
1491 bool
1492 GetPropertyPure(ThreadSafeContext* cx, JSObject* obj, jsid id, Value* vp);
1494 inline bool
1495 GetPropertyPure(ThreadSafeContext* cx, JSObject* obj, PropertyName* name, Value* vp)
1497 return GetPropertyPure(cx, obj, NameToId(name), vp);
1500 bool
1501 GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
1502 MutableHandle<PropertyDescriptor> desc);
1504 bool
1505 GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp);
1507 bool
1508 NewPropertyDescriptorObject(JSContext* cx, Handle<PropertyDescriptor> desc, MutableHandleValue vp);
1511 * If obj has an already-resolved data property for id, return true and
1512 * store the property value in *vp.
1514 extern bool
1515 HasDataProperty(JSContext* cx, JSObject* obj, jsid id, Value* vp);
1517 inline bool
1518 HasDataProperty(JSContext* cx, JSObject* obj, PropertyName* name, Value* vp)
1520 return HasDataProperty(cx, obj, NameToId(name), vp);
1523 extern bool
1524 IsDelegate(JSContext* cx, HandleObject obj, const Value& v, bool* result);
1526 // obj is a JSObject*, but we root it immediately up front. We do it
1527 // that way because we need a Rooted temporary in this method anyway.
1528 extern bool
1529 IsDelegateOfObject(JSContext* cx, HandleObject protoObj, JSObject* obj, bool* result);
1531 bool
1532 GetObjectElementOperationPure(ThreadSafeContext* cx, JSObject* obj, const Value& prop, Value* vp);
1534 /* Wrap boolean, number or string as Boolean, Number or String object. */
1535 extern JSObject*
1536 PrimitiveToObject(JSContext* cx, const Value& v);
1538 } /* namespace js */
1540 namespace js {
1543 * Invokes the ES5 ToObject algorithm on vp, returning the result. If vp might
1544 * already be an object, use ToObject. reportCantConvert controls how null and
1545 * undefined errors are reported.
1547 extern JSObject*
1548 ToObjectSlow(JSContext* cx, HandleValue vp, bool reportScanStack);
1550 /* For object conversion in e.g. native functions. */
1551 MOZ_ALWAYS_INLINE JSObject*
1552 ToObject(JSContext* cx, HandleValue vp)
1554 if (vp.isObject())
1555 return &vp.toObject();
1556 return ToObjectSlow(cx, vp, false);
1559 /* For converting stack values to objects. */
1560 MOZ_ALWAYS_INLINE JSObject*
1561 ToObjectFromStack(JSContext* cx, HandleValue vp)
1563 if (vp.isObject())
1564 return &vp.toObject();
1565 return ToObjectSlow(cx, vp, true);
1568 template<XDRMode mode>
1569 bool
1570 XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj);
1572 extern JSObject*
1573 CloneObjectLiteral(JSContext* cx, HandleObject parent, HandleObject srcObj);
1575 } /* namespace js */
1577 extern void
1578 js_GetObjectSlotName(JSTracer* trc, char* buf, size_t bufsize);
1580 extern bool
1581 js_ReportGetterOnlyAssignment(JSContext* cx, bool strict);
1584 namespace js {
1586 extern JSObject*
1587 NonNullObject(JSContext* cx, const Value& v);
1589 extern const char*
1590 InformalValueTypeName(const Value& v);
1592 extern bool
1593 GetFirstArgumentAsObject(JSContext* cx, const CallArgs& args, const char* method,
1594 MutableHandleObject objp);
1596 /* Helpers for throwing. These always return false. */
1597 extern bool
1598 Throw(JSContext* cx, jsid id, unsigned errorNumber);
1600 extern bool
1601 Throw(JSContext* cx, JSObject* obj, unsigned errorNumber);
1603 } /* namespace js */
1605 #endif /* jsobj_h */