1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla Communicator client code, released
18 : * March 31, 1998.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Netscape Communications Corporation.
22 : * Portions created by the Initial Developer are Copyright (C) 1998
23 : * the Initial Developer. All Rights Reserved.
24 : *
25 : * Contributor(s):
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #ifndef jsobj_h___
42 : #define jsobj_h___
43 :
44 : /*
45 : * JS object definitions.
46 : *
47 : * A JS object consists of a possibly-shared object descriptor containing
48 : * ordered property names, called the map; and a dense vector of property
49 : * values, called slots. The map/slot pointer pair is GC'ed, while the map
50 : * is reference counted and the slot vector is malloc'ed.
51 : */
52 : #include "jsapi.h"
53 : #include "jsatom.h"
54 : #include "jsclass.h"
55 : #include "jsfriendapi.h"
56 : #include "jsinfer.h"
57 : #include "jshash.h"
58 : #include "jspubtd.h"
59 : #include "jsprvtd.h"
60 : #include "jslock.h"
61 : #include "jscell.h"
62 :
63 : #include "gc/Barrier.h"
64 :
65 : #include "vm/ObjectImpl.h"
66 : #include "vm/String.h"
67 :
68 : namespace js {
69 :
70 : class AutoPropDescArrayRooter;
71 : class ProxyHandler;
72 : class CallObject;
73 : struct GCMarker;
74 : struct NativeIterator;
75 :
76 : namespace mjit { class Compiler; }
77 :
78 : static inline PropertyOp
79 639346 : CastAsPropertyOp(JSObject *object)
80 : {
81 639346 : return JS_DATA_TO_FUNC_PTR(PropertyOp, object);
82 : }
83 :
84 : static inline StrictPropertyOp
85 608193 : CastAsStrictPropertyOp(JSObject *object)
86 : {
87 608193 : return JS_DATA_TO_FUNC_PTR(StrictPropertyOp, object);
88 : }
89 :
90 : inline JSObject *
91 2382 : CastAsObject(PropertyOp op)
92 : {
93 2382 : return JS_FUNC_TO_DATA_PTR(JSObject *, op);
94 : }
95 :
96 : inline JSObject *
97 72 : CastAsObject(StrictPropertyOp op)
98 : {
99 72 : return JS_FUNC_TO_DATA_PTR(JSObject *, op);
100 : }
101 :
102 : inline Value
103 2353 : CastAsObjectJsval(PropertyOp op)
104 : {
105 2353 : return ObjectOrNullValue(CastAsObject(op));
106 : }
107 :
108 : inline Value
109 63 : CastAsObjectJsval(StrictPropertyOp op)
110 : {
111 63 : return ObjectOrNullValue(CastAsObject(op));
112 : }
113 :
114 : /*
115 : * JSPropertySpec uses JSAPI JSPropertyOp and JSStrictPropertyOp in function
116 : * signatures, but with JSPROP_NATIVE_ACCESSORS the actual values must be
117 : * JSNatives. To avoid widespread casting, have JS_PSG and JS_PSGS perform
118 : * type-safe casts.
119 : */
120 : #define JS_PSG(name,getter,flags) \
121 : {name, 0, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS, \
122 : (JSPropertyOp)getter, NULL}
123 : #define JS_PSGS(name,getter,setter,flags) \
124 : {name, 0, (flags) | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS, \
125 : (JSPropertyOp)getter, (JSStrictPropertyOp)setter}
126 : #define JS_PS_END {0, 0, 0, 0, 0}
127 :
128 : /******************************************************************************/
129 :
130 : /*
131 : * A representation of ECMA-262 ed. 5's internal Property Descriptor data
132 : * structure.
133 : */
134 597951 : struct PropDesc {
135 : /*
136 : * Original object from which this descriptor derives, passed through for
137 : * the benefit of proxies.
138 : */
139 : js::Value pd;
140 :
141 : js::Value value, get, set;
142 :
143 : /* Property descriptor boolean fields. */
144 : uint8_t attrs;
145 :
146 : /* Bits indicating which values are set. */
147 : bool hasGet : 1;
148 : bool hasSet : 1;
149 : bool hasValue : 1;
150 : bool hasWritable : 1;
151 : bool hasEnumerable : 1;
152 : bool hasConfigurable : 1;
153 :
154 : friend class js::AutoPropDescArrayRooter;
155 :
156 : PropDesc();
157 :
158 : /*
159 : * 8.10.5 ToPropertyDescriptor(Obj)
160 : *
161 : * If checkAccessors is false, skip steps 7.b and 8.b, which throw a
162 : * TypeError if .get or .set is neither a callable object nor undefined.
163 : *
164 : * (DebuggerObject_defineProperty uses this: the .get and .set properties
165 : * are expected to be Debugger.Object wrappers of functions, which are not
166 : * themselves callable.)
167 : */
168 : bool initialize(JSContext* cx, const js::Value &v, bool checkAccessors=true);
169 :
170 : /*
171 : * 8.10.4 FromPropertyDescriptor(Desc)
172 : *
173 : * initFromPropertyDescriptor sets pd to undefined and populates all the
174 : * other fields of this PropDesc from desc.
175 : *
176 : * makeObject populates pd based on the other fields of *this, creating a
177 : * new property descriptor JSObject and defining properties on it.
178 : */
179 : void initFromPropertyDescriptor(const PropertyDescriptor &desc);
180 : bool makeObject(JSContext *cx);
181 :
182 : /* 8.10.1 IsAccessorDescriptor(desc) */
183 1237351 : bool isAccessorDescriptor() const {
184 1237351 : return hasGet || hasSet;
185 : }
186 :
187 : /* 8.10.2 IsDataDescriptor(desc) */
188 629185 : bool isDataDescriptor() const {
189 629185 : return hasValue || hasWritable;
190 : }
191 :
192 : /* 8.10.3 IsGenericDescriptor(desc) */
193 610998 : bool isGenericDescriptor() const {
194 610998 : return !isAccessorDescriptor() && !isDataDescriptor();
195 : }
196 :
197 114 : bool configurable() const {
198 114 : return (attrs & JSPROP_PERMANENT) == 0;
199 : }
200 :
201 15 : bool enumerable() const {
202 15 : return (attrs & JSPROP_ENUMERATE) != 0;
203 : }
204 :
205 27 : bool writable() const {
206 27 : return (attrs & JSPROP_READONLY) == 0;
207 : }
208 :
209 578592 : JSObject* getterObject() const {
210 578592 : return get.isUndefined() ? NULL : &get.toObject();
211 : }
212 594549 : JSObject* setterObject() const {
213 594549 : return set.isUndefined() ? NULL : &set.toObject();
214 : }
215 :
216 35 : const js::Value &getterValue() const {
217 35 : return get;
218 : }
219 16244 : const js::Value &setterValue() const {
220 16244 : return set;
221 : }
222 :
223 578592 : PropertyOp getter() const {
224 578592 : return js::CastAsPropertyOp(getterObject());
225 : }
226 594549 : StrictPropertyOp setter() const {
227 594549 : return js::CastAsStrictPropertyOp(setterObject());
228 : }
229 :
230 : /*
231 : * Throw a TypeError if a getter/setter is present and is neither callable
232 : * nor undefined. These methods do exactly the type checks that are skipped
233 : * by passing false as the checkAccessors parameter of initialize.
234 : */
235 : inline bool checkGetter(JSContext *cx);
236 : inline bool checkSetter(JSContext *cx);
237 : };
238 :
239 : typedef Vector<PropDesc, 1> PropDescArray;
240 :
241 : } /* namespace js */
242 :
243 : /*
244 : * On success, and if id was found, return true with *objp non-null and with a
245 : * property of *objp stored in *propp. If successful but id was not found,
246 : * return true with both *objp and *propp null.
247 : */
248 : extern JS_FRIEND_API(JSBool)
249 : js_LookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
250 : JSProperty **propp);
251 :
252 : namespace js {
253 :
254 : inline bool
255 : LookupProperty(JSContext *cx, JSObject *obj, PropertyName *name,
256 : JSObject **objp, JSProperty **propp)
257 : {
258 : return js_LookupProperty(cx, obj, ATOM_TO_JSID(name), objp, propp);
259 : }
260 :
261 : }
262 :
263 : extern JS_FRIEND_API(JSBool)
264 : js_LookupElement(JSContext *cx, JSObject *obj, uint32_t index,
265 : JSObject **objp, JSProperty **propp);
266 :
267 : extern JSBool
268 : js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const js::Value *value,
269 : JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
270 :
271 : extern JSBool
272 : js_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, const js::Value *value,
273 : JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
274 :
275 : extern JSBool
276 : js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, js::Value *vp);
277 :
278 : extern JSBool
279 : js_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t, js::Value *vp);
280 :
281 : inline JSBool
282 3812 : js_GetProperty(JSContext *cx, JSObject *obj, jsid id, js::Value *vp)
283 : {
284 3812 : return js_GetProperty(cx, obj, obj, id, vp);
285 : }
286 :
287 : inline JSBool
288 : js_GetElement(JSContext *cx, JSObject *obj, uint32_t index, js::Value *vp)
289 : {
290 : return js_GetElement(cx, obj, obj, index, vp);
291 : }
292 :
293 : namespace js {
294 :
295 : extern JSBool
296 : GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, const Value &def, Value *vp);
297 :
298 : } /* namespace js */
299 :
300 : extern JSBool
301 : js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow,
302 : js::Value *vp, JSBool strict);
303 :
304 : namespace js {
305 :
306 : inline bool
307 : SetPropertyHelper(JSContext *cx, JSObject *obj, PropertyName *name, unsigned defineHow,
308 : Value *vp, JSBool strict)
309 : {
310 : return !!js_SetPropertyHelper(cx, obj, ATOM_TO_JSID(name), defineHow, vp, strict);
311 : }
312 :
313 : } /* namespace js */
314 :
315 : extern JSBool
316 : js_SetElementHelper(JSContext *cx, JSObject *obj, uint32_t index, unsigned defineHow,
317 : js::Value *vp, JSBool strict);
318 :
319 : extern JSBool
320 : js_GetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
321 :
322 : extern JSBool
323 : js_GetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
324 :
325 : extern JSBool
326 : js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
327 :
328 : extern JSBool
329 : js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
330 :
331 : extern JSBool
332 : js_DeleteProperty(JSContext *cx, JSObject *obj, js::PropertyName *name, js::Value *rval, JSBool strict);
333 :
334 : extern JSBool
335 : js_DeleteElement(JSContext *cx, JSObject *obj, uint32_t index, js::Value *rval, JSBool strict);
336 :
337 : extern JSBool
338 : js_DeleteSpecial(JSContext *cx, JSObject *obj, js::SpecialId sid, js::Value *rval, JSBool strict);
339 :
340 : extern JSBool
341 : js_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, js::Value *rval, JSBool strict);
342 :
343 : extern JSType
344 : js_TypeOf(JSContext *cx, JSObject *obj);
345 :
346 : namespace js {
347 :
348 : /* ES5 8.12.8. */
349 : extern JSBool
350 : DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
351 :
352 : extern Class ArrayClass;
353 : extern Class ArrayBufferClass;
354 : extern Class BlockClass;
355 : extern Class BooleanClass;
356 : extern Class CallableObjectClass;
357 : extern Class DateClass;
358 : extern Class ErrorClass;
359 : extern Class ElementIteratorClass;
360 : extern Class GeneratorClass;
361 : extern Class IteratorClass;
362 : extern Class JSONClass;
363 : extern Class MathClass;
364 : extern Class NumberClass;
365 : extern Class NormalArgumentsObjectClass;
366 : extern Class ObjectClass;
367 : extern Class ProxyClass;
368 : extern Class RegExpClass;
369 : extern Class RegExpStaticsClass;
370 : extern Class SlowArrayClass;
371 : extern Class StopIterationClass;
372 : extern Class StringClass;
373 : extern Class StrictArgumentsObjectClass;
374 : extern Class WeakMapClass;
375 : extern Class WithClass;
376 : extern Class XMLFilterClass;
377 :
378 : class ArgumentsObject;
379 : class BlockObject;
380 : class BooleanObject;
381 : class ClonedBlockObject;
382 : class DeclEnvObject;
383 : class ElementIteratorObject;
384 : class GlobalObject;
385 : class NestedScopeObject;
386 : class NewObjectCache;
387 : class NormalArgumentsObject;
388 : class NumberObject;
389 : class ScopeObject;
390 : class StaticBlockObject;
391 : class StrictArgumentsObject;
392 : class StringObject;
393 : class RegExpObject;
394 : class WithObject;
395 :
396 : } /* namespace js */
397 :
398 : /*
399 : * The public interface for an object.
400 : *
401 : * Implementation of the underlying structure occurs in ObjectImpl, from which
402 : * this struct inherits. This inheritance is currently public, but it will
403 : * eventually be made protected. For full details, see vm/ObjectImpl.{h,cpp}.
404 : *
405 : * The JSFunction struct is an extension of this struct allocated from a larger
406 : * GC size-class.
407 : */
408 : struct JSObject : public js::ObjectImpl
409 3737027 : {
410 : private:
411 : friend struct js::Shape;
412 : friend struct js::GCMarker;
413 : friend class js::NewObjectCache;
414 :
415 : #ifdef DEBUG
416 : void checkShapeConsistency();
417 : #endif
418 :
419 : /* Make the type object to use for LAZY_TYPE objects. */
420 : void makeLazyType(JSContext *cx);
421 :
422 : public:
423 : /*
424 : * Update the last property, keeping the number of allocated slots in sync
425 : * with the object's new slot span.
426 : */
427 : bool setLastProperty(JSContext *cx, const js::Shape *shape);
428 :
429 : /* As above, but does not change the slot span. */
430 : inline void setLastPropertyInfallible(const js::Shape *shape);
431 :
432 : /* Make a non-array object with the specified initial state. */
433 : static inline JSObject *create(JSContext *cx,
434 : js::gc::AllocKind kind,
435 : js::HandleShape shape,
436 : js::HandleTypeObject type,
437 : js::HeapSlot *slots);
438 :
439 : /* Make a dense array object with the specified initial state. */
440 : static inline JSObject *createDenseArray(JSContext *cx,
441 : js::gc::AllocKind kind,
442 : js::HandleShape shape,
443 : js::HandleTypeObject type,
444 : uint32_t length);
445 :
446 : /*
447 : * Remove the last property of an object, provided that it is safe to do so
448 : * (the shape and previous shape do not carry conflicting information about
449 : * the object itself).
450 : */
451 : inline void removeLastProperty(JSContext *cx);
452 : inline bool canRemoveLastProperty();
453 :
454 : /*
455 : * Update the slot span directly for a dictionary object, and allocate
456 : * slots to cover the new span if necessary.
457 : */
458 : bool setSlotSpan(JSContext *cx, uint32_t span);
459 :
460 : inline bool nativeContains(JSContext *cx, jsid id);
461 : inline bool nativeContains(JSContext *cx, const js::Shape &shape);
462 :
463 : /* Upper bound on the number of elements in an object. */
464 : static const uint32_t NELEMENTS_LIMIT = JS_BIT(28);
465 :
466 : public:
467 : inline bool setDelegate(JSContext *cx);
468 :
469 : inline bool isBoundFunction() const;
470 :
471 : /*
472 : * The meaning of the system object bit is defined by the API client. It is
473 : * set in JS_NewSystemObject and is queried by JS_IsSystemObject, but it
474 : * has no intrinsic meaning to SpiderMonkey.
475 : */
476 : inline bool isSystem() const;
477 : inline bool setSystem(JSContext *cx);
478 :
479 : inline bool hasSpecialEquality() const;
480 :
481 : inline bool watched() const;
482 : inline bool setWatched(JSContext *cx);
483 :
484 : /* See StackFrame::varObj. */
485 : inline bool isVarObj() const;
486 : inline bool setVarObj(JSContext *cx);
487 :
488 : /*
489 : * Objects with an uncacheable proto can have their prototype mutated
490 : * without inducing a shape change on the object. Property cache entries
491 : * and JIT inline caches should not be filled for lookups across prototype
492 : * lookups on the object.
493 : */
494 : inline bool hasUncacheableProto() const;
495 : inline bool setUncacheableProto(JSContext *cx);
496 :
497 908730 : bool generateOwnShape(JSContext *cx, js::Shape *newShape = NULL) {
498 908730 : return replaceWithNewEquivalentShape(cx, lastProperty(), newShape);
499 : }
500 :
501 : private:
502 : js::Shape *replaceWithNewEquivalentShape(JSContext *cx, js::Shape *existingShape,
503 : js::Shape *newShape = NULL);
504 :
505 : enum GenerateShape {
506 : GENERATE_NONE,
507 : GENERATE_SHAPE
508 : };
509 :
510 : bool setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag,
511 : GenerateShape generateShape = GENERATE_NONE);
512 :
513 : public:
514 : inline bool nativeEmpty() const;
515 :
516 : js::Shape *methodShapeChange(JSContext *cx, const js::Shape &shape);
517 : bool shadowingShapeChange(JSContext *cx, const js::Shape &shape);
518 :
519 : /*
520 : * Read barrier to clone a joined function object stored as a method.
521 : * Defined in jsobjinlines.h, but not declared inline per standard style in
522 : * order to avoid gcc warnings.
523 : */
524 : js::Shape *methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp);
525 :
526 : /* Whether method shapes can be added to this object. */
527 : inline bool canHaveMethodBarrier() const;
528 :
529 : /* Whether there may be indexed properties on this object. */
530 : inline bool isIndexed() const;
531 :
532 : inline uint32_t propertyCount() const;
533 :
534 : inline bool hasPropertyTable() const;
535 :
536 : inline size_t computedSizeOfThisSlotsElements() const;
537 :
538 : inline void sizeOfExcludingThis(JSMallocSizeOfFun mallocSizeOf,
539 : size_t *slotsSize, size_t *elementsSize,
540 : size_t *miscSize) const;
541 :
542 : static const uint32_t MAX_FIXED_SLOTS = 16;
543 :
544 : private:
545 : /*
546 : * Get internal pointers to the range of values starting at start and
547 : * running for length.
548 : */
549 : inline void getSlotRangeUnchecked(size_t start, size_t length,
550 : js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
551 : js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd);
552 : inline void getSlotRange(size_t start, size_t length,
553 : js::HeapSlot **fixedStart, js::HeapSlot **fixedEnd,
554 : js::HeapSlot **slotsStart, js::HeapSlot **slotsEnd);
555 : public:
556 :
557 : /* Accessors for properties. */
558 :
559 : /* Whether a slot is at a fixed offset from this object. */
560 : inline bool isFixedSlot(size_t slot);
561 :
562 : /* Index into the dynamic slots array to use for a dynamic slot. */
563 : inline size_t dynamicSlotIndex(size_t slot);
564 :
565 : /* Get a raw pointer to the object's properties. */
566 : inline const js::HeapSlot *getRawSlots();
567 :
568 : /*
569 : * Grow or shrink slots immediately before changing the slot span.
570 : * The number of allocated slots is not stored explicitly, and changes to
571 : * the slots must track changes in the slot span.
572 : */
573 : bool growSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount);
574 : void shrinkSlots(JSContext *cx, uint32_t oldCount, uint32_t newCount);
575 :
576 47931443 : bool hasDynamicSlots() const { return slots != NULL; }
577 :
578 : /* Compute dynamicSlotsCount() for this object. */
579 : inline size_t numDynamicSlots() const;
580 :
581 : protected:
582 : inline bool hasContiguousSlots(size_t start, size_t count) const;
583 :
584 : inline void initializeSlotRange(size_t start, size_t count);
585 : inline void invalidateSlotRange(size_t start, size_t count);
586 :
587 : inline bool updateSlotsForSpan(JSContext *cx, size_t oldSpan, size_t newSpan);
588 :
589 : public:
590 : /*
591 : * Trigger the write barrier on a range of slots that will no longer be
592 : * reachable.
593 : */
594 : inline void prepareSlotRangeForOverwrite(size_t start, size_t end);
595 : inline void prepareElementRangeForOverwrite(size_t start, size_t end);
596 :
597 : /*
598 : * Initialize a flat array of slots to this object at a start slot. The
599 : * caller must ensure that are enough slots.
600 : */
601 : void initSlotRange(size_t start, const js::Value *vector, size_t length);
602 :
603 : /*
604 : * Copy a flat array of slots to this object at a start slot. Caller must
605 : * ensure there are enough slots in this object.
606 : */
607 : void copySlotRange(size_t start, const js::Value *vector, size_t length);
608 :
609 : inline uint32_t slotSpan() const;
610 :
611 : void rollbackProperties(JSContext *cx, uint32_t slotSpan);
612 :
613 : #ifdef DEBUG
614 : enum SentinelAllowed {
615 : SENTINEL_NOT_ALLOWED,
616 : SENTINEL_ALLOWED
617 : };
618 :
619 : /*
620 : * Check that slot is in range for the object's allocated slots.
621 : * If sentinelAllowed then slot may equal the slot capacity.
622 : */
623 : bool slotInRange(unsigned slot, SentinelAllowed sentinel = SENTINEL_NOT_ALLOWED) const;
624 : #endif
625 :
626 : private:
627 219808582 : js::HeapSlot *getSlotAddressUnchecked(unsigned slot) {
628 219808582 : size_t fixed = numFixedSlots();
629 219808582 : if (slot < fixed)
630 93722692 : return fixedSlots() + slot;
631 126085890 : return slots + (slot - fixed);
632 : }
633 :
634 : public:
635 189938846 : js::HeapSlot *getSlotAddress(unsigned slot) {
636 : /*
637 : * This can be used to get the address of the end of the slots for the
638 : * object, which may be necessary when fetching zero-length arrays of
639 : * slots (e.g. for callObjVarArray).
640 : */
641 189938846 : JS_ASSERT(slotInRange(slot, SENTINEL_ALLOWED));
642 189938846 : return getSlotAddressUnchecked(slot);
643 : }
644 :
645 189737512 : js::HeapSlot &getSlotRef(unsigned slot) {
646 189737512 : JS_ASSERT(slotInRange(slot));
647 189737512 : return *getSlotAddress(slot);
648 : }
649 :
650 : inline js::HeapSlot &nativeGetSlotRef(unsigned slot);
651 :
652 271417685 : const js::Value &getSlot(unsigned slot) const {
653 271417685 : JS_ASSERT(slotInRange(slot));
654 271417685 : size_t fixed = numFixedSlots();
655 271417685 : if (slot < fixed)
656 128175553 : return fixedSlots()[slot];
657 143242132 : return slots[slot - fixed];
658 : }
659 :
660 : inline const js::Value &nativeGetSlot(unsigned slot) const;
661 : inline JSFunction *nativeGetMethod(const js::Shape *shape) const;
662 :
663 : inline void setSlot(unsigned slot, const js::Value &value);
664 : inline void initSlot(unsigned slot, const js::Value &value);
665 : inline void initSlotUnchecked(unsigned slot, const js::Value &value);
666 :
667 : inline void nativeSetSlot(unsigned slot, const js::Value &value);
668 : inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
669 :
670 : inline const js::Value &getReservedSlot(unsigned index) const;
671 : inline js::HeapSlot &getReservedSlotRef(unsigned index);
672 : inline void initReservedSlot(unsigned index, const js::Value &v);
673 : inline void setReservedSlot(unsigned index, const js::Value &v);
674 :
675 : /* For slots which are known to always be fixed, due to the way they are allocated. */
676 :
677 45 : js::HeapSlot &getFixedSlotRef(unsigned slot) {
678 45 : JS_ASSERT(slot < numFixedSlots());
679 45 : return fixedSlots()[slot];
680 : }
681 :
682 49050120 : const js::Value &getFixedSlot(unsigned slot) const {
683 49050120 : JS_ASSERT(slot < numFixedSlots());
684 49050120 : return fixedSlots()[slot];
685 : }
686 :
687 : inline void setFixedSlot(unsigned slot, const js::Value &value);
688 : inline void initFixedSlot(unsigned slot, const js::Value &value);
689 :
690 : /*
691 : * Marks this object as having a singleton type, and leave the type lazy.
692 : * Constructs a new, unique shape for the object.
693 : */
694 : inline bool setSingletonType(JSContext *cx);
695 :
696 : inline js::types::TypeObject *getType(JSContext *cx);
697 :
698 54233629 : const js::HeapPtr<js::types::TypeObject> &typeFromGC() const {
699 : /* Direct field access for use by GC. */
700 54233629 : return type_;
701 : }
702 :
703 : inline void setType(js::types::TypeObject *newType);
704 :
705 : js::types::TypeObject *getNewType(JSContext *cx, JSFunction *fun = NULL);
706 :
707 : #ifdef DEBUG
708 : bool hasNewType(js::types::TypeObject *newType);
709 : #endif
710 :
711 : /*
712 : * Mark an object that has been iterated over and is a singleton. We need
713 : * to recover this information in the object's type information after it
714 : * is purged on GC.
715 : */
716 : inline bool setIteratedSingleton(JSContext *cx);
717 :
718 : /*
719 : * Mark an object as requiring its default 'new' type to have unknown
720 : * properties.
721 : */
722 : bool setNewTypeUnknown(JSContext *cx);
723 :
724 : /* Set a new prototype for an object with a singleton type. */
725 : bool splicePrototype(JSContext *cx, JSObject *proto);
726 :
727 : /*
728 : * For bootstrapping, whether to splice a prototype for Function.prototype
729 : * or the global object.
730 : */
731 : bool shouldSplicePrototype(JSContext *cx);
732 :
733 : /*
734 : * Parents and scope chains.
735 : *
736 : * All script-accessible objects with a NULL parent are global objects,
737 : * and all global objects have a NULL parent. Some builtin objects which
738 : * are not script-accessible also have a NULL parent, such as parser
739 : * created functions for non-compileAndGo scripts.
740 : *
741 : * Except for the non-script-accessible builtins, the global with which an
742 : * object is associated can be reached by following parent links to that
743 : * global (see global()).
744 : *
745 : * The scope chain of an object is the link in the search path when a
746 : * script does a name lookup on a scope object. For JS internal scope
747 : * objects --- Call, DeclEnv and block --- the chain is stored in
748 : * the first fixed slot of the object, and the object's parent is the
749 : * associated global. For other scope objects, the chain is stored in the
750 : * object's parent.
751 : *
752 : * In compileAndGo code, scope chains can contain only internal scope
753 : * objects with a global object at the root as the scope of the outermost
754 : * non-function script. In non-compileAndGo code, the scope of the
755 : * outermost non-function script might not be a global object, and can have
756 : * a mix of other objects above it before the global object is reached.
757 : */
758 :
759 : /* Access the parent link of an object. */
760 : inline JSObject *getParent() const;
761 : bool setParent(JSContext *cx, JSObject *newParent);
762 :
763 : /*
764 : * Get the enclosing scope of an object. When called on non-scope object,
765 : * this will just be the global (the name "enclosing scope" still applies
766 : * in this situation because non-scope objects can be on the scope chain).
767 : */
768 : inline JSObject *enclosingScope();
769 :
770 : inline js::GlobalObject &global() const;
771 :
772 : /* Private data accessors. */
773 :
774 : inline bool hasPrivate() const;
775 : inline void *getPrivate() const;
776 : inline void setPrivate(void *data);
777 : inline void setPrivateUnbarriered(void *data);
778 : inline void initPrivate(void *data);
779 :
780 : /* Access private data for an object with a known number of fixed slots. */
781 : inline void *getPrivate(size_t nfixed) const;
782 :
783 : /* N.B. Infallible: NULL means 'no principal', not an error. */
784 : inline JSPrincipals *principals(JSContext *cx);
785 :
786 : /* Remove the type (and prototype) or parent from a new object. */
787 : inline bool clearType(JSContext *cx);
788 : bool clearParent(JSContext *cx);
789 :
790 : /*
791 : * ES5 meta-object properties and operations.
792 : */
793 :
794 : private:
795 : enum ImmutabilityType { SEAL, FREEZE };
796 :
797 : /*
798 : * The guts of Object.seal (ES5 15.2.3.8) and Object.freeze (ES5 15.2.3.9): mark the
799 : * object as non-extensible, and adjust each property's attributes appropriately: each
800 : * property becomes non-configurable, and if |freeze|, data properties become
801 : * read-only as well.
802 : */
803 : bool sealOrFreeze(JSContext *cx, ImmutabilityType it);
804 :
805 : bool isSealedOrFrozen(JSContext *cx, ImmutabilityType it, bool *resultp);
806 :
807 : static inline unsigned getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it);
808 :
809 : inline void *&privateRef(uint32_t nfixed) const;
810 :
811 : public:
812 : bool preventExtensions(JSContext *cx, js::AutoIdVector *props);
813 :
814 : /* ES5 15.2.3.8: non-extensible, all props non-configurable */
815 315 : inline bool seal(JSContext *cx) { return sealOrFreeze(cx, SEAL); }
816 : /* ES5 15.2.3.9: non-extensible, all properties non-configurable, all data props read-only */
817 1223267 : bool freeze(JSContext *cx) { return sealOrFreeze(cx, FREEZE); }
818 :
819 567 : bool isSealed(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, SEAL, resultp); }
820 572 : bool isFrozen(JSContext *cx, bool *resultp) { return isSealedOrFrozen(cx, FREEZE, resultp); }
821 :
822 : /* Accessors for elements. */
823 :
824 : inline bool ensureElements(JSContext *cx, unsigned cap);
825 : bool growElements(JSContext *cx, unsigned cap);
826 : void shrinkElements(JSContext *cx, unsigned cap);
827 :
828 : inline js::ElementIteratorObject *asElementIterator();
829 :
830 : /*
831 : * Array-specific getters and setters (for both dense and slow arrays).
832 : */
833 :
834 : bool allocateSlowArrayElements(JSContext *cx);
835 :
836 : inline uint32_t getArrayLength() const;
837 : inline void setArrayLength(JSContext *cx, uint32_t length);
838 :
839 : inline uint32_t getDenseArrayCapacity();
840 : inline uint32_t getDenseArrayInitializedLength();
841 : inline void setDenseArrayLength(uint32_t length);
842 : inline void setDenseArrayInitializedLength(uint32_t length);
843 : inline void ensureDenseArrayInitializedLength(JSContext *cx, unsigned index, unsigned extra);
844 : inline js::HeapSlotArray getDenseArrayElements();
845 : inline const js::Value &getDenseArrayElement(unsigned idx);
846 : inline void setDenseArrayElement(unsigned idx, const js::Value &val);
847 : inline void initDenseArrayElement(unsigned idx, const js::Value &val);
848 : inline void setDenseArrayElementWithType(JSContext *cx, unsigned idx, const js::Value &val);
849 : inline void initDenseArrayElementWithType(JSContext *cx, unsigned idx, const js::Value &val);
850 : inline void copyDenseArrayElements(unsigned dstStart, const js::Value *src, unsigned count);
851 : inline void initDenseArrayElements(unsigned dstStart, const js::Value *src, unsigned count);
852 : inline void moveDenseArrayElements(unsigned dstStart, unsigned srcStart, unsigned count);
853 : inline void moveDenseArrayElementsUnbarriered(unsigned dstStart, unsigned srcStart, unsigned count);
854 : inline bool denseArrayHasInlineSlots() const;
855 :
856 : /* Packed information for this array. */
857 : inline void markDenseArrayNotPacked(JSContext *cx);
858 :
859 : /*
860 : * ensureDenseArrayElements ensures that the dense array can hold at least
861 : * index + extra elements. It returns ED_OK on success, ED_FAILED on
862 : * failure to grow the array, ED_SPARSE when the array is too sparse to
863 : * grow (this includes the case of index + extra overflow). In the last
864 : * two cases the array is kept intact.
865 : */
866 : enum EnsureDenseResult { ED_OK, ED_FAILED, ED_SPARSE };
867 : inline EnsureDenseResult ensureDenseArrayElements(JSContext *cx, unsigned index, unsigned extra);
868 :
869 : /*
870 : * Check if after growing the dense array will be too sparse.
871 : * newElementsHint is an estimated number of elements to be added.
872 : */
873 : bool willBeSparseDenseArray(unsigned requiredCapacity, unsigned newElementsHint);
874 :
875 : JSBool makeDenseArraySlow(JSContext *cx);
876 :
877 : /*
878 : * If this array object has a data property with index i, set *vp to its
879 : * value and return true. If not, do vp->setMagic(JS_ARRAY_HOLE) and return
880 : * true. On OOM, report it and return false.
881 : */
882 : bool arrayGetOwnDataElement(JSContext *cx, size_t i, js::Value *vp);
883 :
884 : public:
885 : bool allocateArrayBufferSlots(JSContext *cx, uint32_t size, uint8_t *contents = NULL);
886 : inline uint32_t arrayBufferByteLength();
887 : inline uint8_t * arrayBufferDataOffset();
888 :
889 : public:
890 : /*
891 : * Date-specific getters and setters.
892 : */
893 :
894 : static const uint32_t JSSLOT_DATE_UTC_TIME = 0;
895 :
896 : /*
897 : * Cached slots holding local properties of the date.
898 : * These are undefined until the first actual lookup occurs
899 : * and are reset to undefined whenever the date's time is modified.
900 : */
901 : static const uint32_t JSSLOT_DATE_COMPONENTS_START = 1;
902 :
903 : static const uint32_t JSSLOT_DATE_LOCAL_TIME = 1;
904 : static const uint32_t JSSLOT_DATE_LOCAL_YEAR = 2;
905 : static const uint32_t JSSLOT_DATE_LOCAL_MONTH = 3;
906 : static const uint32_t JSSLOT_DATE_LOCAL_DATE = 4;
907 : static const uint32_t JSSLOT_DATE_LOCAL_DAY = 5;
908 : static const uint32_t JSSLOT_DATE_LOCAL_HOURS = 6;
909 : static const uint32_t JSSLOT_DATE_LOCAL_MINUTES = 7;
910 : static const uint32_t JSSLOT_DATE_LOCAL_SECONDS = 8;
911 :
912 : static const uint32_t DATE_CLASS_RESERVED_SLOTS = 9;
913 :
914 : inline const js::Value &getDateUTCTime() const;
915 : inline void setDateUTCTime(const js::Value &pthis);
916 :
917 : /*
918 : * Function-specific getters and setters.
919 : */
920 :
921 : friend struct JSFunction;
922 :
923 : inline JSFunction *toFunction();
924 : inline const JSFunction *toFunction() const;
925 :
926 : public:
927 : /*
928 : * Iterator-specific getters and setters.
929 : */
930 :
931 : static const uint32_t ITER_CLASS_NFIXED_SLOTS = 1;
932 :
933 : inline js::NativeIterator *getNativeIterator() const;
934 : inline void setNativeIterator(js::NativeIterator *);
935 :
936 : /*
937 : * XML-related getters and setters.
938 : */
939 :
940 : /*
941 : * Slots for XML-related classes are as follows:
942 : * - NamespaceClass.base reserves the *_NAME_* and *_NAMESPACE_* slots.
943 : * - QNameClass.base, AttributeNameClass, AnyNameClass reserve
944 : * the *_NAME_* and *_QNAME_* slots.
945 : * - Others (XMLClass, js_XMLFilterClass) don't reserve any slots.
946 : */
947 : private:
948 : static const uint32_t JSSLOT_NAME_PREFIX = 0; // shared
949 : static const uint32_t JSSLOT_NAME_URI = 1; // shared
950 :
951 : static const uint32_t JSSLOT_NAMESPACE_DECLARED = 2;
952 :
953 : static const uint32_t JSSLOT_QNAME_LOCAL_NAME = 2;
954 :
955 : public:
956 : static const uint32_t NAMESPACE_CLASS_RESERVED_SLOTS = 3;
957 : static const uint32_t QNAME_CLASS_RESERVED_SLOTS = 3;
958 :
959 : inline JSLinearString *getNamePrefix() const;
960 : inline jsval getNamePrefixVal() const;
961 : inline void setNamePrefix(JSLinearString *prefix);
962 : inline void clearNamePrefix();
963 :
964 : inline JSLinearString *getNameURI() const;
965 : inline jsval getNameURIVal() const;
966 : inline void setNameURI(JSLinearString *uri);
967 :
968 : inline jsval getNamespaceDeclared() const;
969 : inline void setNamespaceDeclared(jsval decl);
970 :
971 : inline JSAtom *getQNameLocalName() const;
972 : inline jsval getQNameLocalNameVal() const;
973 : inline void setQNameLocalName(JSAtom *name);
974 :
975 : /*
976 : * Proxy-specific getters and setters.
977 : */
978 : inline js::Wrapper *getWrapperHandler() const;
979 :
980 : /*
981 : * Back to generic stuff.
982 : */
983 : inline bool isCallable();
984 :
985 : inline void finish(JSContext *cx);
986 : JS_ALWAYS_INLINE void finalize(JSContext *cx, bool background);
987 :
988 : inline bool hasProperty(JSContext *cx, jsid id, bool *foundp, unsigned flags = 0);
989 :
990 : /*
991 : * Allocate and free an object slot.
992 : *
993 : * FIXME: bug 593129 -- slot allocation should be done by object methods
994 : * after calling object-parameter-free shape methods, avoiding coupling
995 : * logic across the object vs. shape module wall.
996 : */
997 : bool allocSlot(JSContext *cx, uint32_t *slotp);
998 : void freeSlot(JSContext *cx, uint32_t slot);
999 :
1000 : public:
1001 : bool reportNotConfigurable(JSContext* cx, jsid id, unsigned report = JSREPORT_ERROR);
1002 : bool reportNotExtensible(JSContext *cx, unsigned report = JSREPORT_ERROR);
1003 :
1004 : /*
1005 : * Get the property with the given id, then call it as a function with the
1006 : * given arguments, providing this object as |this|. If the property isn't
1007 : * callable a TypeError will be thrown. On success the value returned by
1008 : * the call is stored in *vp.
1009 : */
1010 : bool callMethod(JSContext *cx, jsid id, unsigned argc, js::Value *argv, js::Value *vp);
1011 :
1012 : private:
1013 : js::Shape *getChildProperty(JSContext *cx, js::Shape *parent, js::StackShape &child);
1014 :
1015 : protected:
1016 : /*
1017 : * Internal helper that adds a shape not yet mapped by this object.
1018 : *
1019 : * Notes:
1020 : * 1. getter and setter must be normalized based on flags (see jsscope.cpp).
1021 : * 2. !isExtensible() checking must be done by callers.
1022 : */
1023 : js::Shape *addPropertyInternal(JSContext *cx, jsid id,
1024 : JSPropertyOp getter, JSStrictPropertyOp setter,
1025 : uint32_t slot, unsigned attrs,
1026 : unsigned flags, int shortid, js::Shape **spp,
1027 : bool allowDictionary);
1028 :
1029 : private:
1030 : bool toDictionaryMode(JSContext *cx);
1031 :
1032 : struct TradeGutsReserved;
1033 : static bool ReserveForTradeGuts(JSContext *cx, JSObject *a, JSObject *b,
1034 : TradeGutsReserved &reserved);
1035 :
1036 : static void TradeGuts(JSContext *cx, JSObject *a, JSObject *b,
1037 : TradeGutsReserved &reserved);
1038 :
1039 : public:
1040 : /* Add a property whose id is not yet in this scope. */
1041 : js::Shape *addProperty(JSContext *cx, jsid id,
1042 : JSPropertyOp getter, JSStrictPropertyOp setter,
1043 : uint32_t slot, unsigned attrs,
1044 : unsigned flags, int shortid, bool allowDictionary = true);
1045 :
1046 : /* Add a data property whose id is not yet in this scope. */
1047 1812507 : js::Shape *addDataProperty(JSContext *cx, jsid id, uint32_t slot, unsigned attrs) {
1048 1812507 : JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
1049 1812507 : return addProperty(cx, id, NULL, NULL, slot, attrs, 0, 0);
1050 : }
1051 :
1052 : /* Add or overwrite a property for id in this scope. */
1053 : js::Shape *putProperty(JSContext *cx, jsid id,
1054 : JSPropertyOp getter, JSStrictPropertyOp setter,
1055 : uint32_t slot, unsigned attrs,
1056 : unsigned flags, int shortid);
1057 : inline js::Shape *
1058 3613 : putProperty(JSContext *cx, js::PropertyName *name,
1059 : JSPropertyOp getter, JSStrictPropertyOp setter,
1060 : uint32_t slot, unsigned attrs, unsigned flags, int shortid) {
1061 3613 : return putProperty(cx, js_CheckForStringIndex(ATOM_TO_JSID(name)), getter, setter, slot, attrs, flags, shortid);
1062 : }
1063 :
1064 : /* Change the given property into a sibling with the same id in this scope. */
1065 : js::Shape *changeProperty(JSContext *cx, js::Shape *shape, unsigned attrs, unsigned mask,
1066 : JSPropertyOp getter, JSStrictPropertyOp setter);
1067 :
1068 : /* Remove the property named by id from this object. */
1069 : bool removeProperty(JSContext *cx, jsid id);
1070 :
1071 : /* Clear the scope, making it empty. */
1072 : void clear(JSContext *cx);
1073 :
1074 : inline JSBool lookupGeneric(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp);
1075 : inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name, JSObject **objp, JSProperty **propp);
1076 : inline JSBool lookupElement(JSContext *cx, uint32_t index,
1077 : JSObject **objp, JSProperty **propp);
1078 : inline JSBool lookupSpecial(JSContext *cx, js::SpecialId sid,
1079 : JSObject **objp, JSProperty **propp);
1080 :
1081 : inline JSBool defineGeneric(JSContext *cx, jsid id, const js::Value &value,
1082 : JSPropertyOp getter = JS_PropertyStub,
1083 : JSStrictPropertyOp setter = JS_StrictPropertyStub,
1084 : unsigned attrs = JSPROP_ENUMERATE);
1085 : inline JSBool defineProperty(JSContext *cx, js::PropertyName *name, const js::Value &value,
1086 : JSPropertyOp getter = JS_PropertyStub,
1087 : JSStrictPropertyOp setter = JS_StrictPropertyStub,
1088 : unsigned attrs = JSPROP_ENUMERATE);
1089 :
1090 : inline JSBool defineElement(JSContext *cx, uint32_t index, const js::Value &value,
1091 : JSPropertyOp getter = JS_PropertyStub,
1092 : JSStrictPropertyOp setter = JS_StrictPropertyStub,
1093 : unsigned attrs = JSPROP_ENUMERATE);
1094 : inline JSBool defineSpecial(JSContext *cx, js::SpecialId sid, const js::Value &value,
1095 : JSPropertyOp getter = JS_PropertyStub,
1096 : JSStrictPropertyOp setter = JS_StrictPropertyStub,
1097 : unsigned attrs = JSPROP_ENUMERATE);
1098 :
1099 : inline JSBool getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp);
1100 : inline JSBool getProperty(JSContext *cx, JSObject *receiver, js::PropertyName *name,
1101 : js::Value *vp);
1102 : inline JSBool getElement(JSContext *cx, JSObject *receiver, uint32_t index, js::Value *vp);
1103 : /* If element is not present (e.g. array hole) *present is set to
1104 : false and the contents of *vp are unusable garbage. */
1105 : inline JSBool getElementIfPresent(JSContext *cx, JSObject *receiver, uint32_t index,
1106 : js::Value *vp, bool *present);
1107 : inline JSBool getSpecial(JSContext *cx, JSObject *receiver, js::SpecialId sid, js::Value *vp);
1108 :
1109 : inline JSBool getGeneric(JSContext *cx, jsid id, js::Value *vp);
1110 : inline JSBool getProperty(JSContext *cx, js::PropertyName *name, js::Value *vp);
1111 : inline JSBool getElement(JSContext *cx, uint32_t index, js::Value *vp);
1112 : inline JSBool getSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp);
1113 :
1114 : inline JSBool setGeneric(JSContext *cx, jsid id, js::Value *vp, JSBool strict);
1115 : inline JSBool setProperty(JSContext *cx, js::PropertyName *name, js::Value *vp, JSBool strict);
1116 : inline JSBool setElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict);
1117 : inline JSBool setSpecial(JSContext *cx, js::SpecialId sid, js::Value *vp, JSBool strict);
1118 :
1119 : JSBool nonNativeSetProperty(JSContext *cx, jsid id, js::Value *vp, JSBool strict);
1120 : JSBool nonNativeSetElement(JSContext *cx, uint32_t index, js::Value *vp, JSBool strict);
1121 :
1122 : inline JSBool getGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp);
1123 : inline JSBool getPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp);
1124 : inline JSBool getElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp);
1125 : inline JSBool getSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp);
1126 :
1127 : inline JSBool setGenericAttributes(JSContext *cx, jsid id, unsigned *attrsp);
1128 : inline JSBool setPropertyAttributes(JSContext *cx, js::PropertyName *name, unsigned *attrsp);
1129 : inline JSBool setElementAttributes(JSContext *cx, uint32_t index, unsigned *attrsp);
1130 : inline JSBool setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp);
1131 :
1132 : inline bool deleteProperty(JSContext *cx, js::PropertyName *name, js::Value *rval, bool strict);
1133 : inline bool deleteElement(JSContext *cx, uint32_t index, js::Value *rval, bool strict);
1134 : inline bool deleteSpecial(JSContext *cx, js::SpecialId sid, js::Value *rval, bool strict);
1135 : bool deleteByValue(JSContext *cx, const js::Value &property, js::Value *rval, bool strict);
1136 :
1137 : inline bool enumerate(JSContext *cx, JSIterateOp iterop, js::Value *statep, jsid *idp);
1138 : inline bool defaultValue(JSContext *cx, JSType hint, js::Value *vp);
1139 : inline JSType typeOf(JSContext *cx);
1140 : inline JSObject *thisObject(JSContext *cx);
1141 :
1142 : static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp);
1143 :
1144 : bool swap(JSContext *cx, JSObject *other);
1145 :
1146 : inline void initArrayClass();
1147 :
1148 : /*
1149 : * In addition to the generic object interface provided by JSObject,
1150 : * specific types of objects may provide additional operations. To access,
1151 : * these addition operations, callers should use the pattern:
1152 : *
1153 : * if (obj.isX()) {
1154 : * XObject &x = obj.asX();
1155 : * x.foo();
1156 : * }
1157 : *
1158 : * These XObject classes form a hierarchy. For example, for a cloned block
1159 : * object, the following predicates are true: isClonedBlock, isBlock,
1160 : * isNestedScope and isScope. Each of these has a respective class that
1161 : * derives and adds operations.
1162 : *
1163 : * A class XObject is defined in a vm/XObject{.h, .cpp, -inl.h} file
1164 : * triplet (along with any class YObject that derives XObject).
1165 : *
1166 : * Note that X represents a low-level representation and does not query the
1167 : * [[Class]] property of object defined by the spec (for this, see
1168 : * js::ObjectClassIs).
1169 : *
1170 : * SpiderMonkey has not been completely switched to the isX/asX/XObject
1171 : * pattern so in some cases there is no XObject class and the engine
1172 : * instead pokes directly at reserved slots and getPrivate. In such cases,
1173 : * consider adding the missing XObject class.
1174 : */
1175 :
1176 : /* Direct subtypes of JSObject: */
1177 : inline bool isArguments() const;
1178 : inline bool isArrayBuffer() const;
1179 : inline bool isArray() const;
1180 : inline bool isDate() const;
1181 : inline bool isDenseArray() const;
1182 : inline bool isElementIterator() const;
1183 : inline bool isError() const;
1184 : inline bool isFunction() const;
1185 : inline bool isGenerator() const;
1186 : inline bool isGlobal() const;
1187 : inline bool isIterator() const;
1188 : inline bool isNamespace() const;
1189 : inline bool isObject() const;
1190 : inline bool isQName() const;
1191 : inline bool isPrimitive() const;
1192 : inline bool isProxy() const;
1193 : inline bool isRegExp() const;
1194 : inline bool isRegExpStatics() const;
1195 : inline bool isScope() const;
1196 : inline bool isScript() const;
1197 : inline bool isSlowArray() const;
1198 : inline bool isStopIteration() const;
1199 : inline bool isWeakMap() const;
1200 : inline bool isXML() const;
1201 : inline bool isXMLId() const;
1202 :
1203 : /* Subtypes of ScopeObject. */
1204 : inline bool isBlock() const;
1205 : inline bool isCall() const;
1206 : inline bool isDeclEnv() const;
1207 : inline bool isNestedScope() const;
1208 : inline bool isWith() const;
1209 : inline bool isClonedBlock() const;
1210 : inline bool isStaticBlock() const;
1211 :
1212 : /* Subtypes of PrimitiveObject. */
1213 : inline bool isBoolean() const;
1214 : inline bool isNumber() const;
1215 : inline bool isString() const;
1216 :
1217 : /* Subtypes of ArgumentsObject. */
1218 : inline bool isNormalArguments() const;
1219 : inline bool isStrictArguments() const;
1220 :
1221 : /* Subtypes of Proxy. */
1222 : inline bool isWrapper() const;
1223 : inline bool isFunctionProxy() const;
1224 : inline bool isCrossCompartmentWrapper() const;
1225 :
1226 : inline js::ArgumentsObject &asArguments();
1227 : inline const js::ArgumentsObject &asArguments() const;
1228 : inline js::BlockObject &asBlock();
1229 : inline js::BooleanObject &asBoolean();
1230 : inline js::CallObject &asCall();
1231 : inline js::ClonedBlockObject &asClonedBlock();
1232 : inline js::DeclEnvObject &asDeclEnv();
1233 : inline js::GlobalObject &asGlobal();
1234 : inline js::NestedScopeObject &asNestedScope();
1235 : inline js::NormalArgumentsObject &asNormalArguments();
1236 : inline js::NumberObject &asNumber();
1237 : inline js::RegExpObject &asRegExp();
1238 : inline js::ScopeObject &asScope();
1239 : inline js::StrictArgumentsObject &asStrictArguments();
1240 : inline js::StaticBlockObject &asStaticBlock();
1241 : inline js::StringObject &asString();
1242 : inline js::WithObject &asWith();
1243 :
1244 : static inline js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
1245 :
1246 : #ifdef DEBUG
1247 : void dump();
1248 : #endif
1249 :
1250 : private:
1251 : static void staticAsserts() {
1252 : MOZ_STATIC_ASSERT(sizeof(JSObject) == sizeof(js::shadow::Object),
1253 : "shadow interface must match actual interface");
1254 : MOZ_STATIC_ASSERT(sizeof(JSObject) == sizeof(js::ObjectImpl),
1255 : "JSObject itself must not have any fields");
1256 : MOZ_STATIC_ASSERT(sizeof(JSObject) % sizeof(js::Value) == 0,
1257 : "fixed slots after an object must be aligned");
1258 : }
1259 : };
1260 :
1261 : /*
1262 : * The only sensible way to compare JSObject with == is by identity. We use
1263 : * const& instead of * as a syntactic way to assert non-null. This leads to an
1264 : * abundance of address-of operators to identity. Hence this overload.
1265 : */
1266 : static JS_ALWAYS_INLINE bool
1267 1274515 : operator==(const JSObject &lhs, const JSObject &rhs)
1268 : {
1269 1274515 : return &lhs == &rhs;
1270 : }
1271 :
1272 : static JS_ALWAYS_INLINE bool
1273 262134 : operator!=(const JSObject &lhs, const JSObject &rhs)
1274 : {
1275 262134 : return &lhs != &rhs;
1276 : }
1277 :
1278 : struct JSObject_Slots2 : JSObject { js::Value fslots[2]; };
1279 : struct JSObject_Slots4 : JSObject { js::Value fslots[4]; };
1280 : struct JSObject_Slots8 : JSObject { js::Value fslots[8]; };
1281 : struct JSObject_Slots12 : JSObject { js::Value fslots[12]; };
1282 3737027 : struct JSObject_Slots16 : JSObject { js::Value fslots[16]; };
1283 :
1284 : #define JSSLOT_FREE(clasp) JSCLASS_RESERVED_SLOTS(clasp)
1285 :
1286 : class JSValueArray {
1287 : public:
1288 : jsval *array;
1289 : size_t length;
1290 :
1291 741146 : JSValueArray(jsval *v, size_t c) : array(v), length(c) {}
1292 : };
1293 :
1294 : class ValueArray {
1295 : public:
1296 : js::Value *array;
1297 : size_t length;
1298 :
1299 : ValueArray(js::Value *v, size_t c) : array(v), length(c) {}
1300 : };
1301 :
1302 : /* For manipulating JSContext::sharpObjectMap. */
1303 : extern bool
1304 : js_EnterSharpObject(JSContext *cx, JSObject *obj, JSIdArray **idap, bool *alreadySeen, bool *isSharp);
1305 :
1306 : extern void
1307 : js_LeaveSharpObject(JSContext *cx, JSIdArray **idap);
1308 :
1309 : /*
1310 : * Mark objects stored in map if GC happens between js_EnterSharpObject
1311 : * and js_LeaveSharpObject. GC calls this when map->depth > 0.
1312 : */
1313 : extern void
1314 : js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map);
1315 :
1316 : extern JSBool
1317 : js_HasOwnPropertyHelper(JSContext *cx, js::LookupGenericOp lookup, unsigned argc,
1318 : js::Value *vp);
1319 :
1320 : extern JSBool
1321 : js_HasOwnProperty(JSContext *cx, js::LookupGenericOp lookup, JSObject *obj, jsid id,
1322 : JSObject **objp, JSProperty **propp);
1323 :
1324 : extern JSBool
1325 : js_PropertyIsEnumerable(JSContext *cx, JSObject *obj, jsid id, js::Value *vp);
1326 :
1327 : #if JS_HAS_OBJ_PROTO_PROP
1328 : extern JSPropertySpec object_props[];
1329 : #else
1330 : #define object_props NULL
1331 : #endif
1332 :
1333 : extern JSFunctionSpec object_methods[];
1334 : extern JSFunctionSpec object_static_methods[];
1335 :
1336 : namespace js {
1337 :
1338 : bool
1339 : IsStandardClassResolved(JSObject *obj, js::Class *clasp);
1340 :
1341 : void
1342 : MarkStandardClassInitializedNoProto(JSObject *obj, js::Class *clasp);
1343 :
1344 : /*
1345 : * Cache for speeding up repetitive creation of objects in the VM.
1346 : * When an object is created which matches the criteria in the 'key' section
1347 : * below, an entry is filled with the resulting object.
1348 : */
1349 : class NewObjectCache
1350 91147 : {
1351 : struct Entry
1352 3737027 : {
1353 : /* Class of the constructed object. */
1354 : Class *clasp;
1355 :
1356 : /*
1357 : * Key with one of three possible values:
1358 : *
1359 : * - Global for the object. The object must have a standard class for
1360 : * which the global's prototype can be determined, and the object's
1361 : * parent will be the global.
1362 : *
1363 : * - Prototype for the object (cannot be global). The object's parent
1364 : * will be the prototype's parent.
1365 : *
1366 : * - Type for the object. The object's parent will be the type's
1367 : * prototype's parent.
1368 : */
1369 : gc::Cell *key;
1370 :
1371 : /* Allocation kind for the constructed object. */
1372 : gc::AllocKind kind;
1373 :
1374 : /* Number of bytes to copy from the template object. */
1375 : uint32_t nbytes;
1376 :
1377 : /*
1378 : * Template object to copy from, with the initial values of fields,
1379 : * fixed slots (undefined) and private data (NULL).
1380 : */
1381 : JSObject_Slots16 templateObject;
1382 : };
1383 :
1384 : Entry entries[41];
1385 :
1386 : void staticAsserts() {
1387 : JS_STATIC_ASSERT(gc::FINALIZE_OBJECT_LAST == gc::FINALIZE_OBJECT16_BACKGROUND);
1388 : }
1389 :
1390 : public:
1391 :
1392 : typedef int EntryIndex;
1393 :
1394 181266 : void reset() { PodZero(this); }
1395 :
1396 : /*
1397 : * Get the entry index for the given lookup, return whether there was a hit
1398 : * on an existing entry.
1399 : */
1400 : inline bool lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry);
1401 : inline bool lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry);
1402 : inline bool lookupType(Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, EntryIndex *pentry);
1403 :
1404 : /* Return a new object from a cache hit produced by a lookup method. */
1405 : inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry);
1406 :
1407 : /* Fill an entry after a cache miss. */
1408 : inline void fillProto(EntryIndex entry, Class *clasp, JSObject *proto, gc::AllocKind kind, JSObject *obj);
1409 : inline void fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj);
1410 : inline void fillType(EntryIndex entry, Class *clasp, js::types::TypeObject *type, gc::AllocKind kind, JSObject *obj);
1411 :
1412 : /* Invalidate any entries which might produce an object with shape/proto. */
1413 : void invalidateEntriesForShape(JSContext *cx, Shape *shape, JSObject *proto);
1414 :
1415 : private:
1416 : inline bool lookup(Class *clasp, gc::Cell *key, gc::AllocKind kind, EntryIndex *pentry);
1417 : inline void fill(EntryIndex entry, Class *clasp, gc::Cell *key, gc::AllocKind kind, JSObject *obj);
1418 : static inline void copyCachedToObject(JSObject *dst, JSObject *src);
1419 : };
1420 :
1421 : } /* namespace js */
1422 :
1423 : /*
1424 : * Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
1425 : */
1426 : extern const char js_watch_str[];
1427 : extern const char js_unwatch_str[];
1428 : extern const char js_hasOwnProperty_str[];
1429 : extern const char js_isPrototypeOf_str[];
1430 : extern const char js_propertyIsEnumerable_str[];
1431 :
1432 : #ifdef OLD_GETTER_SETTER_METHODS
1433 : extern const char js_defineGetter_str[];
1434 : extern const char js_defineSetter_str[];
1435 : extern const char js_lookupGetter_str[];
1436 : extern const char js_lookupSetter_str[];
1437 : #endif
1438 :
1439 : extern JSBool
1440 : js_PopulateObject(JSContext *cx, JSObject *newborn, JSObject *props);
1441 :
1442 : /*
1443 : * Fast access to immutable standard objects (constructors and prototypes).
1444 : */
1445 : extern JSBool
1446 : js_GetClassObject(JSContext *cx, JSObject *obj, JSProtoKey key,
1447 : JSObject **objp);
1448 :
1449 : /*
1450 : * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
1451 : * JSProto_Null, clasp must non-null.
1452 : */
1453 : extern JSBool
1454 : js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey key,
1455 : js::Value *vp, js::Class *clasp = NULL);
1456 :
1457 : // Specialized call for constructing |this| with a known function callee,
1458 : // and a known prototype.
1459 : extern JSObject *
1460 : js_CreateThisForFunctionWithProto(JSContext *cx, JSObject *callee, JSObject *proto);
1461 :
1462 : // Specialized call for constructing |this| with a known function callee.
1463 : extern JSObject *
1464 : js_CreateThisForFunction(JSContext *cx, JSObject *callee, bool newType);
1465 :
1466 : // Generic call for constructing |this|.
1467 : extern JSObject *
1468 : js_CreateThis(JSContext *cx, JSObject *callee);
1469 :
1470 : extern jsid
1471 : js_CheckForStringIndex(jsid id);
1472 :
1473 : /*
1474 : * Find or create a property named by id in obj's scope, with the given getter
1475 : * and setter, slot, attributes, and other members.
1476 : */
1477 : extern js::Shape *
1478 : js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
1479 : JSPropertyOp getter, JSStrictPropertyOp setter, uint32_t slot,
1480 : unsigned attrs, unsigned flags, int shortid);
1481 :
1482 : /*
1483 : * Change shape to have the given attrs, getter, and setter in scope, morphing
1484 : * it into a potentially new js::Shape. Return a pointer to the changed
1485 : * or identical property.
1486 : */
1487 : extern js::Shape *
1488 : js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
1489 : js::Shape *shape, unsigned attrs, unsigned mask,
1490 : JSPropertyOp getter, JSStrictPropertyOp setter);
1491 :
1492 : extern JSBool
1493 : js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id,
1494 : const js::Value &descriptor, JSBool *bp);
1495 :
1496 : namespace js {
1497 :
1498 : /*
1499 : * Flags for the defineHow parameter of js_DefineNativeProperty.
1500 : */
1501 : const unsigned DNP_CACHE_RESULT = 1; /* an interpreter call from JSOP_INITPROP */
1502 : const unsigned DNP_DONT_PURGE = 2; /* suppress js_PurgeScopeChain */
1503 : const unsigned DNP_SET_METHOD = 4; /* DefineNativeProperty,js_SetPropertyHelper
1504 : must pass the js::Shape::METHOD
1505 : flag on to JSObject::{add,put}Property */
1506 : const unsigned DNP_UNQUALIFIED = 8; /* Unqualified property set. Only used in
1507 : the defineHow argument of
1508 : js_SetPropertyHelper. */
1509 : const unsigned DNP_SKIP_TYPE = 0x10; /* Don't update type information */
1510 :
1511 : /*
1512 : * Return successfully added or changed shape or NULL on error.
1513 : */
1514 : extern const Shape *
1515 : DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value,
1516 : PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
1517 : unsigned flags, int shortid, unsigned defineHow = 0);
1518 :
1519 : inline const Shape *
1520 302687 : DefineNativeProperty(JSContext *cx, JSObject *obj, PropertyName *name, const Value &value,
1521 : PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
1522 : unsigned flags, int shortid, unsigned defineHow = 0)
1523 : {
1524 302687 : return DefineNativeProperty(cx, obj, ATOM_TO_JSID(name), value, getter, setter, attrs, flags,
1525 302687 : shortid, defineHow);
1526 : }
1527 :
1528 : /*
1529 : * Specialized subroutine that allows caller to preset JSRESOLVE_* flags.
1530 : */
1531 : extern bool
1532 : LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
1533 : JSObject **objp, JSProperty **propp);
1534 :
1535 : inline bool
1536 93070 : LookupPropertyWithFlags(JSContext *cx, JSObject *obj, PropertyName *name, unsigned flags,
1537 : JSObject **objp, JSProperty **propp)
1538 : {
1539 93070 : return LookupPropertyWithFlags(cx, obj, ATOM_TO_JSID(name), flags, objp, propp);
1540 : }
1541 :
1542 : /*
1543 : * Call the [[DefineOwnProperty]] internal method of obj.
1544 : *
1545 : * If obj is an array, this follows ES5 15.4.5.1.
1546 : * If obj is any other native object, this follows ES5 8.12.9.
1547 : * If obj is a proxy, this calls the proxy handler's defineProperty method.
1548 : * Otherwise, this reports an error and returns false.
1549 : */
1550 : extern bool
1551 : DefineProperty(JSContext *cx, JSObject *obj, const jsid &id, const PropDesc &desc, bool throwError,
1552 : bool *rval);
1553 :
1554 : /*
1555 : * Read property descriptors from props, as for Object.defineProperties. See
1556 : * ES5 15.2.3.7 steps 3-5.
1557 : */
1558 : extern bool
1559 : ReadPropertyDescriptors(JSContext *cx, JSObject *props, bool checkAccessors,
1560 : AutoIdVector *ids, AutoPropDescArrayRooter *descs);
1561 :
1562 : /*
1563 : * Constant to pass to js_LookupPropertyWithFlags to infer bits from current
1564 : * bytecode.
1565 : */
1566 : static const unsigned RESOLVE_INFER = 0xffff;
1567 :
1568 : /*
1569 : * If cacheResult is false, return JS_NO_PROP_CACHE_FILL on success.
1570 : */
1571 : extern bool
1572 : FindPropertyHelper(JSContext *cx, PropertyName *name, bool cacheResult, JSObject *scopeChain,
1573 : JSObject **objp, JSObject **pobjp, JSProperty **propp);
1574 :
1575 : /*
1576 : * Search for name either on the current scope chain or on the scope chain's
1577 : * global object, per the global parameter.
1578 : */
1579 : extern bool
1580 : FindProperty(JSContext *cx, PropertyName *name, JSObject *scopeChain,
1581 : JSObject **objp, JSObject **pobjp, JSProperty **propp);
1582 :
1583 : extern JSObject *
1584 : FindIdentifierBase(JSContext *cx, JSObject *scopeChain, PropertyName *name);
1585 :
1586 : }
1587 :
1588 : extern JSObject *
1589 : js_FindVariableScope(JSContext *cx, JSFunction **funp);
1590 :
1591 : /*
1592 : * JSGET_CACHE_RESULT is the analogue of JSDNP_CACHE_RESULT for js_GetMethod.
1593 : *
1594 : * JSGET_METHOD_BARRIER (the default, hence 0 but provided for documentation)
1595 : * enables a read barrier that preserves standard function object semantics (by
1596 : * default we assume our caller won't leak a joined callee to script, where it
1597 : * would create hazardous mutable object sharing as well as observable identity
1598 : * according to == and ===.
1599 : *
1600 : * JSGET_NO_METHOD_BARRIER avoids the performance overhead of the method read
1601 : * barrier, which is not needed when invoking a lambda that otherwise does not
1602 : * leak its callee reference (via arguments.callee or its name).
1603 : */
1604 : const unsigned JSGET_METHOD_BARRIER = 0; // get can leak joined function object
1605 : const unsigned JSGET_NO_METHOD_BARRIER = 1; // call to joined function can't leak
1606 : const unsigned JSGET_CACHE_RESULT = 2; // from a caching interpreter opcode
1607 :
1608 : /*
1609 : * NB: js_NativeGet and js_NativeSet are called with the scope containing shape
1610 : * (pobj's scope for Get, obj's for Set) locked, and on successful return, that
1611 : * scope is again locked. But on failure, both functions return false with the
1612 : * scope containing shape unlocked.
1613 : */
1614 : extern JSBool
1615 : js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, const js::Shape *shape, unsigned getHow,
1616 : js::Value *vp);
1617 :
1618 : extern JSBool
1619 : js_NativeSet(JSContext *cx, JSObject *obj, const js::Shape *shape, bool added,
1620 : bool strict, js::Value *vp);
1621 :
1622 : namespace js {
1623 :
1624 : bool
1625 : GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uint32_t getHow, Value *vp);
1626 :
1627 : inline bool
1628 : GetPropertyHelper(JSContext *cx, JSObject *obj, PropertyName *name, uint32_t getHow, Value *vp)
1629 : {
1630 : return GetPropertyHelper(cx, obj, ATOM_TO_JSID(name), getHow, vp);
1631 : }
1632 :
1633 : bool
1634 : GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, PropertyDescriptor *desc);
1635 :
1636 : bool
1637 : GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, Value *vp);
1638 :
1639 : bool
1640 : NewPropertyDescriptorObject(JSContext *cx, const PropertyDescriptor *desc, Value *vp);
1641 :
1642 : } /* namespace js */
1643 :
1644 : extern JSBool
1645 : js_GetMethod(JSContext *cx, JSObject *obj, jsid id, unsigned getHow, js::Value *vp);
1646 :
1647 : namespace js {
1648 :
1649 : inline bool
1650 : GetMethod(JSContext *cx, JSObject *obj, PropertyName *name, unsigned getHow, Value *vp)
1651 : {
1652 : return js_GetMethod(cx, obj, ATOM_TO_JSID(name), getHow, vp);
1653 : }
1654 :
1655 : } /* namespace js */
1656 :
1657 : /*
1658 : * Change attributes for the given native property. The caller must ensure
1659 : * that obj is locked and this function always unlocks obj on return.
1660 : */
1661 : extern JSBool
1662 : js_SetNativeAttributes(JSContext *cx, JSObject *obj, js::Shape *shape,
1663 : unsigned attrs);
1664 :
1665 : namespace js {
1666 :
1667 : /*
1668 : * If obj has an already-resolved data property for methodid, return true and
1669 : * store the property value in *vp.
1670 : */
1671 : extern bool
1672 : HasDataProperty(JSContext *cx, JSObject *obj, jsid methodid, js::Value *vp);
1673 :
1674 : extern JSBool
1675 : CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
1676 : js::Value *vp, unsigned *attrsp);
1677 :
1678 : } /* namespace js */
1679 :
1680 : extern bool
1681 : js_IsDelegate(JSContext *cx, JSObject *obj, const js::Value &v);
1682 :
1683 : /*
1684 : * Wrap boolean, number or string as Boolean, Number or String object.
1685 : * *vp must not be an object, null or undefined.
1686 : */
1687 : extern JSBool
1688 : js_PrimitiveToObject(JSContext *cx, js::Value *vp);
1689 :
1690 : extern JSBool
1691 : js_ValueToObjectOrNull(JSContext *cx, const js::Value &v, JSObject **objp);
1692 :
1693 : /* Throws if v could not be converted to an object. */
1694 : extern JSObject *
1695 : js_ValueToNonNullObject(JSContext *cx, const js::Value &v);
1696 :
1697 : namespace js {
1698 :
1699 : /*
1700 : * Invokes the ES5 ToObject algorithm on *vp, writing back the object to vp.
1701 : * If *vp might already be an object, use ToObject.
1702 : */
1703 : extern JSObject *
1704 : ToObjectSlow(JSContext *cx, Value *vp);
1705 :
1706 : JS_ALWAYS_INLINE JSObject *
1707 27193592 : ToObject(JSContext *cx, Value *vp)
1708 : {
1709 27193592 : if (vp->isObject())
1710 27192279 : return &vp->toObject();
1711 1313 : return ToObjectSlow(cx, vp);
1712 : }
1713 :
1714 : /* As for ToObject, but preserves the original value. */
1715 : inline JSObject *
1716 139711986 : ValueToObject(JSContext *cx, const Value &v)
1717 : {
1718 139711986 : if (v.isObject())
1719 134678203 : return &v.toObject();
1720 5033783 : return js_ValueToNonNullObject(cx, v);
1721 : }
1722 :
1723 : } /* namespace js */
1724 :
1725 : extern void
1726 : js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
1727 :
1728 : extern bool
1729 : js_ClearNative(JSContext *cx, JSObject *obj);
1730 :
1731 : extern JSBool
1732 : js_ReportGetterOnlyAssignment(JSContext *cx);
1733 :
1734 : extern unsigned
1735 : js_InferFlags(JSContext *cx, unsigned defaultFlags);
1736 :
1737 : /* Object constructor native. Exposed only so the JIT can know its address. */
1738 : JSBool
1739 : js_Object(JSContext *cx, unsigned argc, js::Value *vp);
1740 :
1741 : /*
1742 : * If protoKey is not JSProto_Null, then clasp is ignored. If protoKey is
1743 : * JSProto_Null, clasp must non-null.
1744 : *
1745 : * If protoKey is constant and scope is non-null, use GlobalObject's prototype
1746 : * methods instead.
1747 : */
1748 : extern JS_FRIEND_API(JSBool)
1749 : js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
1750 : JSObject **protop, js::Class *clasp = NULL);
1751 :
1752 : namespace js {
1753 :
1754 : extern bool
1755 : SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles);
1756 :
1757 : extern JSString *
1758 : obj_toStringHelper(JSContext *cx, JSObject *obj);
1759 :
1760 : extern JSBool
1761 : eval(JSContext *cx, unsigned argc, Value *vp);
1762 :
1763 : /*
1764 : * Performs a direct eval for the given arguments, which must correspond to the
1765 : * currently-executing stack frame, which must be a script frame. On completion
1766 : * the result is returned in args.rval.
1767 : */
1768 : extern bool
1769 : DirectEval(JSContext *cx, const CallArgs &args);
1770 :
1771 : /*
1772 : * True iff |v| is the built-in eval function for the global object that
1773 : * corresponds to |scopeChain|.
1774 : */
1775 : extern bool
1776 : IsBuiltinEvalForScope(JSObject *scopeChain, const js::Value &v);
1777 :
1778 : /* True iff fun is a built-in eval function. */
1779 : extern bool
1780 : IsAnyBuiltinEval(JSFunction *fun);
1781 :
1782 : /* 'call' should be for the eval/Function native invocation. */
1783 : extern JSPrincipals *
1784 : PrincipalsForCompiledCode(const CallReceiver &call, JSContext *cx);
1785 :
1786 : extern JSObject *
1787 : NonNullObject(JSContext *cx, const Value &v);
1788 :
1789 : extern const char *
1790 : InformalValueTypeName(const Value &v);
1791 :
1792 : } /* namespace js */
1793 :
1794 : #endif /* jsobj_h___ */
|