LCOV - code coverage report
Current view: directory - js/src - jsobj.h (source / functions) Found Hit Coverage
Test: app.info Lines: 99 99 100.0 %
Date: 2012-06-02 Functions: 51 51 100.0 %

       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___ */

Generated by: LCOV version 1.7