]>
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