LCOV - code coverage report
Current view: directory - js/src - jsclass.h (source / functions) Found Hit Coverage
Test: app.info Lines: 54 30 55.6 %
Date: 2012-06-02 Functions: 18 13 72.2 %

       1                 : /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2                 :  * vim: set ts=4 sw=4 et tw=79 ft=cpp:
       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 SpiderMonkey JavaScript engine.
      18                 :  *
      19                 :  * The Initial Developer of the Original Code is
      20                 :  * Mozilla Corporation.
      21                 :  * Portions created by the Initial Developer are Copyright (C) 2009
      22                 :  * the Initial Developer. All Rights Reserved.
      23                 :  *
      24                 :  * Contributor(s):
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #ifndef jsclass_h__
      41                 : #define jsclass_h__
      42                 : /*
      43                 :  * A JSClass acts as a vtable for JS objects that allows JSAPI clients to
      44                 :  * control various aspects of the behavior of an object like property lookup.
      45                 :  * js::Class is an engine-private extension that allows more control over
      46                 :  * object behavior and, e.g., allows custom slow layout.
      47                 :  */
      48                 : #include "jsapi.h"
      49                 : #include "jsprvtd.h"
      50                 : 
      51                 : #ifdef __cplusplus
      52                 : 
      53                 : namespace js {
      54                 : 
      55                 : class PropertyName;
      56                 : class SpecialId;
      57                 : 
      58                 : static JS_ALWAYS_INLINE jsid
      59                 : SPECIALID_TO_JSID(const SpecialId &sid);
      60                 : 
      61                 : /*
      62                 :  * We partition the ways to refer to a property into three: by an index
      63                 :  * (uint32_t); by a string whose characters do not represent an index
      64                 :  * (PropertyName, see vm/String.h); and by various special values.
      65                 :  *
      66                 :  * Special values are encoded using SpecialId, which is layout-compatible but
      67                 :  * non-interconvertible with jsid.  A SpecialId may be: an object (used by E4X
      68                 :  * and perhaps eventually by Harmony-proposed private names); JSID_VOID, which
      69                 :  * does not occur in JS scripts but may be used to indicate the absence of a
      70                 :  * valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled.
      71                 :  */
      72                 : 
      73                 : class SpecialId {
      74                 :     uintptr_t bits;
      75                 : 
      76                 :     /* Needs access to raw bits. */
      77                 :     friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
      78                 : 
      79                 :     static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
      80                 :     static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
      81                 :     static const uintptr_t TYPE_DEFAULT_XML_NAMESPACE = JSID_TYPE_DEFAULT_XML_NAMESPACE;
      82                 :     static const uintptr_t TYPE_MASK = JSID_TYPE_MASK;
      83                 : 
      84            8172 :     SpecialId(uintptr_t bits) : bits(bits) { }
      85                 : 
      86                 :   public:
      87         4763782 :     SpecialId() : bits(TYPE_VOID) { }
      88                 : 
      89                 :     /* Object-valued */
      90                 : 
      91               0 :     SpecialId(JSObject &obj)
      92               0 :       : bits(uintptr_t(&obj) | TYPE_OBJECT)
      93                 :     {
      94               0 :         JS_ASSERT(&obj != NULL);
      95               0 :         JS_ASSERT((uintptr_t(&obj) & TYPE_MASK) == 0);
      96               0 :     }
      97                 : 
      98            8172 :     bool isObject() const {
      99            8172 :         return (bits & TYPE_MASK) == TYPE_OBJECT && bits != TYPE_OBJECT;
     100                 :     }
     101                 : 
     102               0 :     JSObject *toObject() const {
     103               0 :         JS_ASSERT(isObject());
     104               0 :         return reinterpret_cast<JSObject *>(bits & ~TYPE_MASK);
     105                 :     }
     106                 : 
     107                 :     /* Empty */
     108                 : 
     109               0 :     static SpecialId empty() {
     110               0 :         SpecialId sid(TYPE_OBJECT);
     111               0 :         JS_ASSERT(sid.isEmpty());
     112                 :         return sid;
     113                 :     }
     114                 : 
     115            8172 :     bool isEmpty() const {
     116            8172 :         return bits == TYPE_OBJECT;
     117                 :     }
     118                 : 
     119                 :     /* Void */
     120                 : 
     121               0 :     static SpecialId voidId() {
     122               0 :         SpecialId sid(TYPE_VOID);
     123               0 :         JS_ASSERT(sid.isVoid());
     124                 :         return sid;
     125                 :     }
     126                 : 
     127            8172 :     bool isVoid() const {
     128            8172 :         return bits == TYPE_VOID;
     129                 :     }
     130                 : 
     131                 :     /* Default XML namespace */
     132                 : 
     133            8172 :     static SpecialId defaultXMLNamespace() {
     134            8172 :         SpecialId sid(TYPE_DEFAULT_XML_NAMESPACE);
     135            8172 :         JS_ASSERT(sid.isDefaultXMLNamespace());
     136                 :         return sid;
     137                 :     }
     138                 : 
     139           16344 :     bool isDefaultXMLNamespace() const {
     140           16344 :         return bits == TYPE_DEFAULT_XML_NAMESPACE;
     141                 :     }
     142                 : };
     143                 : 
     144                 : static JS_ALWAYS_INLINE jsid
     145            8172 : SPECIALID_TO_JSID(const SpecialId &sid)
     146                 : {
     147                 :     jsid id;
     148            8172 :     JSID_BITS(id) = sid.bits;
     149            8172 :     JS_ASSERT_IF(sid.isObject(), JSID_IS_OBJECT(id) && JSID_TO_OBJECT(id) == sid.toObject());
     150            8172 :     JS_ASSERT_IF(sid.isVoid(), JSID_IS_VOID(id));
     151            8172 :     JS_ASSERT_IF(sid.isEmpty(), JSID_IS_EMPTY(id));
     152            8172 :     JS_ASSERT_IF(sid.isDefaultXMLNamespace(), JSID_IS_DEFAULT_XML_NAMESPACE(id));
     153                 :     return id;
     154                 : }
     155                 : 
     156                 : static JS_ALWAYS_INLINE bool
     157               9 : JSID_IS_SPECIAL(jsid id)
     158                 : {
     159              27 :     return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id) ||
     160              27 :            JSID_IS_DEFAULT_XML_NAMESPACE(id);
     161                 : }
     162                 : 
     163                 : static JS_ALWAYS_INLINE SpecialId
     164               0 : JSID_TO_SPECIALID(jsid id)
     165                 : {
     166               0 :     JS_ASSERT(JSID_IS_SPECIAL(id));
     167               0 :     if (JSID_IS_OBJECT(id))
     168               0 :         return SpecialId(*JSID_TO_OBJECT(id));
     169               0 :     if (JSID_IS_EMPTY(id))
     170               0 :         return SpecialId::empty();
     171               0 :     if (JSID_IS_VOID(id))
     172               0 :         return SpecialId::voidId();
     173               0 :     JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id));
     174               0 :     return SpecialId::defaultXMLNamespace();
     175                 : }
     176                 : 
     177                 : /* js::Class operation signatures. */
     178                 : 
     179                 : typedef JSBool
     180                 : (* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
     181                 :                     JSProperty **propp);
     182                 : typedef JSBool
     183                 : (* LookupPropOp)(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
     184                 :                  JSProperty **propp);
     185                 : typedef JSBool
     186                 : (* LookupElementOp)(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
     187                 :                     JSProperty **propp);
     188                 : typedef JSBool
     189                 : (* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
     190                 :                     JSProperty **propp);
     191                 : typedef JSBool
     192                 : (* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
     193                 :                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     194                 : typedef JSBool
     195                 : (* DefinePropOp)(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value,
     196                 :                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     197                 : typedef JSBool
     198                 : (* DefineElementOp)(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
     199                 :                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     200                 : typedef JSBool
     201                 : (* DefineSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
     202                 :                     PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
     203                 : typedef JSBool
     204                 : (* GenericIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
     205                 : typedef JSBool
     206                 : (* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp);
     207                 : typedef JSBool
     208                 : (* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp);
     209                 : typedef JSBool
     210                 : (* ElementIfPresentOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool* present);
     211                 : typedef JSBool
     212                 : (* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
     213                 : typedef JSBool
     214                 : (* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
     215                 : typedef JSBool
     216                 : (* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
     217                 : typedef JSBool
     218                 : (* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
     219                 : typedef JSBool
     220                 : (* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
     221                 : typedef JSBool
     222                 : (* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
     223                 : typedef JSBool
     224                 : (* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
     225                 : typedef JSBool
     226                 : (* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
     227                 : typedef JSBool
     228                 : (* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
     229                 : typedef JSBool
     230                 : (* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
     231                 : typedef JSBool
     232                 : (* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
     233                 : typedef JSBool
     234                 : (* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
     235                 : typedef JSType
     236                 : (* TypeOfOp)(JSContext *cx, JSObject *obj);
     237                 : 
     238                 : /*
     239                 :  * Prepare to make |obj| non-extensible; in particular, fully resolve its properties.
     240                 :  * On error, return false.
     241                 :  * If |obj| is now ready to become non-extensible, set |*fixed| to true and return true.
     242                 :  * If |obj| refuses to become non-extensible, set |*fixed| to false and return true; the
     243                 :  * caller will throw an appropriate error.
     244                 :  */
     245                 : typedef JSBool
     246                 : (* FixOp)(JSContext *cx, JSObject *obj, bool *fixed, AutoIdVector *props);
     247                 : 
     248                 : typedef JSObject *
     249                 : (* ObjectOp)(JSContext *cx, JSObject *obj);
     250                 : typedef void
     251                 : (* FinalizeOp)(JSContext *cx, JSObject *obj);
     252                 : 
     253                 : #define JS_CLASS_MEMBERS                                                      \
     254                 :     const char          *name;                                                \
     255                 :     uint32_t            flags;                                                \
     256                 :                                                                               \
     257                 :     /* Mandatory non-null function pointer members. */                        \
     258                 :     JSPropertyOp        addProperty;                                          \
     259                 :     JSPropertyOp        delProperty;                                          \
     260                 :     JSPropertyOp        getProperty;                                          \
     261                 :     JSStrictPropertyOp  setProperty;                                          \
     262                 :     JSEnumerateOp       enumerate;                                            \
     263                 :     JSResolveOp         resolve;                                              \
     264                 :     JSConvertOp         convert;                                              \
     265                 :     JSFinalizeOp        finalize;                                             \
     266                 :                                                                               \
     267                 :     /* Optionally non-null members start here. */                             \
     268                 :     JSCheckAccessOp     checkAccess;                                          \
     269                 :     JSNative            call;                                                 \
     270                 :     JSNative            construct;                                            \
     271                 :     JSHasInstanceOp     hasInstance;                                          \
     272                 :     JSTraceOp           trace
     273                 : 
     274                 : /*
     275                 :  * The helper struct to measure the size of JS_CLASS_MEMBERS to know how much
     276                 :  * we have to padd js::Class to match the size of JSClass;
     277                 :  */
     278                 : struct ClassSizeMeasurement
     279                 : {
     280                 :     JS_CLASS_MEMBERS;
     281                 : };
     282                 : 
     283                 : struct ClassExtension
     284                 : {
     285                 :     JSEqualityOp        equality;
     286                 :     JSObjectOp          outerObject;
     287                 :     JSObjectOp          innerObject;
     288                 :     JSIteratorOp        iteratorObject;
     289                 :     void               *unused;
     290                 : 
     291                 :     /*
     292                 :      * isWrappedNative is true only if the class is an XPCWrappedNative.
     293                 :      * WeakMaps use this to override the wrapper disposal optimization.
     294                 :      */
     295                 :     bool                isWrappedNative;
     296                 : };
     297                 : 
     298                 : #define JS_NULL_CLASS_EXT   {NULL,NULL,NULL,NULL,NULL,false}
     299                 : 
     300                 : struct ObjectOps
     301                 : {
     302                 :     LookupGenericOp     lookupGeneric;
     303                 :     LookupPropOp        lookupProperty;
     304                 :     LookupElementOp     lookupElement;
     305                 :     LookupSpecialOp     lookupSpecial;
     306                 :     DefineGenericOp     defineGeneric;
     307                 :     DefinePropOp        defineProperty;
     308                 :     DefineElementOp     defineElement;
     309                 :     DefineSpecialOp     defineSpecial;
     310                 :     GenericIdOp         getGeneric;
     311                 :     PropertyIdOp        getProperty;
     312                 :     ElementIdOp         getElement;
     313                 :     ElementIfPresentOp  getElementIfPresent; /* can be null */
     314                 :     SpecialIdOp         getSpecial;
     315                 :     StrictGenericIdOp   setGeneric;
     316                 :     StrictPropertyIdOp  setProperty;
     317                 :     StrictElementIdOp   setElement;
     318                 :     StrictSpecialIdOp   setSpecial;
     319                 :     GenericAttributesOp getGenericAttributes;
     320                 :     PropertyAttributesOp getPropertyAttributes;
     321                 :     ElementAttributesOp getElementAttributes;
     322                 :     SpecialAttributesOp getSpecialAttributes;
     323                 :     GenericAttributesOp setGenericAttributes;
     324                 :     PropertyAttributesOp setPropertyAttributes;
     325                 :     ElementAttributesOp setElementAttributes;
     326                 :     SpecialAttributesOp setSpecialAttributes;
     327                 :     DeletePropertyOp    deleteProperty;
     328                 :     DeleteElementOp     deleteElement;
     329                 :     DeleteSpecialOp     deleteSpecial;
     330                 : 
     331                 :     JSNewEnumerateOp    enumerate;
     332                 :     TypeOfOp            typeOf;
     333                 :     FixOp               fix;
     334                 :     ObjectOp            thisObject;
     335                 :     FinalizeOp          clear;
     336                 : };
     337                 : 
     338                 : #define JS_NULL_OBJECT_OPS                                                    \
     339                 :     {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,   \
     340                 :      NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,        \
     341                 :      NULL,NULL,NULL,NULL,NULL,NULL}
     342                 : 
     343                 : struct Class
     344                 : {
     345                 :     JS_CLASS_MEMBERS;
     346                 :     ClassExtension      ext;
     347                 :     ObjectOps           ops;
     348                 :     uint8_t             pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
     349                 :                             sizeof(ClassExtension) - sizeof(ObjectOps)];
     350                 : 
     351                 :     /* Class is not native and its map is not a scope. */
     352                 :     static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
     353                 : 
     354       749529233 :     bool isNative() const {
     355       749529233 :         return !(flags & NON_NATIVE);
     356                 :     }
     357                 : 
     358        71632106 :     bool hasPrivate() const {
     359        71632106 :         return !!(flags & JSCLASS_HAS_PRIVATE);
     360                 :     }
     361                 : };
     362                 : 
     363                 : JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
     364                 : JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
     365                 : JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
     366                 : JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
     367                 : JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
     368                 : JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
     369                 : JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate));
     370                 : JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve));
     371                 : JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert));
     372                 : JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize));
     373                 : JS_STATIC_ASSERT(offsetof(JSClass, checkAccess) == offsetof(Class, checkAccess));
     374                 : JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call));
     375                 : JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct));
     376                 : JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance));
     377                 : JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace));
     378                 : JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
     379                 : 
     380                 : static JS_ALWAYS_INLINE JSClass *
     381         4523542 : Jsvalify(Class *c)
     382                 : {
     383         4523542 :     return (JSClass *)c;
     384                 : }
     385                 : static JS_ALWAYS_INLINE const JSClass *
     386                 : Jsvalify(const Class *c)
     387                 : {
     388                 :     return (const JSClass *)c;
     389                 : }
     390                 : 
     391                 : static JS_ALWAYS_INLINE Class *
     392         3444831 : Valueify(JSClass *c)
     393                 : {
     394         3444831 :     return (Class *)c;
     395                 : }
     396                 : static JS_ALWAYS_INLINE const Class *
     397                 : Valueify(const JSClass *c)
     398                 : {
     399                 :     return (const Class *)c;
     400                 : }
     401                 : 
     402                 : /*
     403                 :  * Enumeration describing possible values of the [[Class]] internal property
     404                 :  * value of objects.
     405                 :  */
     406                 : enum ESClassValue {
     407                 :     ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, ESClass_RegExp
     408                 : };
     409                 : 
     410                 : /*
     411                 :  * Return whether the given object has the given [[Class]] internal property
     412                 :  * value. Beware, this query says nothing about the js::Class of the JSObject
     413                 :  * so the caller must not assume anything about obj's representation (e.g., obj
     414                 :  * may be a proxy).
     415                 :  */
     416                 : inline bool
     417                 : ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
     418                 : 
     419                 : /* Just a helper that checks v.isObject before calling ObjectClassIs. */
     420                 : inline bool
     421                 : IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx);
     422                 : 
     423                 : }  /* namespace js */
     424                 : 
     425                 : #endif  /* __cplusplus */
     426                 : 
     427                 : #endif  /* jsclass_h__ */

Generated by: LCOV version 1.7