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/. */
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"
24 #include "js/HeapAPI.h"
25 #include "vm/ObjectImpl.h"
35 class AutoPropDescVector
;
37 struct NativeIterator
;
42 CastAsObject(PropertyOp op
)
44 return JS_FUNC_TO_DATA_PTR(JSObject
*, op
);
48 CastAsObject(StrictPropertyOp op
)
50 return JS_FUNC_TO_DATA_PTR(JSObject
*, op
);
54 CastAsObjectJsval(PropertyOp op
)
56 return ObjectOrNullValue(CastAsObject(op
));
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.
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
>
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
);
91 LookupElement(JSContext
*cx
, HandleObject obj
, uint32_t index
,
92 MutableHandleObject objp
, MutableHandleShape propp
);
95 DefineGeneric(ExclusiveContext
*cx
, HandleObject obj
, HandleId id
, HandleValue value
,
96 JSPropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
);
99 DefineElement(ExclusiveContext
*cx
, HandleObject obj
, uint32_t index
, HandleValue value
,
100 JSPropertyOp getter
, JSStrictPropertyOp setter
, unsigned attrs
);
103 GetProperty(JSContext
*cx
, HandleObject obj
, HandleObject receiver
, HandleId id
, MutableHandleValue vp
);
106 GetPropertyNoGC(JSContext
*cx
, JSObject
*obj
, JSObject
*receiver
, jsid id
, Value
*vp
);
109 GetElement(JSContext
*cx
, HandleObject obj
, HandleObject receiver
, uint32_t index
, MutableHandleValue vp
);
112 GetProperty(JSContext
*cx
, HandleObject obj
, HandleId id
, MutableHandleValue vp
)
114 return GetProperty(cx
, obj
, obj
, id
, vp
);
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.
135 template <ExecutionMode mode
>
137 SetPropertyHelper(typename ExecutionModeTraits
<mode
>::ContextType cx
, HandleObject obj
,
138 HandleObject receiver
, HandleId id
, QualifiedBool qualified
,
139 MutableHandleValue vp
, bool strict
);
142 SetElementHelper(JSContext
*cx
, HandleObject obj
, HandleObject Receiver
, uint32_t index
,
143 MutableHandleValue vp
, bool strict
);
146 GetAttributes(JSContext
*cx
, HandleObject obj
, HandleId id
, unsigned *attrsp
);
149 SetAttributes(JSContext
*cx
, HandleObject obj
, HandleId id
, unsigned *attrsp
);
152 DeleteGeneric(JSContext
*cx
, HandleObject obj
, HandleId id
, bool *succeeded
);
155 Watch(JSContext
*cx
, JS::HandleObject obj
, JS::HandleId id
, JS::HandleObject callable
);
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
;
168 class NewObjectCache
;
169 class NormalArgumentsObject
;
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
180 DenseRangeWriteBarrierPost(JSRuntime
*rt
, JSObject
*obj
, uint32_t start
, uint32_t count
)
182 #ifdef JSGC_GENERATIONAL
184 JS::shadow::Runtime
*shadowRuntime
= JS::shadow::Runtime::asShadowRuntime(rt
);
185 shadowRuntime
->gcStoreBufferPtr()->putSlotFromAnyThread(obj
, HeapSlot::Element
, start
, count
);
191 class ForkJoinNursery
;
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
206 class JSObject
: public js::ObjectImpl
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
);
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
,
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
);
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
);
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);
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
);
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;
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
,
386 static void shrinkSlots(js::ThreadSafeContext
*cx
, js::HandleObject obj
, uint32_t oldCount
,
389 bool hasDynamicSlots() const { return !!slots
; }
392 static inline bool updateSlotsForSpan(js::ThreadSafeContext
*cx
,
393 js::HandleObject obj
, size_t oldSpan
, size_t newSpan
);
397 * Trigger the write barrier on a range of slots that will no longer be
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
,
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()));
446 void setReservedSlot(uint32_t index
, const js::Value
&v
) {
447 JS_ASSERT(index
< JSSLOT_FREE(getClass()));
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. */
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
);
494 bool hasNewType(const js::Class
*clasp
, js::types::TypeObject
*newType
);
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
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
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
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.
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
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
);
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
);
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);
646 inline void ensureDenseInitializedLengthNoPackedCheck(js::ThreadSafeContext
*cx
,
647 uint32_t index
, uint32_t extra
);
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()));
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
]);
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
);
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
);
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
};
790 inline EnsureDenseResult
ensureDenseElementsNoPackedCheck(js::ThreadSafeContext
*cx
,
791 uint32_t index
, uint32_t extra
);
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
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
828 static EnsureDenseResult
maybeDensifySparseElements(js::ExclusiveContext
*cx
, js::HandleObject obj
);
832 * Iterator-specific getters and setters.
835 static const uint32_t ITER_CLASS_NFIXED_SLOTS
= 1;
838 * Back to generic stuff.
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
);
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
);
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
);
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
);
901 * Internal helper that adds a shape not yet mapped by this object.
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
>
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
);
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
);
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
>
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
,
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
,
952 /* Change the given property into a sibling with the same id in this scope. */
953 template <js::ExecutionMode mode
>
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
;
1009 if (!op(cx
, obj
, receiver
, id
, vp
))
1012 if (!js::baseops::GetProperty(cx
, obj
, receiver
, id
, vp
))
1018 static bool getGenericNoGC(JSContext
*cx
, JSObject
*obj
, JSObject
*receiver
,
1019 jsid id
, js::Value
*vp
)
1021 js::GenericIdOp op
= obj
->getOps()->getGeneric
;
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
,
1087 static inline bool deleteElement(JSContext
*cx
, js::HandleObject obj
, uint32_t index
,
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
;
1106 if (op
== JS_ConvertStub
)
1107 ok
= js::DefaultValue(cx
, obj
, hint
, vp
);
1109 ok
= op(cx
, obj
, hint
, vp
);
1110 JS_ASSERT_IF(ok
, vp
.isPrimitive());
1114 static JSObject
*thisObject(JSContext
*cx
, js::HandleObject obj
)
1116 if (js::ObjectOp op
= obj
->getOps()->thisObject
)
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>();
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).
1151 inline bool is() const { return getClass() == &T::class_
; }
1156 return *static_cast<T
*>(this);
1160 const T
&as() const {
1162 return *static_cast<const T
*>(this);
1165 static inline js::ThingRootKind
rootKind() { return js::THING_ROOT_OBJECT
; }
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
;
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]; };
1224 IsCallable(const Value
&v
)
1226 return v
.isObject() && v
.toObject().isCallable();
1229 // ES6 rev 24 (2014 April 27) 7.2.5 IsConstructor
1231 IsConstructor(const Value
&v
)
1233 return v
.isObject() && v
.toObject().isConstructor();
1237 GetInnerObject(JSObject
*obj
)
1239 if (js::InnerObjectOp op
= obj
->getClass()->ext
.innerObject
) {
1240 JS::AutoSuppressGCAnalysis nogc
;
1247 GetOuterObject(JSContext
*cx
, js::HandleObject obj
)
1249 if (js::ObjectOp op
= obj
->getClass()->ext
.outerObject
)
1254 } /* namespace js */
1256 class JSValueArray
{
1261 JSValueArray(const jsval
*v
, size_t c
) : array(v
), length(c
) {}
1269 ValueArray(js::Value
*v
, size_t c
) : array(v
), length(c
) {}
1274 /* Set *resultp to tell whether obj has an own property with the given id. */
1276 HasOwnProperty(JSContext
*cx
, HandleObject obj
, HandleId id
, bool *resultp
);
1278 template <AllowGC allowGC
>
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. */
1290 GetBuiltinConstructor(ExclusiveContext
*cx
, JSProtoKey key
, MutableHandleObject objp
);
1293 GetBuiltinPrototype(ExclusiveContext
*cx
, JSProtoKey key
, MutableHandleObject objp
);
1296 GetBuiltinPrototypePure(GlobalObject
*global
, JSProtoKey protoKey
);
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}.
1309 FindClassObject(ExclusiveContext
*cx
, MutableHandleObject protop
, const Class
*clasp
);
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
[];
1333 js_PopulateObject(JSContext
*cx
, js::HandleObject newborn
, js::HandleObject props
);
1339 DefineOwnProperty(JSContext
*cx
, JS::HandleObject obj
, JS::HandleId id
,
1340 JS::HandleValue descriptor
, bool *bp
);
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. */
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.
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.
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.
1387 CreateThisForFunctionWithProto(JSContext
*cx
, js::HandleObject callee
, JSObject
*proto
,
1388 NewObjectKind newKind
= GenericObject
);
1390 // Specialized call for constructing |this| with a known function callee.
1392 CreateThisForFunction(JSContext
*cx
, js::HandleObject callee
, NewObjectKind newKind
);
1394 // Generic call for constructing |this|.
1396 CreateThis(JSContext
*cx
, const js::Class
*clasp
, js::HandleObject callee
);
1399 CloneObject(JSContext
*cx
, HandleObject obj
, Handle
<js::TaggedProto
> proto
, HandleObject parent
);
1402 DeepCloneObjectLiteral(JSContext
*cx
, HandleObject obj
, NewObjectKind newKind
= GenericObject
);
1405 * Return successfully added or changed shape or nullptr on error.
1408 DefineNativeProperty(ExclusiveContext
*cx
, HandleObject obj
, HandleId id
, HandleValue value
,
1409 PropertyOp getter
, StrictPropertyOp setter
, unsigned attrs
);
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.
1424 DefineProperty(JSContext
*cx
, js::HandleObject obj
,
1425 js::HandleId id
, const PropDesc
&desc
, bool throwError
,
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.
1436 ReadPropertyDescriptors(JSContext
*cx
, HandleObject props
, bool checkAccessors
,
1437 AutoIdVector
*ids
, AutoPropDescVector
*descs
);
1439 /* Read the name using a dynamic lookup on the scopeChain. */
1441 LookupName(JSContext
*cx
, HandlePropertyName name
, HandleObject scopeChain
,
1442 MutableHandleObject objp
, MutableHandleObject pobjp
, MutableHandleShape propp
);
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
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
1467 LookupNameUnqualified(JSContext
*cx
, HandlePropertyName name
, HandleObject scopeChain
,
1468 MutableHandleObject objp
);
1473 js_FindVariableScope(JSContext
*cx
, JSFunction
**funp
);
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
>
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
);
1489 LookupPropertyPure(JSObject
*obj
, jsid id
, JSObject
**objp
, Shape
**propp
);
1492 GetPropertyPure(ThreadSafeContext
*cx
, JSObject
*obj
, jsid id
, Value
*vp
);
1495 GetPropertyPure(ThreadSafeContext
*cx
, JSObject
*obj
, PropertyName
*name
, Value
*vp
)
1497 return GetPropertyPure(cx
, obj
, NameToId(name
), vp
);
1501 GetOwnPropertyDescriptor(JSContext
*cx
, HandleObject obj
, HandleId id
,
1502 MutableHandle
<PropertyDescriptor
> desc
);
1505 GetOwnPropertyDescriptor(JSContext
*cx
, HandleObject obj
, HandleId id
, MutableHandleValue vp
);
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.
1515 HasDataProperty(JSContext
*cx
, JSObject
*obj
, jsid id
, Value
*vp
);
1518 HasDataProperty(JSContext
*cx
, JSObject
*obj
, PropertyName
*name
, Value
*vp
)
1520 return HasDataProperty(cx
, obj
, NameToId(name
), vp
);
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.
1529 IsDelegateOfObject(JSContext
*cx
, HandleObject protoObj
, JSObject
* obj
, bool *result
);
1532 GetObjectElementOperationPure(ThreadSafeContext
*cx
, JSObject
*obj
, const Value
&prop
, Value
*vp
);
1534 /* Wrap boolean, number or string as Boolean, Number or String object. */
1536 PrimitiveToObject(JSContext
*cx
, const Value
&v
);
1538 } /* 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.
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
)
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
)
1564 return &vp
.toObject();
1565 return ToObjectSlow(cx
, vp
, true);
1568 template<XDRMode mode
>
1570 XDRObjectLiteral(XDRState
<mode
> *xdr
, MutableHandleObject obj
);
1573 CloneObjectLiteral(JSContext
*cx
, HandleObject parent
, HandleObject srcObj
);
1575 } /* namespace js */
1578 js_GetObjectSlotName(JSTracer
*trc
, char *buf
, size_t bufsize
);
1581 js_ReportGetterOnlyAssignment(JSContext
*cx
, bool strict
);
1587 NonNullObject(JSContext
*cx
, const Value
&v
);
1590 InformalValueTypeName(const Value
&v
);
1593 GetFirstArgumentAsObject(JSContext
*cx
, const CallArgs
&args
, const char *method
,
1594 MutableHandleObject objp
);
1596 /* Helpers for throwing. These always return false. */
1598 Throw(JSContext
*cx
, jsid id
, unsigned errorNumber
);
1601 Throw(JSContext
*cx
, JSObject
*obj
, unsigned errorNumber
);
1603 } /* namespace js */
1605 #endif /* jsobj_h */