]>
git.saurik.com Git - apple/javascriptcore.git/blob - kjs/object.h
3807bed013f511adc55c5dd1a1bf0b41a012f37f
   1 // -*- c-basic-offset: 2 -*- 
   3  *  This file is part of the KDE libraries 
   4  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 
   5  *  Copyright (C) 2001 Peter Kelly (pmk@post.com) 
   6  *  Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. 
   8  *  This library is free software; you can redistribute it and/or 
   9  *  modify it under the terms of the GNU Library General Public 
  10  *  License as published by the Free Software Foundation; either 
  11  *  version 2 of the License, or (at your option) any later version. 
  13  *  This library is distributed in the hope that it will be useful, 
  14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  16  *  Library General Public License for more details. 
  18  *  You should have received a copy of the GNU Library General Public License 
  19  *  along with this library; see the file COPYING.LIB.  If not, write to 
  20  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  21  *  Boston, MA 02110-1301, USA. 
  28 #include "CommonIdentifiers.h" 
  29 #include "ExecState.h" 
  32 #include "property_map.h" 
  33 #include "property_slot.h" 
  34 #include "scope_chain.h" 
  38   class InternalFunctionImp
; 
  39   class PropertyNameArray
; 
  45   // Property attributes 
  46   enum Attribute 
{ None         
= 0, 
  47                    ReadOnly     
= 1 << 1, // property can be only read, not written 
  48                    DontEnum     
= 1 << 2, // property doesn't appear in (for .. in ..) 
  49                    DontDelete   
= 1 << 3, // property can't be deleted 
  50                    Internal     
= 1 << 4, // an internal property, set to bypass checks 
  51                    Function     
= 1 << 5, // property is a function - only used by static hashtables 
  52                    GetterSetter 
= 1 << 6 }; // property is a getter or setter 
  59      * A string denoting the class name. Example: "Window". 
  61     const char* className
; 
  63      * Pointer to the class information of the base class. 
  64      * 0L if there is none. 
  66     const ClassInfo
* parentClass
; 
  68      * Static hash-table of properties. 
  70     const HashTable
* propHashTable
; 
  73   // This is an internal value object which stores getter and setter functions 
  75   class GetterSetterImp 
: public JSCell 
{ 
  77     JSType 
type() const { return GetterSetterType
; } 
  79     GetterSetterImp() : getter(0), setter(0) { } 
  81     virtual JSValue
* toPrimitive(ExecState
*, JSType preferred 
= UnspecifiedType
) const; 
  82     virtual bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
*& value
); 
  83     virtual bool toBoolean(ExecState 
*exec
) const; 
  84     virtual double toNumber(ExecState 
*exec
) const; 
  85     virtual UString 
toString(ExecState 
*exec
) const; 
  86     virtual JSObject 
*toObject(ExecState 
*exec
) const; 
  90     JSObject 
*getGetter() { return getter
; } 
  91     void setGetter(JSObject 
*g
) { getter 
= g
; } 
  92     JSObject 
*getSetter() { return setter
; } 
  93     void setSetter(JSObject 
*s
) { setter 
= s
; } 
 100   class JSObject 
