also propagate updateContents() calls to parent frame
[kdelibs.git] / kjs / object.h
blob4d8552e0fbb4dc791c93101bc4c81b9d5faa3b49
1 // -*- c-basic-offset: 2 -*-
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.
25 #ifndef KJS_OBJECT_H
26 #define KJS_OBJECT_H
28 #include "global.h"
29 #include "JSType.h"
30 #include "interpreter.h"
31 #include "property_map.h"
32 #include "property_slot.h"
33 #include "scope_chain.h"
34 #include <wtf/AlwaysInline.h>
36 namespace KJS {
38 struct HashTable;
39 struct HashEntry;
40 struct ListImp;
41 class InternalFunctionImp;
42 class PropertyNameArray;
44 // ECMA 262-3 8.6.1
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
54 /**
55 * Class Information
57 struct ClassInfo {
58 /**
59 * A string denoting the class name. Example: "Window".
61 const char* className;
62 /**
63 * Pointer to the class information of the base class.
64 * 0L if there is none.
66 const ClassInfo *parentClass;
67 /**
68 * Static hash-table of properties.
70 const HashTable *propHashTable;
71 /**
72 * Reserved for future extension.
74 void *dummy;
77 // This is an internal value object which stores getter and setter functions
78 // for a property.
79 class GetterSetterImp : public JSCell {
80 public:
81 JSType type() const { return GetterSetterType; }
83 GetterSetterImp() : getter(0), setter(0) { }
85 virtual JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
86 virtual bool toBoolean(ExecState *exec) const;
87 virtual double toNumber(ExecState *exec) const;
88 virtual UString toString(ExecState *exec) const;
89 virtual JSObject *toObject(ExecState *exec) const;
91 virtual void mark();
93 JSObject *getGetter() { return getter; }
94 void setGetter(JSObject *g) { getter = g; }
95 JSObject *getSetter() { return setter; }
96 void setSetter(JSObject *s) { setter = s; }
98 private:
99 JSObject *getter;
100 JSObject *setter;
103 class KJS_EXPORT JSObject : public JSCell {
104 public:
106 * Creates a new JSObject with the specified prototype
108 * @param proto The prototype
110 explicit JSObject(JSValue* proto);
113 * Creates a new JSObject with a prototype of jsNull()
114 * (that is, the ECMAScript "null" value, not a null object pointer).
116 explicit JSObject();
118 virtual void mark();
119 virtual JSType type() const;
122 * A pointer to a ClassInfo struct for this class. This provides a basic
123 * facility for run-time type information, and can be used to check an
124 * object's class an inheritance (see inherits()). This should
125 * always return a statically declared pointer, or 0 to indicate that
126 * there is no class information.
128 * This is primarily useful if you have application-defined classes that you
129 * wish to check against for casting purposes.
131 * For example, to specify the class info for classes FooImp and BarImp,
132 * where FooImp inherits from BarImp, you would add the following in your
133 * class declarations:
135 * \code
136 * class BarImp : public JSObject {
137 * virtual const ClassInfo *classInfo() const { return &info; }
138 * static const ClassInfo info;
139 * // ...
140 * };
142 * class FooImp : public JSObject {
143 * virtual const ClassInfo *classInfo() const { return &info; }
144 * static const ClassInfo info;
145 * // ...
146 * };
147 * \endcode
149 * And in your source file:
151 * \code
152 * const ClassInfo BarImp::info = {"Bar", 0, 0, 0}; // no parent class
153 * const ClassInfo FooImp::info = {"Foo", &BarImp::info, 0, 0};
154 * \endcode
156 * @see inherits()
158 virtual const ClassInfo *classInfo() const;
161 * Checks whether this object inherits from the class with the specified
162 * classInfo() pointer. This requires that both this class and the other
163 * class return a non-NULL pointer for their classInfo() methods (otherwise
164 * it will return false).
166 * For example, for two JSObject pointers obj1 and obj2, you can check
167 * if obj1's class inherits from obj2's class using the following:
169 * if (obj1->inherits(obj2->classInfo())) {
170 * // ...
173 * If you have a handle to a statically declared ClassInfo, such as in the
174 * classInfo() example, you can check for inheritance without needing
175 * an instance of the other class:
177 * if (obj1->inherits(FooImp::info)) {
178 * // ...
181 * @param cinfo The ClassInfo pointer for the class you want to check
182 * inheritance against.
183 * @return true if this object's class inherits from class with the
184 * ClassInfo pointer specified in cinfo
186 bool inherits(const ClassInfo *cinfo) const;
188 // internal properties (ECMA 262-3 8.6.2)
191 * Returns the prototype of this object. Note that this is not the same as
192 * the "prototype" property.
194 * See ECMA 8.6.2
196 * @return The object's prototype
198 JSValue *prototype() const;
199 void setPrototype(JSValue *proto);
202 * Returns the class name of the object
204 * See ECMA 8.6.2
206 * @return The object's class name
209 * Implementation of the [[Class]] internal property (implemented by all
210 * Objects)
212 * The default implementation uses classInfo().
213 * You should either implement classInfo(), or
214 * if you simply need a classname, you can reimplement className()
215 * instead.
217 virtual UString className() const;
220 * Retrieves the specified property from the object. If neither the object
221 * or any other object in it's prototype chain have the property, this
222 * function will return Undefined.
224 * See ECMA 8.6.2.1
226 * @param exec The current execution state
227 * @param propertyName The name of the property to retrieve
229 * @return The specified property, or Undefined
231 JSValue *get(ExecState *exec, const Identifier &propertyName) const;
232 JSValue *get(ExecState *exec, unsigned propertyName) const;
234 bool getPropertySlot(ExecState *, const Identifier&, PropertySlot&);
235 bool getPropertySlot(ExecState *, unsigned, PropertySlot&);
237 virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
238 virtual bool getOwnPropertySlot(ExecState *, unsigned index, PropertySlot&);
241 * Sets the specified property.
243 * See ECMA 8.6.2.2
245 * @param exec The current execution state
246 * @param propertyName The name of the property to set
247 * @param propertyValue The value to set
249 virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
250 virtual void put(ExecState *exec, unsigned propertyName, JSValue *value, int attr = None);
253 * Used to check whether or not a particular property is allowed to be set
254 * on an object
256 * See ECMA 8.6.2.3
258 * @param exec The current execution state
259 * @param propertyName The name of the property
260 * @return true if the property can be set, otherwise false
263 * Implementation of the [[CanPut]] internal property (implemented by all
264 * Objects)
266 virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
269 * Checks if a property is enumerable, that is if it doesn't have the DontEnum
270 * flag set
272 * See ECMA 15.2.4
273 * @param exec The current execution state
274 * @param propertyName The name of the property
275 * @return true if the property is enumerable, otherwise false
277 bool propertyIsEnumerable(ExecState *exec, const Identifier &propertyName) const;
280 * Checks to see whether the object (or any object in it's prototype chain)
281 * has a property with the specified name.
283 * See ECMA 8.6.2.4
285 * @param exec The current execution state
286 * @param propertyName The name of the property to check for
287 * @return true if the object has the property, otherwise false
289 bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
290 bool hasProperty(ExecState *exec, unsigned propertyName) const;
293 * Removes the specified property from the object.
295 * See ECMA 8.6.2.5
297 * @param exec The current execution state
298 * @param propertyName The name of the property to delete
299 * @return true if the property was successfully deleted or did not
300 * exist on the object. false if deleting the specified property is not
301 * allowed.
303 virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
304 virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
307 * Converts the object into a primitive value. The value return may differ
308 * depending on the supplied hint
310 * See ECMA 8.6.2.6
312 * @param exec The current execution state
313 * @param hint The desired primitive type to convert to
314 * @return A primitive value converted from the objetc. Note that the
315 * type of primitive value returned may not be the same as the requested
316 * hint.
319 * Implementation of the [[DefaultValue]] internal property (implemented by
320 * all Objects)
322 virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
325 * Whether or not the object implements the construct() method. If this
326 * returns false you should not call the construct() method on this
327 * object (typically, an assertion will fail to indicate this).
329 * @return true if this object implements the construct() method, otherwise
330 * false
332 virtual bool implementsConstruct() const;
335 * Creates a new object based on this object. Typically this means the
336 * following:
337 * 1. A new object is created
338 * 2. The prototype of the new object is set to the value of this object's
339 * "prototype" property
340 * 3. The call() method of this object is called, with the new object
341 * passed as the this value
342 * 4. The new object is returned
344 * In some cases, Host objects may differ from these semantics, although
345 * this is discouraged.
347 * If an error occurs during construction, the execution state's exception
348 * will be set. This can be tested for with ExecState::hadException().
349 * Under some circumstances, the exception object may also be returned.
351 * Note: This function should not be called if implementsConstruct() returns
352 * false, in which case it will result in an assertion failure.
354 * @param exec The current execution state
355 * @param args The arguments to be passed to call() once the new object has
356 * been created
357 * @return The newly created &amp; initialized object
360 * Implementation of the [[Construct]] internal property
362 virtual JSObject* construct(ExecState* exec, const List& args);
363 virtual JSObject* construct(ExecState* exec, const List& args, const Identifier& functionName, const UString& sourceURL, int lineNumber);
366 * Whether or not the object implements the call() method. If this returns
367 * false you should not call the call() method on this object (typically,
368 * an assertion will fail to indicate this).
370 * @return true if this object implements the call() method, otherwise
371 * false
373 virtual bool implementsCall() const;
376 * Calls this object as if it is a function.
378 * Note: This function should not be called if implementsCall() returns
379 * false, in which case it will result in an assertion failure.
381 * See ECMA 8.6.2.3
383 * @param exec The current execution state
384 * @param thisObj The obj to be used as "this" within function execution.
385 * Note that in most cases this will be different from the C++ "this"
386 * object. For example, if the ECMAScript code "window.location->toString()"
387 * is executed, call() will be invoked on the C++ object which implements
388 * the toString method, with the thisObj being window.location
389 * @param args List of arguments to be passed to the function
390 * @return The return value from the function
392 JSValue *call(ExecState *exec, JSObject *thisObj, const List &args);
393 virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
396 * Whether or not the object implements the hasInstance() method. If this
397 * returns false you should not call the hasInstance() method on this
398 * object (typically, an assertion will fail to indicate this).
400 * @return true if this object implements the hasInstance() method,
401 * otherwise false
403 virtual bool implementsHasInstance() const;
406 * Checks whether value delegates behavior to this object. Used by the
407 * instanceof operator.
409 * @param exec The current execution state
410 * @param value The value to check
411 * @return true if value delegates behavior to this object, otherwise
412 * false
414 virtual bool hasInstance(ExecState *exec, JSValue *value);
416 virtual void getPropertyNames(ExecState*, PropertyNameArray&);
418 virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
419 virtual bool toBoolean(ExecState *exec) const;
420 virtual double toNumber(ExecState *exec) const;
421 virtual UString toString(ExecState *exec) const;
422 virtual JSObject *toObject(ExecState *exec) const;
424 bool getPropertyAttributes(const Identifier& propertyName, unsigned& attributes) const;
426 // Returns whether the object should be treated as undefined when doing equality comparisons
427 virtual bool masqueradeAsUndefined() const { return false; }
429 // This get function only looks at the property map.
430 // This is used e.g. by lookupOrCreateFunction (to cache a function, we don't want
431 // to look up in the prototype, it might already exist there)
432 JSValue *getDirect(const Identifier& propertyName) const
433 { return _prop.get(propertyName); }
434 JSValue **getDirectLocation(const Identifier& propertyName)
435 { return _prop.getLocation(propertyName); }
437 void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0)
438 { _prop.put(propertyName, value, attr); }
439 void putDirect(const Identifier &propertyName, int value, int attr = 0);
440 void removeDirect(const Identifier &propertyName);
442 // convenience to add a function property under the function's own built-in name
443 void putDirectFunction(InternalFunctionImp*, int attr = 0);
445 void fillGetterPropertySlot(PropertySlot& slot, JSValue **location);
447 void defineGetter(ExecState *exec, const Identifier& propertyName, JSObject *getterFunc);
448 void defineSetter(ExecState *exec, const Identifier& propertyName, JSObject *setterFunc);
451 * Remove all properties from this object.
452 * This doesn't take DontDelete into account, and isn't in the ECMA spec.
453 * It's simply a quick way to remove everything stored in the property map.
455 void clearProperties() { _prop.clear(); }
457 void saveProperties(SavedProperties &p) const { _prop.save(p); }
458 void restoreProperties(const SavedProperties &p) { _prop.restore(p); }
460 virtual bool isActivation() const { return false; }
462 // This is used to keep track of whether scope object have local
463 // variables introduced by something other than 'var'
464 bool isLocalInjected() const { return _prop.m_objLocalInjected; }
465 void setLocalInjected() { _prop.m_objLocalInjected = true; }
467 protected:
468 PropertyMap _prop;
469 private:
472 const HashEntry* findPropertyHashEntry( const Identifier& propertyName ) const;
473 JSValue *_proto;
474 #ifdef WIN32
475 JSObject(const JSObject&);
476 JSObject& operator=(const JSObject&);
477 #endif
481 * Types of Native Errors available. For custom errors, GeneralError
482 * should be used.
484 enum ErrorType { GeneralError = 0,
485 EvalError = 1,
486 RangeError = 2,
487 ReferenceError = 3,
488 SyntaxError = 4,
489 TypeError = 5,
490 URIError = 6};
493 * @short Factory methods for error objects.
495 class KJS_EXPORT Error {
496 public:
498 * Factory method for error objects.
500 * @param exec The current execution state
501 * @param errtype Type of error.
502 * @param message Optional error message.
503 * @param lineNumber Optional line number.
504 * @param sourceId Optional source id.
505 * @param sourceURL Optional source URL.
507 static JSObject *create(ExecState *, ErrorType, const UString &message, int lineNumber, int sourceId, const UString &sourceURL);
508 static JSObject *create(ExecState *, ErrorType, const char *message);
511 * Array of error names corresponding to ErrorType
513 static const char * const * const errorNames;
516 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const UString &message, int lineNumber, int sourceId, const UString &sourceURL);
517 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const UString &message);
518 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const char *message);
519 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType);
521 inline JSObject::JSObject(JSValue* proto)
522 : _proto(proto)
524 assert(proto);
527 inline JSObject::JSObject()
528 :_proto(jsNull())
531 inline JSValue *JSObject::prototype() const
533 return _proto;
536 inline void JSObject::setPrototype(JSValue *proto)
538 assert(proto);
539 _proto = proto;
542 inline bool JSObject::inherits(const ClassInfo *info) const
544 for (const ClassInfo *ci = classInfo(); ci; ci = ci->parentClass)
545 if (ci == info)
546 return true;
547 return false;
550 // this method is here to be after the inline declaration of JSObject::inherits
551 inline bool JSCell::isObject(const ClassInfo *info) const
553 return isObject() && static_cast<const JSObject *>(this)->inherits(info);
556 // this method is here to be after the inline declaration of JSCell::isObject
557 inline bool JSValue::isObject(const ClassInfo *c) const
559 return !JSImmediate::isImmediate(this) && asCell()->isObject(c);
562 // It may seem crazy to inline a function this large but it makes a big difference
563 // since this is function very hot in variable lookup
564 inline bool JSObject::getPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
566 JSObject *object = this;
567 slot.setPotentiallyWriteable();
568 while (true) {
569 if (object->getOwnPropertySlot(exec, propertyName, slot))
570 return true;
572 JSValue *proto = object->_proto;
573 if (!proto->isObject())
574 return false;
576 slot.setReadOnly();
578 object = static_cast<JSObject *>(proto);
582 // It may seem crazy to inline a function this large, especially a virtual function,
583 // but it makes a big difference to property lookup that derived classes can inline their
584 // base class call to this.
585 ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
587 if (JSValue **location = getDirectLocation(propertyName)) {
588 if (_prop.hasGetterSetterProperties() && location[0]->type() == GetterSetterType)
589 fillGetterPropertySlot(slot, location);
590 else
591 slot.setValueSlot(this, location);
592 return true;
595 // non-standard Netscape extension
596 if (propertyName == exec->propertyNames().underscoreProto) {
597 slot.setValueSlot(this, &_proto, PropertySlot::ForbidDirectWrite);
598 return true;
601 return false;
605 // FIXME: Put this function in a separate file named something like scope_chain_mark.h -- can't put it in scope_chain.h since it depends on JSObject.
607 inline void ScopeChain::mark()
609 for (ScopeChainNode *n = _node; n; n = n->next) {
610 JSObject *o = n->object;
611 if (!o->marked())
612 o->mark();
616 inline void ScopeChain::release()
618 // This function is only called by deref(),
619 // Deref ensures these conditions are true.
620 assert(_node && _node->refCount == 0);
621 ScopeChainNode *n = _node;
622 do {
623 ScopeChainNode *next = n->next;
624 delete n;
625 n = next;
626 } while (n && --n->refCount == 0);
629 inline JSValue* JSObject::toPrimitive(ExecState* exec, JSType preferredType) const
631 return defaultValue(exec, preferredType);
634 } // namespace
636 #endif // KJS_OBJECT_H