1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jsobj.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1559 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jsobj_h 1.11 +#define jsobj_h 1.12 + 1.13 +/* 1.14 + * JS object definitions. 1.15 + * 1.16 + * A JS object consists of a possibly-shared object descriptor containing 1.17 + * ordered property names, called the map; and a dense vector of property 1.18 + * values, called slots. The map/slot pointer pair is GC'ed, while the map 1.19 + * is reference counted and the slot vector is malloc'ed. 1.20 + */ 1.21 + 1.22 +#include "mozilla/MemoryReporting.h" 1.23 + 1.24 +#include "gc/Barrier.h" 1.25 +#include "gc/Marking.h" 1.26 +#include "js/GCAPI.h" 1.27 +#include "vm/ObjectImpl.h" 1.28 +#include "vm/Shape.h" 1.29 +#include "vm/Xdr.h" 1.30 + 1.31 +namespace JS { 1.32 +struct ObjectsExtraSizes; 1.33 +} 1.34 + 1.35 +namespace js { 1.36 + 1.37 +class AutoPropDescArrayRooter; 1.38 +struct GCMarker; 1.39 +struct NativeIterator; 1.40 +class Nursery; 1.41 +struct StackShape; 1.42 + 1.43 +inline JSObject * 1.44 +CastAsObject(PropertyOp op) 1.45 +{ 1.46 + return JS_FUNC_TO_DATA_PTR(JSObject *, op); 1.47 +} 1.48 + 1.49 +inline JSObject * 1.50 +CastAsObject(StrictPropertyOp op) 1.51 +{ 1.52 + return JS_FUNC_TO_DATA_PTR(JSObject *, op); 1.53 +} 1.54 + 1.55 +inline Value 1.56 +CastAsObjectJsval(PropertyOp op) 1.57 +{ 1.58 + return ObjectOrNullValue(CastAsObject(op)); 1.59 +} 1.60 + 1.61 +inline Value 1.62 +CastAsObjectJsval(StrictPropertyOp op) 1.63 +{ 1.64 + return ObjectOrNullValue(CastAsObject(op)); 1.65 +} 1.66 + 1.67 +/******************************************************************************/ 1.68 + 1.69 +typedef Vector<PropDesc, 1> PropDescArray; 1.70 + 1.71 +/* 1.72 + * The baseops namespace encapsulates the default behavior when performing 1.73 + * various operations on an object, irrespective of hooks installed in the 1.74 + * object's class. In general, instance methods on the object itself should be 1.75 + * called instead of calling these methods directly. 1.76 + */ 1.77 +namespace baseops { 1.78 + 1.79 +/* 1.80 + * On success, and if id was found, return true with *objp non-null and with a 1.81 + * property of *objp stored in *propp. If successful but id was not found, 1.82 + * return true with both *objp and *propp null. 1.83 + */ 1.84 +template <AllowGC allowGC> 1.85 +extern bool 1.86 +LookupProperty(ExclusiveContext *cx, 1.87 + typename MaybeRooted<JSObject*, allowGC>::HandleType obj, 1.88 + typename MaybeRooted<jsid, allowGC>::HandleType id, 1.89 + typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp, 1.90 + typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp); 1.91 + 1.92 +extern bool 1.93 +LookupElement(JSContext *cx, HandleObject obj, uint32_t index, 1.94 + MutableHandleObject objp, MutableHandleShape propp); 1.95 + 1.96 +extern bool 1.97 +DefineGeneric(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value, 1.98 + JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); 1.99 + 1.100 +extern bool 1.101 +DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value, 1.102 + JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs); 1.103 + 1.104 +extern bool 1.105 +GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id, MutableHandleValue vp); 1.106 + 1.107 +extern bool 1.108 +GetPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp); 1.109 + 1.110 +extern bool 1.111 +GetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index, MutableHandleValue vp); 1.112 + 1.113 +inline bool 1.114 +GetProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp) 1.115 +{ 1.116 + return GetProperty(cx, obj, obj, id, vp); 1.117 +} 1.118 + 1.119 +inline bool 1.120 +GetElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp) 1.121 +{ 1.122 + return GetElement(cx, obj, obj, index, vp); 1.123 +} 1.124 + 1.125 +/* 1.126 + * Indicates whether an assignment operation is qualified (`x.y = 0`) or 1.127 + * unqualified (`y = 0`). In strict mode, the latter is an error if no such 1.128 + * variable already exists. 1.129 + * 1.130 + * Used as an argument to baseops::SetPropertyHelper. 1.131 + */ 1.132 +enum QualifiedBool { 1.133 + Unqualified = 0, 1.134 + Qualified = 1 1.135 +}; 1.136 + 1.137 +template <ExecutionMode mode> 1.138 +extern bool 1.139 +SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cx, HandleObject obj, 1.140 + HandleObject receiver, HandleId id, QualifiedBool qualified, 1.141 + MutableHandleValue vp, bool strict); 1.142 + 1.143 +extern bool 1.144 +SetElementHelper(JSContext *cx, HandleObject obj, HandleObject Receiver, uint32_t index, 1.145 + MutableHandleValue vp, bool strict); 1.146 + 1.147 +extern bool 1.148 +GetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); 1.149 + 1.150 +extern bool 1.151 +SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *attrsp); 1.152 + 1.153 +extern bool 1.154 +DeleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, bool *succeeded); 1.155 + 1.156 +extern bool 1.157 +DeleteElement(JSContext *cx, HandleObject obj, uint32_t index, bool *succeeded); 1.158 + 1.159 +extern bool 1.160 +DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded); 1.161 + 1.162 +extern bool 1.163 +Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable); 1.164 + 1.165 +extern bool 1.166 +Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id); 1.167 + 1.168 +} /* namespace js::baseops */ 1.169 + 1.170 +extern const Class IntlClass; 1.171 +extern const Class JSONClass; 1.172 +extern const Class MathClass; 1.173 + 1.174 +class GlobalObject; 1.175 +class MapObject; 1.176 +class NewObjectCache; 1.177 +class NormalArgumentsObject; 1.178 +class SetObject; 1.179 +class StrictArgumentsObject; 1.180 + 1.181 +/* 1.182 + * NOTE: This is a placeholder for bug 619558. 1.183 + * 1.184 + * Run a post write barrier that encompasses multiple contiguous slots in a 1.185 + * single step. 1.186 + */ 1.187 +inline void 1.188 +DenseRangeWriteBarrierPost(JSRuntime *rt, JSObject *obj, uint32_t start, uint32_t count) 1.189 +{ 1.190 +#ifdef JSGC_GENERATIONAL 1.191 + if (count > 0) { 1.192 + JS::shadow::Runtime *shadowRuntime = JS::shadow::Runtime::asShadowRuntime(rt); 1.193 + shadowRuntime->gcStoreBufferPtr()->putSlot(obj, HeapSlot::Element, start, count); 1.194 + } 1.195 +#endif 1.196 +} 1.197 + 1.198 +} /* namespace js */ 1.199 + 1.200 +/* 1.201 + * The public interface for an object. 1.202 + * 1.203 + * Implementation of the underlying structure occurs in ObjectImpl, from which 1.204 + * this struct inherits. This inheritance is currently public, but it will 1.205 + * eventually be made protected. For full details, see vm/ObjectImpl.{h,cpp}. 1.206 + * 1.207 + * The JSFunction struct is an extension of this struct allocated from a larger 1.208 + * GC size-class. 1.209 + */ 1.210 +class JSObject : public js::ObjectImpl 1.211 +{ 1.212 + private: 1.213 + friend class js::Shape; 1.214 + friend struct js::GCMarker; 1.215 + friend class js::NewObjectCache; 1.216 + friend class js::Nursery; 1.217 + 1.218 + /* Make the type object to use for LAZY_TYPE objects. */ 1.219 + static js::types::TypeObject *makeLazyType(JSContext *cx, js::HandleObject obj); 1.220 + 1.221 + public: 1.222 + static const js::Class class_; 1.223 + 1.224 + /* 1.225 + * Update the last property, keeping the number of allocated slots in sync 1.226 + * with the object's new slot span. 1.227 + */ 1.228 + static bool setLastProperty(js::ThreadSafeContext *cx, 1.229 + JS::HandleObject obj, js::HandleShape shape); 1.230 + 1.231 + /* As above, but does not change the slot span. */ 1.232 + inline void setLastPropertyInfallible(js::Shape *shape); 1.233 + 1.234 + /* 1.235 + * Make a non-array object with the specified initial state. This method 1.236 + * takes ownership of any extantSlots it is passed. 1.237 + */ 1.238 + static inline JSObject *create(js::ExclusiveContext *cx, 1.239 + js::gc::AllocKind kind, 1.240 + js::gc::InitialHeap heap, 1.241 + js::HandleShape shape, 1.242 + js::HandleTypeObject type, 1.243 + js::HeapSlot *extantSlots = nullptr); 1.244 + 1.245 + /* Make an array object with the specified initial state. */ 1.246 + static inline js::ArrayObject *createArray(js::ExclusiveContext *cx, 1.247 + js::gc::AllocKind kind, 1.248 + js::gc::InitialHeap heap, 1.249 + js::HandleShape shape, 1.250 + js::HandleTypeObject type, 1.251 + uint32_t length); 1.252 + 1.253 + /* 1.254 + * Remove the last property of an object, provided that it is safe to do so 1.255 + * (the shape and previous shape do not carry conflicting information about 1.256 + * the object itself). 1.257 + */ 1.258 + inline void removeLastProperty(js::ExclusiveContext *cx); 1.259 + inline bool canRemoveLastProperty(); 1.260 + 1.261 + /* 1.262 + * Update the slot span directly for a dictionary object, and allocate 1.263 + * slots to cover the new span if necessary. 1.264 + */ 1.265 + static bool setSlotSpan(js::ThreadSafeContext *cx, JS::HandleObject obj, uint32_t span); 1.266 + 1.267 + /* Upper bound on the number of elements in an object. */ 1.268 + static const uint32_t NELEMENTS_LIMIT = JS_BIT(28); 1.269 + 1.270 + public: 1.271 + bool setDelegate(js::ExclusiveContext *cx) { 1.272 + return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE); 1.273 + } 1.274 + 1.275 + bool isBoundFunction() const { 1.276 + return lastProperty()->hasObjectFlag(js::BaseShape::BOUND_FUNCTION); 1.277 + } 1.278 + 1.279 + inline bool hasSpecialEquality() const; 1.280 + 1.281 + bool watched() const { 1.282 + return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED); 1.283 + } 1.284 + bool setWatched(js::ExclusiveContext *cx) { 1.285 + return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE); 1.286 + } 1.287 + 1.288 + /* See InterpreterFrame::varObj. */ 1.289 + inline bool isVarObj(); 1.290 + bool setVarObj(js::ExclusiveContext *cx) { 1.291 + return setFlag(cx, js::BaseShape::VAROBJ); 1.292 + } 1.293 + 1.294 + /* 1.295 + * Objects with an uncacheable proto can have their prototype mutated 1.296 + * without inducing a shape change on the object. Property cache entries 1.297 + * and JIT inline caches should not be filled for lookups across prototype 1.298 + * lookups on the object. 1.299 + */ 1.300 + bool hasUncacheableProto() const { 1.301 + return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO); 1.302 + } 1.303 + bool setUncacheableProto(js::ExclusiveContext *cx) { 1.304 + return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE); 1.305 + } 1.306 + 1.307 + /* 1.308 + * Whether SETLELEM was used to access this object. See also the comment near 1.309 + * PropertyTree::MAX_HEIGHT. 1.310 + */ 1.311 + bool hadElementsAccess() const { 1.312 + return lastProperty()->hasObjectFlag(js::BaseShape::HAD_ELEMENTS_ACCESS); 1.313 + } 1.314 + bool setHadElementsAccess(js::ExclusiveContext *cx) { 1.315 + return setFlag(cx, js::BaseShape::HAD_ELEMENTS_ACCESS); 1.316 + } 1.317 + 1.318 + public: 1.319 + bool nativeEmpty() const { 1.320 + return lastProperty()->isEmptyShape(); 1.321 + } 1.322 + 1.323 + bool shadowingShapeChange(js::ExclusiveContext *cx, const js::Shape &shape); 1.324 + 1.325 + /* 1.326 + * Whether there may be indexed properties on this object, excluding any in 1.327 + * the object's elements. 1.328 + */ 1.329 + bool isIndexed() const { 1.330 + return lastProperty()->hasObjectFlag(js::BaseShape::INDEXED); 1.331 + } 1.332 + 1.333 + uint32_t propertyCount() const { 1.334 + return lastProperty()->entryCount(); 1.335 + } 1.336 + 1.337 + bool hasShapeTable() const { 1.338 + return lastProperty()->hasTable(); 1.339 + } 1.340 + 1.341 + void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ObjectsExtraSizes *sizes); 1.342 + 1.343 + bool hasIdempotentProtoChain() const; 1.344 + 1.345 + // MAX_FIXED_SLOTS is the biggest number of fixed slots our GC 1.346 + // size classes will give an object. 1.347 + static const uint32_t MAX_FIXED_SLOTS = 16; 1.348 + 1.349 + public: 1.350 + 1.351 + /* Accessors for properties. */ 1.352 + 1.353 + /* Whether a slot is at a fixed offset from this object. */ 1.354 + bool isFixedSlot(size_t slot) { 1.355 + return slot < numFixedSlots(); 1.356 + } 1.357 + 1.358 + /* Index into the dynamic slots array to use for a dynamic slot. */ 1.359 + size_t dynamicSlotIndex(size_t slot) { 1.360 + JS_ASSERT(slot >= numFixedSlots()); 1.361 + return slot - numFixedSlots(); 1.362 + } 1.363 + 1.364 + /* 1.365 + * Grow or shrink slots immediately before changing the slot span. 1.366 + * The number of allocated slots is not stored explicitly, and changes to 1.367 + * the slots must track changes in the slot span. 1.368 + */ 1.369 + static bool growSlots(js::ThreadSafeContext *cx, js::HandleObject obj, uint32_t oldCount, 1.370 + uint32_t newCount); 1.371 + static void shrinkSlots(js::ThreadSafeContext *cx, js::HandleObject obj, uint32_t oldCount, 1.372 + uint32_t newCount); 1.373 + 1.374 + bool hasDynamicSlots() const { return !!slots; } 1.375 + 1.376 + protected: 1.377 + static inline bool updateSlotsForSpan(js::ThreadSafeContext *cx, 1.378 + js::HandleObject obj, size_t oldSpan, size_t newSpan); 1.379 + 1.380 + public: 1.381 + /* 1.382 + * Trigger the write barrier on a range of slots that will no longer be 1.383 + * reachable. 1.384 + */ 1.385 + void prepareSlotRangeForOverwrite(size_t start, size_t end) { 1.386 + for (size_t i = start; i < end; i++) 1.387 + getSlotAddressUnchecked(i)->js::HeapSlot::~HeapSlot(); 1.388 + } 1.389 + 1.390 + void prepareElementRangeForOverwrite(size_t start, size_t end) { 1.391 + JS_ASSERT(end <= getDenseInitializedLength()); 1.392 + for (size_t i = start; i < end; i++) 1.393 + elements[i].js::HeapSlot::~HeapSlot(); 1.394 + } 1.395 + 1.396 + static bool rollbackProperties(js::ExclusiveContext *cx, js::HandleObject obj, 1.397 + uint32_t slotSpan); 1.398 + 1.399 + void nativeSetSlot(uint32_t slot, const js::Value &value) { 1.400 + JS_ASSERT(isNative()); 1.401 + JS_ASSERT(slot < slotSpan()); 1.402 + return setSlot(slot, value); 1.403 + } 1.404 + 1.405 + inline bool nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value); 1.406 + inline void nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape, 1.407 + const js::Value &value); 1.408 + 1.409 + inline const js::Value &getReservedSlot(uint32_t index) const { 1.410 + JS_ASSERT(index < JSSLOT_FREE(getClass())); 1.411 + return getSlot(index); 1.412 + } 1.413 + 1.414 + const js::HeapSlot &getReservedSlotRef(uint32_t index) const { 1.415 + JS_ASSERT(index < JSSLOT_FREE(getClass())); 1.416 + return getSlotRef(index); 1.417 + } 1.418 + 1.419 + js::HeapSlot &getReservedSlotRef(uint32_t index) { 1.420 + JS_ASSERT(index < JSSLOT_FREE(getClass())); 1.421 + return getSlotRef(index); 1.422 + } 1.423 + 1.424 + void initReservedSlot(uint32_t index, const js::Value &v) { 1.425 + JS_ASSERT(index < JSSLOT_FREE(getClass())); 1.426 + initSlot(index, v); 1.427 + } 1.428 + 1.429 + void setReservedSlot(uint32_t index, const js::Value &v) { 1.430 + JS_ASSERT(index < JSSLOT_FREE(getClass())); 1.431 + setSlot(index, v); 1.432 + } 1.433 + 1.434 + /* 1.435 + * Marks this object as having a singleton type, and leave the type lazy. 1.436 + * Constructs a new, unique shape for the object. 1.437 + */ 1.438 + static inline bool setSingletonType(js::ExclusiveContext *cx, js::HandleObject obj); 1.439 + 1.440 + // uninlinedGetType() is the same as getType(), but not inlined. 1.441 + inline js::types::TypeObject* getType(JSContext *cx); 1.442 + js::types::TypeObject* uninlinedGetType(JSContext *cx); 1.443 + 1.444 + const js::HeapPtr<js::types::TypeObject> &typeFromGC() const { 1.445 + /* Direct field access for use by GC. */ 1.446 + return type_; 1.447 + } 1.448 + 1.449 + /* 1.450 + * We allow the prototype of an object to be lazily computed if the object 1.451 + * is a proxy. In the lazy case, we store (JSObject *)0x1 in the proto field 1.452 + * of the object's TypeObject. We offer three ways of getting the prototype: 1.453 + * 1.454 + * 1. obj->getProto() returns the prototype, but asserts if obj is a proxy. 1.455 + * 2. obj->getTaggedProto() returns a TaggedProto, which can be tested to 1.456 + * check if the proto is an object, nullptr, or lazily computed. 1.457 + * 3. JSObject::getProto(cx, obj, &proto) computes the proto of an object. 1.458 + * If obj is a proxy and the proto is lazy, this code may allocate or 1.459 + * GC in order to compute the proto. Currently, it will not run JS code. 1.460 + */ 1.461 + bool uninlinedIsProxy() const; 1.462 + JSObject *getProto() const { 1.463 + JS_ASSERT(!uninlinedIsProxy()); 1.464 + return getTaggedProto().toObjectOrNull(); 1.465 + } 1.466 + static inline bool getProto(JSContext *cx, js::HandleObject obj, 1.467 + js::MutableHandleObject protop); 1.468 + // Returns false on error, success of operation in outparam. 1.469 + static inline bool setProto(JSContext *cx, JS::HandleObject obj, 1.470 + JS::HandleObject proto, bool *succeeded); 1.471 + 1.472 + // uninlinedSetType() is the same as setType(), but not inlined. 1.473 + inline void setType(js::types::TypeObject *newType); 1.474 + void uninlinedSetType(js::types::TypeObject *newType); 1.475 + 1.476 +#ifdef DEBUG 1.477 + bool hasNewType(const js::Class *clasp, js::types::TypeObject *newType); 1.478 +#endif 1.479 + 1.480 + /* 1.481 + * Mark an object that has been iterated over and is a singleton. We need 1.482 + * to recover this information in the object's type information after it 1.483 + * is purged on GC. 1.484 + */ 1.485 + bool isIteratedSingleton() const { 1.486 + return lastProperty()->hasObjectFlag(js::BaseShape::ITERATED_SINGLETON); 1.487 + } 1.488 + bool setIteratedSingleton(js::ExclusiveContext *cx) { 1.489 + return setFlag(cx, js::BaseShape::ITERATED_SINGLETON); 1.490 + } 1.491 + 1.492 + /* 1.493 + * Mark an object as requiring its default 'new' type to have unknown 1.494 + * properties. 1.495 + */ 1.496 + bool isNewTypeUnknown() const { 1.497 + return lastProperty()->hasObjectFlag(js::BaseShape::NEW_TYPE_UNKNOWN); 1.498 + } 1.499 + static bool setNewTypeUnknown(JSContext *cx, const js::Class *clasp, JS::HandleObject obj); 1.500 + 1.501 + /* Set a new prototype for an object with a singleton type. */ 1.502 + bool splicePrototype(JSContext *cx, const js::Class *clasp, js::Handle<js::TaggedProto> proto); 1.503 + 1.504 + /* 1.505 + * For bootstrapping, whether to splice a prototype for Function.prototype 1.506 + * or the global object. 1.507 + */ 1.508 + bool shouldSplicePrototype(JSContext *cx); 1.509 + 1.510 + /* 1.511 + * Parents and scope chains. 1.512 + * 1.513 + * All script-accessible objects with a nullptr parent are global objects, 1.514 + * and all global objects have a nullptr parent. Some builtin objects 1.515 + * which are not script-accessible also have a nullptr parent, such as 1.516 + * parser created functions for non-compileAndGo scripts. 1.517 + * 1.518 + * Except for the non-script-accessible builtins, the global with which an 1.519 + * object is associated can be reached by following parent links to that 1.520 + * global (see global()). 1.521 + * 1.522 + * The scope chain of an object is the link in the search path when a 1.523 + * script does a name lookup on a scope object. For JS internal scope 1.524 + * objects --- Call, DeclEnv and Block --- the chain is stored in 1.525 + * the first fixed slot of the object, and the object's parent is the 1.526 + * associated global. For other scope objects, the chain is stored in the 1.527 + * object's parent. 1.528 + * 1.529 + * In compileAndGo code, scope chains can contain only internal scope 1.530 + * objects with a global object at the root as the scope of the outermost 1.531 + * non-function script. In non-compileAndGo code, the scope of the 1.532 + * outermost non-function script might not be a global object, and can have 1.533 + * a mix of other objects above it before the global object is reached. 1.534 + */ 1.535 + 1.536 + /* Access the parent link of an object. */ 1.537 + JSObject *getParent() const { 1.538 + return lastProperty()->getObjectParent(); 1.539 + } 1.540 + static bool setParent(JSContext *cx, js::HandleObject obj, js::HandleObject newParent); 1.541 + 1.542 + /* 1.543 + * Get the enclosing scope of an object. When called on non-scope object, 1.544 + * this will just be the global (the name "enclosing scope" still applies 1.545 + * in this situation because non-scope objects can be on the scope chain). 1.546 + */ 1.547 + inline JSObject *enclosingScope(); 1.548 + 1.549 + /* Access the metadata on an object. */ 1.550 + inline JSObject *getMetadata() const { 1.551 + return lastProperty()->getObjectMetadata(); 1.552 + } 1.553 + static bool setMetadata(JSContext *cx, js::HandleObject obj, js::HandleObject newMetadata); 1.554 + 1.555 + inline js::GlobalObject &global() const; 1.556 + inline bool isOwnGlobal() const; 1.557 + 1.558 + /* Remove the type (and prototype) or parent from a new object. */ 1.559 + static inline bool clearType(JSContext *cx, js::HandleObject obj); 1.560 + static bool clearParent(JSContext *cx, js::HandleObject obj); 1.561 + 1.562 + /* 1.563 + * ES5 meta-object properties and operations. 1.564 + */ 1.565 + 1.566 + private: 1.567 + enum ImmutabilityType { SEAL, FREEZE }; 1.568 + 1.569 + /* 1.570 + * The guts of Object.seal (ES5 15.2.3.8) and Object.freeze (ES5 15.2.3.9): mark the 1.571 + * object as non-extensible, and adjust each property's attributes appropriately: each 1.572 + * property becomes non-configurable, and if |freeze|, data properties become 1.573 + * read-only as well. 1.574 + */ 1.575 + static bool sealOrFreeze(JSContext *cx, js::HandleObject obj, ImmutabilityType it); 1.576 + 1.577 + static bool isSealedOrFrozen(JSContext *cx, js::HandleObject obj, ImmutabilityType it, bool *resultp); 1.578 + 1.579 + static inline unsigned getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it); 1.580 + 1.581 + public: 1.582 + /* ES5 15.2.3.8: non-extensible, all props non-configurable */ 1.583 + static inline bool seal(JSContext *cx, js::HandleObject obj) { return sealOrFreeze(cx, obj, SEAL); } 1.584 + /* ES5 15.2.3.9: non-extensible, all properties non-configurable, all data props read-only */ 1.585 + static inline bool freeze(JSContext *cx, js::HandleObject obj) { return sealOrFreeze(cx, obj, FREEZE); } 1.586 + 1.587 + static inline bool isSealed(JSContext *cx, js::HandleObject obj, bool *resultp) { 1.588 + return isSealedOrFrozen(cx, obj, SEAL, resultp); 1.589 + } 1.590 + static inline bool isFrozen(JSContext *cx, js::HandleObject obj, bool *resultp) { 1.591 + return isSealedOrFrozen(cx, obj, FREEZE, resultp); 1.592 + } 1.593 + 1.594 + /* toString support. */ 1.595 + static const char *className(JSContext *cx, js::HandleObject obj); 1.596 + 1.597 + /* Accessors for elements. */ 1.598 + bool ensureElements(js::ThreadSafeContext *cx, uint32_t capacity) { 1.599 + if (capacity > getDenseCapacity()) 1.600 + return growElements(cx, capacity); 1.601 + return true; 1.602 + } 1.603 + 1.604 + bool growElements(js::ThreadSafeContext *cx, uint32_t newcap); 1.605 + void shrinkElements(js::ThreadSafeContext *cx, uint32_t cap); 1.606 + void setDynamicElements(js::ObjectElements *header) { 1.607 + JS_ASSERT(!hasDynamicElements()); 1.608 + elements = header->elements(); 1.609 + JS_ASSERT(hasDynamicElements()); 1.610 + } 1.611 + 1.612 + uint32_t getDenseCapacity() { 1.613 + JS_ASSERT(isNative()); 1.614 + JS_ASSERT(getElementsHeader()->capacity >= getElementsHeader()->initializedLength); 1.615 + return getElementsHeader()->capacity; 1.616 + } 1.617 + 1.618 + private: 1.619 + inline void ensureDenseInitializedLengthNoPackedCheck(js::ThreadSafeContext *cx, 1.620 + uint32_t index, uint32_t extra); 1.621 + 1.622 + public: 1.623 + void setDenseInitializedLength(uint32_t length) { 1.624 + JS_ASSERT(isNative()); 1.625 + JS_ASSERT(length <= getDenseCapacity()); 1.626 + prepareElementRangeForOverwrite(length, getElementsHeader()->initializedLength); 1.627 + getElementsHeader()->initializedLength = length; 1.628 + } 1.629 + 1.630 + inline void ensureDenseInitializedLength(js::ExclusiveContext *cx, 1.631 + uint32_t index, uint32_t extra); 1.632 + inline void ensureDenseInitializedLengthPreservePackedFlag(js::ThreadSafeContext *cx, 1.633 + uint32_t index, uint32_t extra); 1.634 + void setDenseElement(uint32_t index, const js::Value &val) { 1.635 + JS_ASSERT(isNative() && index < getDenseInitializedLength()); 1.636 + elements[index].set(this, js::HeapSlot::Element, index, val); 1.637 + } 1.638 + 1.639 + void initDenseElement(uint32_t index, const js::Value &val) { 1.640 + JS_ASSERT(isNative() && index < getDenseInitializedLength()); 1.641 + elements[index].init(this, js::HeapSlot::Element, index, val); 1.642 + } 1.643 + 1.644 + void setDenseElementMaybeConvertDouble(uint32_t index, const js::Value &val) { 1.645 + if (val.isInt32() && shouldConvertDoubleElements()) 1.646 + setDenseElement(index, js::DoubleValue(val.toInt32())); 1.647 + else 1.648 + setDenseElement(index, val); 1.649 + } 1.650 + 1.651 + inline bool setDenseElementIfHasType(uint32_t index, const js::Value &val); 1.652 + inline void setDenseElementWithType(js::ExclusiveContext *cx, uint32_t index, 1.653 + const js::Value &val); 1.654 + inline void initDenseElementWithType(js::ExclusiveContext *cx, uint32_t index, 1.655 + const js::Value &val); 1.656 + inline void setDenseElementHole(js::ExclusiveContext *cx, uint32_t index); 1.657 + static inline void removeDenseElementForSparseIndex(js::ExclusiveContext *cx, 1.658 + js::HandleObject obj, uint32_t index); 1.659 + 1.660 + inline js::Value getDenseOrTypedArrayElement(uint32_t idx); 1.661 + 1.662 + void copyDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count) { 1.663 + JS_ASSERT(dstStart + count <= getDenseCapacity()); 1.664 + JSRuntime *rt = runtimeFromMainThread(); 1.665 + if (JS::IsIncrementalBarrierNeeded(rt)) { 1.666 + JS::Zone *zone = this->zone(); 1.667 + for (uint32_t i = 0; i < count; ++i) 1.668 + elements[dstStart + i].set(zone, this, js::HeapSlot::Element, dstStart + i, src[i]); 1.669 + } else { 1.670 + memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot)); 1.671 + DenseRangeWriteBarrierPost(rt, this, dstStart, count); 1.672 + } 1.673 + } 1.674 + 1.675 + void initDenseElements(uint32_t dstStart, const js::Value *src, uint32_t count) { 1.676 + JS_ASSERT(dstStart + count <= getDenseCapacity()); 1.677 + memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot)); 1.678 + DenseRangeWriteBarrierPost(runtimeFromMainThread(), this, dstStart, count); 1.679 + } 1.680 + 1.681 + void initDenseElementsUnbarriered(uint32_t dstStart, const js::Value *src, uint32_t count) { 1.682 + /* 1.683 + * For use by parallel threads, which since they cannot see nursery 1.684 + * things do not require a barrier. 1.685 + */ 1.686 + JS_ASSERT(dstStart + count <= getDenseCapacity()); 1.687 +#if defined(DEBUG) && defined(JSGC_GENERATIONAL) 1.688 + JS::shadow::Runtime *rt = JS::shadow::Runtime::asShadowRuntime(runtimeFromAnyThread()); 1.689 + JS_ASSERT(!js::gc::IsInsideNursery(rt, this)); 1.690 + for (uint32_t index = 0; index < count; ++index) { 1.691 + const JS::Value& value = src[index]; 1.692 + if (value.isMarkable()) 1.693 + JS_ASSERT(!js::gc::IsInsideNursery(rt, value.toGCThing())); 1.694 + } 1.695 +#endif 1.696 + memcpy(&elements[dstStart], src, count * sizeof(js::HeapSlot)); 1.697 + } 1.698 + 1.699 + void moveDenseElements(uint32_t dstStart, uint32_t srcStart, uint32_t count) { 1.700 + JS_ASSERT(dstStart + count <= getDenseCapacity()); 1.701 + JS_ASSERT(srcStart + count <= getDenseInitializedLength()); 1.702 + 1.703 + /* 1.704 + * Using memmove here would skip write barriers. Also, we need to consider 1.705 + * an array containing [A, B, C], in the following situation: 1.706 + * 1.707 + * 1. Incremental GC marks slot 0 of array (i.e., A), then returns to JS code. 1.708 + * 2. JS code moves slots 1..2 into slots 0..1, so it contains [B, C, C]. 1.709 + * 3. Incremental GC finishes by marking slots 1 and 2 (i.e., C). 1.710 + * 1.711 + * Since normal marking never happens on B, it is very important that the 1.712 + * write barrier is invoked here on B, despite the fact that it exists in 1.713 + * the array before and after the move. 1.714 + */ 1.715 + JS::Zone *zone = this->zone(); 1.716 + JS::shadow::Zone *shadowZone = JS::shadow::Zone::asShadowZone(zone); 1.717 + if (shadowZone->needsBarrier()) { 1.718 + if (dstStart < srcStart) { 1.719 + js::HeapSlot *dst = elements + dstStart; 1.720 + js::HeapSlot *src = elements + srcStart; 1.721 + for (uint32_t i = 0; i < count; i++, dst++, src++) 1.722 + dst->set(zone, this, js::HeapSlot::Element, dst - elements, *src); 1.723 + } else { 1.724 + js::HeapSlot *dst = elements + dstStart + count - 1; 1.725 + js::HeapSlot *src = elements + srcStart + count - 1; 1.726 + for (uint32_t i = 0; i < count; i++, dst--, src--) 1.727 + dst->set(zone, this, js::HeapSlot::Element, dst - elements, *src); 1.728 + } 1.729 + } else { 1.730 + memmove(elements + dstStart, elements + srcStart, count * sizeof(js::HeapSlot)); 1.731 + DenseRangeWriteBarrierPost(runtimeFromMainThread(), this, dstStart, count); 1.732 + } 1.733 + } 1.734 + 1.735 + void moveDenseElementsNoPreBarrier(uint32_t dstStart, uint32_t srcStart, uint32_t count) { 1.736 + JS_ASSERT(!shadowZone()->needsBarrier()); 1.737 + 1.738 + JS_ASSERT(dstStart + count <= getDenseCapacity()); 1.739 + JS_ASSERT(srcStart + count <= getDenseCapacity()); 1.740 + 1.741 + memmove(elements + dstStart, elements + srcStart, count * sizeof(js::Value)); 1.742 + DenseRangeWriteBarrierPost(runtimeFromMainThread(), this, dstStart, count); 1.743 + } 1.744 + 1.745 + bool shouldConvertDoubleElements() { 1.746 + JS_ASSERT(getClass()->isNative()); 1.747 + return getElementsHeader()->shouldConvertDoubleElements(); 1.748 + } 1.749 + 1.750 + inline void setShouldConvertDoubleElements(); 1.751 + inline void clearShouldConvertDoubleElements(); 1.752 + 1.753 + /* Packed information for this object's elements. */ 1.754 + inline bool writeToIndexWouldMarkNotPacked(uint32_t index); 1.755 + inline void markDenseElementsNotPacked(js::ExclusiveContext *cx); 1.756 + 1.757 + /* 1.758 + * ensureDenseElements ensures that the object can hold at least 1.759 + * index + extra elements. It returns ED_OK on success, ED_FAILED on 1.760 + * failure to grow the array, ED_SPARSE when the object is too sparse to 1.761 + * grow (this includes the case of index + extra overflow). In the last 1.762 + * two cases the object is kept intact. 1.763 + */ 1.764 + enum EnsureDenseResult { ED_OK, ED_FAILED, ED_SPARSE }; 1.765 + 1.766 + private: 1.767 + inline EnsureDenseResult ensureDenseElementsNoPackedCheck(js::ThreadSafeContext *cx, 1.768 + uint32_t index, uint32_t extra); 1.769 + 1.770 + public: 1.771 + inline EnsureDenseResult ensureDenseElements(js::ExclusiveContext *cx, 1.772 + uint32_t index, uint32_t extra); 1.773 + inline EnsureDenseResult ensureDenseElementsPreservePackedFlag(js::ThreadSafeContext *cx, 1.774 + uint32_t index, uint32_t extra); 1.775 + 1.776 + inline EnsureDenseResult extendDenseElements(js::ThreadSafeContext *cx, 1.777 + uint32_t requiredCapacity, uint32_t extra); 1.778 + 1.779 + /* Convert a single dense element to a sparse property. */ 1.780 + static bool sparsifyDenseElement(js::ExclusiveContext *cx, 1.781 + js::HandleObject obj, uint32_t index); 1.782 + 1.783 + /* Convert all dense elements to sparse properties. */ 1.784 + static bool sparsifyDenseElements(js::ExclusiveContext *cx, js::HandleObject obj); 1.785 + 1.786 + /* Small objects are dense, no matter what. */ 1.787 + static const uint32_t MIN_SPARSE_INDEX = 1000; 1.788 + 1.789 + /* 1.790 + * Element storage for an object will be sparse if fewer than 1/8 indexes 1.791 + * are filled in. 1.792 + */ 1.793 + static const unsigned SPARSE_DENSITY_RATIO = 8; 1.794 + 1.795 + /* 1.796 + * Check if after growing the object's elements will be too sparse. 1.797 + * newElementsHint is an estimated number of elements to be added. 1.798 + */ 1.799 + bool willBeSparseElements(uint32_t requiredCapacity, uint32_t newElementsHint); 1.800 + 1.801 + /* 1.802 + * After adding a sparse index to obj, see if it should be converted to use 1.803 + * dense elements. 1.804 + */ 1.805 + static EnsureDenseResult maybeDensifySparseElements(js::ExclusiveContext *cx, js::HandleObject obj); 1.806 + 1.807 + public: 1.808 + /* 1.809 + * Iterator-specific getters and setters. 1.810 + */ 1.811 + 1.812 + static const uint32_t ITER_CLASS_NFIXED_SLOTS = 1; 1.813 + 1.814 + /* 1.815 + * Back to generic stuff. 1.816 + */ 1.817 + bool isCallable() { 1.818 + return getClass()->isCallable(); 1.819 + } 1.820 + 1.821 + inline void finish(js::FreeOp *fop); 1.822 + MOZ_ALWAYS_INLINE void finalize(js::FreeOp *fop); 1.823 + 1.824 + static inline bool hasProperty(JSContext *cx, js::HandleObject obj, 1.825 + js::HandleId id, bool *foundp); 1.826 + 1.827 + /* 1.828 + * Allocate and free an object slot. 1.829 + * 1.830 + * FIXME: bug 593129 -- slot allocation should be done by object methods 1.831 + * after calling object-parameter-free shape methods, avoiding coupling 1.832 + * logic across the object vs. shape module wall. 1.833 + */ 1.834 + static bool allocSlot(js::ThreadSafeContext *cx, JS::HandleObject obj, uint32_t *slotp); 1.835 + void freeSlot(uint32_t slot); 1.836 + 1.837 + public: 1.838 + static bool reportReadOnly(js::ThreadSafeContext *cx, jsid id, unsigned report = JSREPORT_ERROR); 1.839 + bool reportNotConfigurable(js::ThreadSafeContext *cx, jsid id, unsigned report = JSREPORT_ERROR); 1.840 + bool reportNotExtensible(js::ThreadSafeContext *cx, unsigned report = JSREPORT_ERROR); 1.841 + 1.842 + /* 1.843 + * Get the property with the given id, then call it as a function with the 1.844 + * given arguments, providing this object as |this|. If the property isn't 1.845 + * callable a TypeError will be thrown. On success the value returned by 1.846 + * the call is stored in *vp. 1.847 + */ 1.848 + bool callMethod(JSContext *cx, js::HandleId id, unsigned argc, js::Value *argv, 1.849 + js::MutableHandleValue vp); 1.850 + 1.851 + private: 1.852 + static js::Shape *getChildPropertyOnDictionary(js::ThreadSafeContext *cx, JS::HandleObject obj, 1.853 + js::HandleShape parent, js::StackShape &child); 1.854 + static js::Shape *getChildProperty(js::ExclusiveContext *cx, JS::HandleObject obj, 1.855 + js::HandleShape parent, js::StackShape &child); 1.856 + template <js::ExecutionMode mode> 1.857 + static inline js::Shape * 1.858 + getOrLookupChildProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx, 1.859 + JS::HandleObject obj, js::HandleShape parent, js::StackShape &child) 1.860 + { 1.861 + if (mode == js::ParallelExecution) 1.862 + return lookupChildProperty(cx, obj, parent, child); 1.863 + return getChildProperty(cx->asExclusiveContext(), obj, parent, child); 1.864 + } 1.865 + 1.866 + public: 1.867 + /* 1.868 + * XXX: This should be private, but is public because it needs to be a 1.869 + * friend of ThreadSafeContext to get to the propertyTree on cx->compartment_. 1.870 + */ 1.871 + static js::Shape *lookupChildProperty(js::ThreadSafeContext *cx, JS::HandleObject obj, 1.872 + js::HandleShape parent, js::StackShape &child); 1.873 + 1.874 + 1.875 + protected: 1.876 + /* 1.877 + * Internal helper that adds a shape not yet mapped by this object. 1.878 + * 1.879 + * Notes: 1.880 + * 1. getter and setter must be normalized based on flags (see jsscope.cpp). 1.881 + * 2. Checks for non-extensibility must be done by callers. 1.882 + */ 1.883 + template <js::ExecutionMode mode> 1.884 + static js::Shape * 1.885 + addPropertyInternal(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx, 1.886 + JS::HandleObject obj, JS::HandleId id, 1.887 + JSPropertyOp getter, JSStrictPropertyOp setter, 1.888 + uint32_t slot, unsigned attrs, unsigned flags, js::Shape **spp, 1.889 + bool allowDictionary); 1.890 + 1.891 + private: 1.892 + struct TradeGutsReserved; 1.893 + static bool ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b, 1.894 + TradeGutsReserved &reserved); 1.895 + 1.896 + static void TradeGuts(JSContext *cx, JSObject *a, JSObject *b, 1.897 + TradeGutsReserved &reserved); 1.898 + 1.899 + public: 1.900 + /* Add a property whose id is not yet in this scope. */ 1.901 + static js::Shape *addProperty(js::ExclusiveContext *cx, JS::HandleObject, JS::HandleId id, 1.902 + JSPropertyOp getter, JSStrictPropertyOp setter, 1.903 + uint32_t slot, unsigned attrs, unsigned flags, 1.904 + bool allowDictionary = true); 1.905 + 1.906 + /* Add a data property whose id is not yet in this scope. */ 1.907 + js::Shape *addDataProperty(js::ExclusiveContext *cx, 1.908 + jsid id_, uint32_t slot, unsigned attrs); 1.909 + js::Shape *addDataProperty(js::ExclusiveContext *cx, js::HandlePropertyName name, 1.910 + uint32_t slot, unsigned attrs); 1.911 + 1.912 + /* Add or overwrite a property for id in this scope. */ 1.913 + template <js::ExecutionMode mode> 1.914 + static js::Shape * 1.915 + putProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx, 1.916 + JS::HandleObject obj, JS::HandleId id, 1.917 + JSPropertyOp getter, JSStrictPropertyOp setter, 1.918 + uint32_t slot, unsigned attrs, 1.919 + unsigned flags); 1.920 + template <js::ExecutionMode mode> 1.921 + static inline js::Shape * 1.922 + putProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx, 1.923 + JS::HandleObject obj, js::PropertyName *name, 1.924 + JSPropertyOp getter, JSStrictPropertyOp setter, 1.925 + uint32_t slot, unsigned attrs, 1.926 + unsigned flags); 1.927 + 1.928 + /* Change the given property into a sibling with the same id in this scope. */ 1.929 + template <js::ExecutionMode mode> 1.930 + static js::Shape * 1.931 + changeProperty(typename js::ExecutionModeTraits<mode>::ExclusiveContextType cx, 1.932 + js::HandleObject obj, js::HandleShape shape, unsigned attrs, unsigned mask, 1.933 + JSPropertyOp getter, JSStrictPropertyOp setter); 1.934 + 1.935 + static inline bool changePropertyAttributes(JSContext *cx, js::HandleObject obj, 1.936 + js::HandleShape shape, unsigned attrs); 1.937 + 1.938 + /* Remove the property named by id from this object. */ 1.939 + bool removeProperty(js::ExclusiveContext *cx, jsid id); 1.940 + 1.941 + /* Clear the scope, making it empty. */ 1.942 + static void clear(JSContext *cx, js::HandleObject obj); 1.943 + 1.944 + static bool lookupGeneric(JSContext *cx, js::HandleObject obj, js::HandleId id, 1.945 + js::MutableHandleObject objp, js::MutableHandleShape propp); 1.946 + 1.947 + static bool lookupProperty(JSContext *cx, js::HandleObject obj, js::PropertyName *name, 1.948 + js::MutableHandleObject objp, js::MutableHandleShape propp) 1.949 + { 1.950 + JS::RootedId id(cx, js::NameToId(name)); 1.951 + return lookupGeneric(cx, obj, id, objp, propp); 1.952 + } 1.953 + 1.954 + static bool lookupElement(JSContext *cx, js::HandleObject obj, uint32_t index, 1.955 + js::MutableHandleObject objp, js::MutableHandleShape propp) 1.956 + { 1.957 + js::LookupElementOp op = obj->getOps()->lookupElement; 1.958 + return (op ? op : js::baseops::LookupElement)(cx, obj, index, objp, propp); 1.959 + } 1.960 + 1.961 + static bool defineGeneric(js::ExclusiveContext *cx, js::HandleObject obj, 1.962 + js::HandleId id, js::HandleValue value, 1.963 + JSPropertyOp getter = JS_PropertyStub, 1.964 + JSStrictPropertyOp setter = JS_StrictPropertyStub, 1.965 + unsigned attrs = JSPROP_ENUMERATE); 1.966 + 1.967 + static bool defineProperty(js::ExclusiveContext *cx, js::HandleObject obj, 1.968 + js::PropertyName *name, js::HandleValue value, 1.969 + JSPropertyOp getter = JS_PropertyStub, 1.970 + JSStrictPropertyOp setter = JS_StrictPropertyStub, 1.971 + unsigned attrs = JSPROP_ENUMERATE); 1.972 + 1.973 + static bool defineElement(js::ExclusiveContext *cx, js::HandleObject obj, 1.974 + uint32_t index, js::HandleValue value, 1.975 + JSPropertyOp getter = JS_PropertyStub, 1.976 + JSStrictPropertyOp setter = JS_StrictPropertyStub, 1.977 + unsigned attrs = JSPROP_ENUMERATE); 1.978 + 1.979 + static bool getGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, 1.980 + js::HandleId id, js::MutableHandleValue vp) 1.981 + { 1.982 + JS_ASSERT(!!obj->getOps()->getGeneric == !!obj->getOps()->getProperty); 1.983 + js::GenericIdOp op = obj->getOps()->getGeneric; 1.984 + if (op) { 1.985 + if (!op(cx, obj, receiver, id, vp)) 1.986 + return false; 1.987 + } else { 1.988 + if (!js::baseops::GetProperty(cx, obj, receiver, id, vp)) 1.989 + return false; 1.990 + } 1.991 + return true; 1.992 + } 1.993 + 1.994 + static bool getGenericNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, 1.995 + jsid id, js::Value *vp) 1.996 + { 1.997 + js::GenericIdOp op = obj->getOps()->getGeneric; 1.998 + if (op) 1.999 + return false; 1.1000 + return js::baseops::GetPropertyNoGC(cx, obj, receiver, id, vp); 1.1001 + } 1.1002 + 1.1003 + static bool getProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, 1.1004 + js::PropertyName *name, js::MutableHandleValue vp) 1.1005 + { 1.1006 + JS::RootedId id(cx, js::NameToId(name)); 1.1007 + return getGeneric(cx, obj, receiver, id, vp); 1.1008 + } 1.1009 + 1.1010 + static bool getPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, 1.1011 + js::PropertyName *name, js::Value *vp) 1.1012 + { 1.1013 + return getGenericNoGC(cx, obj, receiver, js::NameToId(name), vp); 1.1014 + } 1.1015 + 1.1016 + static inline bool getElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, 1.1017 + uint32_t index, js::MutableHandleValue vp); 1.1018 + static inline bool getElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, 1.1019 + uint32_t index, js::Value *vp); 1.1020 + 1.1021 + static bool setGeneric(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, 1.1022 + js::HandleId id, js::MutableHandleValue vp, bool strict) 1.1023 + { 1.1024 + if (obj->getOps()->setGeneric) 1.1025 + return nonNativeSetProperty(cx, obj, id, vp, strict); 1.1026 + return js::baseops::SetPropertyHelper<js::SequentialExecution>( 1.1027 + cx, obj, receiver, id, js::baseops::Qualified, vp, strict); 1.1028 + } 1.1029 + 1.1030 + static bool setProperty(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, 1.1031 + js::PropertyName *name, 1.1032 + js::MutableHandleValue vp, bool strict) 1.1033 + { 1.1034 + JS::RootedId id(cx, js::NameToId(name)); 1.1035 + return setGeneric(cx, obj, receiver, id, vp, strict); 1.1036 + } 1.1037 + 1.1038 + static bool setElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver, 1.1039 + uint32_t index, js::MutableHandleValue vp, bool strict) 1.1040 + { 1.1041 + if (obj->getOps()->setElement) 1.1042 + return nonNativeSetElement(cx, obj, index, vp, strict); 1.1043 + return js::baseops::SetElementHelper(cx, obj, receiver, index, vp, strict); 1.1044 + } 1.1045 + 1.1046 + static bool nonNativeSetProperty(JSContext *cx, js::HandleObject obj, 1.1047 + js::HandleId id, js::MutableHandleValue vp, bool strict); 1.1048 + static bool nonNativeSetElement(JSContext *cx, js::HandleObject obj, 1.1049 + uint32_t index, js::MutableHandleValue vp, bool strict); 1.1050 + 1.1051 + static bool getGenericAttributes(JSContext *cx, js::HandleObject obj, 1.1052 + js::HandleId id, unsigned *attrsp) 1.1053 + { 1.1054 + js::GenericAttributesOp op = obj->getOps()->getGenericAttributes; 1.1055 + return (op ? op : js::baseops::GetAttributes)(cx, obj, id, attrsp); 1.1056 + } 1.1057 + 1.1058 + static inline bool setGenericAttributes(JSContext *cx, js::HandleObject obj, 1.1059 + js::HandleId id, unsigned *attrsp); 1.1060 + 1.1061 + static inline bool deleteProperty(JSContext *cx, js::HandleObject obj, 1.1062 + js::HandlePropertyName name, 1.1063 + bool *succeeded); 1.1064 + static inline bool deleteElement(JSContext *cx, js::HandleObject obj, 1.1065 + uint32_t index, bool *succeeded); 1.1066 + static bool deleteByValue(JSContext *cx, js::HandleObject obj, 1.1067 + const js::Value &property, bool *succeeded); 1.1068 + 1.1069 + static inline bool watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.1070 + JS::HandleObject callable); 1.1071 + static inline bool unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id); 1.1072 + 1.1073 + static bool enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop, 1.1074 + JS::MutableHandleValue statep, JS::MutableHandleId idp) 1.1075 + { 1.1076 + JSNewEnumerateOp op = obj->getOps()->enumerate; 1.1077 + return (op ? op : JS_EnumerateState)(cx, obj, iterop, statep, idp); 1.1078 + } 1.1079 + 1.1080 + static bool defaultValue(JSContext *cx, js::HandleObject obj, JSType hint, 1.1081 + js::MutableHandleValue vp) 1.1082 + { 1.1083 + JSConvertOp op = obj->getClass()->convert; 1.1084 + bool ok; 1.1085 + if (op == JS_ConvertStub) 1.1086 + ok = js::DefaultValue(cx, obj, hint, vp); 1.1087 + else 1.1088 + ok = op(cx, obj, hint, vp); 1.1089 + JS_ASSERT_IF(ok, vp.isPrimitive()); 1.1090 + return ok; 1.1091 + } 1.1092 + 1.1093 + static JSObject *thisObject(JSContext *cx, js::HandleObject obj) 1.1094 + { 1.1095 + JSObjectOp op = obj->getOps()->thisObject; 1.1096 + return op ? op(cx, obj) : obj; 1.1097 + } 1.1098 + 1.1099 + static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp); 1.1100 + 1.1101 + static bool swap(JSContext *cx, JS::HandleObject a, JS::HandleObject b); 1.1102 + 1.1103 + inline void initArrayClass(); 1.1104 + 1.1105 + /* 1.1106 + * In addition to the generic object interface provided by JSObject, 1.1107 + * specific types of objects may provide additional operations. To access, 1.1108 + * these addition operations, callers should use the pattern: 1.1109 + * 1.1110 + * if (obj.is<XObject>()) { 1.1111 + * XObject &x = obj.as<XObject>(); 1.1112 + * x.foo(); 1.1113 + * } 1.1114 + * 1.1115 + * These XObject classes form a hierarchy. For example, for a cloned block 1.1116 + * object, the following predicates are true: is<ClonedBlockObject>, 1.1117 + * is<BlockObject>, is<NestedScopeObject> and is<ScopeObject>. Each of 1.1118 + * these has a respective class that derives and adds operations. 1.1119 + * 1.1120 + * A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file 1.1121 + * triplet (along with any class YObject that derives XObject). 1.1122 + * 1.1123 + * Note that X represents a low-level representation and does not query the 1.1124 + * [[Class]] property of object defined by the spec (for this, see 1.1125 + * js::ObjectClassIs). 1.1126 + */ 1.1127 + 1.1128 + template <class T> 1.1129 + inline bool is() const { return getClass() == &T::class_; } 1.1130 + 1.1131 + template <class T> 1.1132 + T &as() { 1.1133 + JS_ASSERT(is<T>()); 1.1134 + return *static_cast<T *>(this); 1.1135 + } 1.1136 + 1.1137 + template <class T> 1.1138 + const T &as() const { 1.1139 + JS_ASSERT(is<T>()); 1.1140 + return *static_cast<const T *>(this); 1.1141 + } 1.1142 + 1.1143 + static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; } 1.1144 + 1.1145 +#ifdef DEBUG 1.1146 + void dump(); 1.1147 +#endif 1.1148 + 1.1149 + private: 1.1150 + static void staticAsserts() { 1.1151 + static_assert(sizeof(JSObject) == sizeof(js::shadow::Object), 1.1152 + "shadow interface must match actual interface"); 1.1153 + static_assert(sizeof(JSObject) == sizeof(js::ObjectImpl), 1.1154 + "JSObject itself must not have any fields"); 1.1155 + static_assert(sizeof(JSObject) % sizeof(js::Value) == 0, 1.1156 + "fixed slots after an object must be aligned"); 1.1157 + static_assert(js::shadow::Object::MAX_FIXED_SLOTS == MAX_FIXED_SLOTS, 1.1158 + "We shouldn't be confused about our actual maximum " 1.1159 + "number of fixed slots"); 1.1160 + } 1.1161 + 1.1162 + JSObject() MOZ_DELETE; 1.1163 + JSObject(const JSObject &other) MOZ_DELETE; 1.1164 + void operator=(const JSObject &other) MOZ_DELETE; 1.1165 +}; 1.1166 + 1.1167 +template <class U> 1.1168 +MOZ_ALWAYS_INLINE JS::Handle<U*> 1.1169 +js::RootedBase<JSObject*>::as() const 1.1170 +{ 1.1171 + const JS::Rooted<JSObject*> &self = *static_cast<const JS::Rooted<JSObject*>*>(this); 1.1172 + JS_ASSERT(self->is<U>()); 1.1173 + return Handle<U*>::fromMarkedLocation(reinterpret_cast<U* const*>(self.address())); 1.1174 +} 1.1175 + 1.1176 +/* 1.1177 + * The only sensible way to compare JSObject with == is by identity. We use 1.1178 + * const& instead of * as a syntactic way to assert non-null. This leads to an 1.1179 + * abundance of address-of operators to identity. Hence this overload. 1.1180 + */ 1.1181 +static MOZ_ALWAYS_INLINE bool 1.1182 +operator==(const JSObject &lhs, const JSObject &rhs) 1.1183 +{ 1.1184 + return &lhs == &rhs; 1.1185 +} 1.1186 + 1.1187 +static MOZ_ALWAYS_INLINE bool 1.1188 +operator!=(const JSObject &lhs, const JSObject &rhs) 1.1189 +{ 1.1190 + return &lhs != &rhs; 1.1191 +} 1.1192 + 1.1193 +struct JSObject_Slots2 : JSObject { js::Value fslots[2]; }; 1.1194 +struct JSObject_Slots4 : JSObject { js::Value fslots[4]; }; 1.1195 +struct JSObject_Slots8 : JSObject { js::Value fslots[8]; }; 1.1196 +struct JSObject_Slots12 : JSObject { js::Value fslots[12]; }; 1.1197 +struct JSObject_Slots16 : JSObject { js::Value fslots[16]; }; 1.1198 + 1.1199 +static inline bool 1.1200 +js_IsCallable(const js::Value &v) 1.1201 +{ 1.1202 + return v.isObject() && v.toObject().isCallable(); 1.1203 +} 1.1204 + 1.1205 +inline JSObject * 1.1206 +GetInnerObject(JSContext *cx, js::HandleObject obj) 1.1207 +{ 1.1208 + if (JSObjectOp op = obj->getClass()->ext.innerObject) 1.1209 + return op(cx, obj); 1.1210 + return obj; 1.1211 +} 1.1212 + 1.1213 +inline JSObject * 1.1214 +GetOuterObject(JSContext *cx, js::HandleObject obj) 1.1215 +{ 1.1216 + if (JSObjectOp op = obj->getClass()->ext.outerObject) 1.1217 + return op(cx, obj); 1.1218 + return obj; 1.1219 +} 1.1220 + 1.1221 +class JSValueArray { 1.1222 + public: 1.1223 + const jsval *array; 1.1224 + size_t length; 1.1225 + 1.1226 + JSValueArray(const jsval *v, size_t c) : array(v), length(c) {} 1.1227 +}; 1.1228 + 1.1229 +class ValueArray { 1.1230 + public: 1.1231 + js::Value *array; 1.1232 + size_t length; 1.1233 + 1.1234 + ValueArray(js::Value *v, size_t c) : array(v), length(c) {} 1.1235 +}; 1.1236 + 1.1237 +namespace js { 1.1238 + 1.1239 +/* Set *resultp to tell whether obj has an own property with the given id. */ 1.1240 +bool 1.1241 +HasOwnProperty(JSContext *cx, HandleObject obj, HandleId id, bool *resultp); 1.1242 + 1.1243 +template <AllowGC allowGC> 1.1244 +extern bool 1.1245 +HasOwnProperty(JSContext *cx, LookupGenericOp lookup, 1.1246 + typename MaybeRooted<JSObject*, allowGC>::HandleType obj, 1.1247 + typename MaybeRooted<jsid, allowGC>::HandleType id, 1.1248 + typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp, 1.1249 + typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp); 1.1250 + 1.1251 +typedef JSObject *(*ClassInitializerOp)(JSContext *cx, JS::HandleObject obj); 1.1252 + 1.1253 +/* Fast access to builtin constructors and prototypes. */ 1.1254 +bool 1.1255 +GetBuiltinConstructor(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject objp); 1.1256 + 1.1257 +bool 1.1258 +GetBuiltinPrototype(ExclusiveContext *cx, JSProtoKey key, MutableHandleObject objp); 1.1259 + 1.1260 +const Class * 1.1261 +ProtoKeyToClass(JSProtoKey key); 1.1262 + 1.1263 +JSObject * 1.1264 +GetBuiltinPrototypePure(GlobalObject *global, JSProtoKey protoKey); 1.1265 + 1.1266 +extern bool 1.1267 +SetClassAndProto(JSContext *cx, HandleObject obj, 1.1268 + const Class *clasp, Handle<TaggedProto> proto, bool *succeeded); 1.1269 + 1.1270 +/* 1.1271 + * Property-lookup-based access to interface and prototype objects for classes. 1.1272 + * If the class is built-in (hhas a non-null JSProtoKey), these forward to 1.1273 + * GetClass{Object,Prototype}. 1.1274 + */ 1.1275 + 1.1276 +bool 1.1277 +FindClassObject(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp); 1.1278 + 1.1279 +extern bool 1.1280 +FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class *clasp); 1.1281 + 1.1282 +} /* namespace js */ 1.1283 + 1.1284 +/* 1.1285 + * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp. 1.1286 + */ 1.1287 +extern const char js_watch_str[]; 1.1288 +extern const char js_unwatch_str[]; 1.1289 +extern const char js_hasOwnProperty_str[]; 1.1290 +extern const char js_isPrototypeOf_str[]; 1.1291 +extern const char js_propertyIsEnumerable_str[]; 1.1292 + 1.1293 +#ifdef JS_OLD_GETTER_SETTER_METHODS 1.1294 +extern const char js_defineGetter_str[]; 1.1295 +extern const char js_defineSetter_str[]; 1.1296 +extern const char js_lookupGetter_str[]; 1.1297 +extern const char js_lookupSetter_str[]; 1.1298 +#endif 1.1299 + 1.1300 +extern bool 1.1301 +js_PopulateObject(JSContext *cx, js::HandleObject newborn, js::HandleObject props); 1.1302 + 1.1303 + 1.1304 +namespace js { 1.1305 + 1.1306 +extern bool 1.1307 +DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.1308 + JS::HandleValue descriptor, bool *bp); 1.1309 + 1.1310 +extern bool 1.1311 +DefineOwnProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, 1.1312 + JS::Handle<js::PropertyDescriptor> descriptor, bool *bp); 1.1313 + 1.1314 +/* 1.1315 + * The NewObjectKind allows an allocation site to specify the type properties 1.1316 + * and lifetime requirements that must be fixed at allocation time. 1.1317 + */ 1.1318 +enum NewObjectKind { 1.1319 + /* This is the default. Most objects are generic. */ 1.1320 + GenericObject, 1.1321 + 1.1322 + /* 1.1323 + * Singleton objects are treated specially by the type system. This flag 1.1324 + * ensures that the new object is automatically set up correctly as a 1.1325 + * singleton and is allocated in the correct heap. 1.1326 + */ 1.1327 + SingletonObject, 1.1328 + 1.1329 + /* 1.1330 + * Objects which may be marked as a singleton after allocation must still 1.1331 + * be allocated on the correct heap, but are not automatically setup as a 1.1332 + * singleton after allocation. 1.1333 + */ 1.1334 + MaybeSingletonObject, 1.1335 + 1.1336 + /* 1.1337 + * Objects which will not benefit from being allocated in the nursery 1.1338 + * (e.g. because they are known to have a long lifetime) may be allocated 1.1339 + * with this kind to place them immediately into the tenured generation. 1.1340 + */ 1.1341 + TenuredObject 1.1342 +}; 1.1343 + 1.1344 +inline gc::InitialHeap 1.1345 +GetInitialHeap(NewObjectKind newKind, const Class *clasp) 1.1346 +{ 1.1347 + if (clasp->finalize || newKind != GenericObject) 1.1348 + return gc::TenuredHeap; 1.1349 + return gc::DefaultHeap; 1.1350 +} 1.1351 + 1.1352 +// Specialized call for constructing |this| with a known function callee, 1.1353 +// and a known prototype. 1.1354 +extern JSObject * 1.1355 +CreateThisForFunctionWithProto(JSContext *cx, js::HandleObject callee, JSObject *proto, 1.1356 + NewObjectKind newKind = GenericObject); 1.1357 + 1.1358 +// Specialized call for constructing |this| with a known function callee. 1.1359 +extern JSObject * 1.1360 +CreateThisForFunction(JSContext *cx, js::HandleObject callee, NewObjectKind newKind); 1.1361 + 1.1362 +// Generic call for constructing |this|. 1.1363 +extern JSObject * 1.1364 +CreateThis(JSContext *cx, const js::Class *clasp, js::HandleObject callee); 1.1365 + 1.1366 +extern JSObject * 1.1367 +CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent); 1.1368 + 1.1369 +extern JSObject * 1.1370 +DeepCloneObjectLiteral(JSContext *cx, HandleObject obj, NewObjectKind newKind = GenericObject); 1.1371 + 1.1372 +/* 1.1373 + * Return successfully added or changed shape or nullptr on error. 1.1374 + */ 1.1375 +extern bool 1.1376 +DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value, 1.1377 + PropertyOp getter, StrictPropertyOp setter, unsigned attrs); 1.1378 + 1.1379 +extern bool 1.1380 +LookupNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, 1.1381 + js::MutableHandleObject objp, js::MutableHandleShape propp); 1.1382 + 1.1383 +/* 1.1384 + * Call the [[DefineOwnProperty]] internal method of obj. 1.1385 + * 1.1386 + * If obj is an array, this follows ES5 15.4.5.1. 1.1387 + * If obj is any other native object, this follows ES5 8.12.9. 1.1388 + * If obj is a proxy, this calls the proxy handler's defineProperty method. 1.1389 + * Otherwise, this reports an error and returns false. 1.1390 + */ 1.1391 +extern bool 1.1392 +DefineProperty(JSContext *cx, js::HandleObject obj, 1.1393 + js::HandleId id, const PropDesc &desc, bool throwError, 1.1394 + bool *rval); 1.1395 + 1.1396 +bool 1.1397 +DefineProperties(JSContext *cx, HandleObject obj, HandleObject props); 1.1398 + 1.1399 +/* 1.1400 + * Read property descriptors from props, as for Object.defineProperties. See 1.1401 + * ES5 15.2.3.7 steps 3-5. 1.1402 + */ 1.1403 +extern bool 1.1404 +ReadPropertyDescriptors(JSContext *cx, HandleObject props, bool checkAccessors, 1.1405 + AutoIdVector *ids, AutoPropDescArrayRooter *descs); 1.1406 + 1.1407 +/* Read the name using a dynamic lookup on the scopeChain. */ 1.1408 +extern bool 1.1409 +LookupName(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, 1.1410 + MutableHandleObject objp, MutableHandleObject pobjp, MutableHandleShape propp); 1.1411 + 1.1412 +extern bool 1.1413 +LookupNameNoGC(JSContext *cx, PropertyName *name, JSObject *scopeChain, 1.1414 + JSObject **objp, JSObject **pobjp, Shape **propp); 1.1415 + 1.1416 +/* 1.1417 + * Like LookupName except returns the global object if 'name' is not found in 1.1418 + * any preceding non-global scope. 1.1419 + * 1.1420 + * Additionally, pobjp and propp are not needed by callers so they are not 1.1421 + * returned. 1.1422 + */ 1.1423 +extern bool 1.1424 +LookupNameWithGlobalDefault(JSContext *cx, HandlePropertyName name, HandleObject scopeChain, 1.1425 + MutableHandleObject objp); 1.1426 + 1.1427 +} 1.1428 + 1.1429 +extern JSObject * 1.1430 +js_FindVariableScope(JSContext *cx, JSFunction **funp); 1.1431 + 1.1432 + 1.1433 +namespace js { 1.1434 + 1.1435 +bool 1.1436 +NativeGet(JSContext *cx, js::Handle<JSObject*> obj, js::Handle<JSObject*> pobj, 1.1437 + js::Handle<js::Shape*> shape, js::MutableHandle<js::Value> vp); 1.1438 + 1.1439 +template <js::ExecutionMode mode> 1.1440 +bool 1.1441 +NativeSet(typename js::ExecutionModeTraits<mode>::ContextType cx, 1.1442 + js::Handle<JSObject*> obj, js::Handle<JSObject*> receiver, 1.1443 + js::Handle<js::Shape*> shape, bool strict, js::MutableHandleValue vp); 1.1444 + 1.1445 +bool 1.1446 +LookupPropertyPure(JSObject *obj, jsid id, JSObject **objp, Shape **propp); 1.1447 + 1.1448 +bool 1.1449 +GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, jsid id, Value *vp); 1.1450 + 1.1451 +inline bool 1.1452 +GetPropertyPure(ThreadSafeContext *cx, JSObject *obj, PropertyName *name, Value *vp) 1.1453 +{ 1.1454 + return GetPropertyPure(cx, obj, NameToId(name), vp); 1.1455 +} 1.1456 + 1.1457 +bool 1.1458 +GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, 1.1459 + MutableHandle<PropertyDescriptor> desc); 1.1460 + 1.1461 +bool 1.1462 +GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp); 1.1463 + 1.1464 +bool 1.1465 +NewPropertyDescriptorObject(JSContext *cx, Handle<PropertyDescriptor> desc, MutableHandleValue vp); 1.1466 + 1.1467 +/* 1.1468 + * If obj has an already-resolved data property for id, return true and 1.1469 + * store the property value in *vp. 1.1470 + */ 1.1471 +extern bool 1.1472 +HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp); 1.1473 + 1.1474 +inline bool 1.1475 +HasDataProperty(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp) 1.1476 +{ 1.1477 + return HasDataProperty(cx, obj, NameToId(name), vp); 1.1478 +} 1.1479 + 1.1480 +extern bool 1.1481 +IsDelegate(JSContext *cx, HandleObject obj, const Value &v, bool *result); 1.1482 + 1.1483 +// obj is a JSObject*, but we root it immediately up front. We do it 1.1484 +// that way because we need a Rooted temporary in this method anyway. 1.1485 +extern bool 1.1486 +IsDelegateOfObject(JSContext *cx, HandleObject protoObj, JSObject* obj, bool *result); 1.1487 + 1.1488 +bool 1.1489 +GetObjectElementOperationPure(ThreadSafeContext *cx, JSObject *obj, const Value &prop, Value *vp); 1.1490 + 1.1491 +/* Wrap boolean, number or string as Boolean, Number or String object. */ 1.1492 +extern JSObject * 1.1493 +PrimitiveToObject(JSContext *cx, const Value &v); 1.1494 + 1.1495 +} /* namespace js */ 1.1496 + 1.1497 +namespace js { 1.1498 + 1.1499 +/* 1.1500 + * Invokes the ES5 ToObject algorithm on vp, returning the result. If vp might 1.1501 + * already be an object, use ToObject. reportCantConvert controls how null and 1.1502 + * undefined errors are reported. 1.1503 + */ 1.1504 +extern JSObject * 1.1505 +ToObjectSlow(JSContext *cx, HandleValue vp, bool reportScanStack); 1.1506 + 1.1507 +/* For object conversion in e.g. native functions. */ 1.1508 +MOZ_ALWAYS_INLINE JSObject * 1.1509 +ToObject(JSContext *cx, HandleValue vp) 1.1510 +{ 1.1511 + if (vp.isObject()) 1.1512 + return &vp.toObject(); 1.1513 + return ToObjectSlow(cx, vp, false); 1.1514 +} 1.1515 + 1.1516 +/* For converting stack values to objects. */ 1.1517 +MOZ_ALWAYS_INLINE JSObject * 1.1518 +ToObjectFromStack(JSContext *cx, HandleValue vp) 1.1519 +{ 1.1520 + if (vp.isObject()) 1.1521 + return &vp.toObject(); 1.1522 + return ToObjectSlow(cx, vp, true); 1.1523 +} 1.1524 + 1.1525 +template<XDRMode mode> 1.1526 +bool 1.1527 +XDRObjectLiteral(XDRState<mode> *xdr, MutableHandleObject obj); 1.1528 + 1.1529 +extern JSObject * 1.1530 +CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj); 1.1531 + 1.1532 +} /* namespace js */ 1.1533 + 1.1534 +extern void 1.1535 +js_GetObjectSlotName(JSTracer *trc, char *buf, size_t bufsize); 1.1536 + 1.1537 +extern bool 1.1538 +js_ReportGetterOnlyAssignment(JSContext *cx, bool strict); 1.1539 + 1.1540 + 1.1541 +namespace js { 1.1542 + 1.1543 +extern JSObject * 1.1544 +NonNullObject(JSContext *cx, const Value &v); 1.1545 + 1.1546 +extern const char * 1.1547 +InformalValueTypeName(const Value &v); 1.1548 + 1.1549 +extern bool 1.1550 +GetFirstArgumentAsObject(JSContext *cx, const CallArgs &args, const char *method, 1.1551 + MutableHandleObject objp); 1.1552 + 1.1553 +/* Helpers for throwing. These always return false. */ 1.1554 +extern bool 1.1555 +Throw(JSContext *cx, jsid id, unsigned errorNumber); 1.1556 + 1.1557 +extern bool 1.1558 +Throw(JSContext *cx, JSObject *obj, unsigned errorNumber); 1.1559 + 1.1560 +} /* namespace js */ 1.1561 + 1.1562 +#endif /* jsobj_h */