: public JSCell 
{ 
 103      * Creates a new JSObject with the specified prototype 
 105      * @param proto The prototype 
 107     JSObject(JSValue
* proto
); 
 110      * Creates a new JSObject with a prototype of jsNull() 
 111      * (that is, the ECMAScript "null" value, not a null object pointer). 
 116     virtual JSType 
type() const; 
 119      * A pointer to a ClassInfo struct for this class. This provides a basic 
 120      * facility for run-time type information, and can be used to check an 
 121      * object's class an inheritance (see inherits()). This should 
 122      * always return a statically declared pointer, or 0 to indicate that 
 123      * there is no class information. 
 125      * This is primarily useful if you have application-defined classes that you 
 126      * wish to check against for casting purposes. 
 128      * For example, to specify the class info for classes FooImp and BarImp, 
 129      * where FooImp inherits from BarImp, you would add the following in your 
 130      * class declarations: 
 133      *   class BarImp : public JSObject { 
 134      *     virtual const ClassInfo *classInfo() const { return &info; } 
 135      *     static const ClassInfo info; 
 139      *   class FooImp : public JSObject { 
 140      *     virtual const ClassInfo *classInfo() const { return &info; } 
 141      *     static const ClassInfo info; 
 146      * And in your source file: 
 149      *   const ClassInfo BarImp::info = { "Bar", 0, 0 }; // no parent class 
 150      *   const ClassInfo FooImp::info = { "Foo", &BarImp::info, 0 }; 
 155     virtual const ClassInfo 
*classInfo() const; 
 158      * Checks whether this object inherits from the class with the specified 
 159      * classInfo() pointer. This requires that both this class and the other 
 160      * class return a non-NULL pointer for their classInfo() methods (otherwise 
 161      * it will return false). 
 163      * For example, for two JSObject pointers obj1 and obj2, you can check 
 164      * if obj1's class inherits from obj2's class using the following: 
 166      *   if (obj1->inherits(obj2->classInfo())) { 
 170      * If you have a handle to a statically declared ClassInfo, such as in the 
 171      * classInfo() example, you can check for inheritance without needing 
 172      * an instance of the other class: 
 174      *   if (obj1->inherits(FooImp::info)) { 
 178      * @param cinfo The ClassInfo pointer for the class you want to check 
 179      * inheritance against. 
 180      * @return true if this object's class inherits from class with the 
 181      * ClassInfo pointer specified in cinfo 
 183     bool inherits(const ClassInfo 
*cinfo
) const; 
 185     // internal properties (ECMA 262-3 8.6.2) 
 188      * Returns the prototype of this object. Note that this is not the same as 
 189      * the "prototype" property. 
 193      * @return The object's prototype 
 195     JSValue 
*prototype() const; 
 196     void setPrototype(JSValue 
*proto
); 
 199      * Returns the class name of the object 
 203      * @return The object's class name 
 206      * Implementation of the [[Class]] internal property (implemented by all 
 209      * The default implementation uses classInfo(). 
 210      * You should either implement classInfo(), or 
 211      * if you simply need a classname, you can reimplement className() 
 214     virtual UString 
className() const; 
 217      * Retrieves the specified property from the object. If neither the object 
 218      * or any other object in it's prototype chain have the property, this 
 219      * function will return Undefined. 
 223      * @param exec The current execution state 
 224      * @param propertyName The name of the property to retrieve 
 226      * @return The specified property, or Undefined 
 228     JSValue 
*get(ExecState 
*exec
, const Identifier 
&propertyName
) const; 
 229     JSValue 
*get(ExecState 
*exec
, unsigned propertyName
) const; 
 231     bool getPropertySlot(ExecState 
*, const Identifier
&, PropertySlot
&); 
 232     bool getPropertySlot(ExecState 
*, unsigned, PropertySlot
&); 
 234     virtual bool getOwnPropertySlot(ExecState 
*, const Identifier
&, PropertySlot
&); 
 235     virtual bool getOwnPropertySlot(ExecState 
*, unsigned index
, PropertySlot
&); 
 238      * Sets the specified property. 
 242      * @param exec The current execution state 
 243      * @param propertyName The name of the property to set 
 244      * @param propertyValue The value to set 
 246     virtual void put(ExecState
* exec
, const Identifier 
&propertyName
, JSValue
* value
, int attr 
= None
); 
 247     virtual void put(ExecState
* exec
, unsigned propertyName
, JSValue
* value
, int attr 
= None
); 
 250      * Used to check whether or not a particular property is allowed to be set 
 255      * @param exec The current execution state 
 256      * @param propertyName The name of the property 
 257      * @return true if the property can be set, otherwise false 
 260      * Implementation of the [[CanPut]] internal property (implemented by all 
 263     virtual bool canPut(ExecState 
*exec
, const Identifier 
&propertyName
) const; 
 266      * Checks if a property is enumerable, that is if it doesn't have the DontEnum 
 270      * @param exec The current execution state 
 271      * @param propertyName The name of the property 
 272      * @return true if the property is enumerable, otherwise false 
 274     bool propertyIsEnumerable(ExecState 
*exec
, const Identifier 
&propertyName
) const; 
 277      * Checks to see whether the object (or any object in it's prototype chain) 
 278      * has a property with the specified name. 
 282      * @param exec The current execution state 
 283      * @param propertyName The name of the property to check for 
 284      * @return true if the object has the property, otherwise false 
 286     bool hasProperty(ExecState
*, const Identifier
&) const; 
 287     bool hasProperty(ExecState
*, unsigned) const; 
 288     bool hasOwnProperty(ExecState
*, const Identifier
&) const; 
 291      * Removes the specified property from the object. 
 295      * @param exec The current execution state 
 296      * @param propertyName The name of the property to delete 
 297      * @return true if the property was successfully deleted or did not 
 298      * exist on the object. false if deleting the specified property is not 
 301     virtual bool deleteProperty(ExecState 
*exec
, const Identifier 
&propertyName
); 
 302     virtual bool deleteProperty(ExecState 
*exec
, unsigned propertyName
); 
 305      * Converts the object into a primitive value. The value return may differ 
 306      * depending on the supplied hint 
 310      * @param exec The current execution state 
 311      * @param hint The desired primitive type to convert to 
 312      * @return A primitive value converted from the objetc. Note that the 
 313      * type of primitive value returned may not be the same as the requested 
 317      * Implementation of the [[DefaultValue]] internal property (implemented by 
 320     virtual JSValue 
*defaultValue(ExecState 
*exec
, JSType hint
) const; 
 323      * Whether or not the object implements the construct() method. If this 
 324      * returns false you should not call the construct() method on this 
 325      * object (typically, an assertion will fail to indicate this). 
 327      * @return true if this object implements the construct() method, otherwise 
 330     virtual bool implementsConstruct() const; 
 333      * Creates a new object based on this object. Typically this means the 
 335      * 1. A new object is created 
 336      * 2. The prototype of the new object is set to the value of this object's 
 337      *    "prototype" property 
 338      * 3. The call() method of this object is called, with the new object 
 339      *    passed as the this value 
 340      * 4. The new object is returned 
 342      * In some cases, Host objects may differ from these semantics, although 
 343      * this is discouraged. 
 345      * If an error occurs during construction, the execution state's exception 
 346      * will be set. This can be tested for with ExecState::hadException(). 
 347      * Under some circumstances, the exception object may also be returned. 
 349      * Note: This function should not be called if implementsConstruct() returns 
 350      * false, in which case it will result in an assertion failure. 
 352      * @param exec The current execution state 
 353      * @param args The arguments to be passed to call() once the new object has 
 355      * @return The newly created & initialized object 
 358      * Implementation of the [[Construct]] internal property 
 360     virtual JSObject
* construct(ExecState
* exec
, const List
& args
); 
 361     virtual JSObject
* construct(ExecState
* exec
, const List
& args
, const Identifier
& functionName
, const UString
& sourceURL
, int lineNumber
); 
 364      * Whether or not the object implements the call() method. If this returns 
 365      * false you should not call the call() method on this object (typically, 
 366      * an assertion will fail to indicate this). 
 368      * @return true if this object implements the call() method, otherwise 
 371     virtual bool implementsCall() const; 
 374      * Calls this object as if it is a function. 
 376      * Note: This function should not be called if implementsCall() returns 
 377      * false, in which case it will result in an assertion failure. 
 381      * @param exec The current execution state 
 382      * @param thisObj The obj to be used as "this" within function execution. 
 383      * Note that in most cases this will be different from the C++ "this" 
 384      * object. For example, if the ECMAScript code "window.location->toString()" 
 385      * is executed, call() will be invoked on the C++ object which implements 
 386      * the toString method, with the thisObj being window.location 
 387      * @param args List of arguments to be passed to the function 
 388      * @return The return value from the function 
 390     JSValue 
*call(ExecState 
*exec
, JSObject 
*thisObj
, const List 
&args
); 
 391     virtual JSValue 
*callAsFunction(ExecState 
*exec
, JSObject 
*thisObj
, const List 
&args
); 
 394      * Whether or not the object implements the hasInstance() method. If this 
 395      * returns false you should not call the hasInstance() method on this 
 396      * object (typically, an assertion will fail to indicate this). 
 398      * @return true if this object implements the hasInstance() method, 
 401     virtual bool implementsHasInstance() const; 
 404      * Checks whether value delegates behavior to this object. Used by the 
 405      * instanceof operator. 
 407      * @param exec The current execution state 
 408      * @param value The value to check 
 409      * @return true if value delegates behavior to this object, otherwise 
 412     virtual bool hasInstance(ExecState 
*exec
, JSValue 
*value
); 
 414     virtual void getPropertyNames(ExecState
*, PropertyNameArray
&); 
 416     virtual JSValue
* toPrimitive(ExecState
*, JSType preferredType 
= UnspecifiedType
) const; 
 417     virtual bool getPrimitiveNumber(ExecState
*, double& number
, JSValue
*& value
); 
 418     virtual bool toBoolean(ExecState 
*exec
) const; 
 419     virtual double toNumber(ExecState 
*exec
) const; 
 420     virtual UString 
toString(ExecState 
*exec
) const; 
 421     virtual JSObject 
*toObject(ExecState 
*exec
) const; 
 423     bool getPropertyAttributes(const Identifier
& propertyName
, unsigned& attributes
) const; 
 425     // WebCore uses this to make document.all and style.filter undetectable 
 426     virtual bool masqueradeAsUndefined() const { return false; } 
 428     // This get function only looks at the property map. 
 429     // This is used e.g. by lookupOrCreateFunction (to cache a function, we don't want 
 430     // to look up in the prototype, it might already exist there) 
 431     JSValue 
*getDirect(const Identifier
& propertyName
) const 
 432         { return _prop
.get(propertyName
); } 
 433     JSValue 
**getDirectLocation(const Identifier
& propertyName
) 
 434         { return _prop
.getLocation(propertyName
); } 
 435     void putDirect(const Identifier 
&propertyName
, JSValue 
*value
, int attr 
= 0); 
 436     void putDirect(const Identifier 
&propertyName
, int value
, int attr 
= 0); 
 437     void removeDirect(const Identifier 
&propertyName
); 
 439     // convenience to add a function property under the function's own built-in name 
 440     void putDirectFunction(InternalFunctionImp
*, int attr 
= 0); 
 442     void fillGetterPropertySlot(PropertySlot
& slot
, JSValue 
**location
); 
 444     void defineGetter(ExecState 
*exec
, const Identifier
& propertyName
, JSObject 
*getterFunc
); 
 445     void defineSetter(ExecState 
*exec
, const Identifier
& propertyName
, JSObject 
*setterFunc
); 
 447     void saveProperties(SavedProperties 
&p
) const { _prop
.save(p
); } 
 448     void restoreProperties(const SavedProperties 
&p
) { _prop
.restore(p
); } 
 450     virtual bool isActivationObject() { return false; } 
 451     virtual bool isGlobalObject() const { return false; } 
 457     const HashEntry
* findPropertyHashEntry( const Identifier
& propertyName 
) const; 
 462    * Types of Native Errors available. For custom errors, GeneralError 
 465   enum ErrorType 
{ GeneralError   
= 0, 
 476    * @short Factory methods for error objects. 
 481      * Factory method for error objects. 
 483      * @param exec The current execution state 
 484      * @param errtype Type of error. 
 485      * @param message Optional error message. 
 486      * @param lineNumber Optional line number. 
 487      * @param sourceId Optional source id. 
 488      * @param sourceURL Optional source URL. 
 490     static JSObject 
*create(ExecState 
*, ErrorType
, const UString 
&message
, int lineNumber
, int sourceId
, const UString 
&sourceURL
); 
 491     static JSObject 
*create(ExecState 
*, ErrorType
, const char *message
); 
 494      * Array of error names corresponding to ErrorType 
 496     static const char * const * const errorNames
; 
 499 JSObject 
*throwError(ExecState 
*, ErrorType
, const UString 
&message
, int lineNumber
, int sourceId
, const UString 
&sourceURL
); 
 500 JSObject 
*throwError(ExecState 
*, ErrorType
, const UString 
&message
); 
 501 JSObject 
*throwError(ExecState 
*, ErrorType
, const char *message
); 
 502 JSObject 
*throwError(ExecState 
*, ErrorType
); 
 504 inline JSObject::JSObject(JSValue
* proto
) 
 510 inline JSObject::JSObject() 
 515 inline JSValue 
*JSObject::prototype() const 
 520 inline void JSObject::setPrototype(JSValue 
*proto
) 
 526 inline bool JSObject::inherits(const ClassInfo 
*info
) const 
 528     for (const ClassInfo 
*ci 
= classInfo(); ci
; ci 
= ci
->parentClass
) 
 534 // this method is here to be after the inline declaration of JSObject::inherits 
 535 inline bool JSCell::isObject(const ClassInfo 
*info
) const 
 537     return isObject() && static_cast<const JSObject 
*>(this)->inherits(info
); 
 540 // this method is here to be after the inline declaration of JSCell::isObject 
 541 inline bool JSValue::isObject(const ClassInfo 
*c
) const 
 543     return !JSImmediate::isImmediate(this) && asCell()->isObject(c
); 
 546 // It may seem crazy to inline a function this large but it makes a big difference 
 547 // since this is function very hot in variable lookup 
 548 inline bool JSObject::getPropertySlot(ExecState 
*exec
, const Identifier
& propertyName
, PropertySlot
& slot
) 
 550     JSObject 
*object 
= this; 
 552         if (object
->getOwnPropertySlot(exec
, propertyName
, slot
)) 
 555         JSValue 
*proto 
= object
->_proto
; 
 556         if (!proto
->isObject()) 
 559         object 
= static_cast<JSObject 
*>(proto
); 
 563 // It may seem crazy to inline a function this large, especially a virtual function, 
 564 // but it makes a big difference to property lookup that derived classes can inline their 
 565 // base class call to this. 
 566 ALWAYS_INLINE 
bool JSObject::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) 
 568     if (JSValue 
**location 
= getDirectLocation(propertyName
)) { 
 569         if (_prop
.hasGetterSetterProperties() && location
[0]->type() == GetterSetterType
) 
 570             fillGetterPropertySlot(slot
, location
); 
 572             slot
.setValueSlot(this, location
); 
 576     // non-standard Netscape extension 
 577     if (propertyName 
== exec
->propertyNames().underscoreProto
) { 
 578         slot
.setValueSlot(this, &_proto
); 
 585 inline void ScopeChain::release() 
 587     // This function is only called by deref(), 
 588     // Deref ensures these conditions are true. 
 589     ASSERT(_node 
&& _node
->refCount 
== 0); 
 590     ScopeChainNode 
*n 
= _node
; 
 592         ScopeChainNode 
*next 
= n
->next
; 
 595     } while (n 
&& --n
->refCount 
== 0); 
 598 inline JSValue
* JSObject::toPrimitive(ExecState
* exec
, JSType preferredType
) const 
 600     return defaultValue(exec
, preferredType
); 
 605 #endif // KJS_OBJECT_H