WebCore:
[WebKit-https.git] / JavaScriptCore / kjs / object.h
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 Apple Computer, Inc.
7  *
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.
12  *
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.
17  *
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., 59 Temple Place - Suite 330,
21  *  Boston, MA 02111-1307, USA.
22  *
23  */
24
25
26 #ifndef _KJS_OBJECT_H_
27 #define _KJS_OBJECT_H_
28
29 // Objects
30
31 // maximum global call stack size. Protects against accidental or
32 // malicious infinite recursions. Define to -1 if you want no limit.
33 #if APPLE_CHANGES
34 // Given OS X stack sizes we run out of stack at about 350 levels.
35 // If we improve our stack usage, we can bump this number.
36 #define KJS_MAX_STACK 100
37 #else
38 #define KJS_MAX_STACK 1000
39 #endif
40
41 #include "value.h"
42 #include "types.h"
43 #include "reference_list.h"
44 #include "property_map.h"
45 #include "scope_chain.h"
46
47 namespace KJS {
48
49   class HashTable;
50   class HashEntry;
51   class ListImp;
52   class ReferenceList;
53
54   // ECMA 262-3 8.6.1
55   // Attributes (only applicable to the Object type)
56   enum Attribute { None       = 0,
57                    ReadOnly   = 1 << 1, // property can be only read, not written
58                    DontEnum   = 1 << 2, // property doesn't appear in (for .. in ..)
59                    DontDelete = 1 << 3, // property can't be deleted
60                    Internal   = 1 << 4, // an internal property, set to by pass checks
61                    Function   = 1 << 5 }; // property is a function - only used by static hashtables
62
63   /**
64    * Class Information
65    */
66   struct ClassInfo {
67     /**
68      * A string denoting the class name. Example: "Window".
69      */
70     const char* className;
71     /**
72      * Pointer to the class information of the base class.
73      * 0L if there is none.
74      */
75     const ClassInfo *parentClass;
76     /**
77      * Static hash-table of properties.
78      */
79     const HashTable *propHashTable;
80     /**
81      * Reserved for future extension.
82      */
83     void *dummy;
84   };
85   
86   /**
87    * Represents an Object. This is a wrapper for ObjectImp
88    */
89   class Object : public Value {
90   public:
91     Object() { }
92     explicit Object(ObjectImp *v);
93     
94     ObjectImp *imp() const;
95
96     const ClassInfo *classInfo() const;
97     bool inherits(const ClassInfo *cinfo) const;
98
99     /**
100      * Converts a Value into an Object. If the value's type is not ObjectType,
101      * a null object will be returned (i.e. one with it's internal pointer set
102      * to 0). If you do not know for sure whether the value is of type
103      * ObjectType, you should check the @ref isNull() methods afterwards before
104      * calling any methods on the Object.
105      *
106      * @return The value converted to an object
107      */
108     static Object dynamicCast(const Value &v);
109
110     /**
111      * Returns the prototype of this object. Note that this is not the same as
112      * the "prototype" property.
113      *
114      * See ECMA 8.6.2
115      *
116      * @return The object's prototype
117      */
118     Value prototype() const;
119
120     /**
121      * Returns the class name of the object
122      *
123      * See ECMA 8.6.2
124      *
125      * @return The object's class name
126      */
127     UString className() const;
128
129     /**
130      * Retrieves the specified property from the object. If neither the object
131      * or any other object in it's prototype chain have the property, this
132      * function will return Undefined.
133      *
134      * See ECMA 8.6.2.1
135      *
136      * @param exec The current execution state
137      * @param propertyName The name of the property to retrieve
138      *
139      * @return The specified property, or Undefined
140      */
141     Value get(ExecState *exec, const Identifier &propertyName) const;
142     Value get(ExecState *exec, unsigned propertyName) const;
143
144     /**
145      * Sets the specified property.
146      *
147      * See ECMA 8.6.2.2
148      *
149      * @param exec The current execution state
150      * @param propertyName The name of the property to set
151      * @param propertyValue The value to set
152      */
153     void put(ExecState *exec, const Identifier &propertyName,
154              const Value &value, int attr = None);
155     void put(ExecState *exec, unsigned propertyName,
156              const Value &value, int attr = None);
157
158     /**
159      * Used to check whether or not a particular property is allowed to be set
160      * on an object
161      *
162      * See ECMA 8.6.2.3
163      *
164      * @param exec The current execution state
165      * @param propertyName The name of the property
166      * @return true if the property can be set, otherwise false
167      */
168     bool canPut(ExecState *exec, const Identifier &propertyName) const;
169
170     /**
171      * Checks to see whether the object (or any object in it's prototype chain)
172      * has a property with the specified name.
173      *
174      * See ECMA 8.6.2.4
175      *
176      * @param exec The current execution state
177      * @param propertyName The name of the property to check for
178      * @return true if the object has the property, otherwise false
179      */
180     bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
181     bool hasProperty(ExecState *exec, unsigned propertyName) const;
182
183     /**
184      * Removes the specified property from the object.
185      *
186      * See ECMA 8.6.2.5
187      *
188      * @param exec The current execution state
189      * @param propertyName The name of the property to delete
190      * @return true if the property was successfully deleted or did not
191      * exist on the object. false if deleting the specified property is not
192      * allowed.
193      */
194     bool deleteProperty(ExecState *exec, const Identifier &propertyName);
195     bool deleteProperty(ExecState *exec, unsigned propertyName);
196
197     /**
198      * Converts the object into a primitive value. The value return may differ
199      * depending on the supplied hint
200      *
201      * See ECMA 8.6.2.6
202      *
203      * @param exec The current execution state
204      * @param hint The desired primitive type to convert to
205      * @return A primitive value converted from the objetc. Note that the
206      * type of primitive value returned may not be the same as the requested
207      * hint.
208      */
209     Value defaultValue(ExecState *exec, Type hint) const;
210
211     /**
212      * Whether or not the object implements the construct() method. If this
213      * returns false you should not call the construct() method on this
214      * object (typically, an assertion will fail to indicate this).
215      *
216      * @return true if this object implements the construct() method, otherwise
217      * false
218      */
219     bool implementsConstruct() const;
220
221     /**
222      * Creates a new object based on this object. Typically this means the
223      * following:
224      * 1. A new object is created
225      * 2. The prototype of the new object is set to the value of this object's
226      *    "prototype" property
227      * 3. The call() method of this object is called, with the new object
228      *    passed as the this value
229      * 4. The new object is returned
230      *
231      * In some cases, Host objects may differ from these semantics, although
232      * this is discouraged.
233      *
234      * If an error occurs during construction, the execution state's exception
235      * will be set. This can be tested for with @ref ExecState::hadException().
236      * Under some circumstances, the exception object may also be returned.
237      *
238      * Note: This function should not be called if implementsConstruct() returns
239      * false, in which case it will result in an assertion failure.
240      *
241      * @param exec The current execution state
242      * @param args The arguments to be passed to call() once the new object has
243      * been created
244      * @return The newly created &amp; initialized object
245      */
246     Object construct(ExecState *exec, const List &args);
247     Object construct(ExecState *exec, const List &args, const UString &sourceURL, int lineNumber);
248
249     /**
250      * Whether or not the object implements the call() method. If this returns
251      * false you should not call the call() method on this object (typically,
252      * an assertion will fail to indicate this).
253      *
254      * @return true if this object implements the call() method, otherwise
255      * false
256      */
257     bool implementsCall() const;
258
259
260     /**
261      * Calls this object as if it is a function.
262      *
263      * Note: This function should not be called if implementsCall() returns
264      * false, in which case it will result in an assertion failure.
265      *
266      * See ECMA 8.6.2.3
267      *
268      * @param exec The current execution state
269      * @param thisObj The obj to be used as "this" within function execution.
270      * Note that in most cases this will be different from the C++ "this"
271      * object. For example, if the ECMAScript code "window.location.toString()"
272      * is executed, call() will be invoked on the C++ object which implements
273      * the toString method, with the thisObj being window.location
274      * @param args List of arguments to be passed to the function
275      * @return The return value from the function
276      */
277     Value call(ExecState *exec, Object &thisObj, const List &args);
278
279     /**
280      * Whether or not the object implements the hasInstance() method. If this
281      * returns false you should not call the hasInstance() method on this
282      * object (typically, an assertion will fail to indicate this).
283      *
284      * @return true if this object implements the hasInstance() method,
285      * otherwise false
286      */
287     bool implementsHasInstance() const;
288
289     /**
290      * Checks whether value delegates behaviour to this object. Used by the
291      * instanceof operator.
292      *
293      * @param exec The current execution state
294      * @param value The value to check
295      * @return true if value delegates behaviour to this object, otherwise
296      * false
297      */
298     Boolean hasInstance(ExecState *exec, const Value &value);
299
300     /**
301      * Returns the scope of this object. This is used when execution declared
302      * functions - the execution context for the function is initialized with
303      * extra object in it's scope. An example of this is functions declared
304      * inside other functions:
305      *
306      * function f() {
307      *
308      *   function b() {
309      *     return prototype;
310      *   }
311      *
312      *   var x = 4;
313      *   // do some stuff
314      * }
315      * f.prototype = new String();
316      *
317      * When the function f.b is executed, its scope will include properties of
318      * f. So in the example above the return value of f.b() would be the new
319      * String object that was assigned to f.prototype.
320      *
321      * @param exec The current execution state
322      * @return The function's scope
323      */
324     const ScopeChain &scope() const;
325     void setScope(const ScopeChain &s);
326
327     /**
328      * Returns a List of References to all the properties of the object. Used
329      * in "for x in y" statements. The list is created new, so it can be freely
330      * modified without affecting the object's properties. It should be deleted
331      * by the caller.
332      *
333      * Subclasses can override this method in ObjectImpl to provide the
334      * appearance of
335      * having extra properties other than those set specifically with put().
336      *
337      * @param exec The current execution state
338      * @param recursive Whether or not properties in the object's prototype
339      * chain should be
340      * included in the list.
341      * @return A List of References to properties of the object.
342      **/
343     ReferenceList propList(ExecState *exec, bool recursive = true);
344
345     /**
346      * Returns the internal value of the object. This is used for objects such
347      * as String and Boolean which are wrappers for native types. The interal
348      * value is the actual value represented by the wrapper objects.
349      *
350      * @see ECMA 8.6.2
351      * @return The internal value of the object
352      */
353     Value internalValue() const;
354
355     /**
356      * Sets the internal value of the object
357      *
358      * @see internalValue()
359      *
360      * @param v The new internal value
361      */
362     void setInternalValue(const Value &v);
363
364     void saveProperties(SavedProperties &p) const;
365     void restoreProperties(const SavedProperties &p);
366   };
367
368   inline Object Value::toObject(ExecState *exec) const { return rep->dispatchToObject(exec); }
369   
370   class ObjectImp : public ValueImp {
371   public:
372     /**
373      * Creates a new ObjectImp with the specified prototype
374      *
375      * @param proto The prototype
376      */
377     ObjectImp(const Object &proto);
378     ObjectImp(ObjectImp *proto);
379
380     /**
381      * Creates a new ObjectImp with a prototype of Null()
382      * (that is, the ECMAScript "null" value, not a null Object).
383      *
384      */
385     ObjectImp();
386
387     virtual ~ObjectImp();
388
389     virtual void mark();
390
391     Type type() const;
392
393     /**
394      * A pointer to a ClassInfo struct for this class. This provides a basic
395      * facility for run-time type information, and can be used to check an
396      * object's class an inheritance (see @ref inherits()). This should
397      * always return a statically declared pointer, or 0 to indicate that
398      * there is no class information.
399      *
400      * This is primarily useful if you have application-defined classes that you
401      * wish to check against for casting purposes.
402      *
403      * For example, to specify the class info for classes FooImp and BarImp,
404      * where FooImp inherits from BarImp, you would add the following in your
405      * class declarations:
406      *
407      *   class BarImp : public ObjectImp {
408      *     virtual const ClassInfo *classInfo() const { return &info; }
409      *     static const ClassInfo info;
410      *     // ...
411      *   };
412      *
413      *   class FooImp : public ObjectImp {
414      *     virtual const ClassInfo *classInfo() const { return &info; }
415      *     static const ClassInfo info;
416      *     // ...
417      *   };
418      *
419      * And in your source file:
420      *
421      *   const ClassInfo BarImp::info = {0, 0, 0}; // no parent class
422      *   const ClassInfo FooImp::info = {&BarImp::info, 0, 0};
423      *
424      * @see inherits()
425      */
426     virtual const ClassInfo *classInfo() const;
427
428     /**
429      * Checks whether this object inherits from the class with the specified
430      * classInfo() pointer. This requires that both this class and the other
431      * class return a non-NULL pointer for their classInfo() methods (otherwise
432      * it will return false).
433      *
434      * For example, for two ObjectImp pointers obj1 and obj2, you can check
435      * if obj1's class inherits from obj2's class using the following:
436      *
437      *   if (obj1->inherits(obj2->classInfo())) {
438      *     // ...
439      *   }
440      *
441      * If you have a handle to a statically declared ClassInfo, such as in the
442      * @ref classInfo() example, you can check for inheritance without needing
443      * an instance of the other class:
444      *
445      *   if (obj1->inherits(FooImp::info)) {
446      *     // ...
447      *   }
448      *
449      * @param cinfo The ClassInfo pointer for the class you want to check
450      * inheritance against.
451      * @return true if this object's class inherits from class with the
452      * ClassInfo pointer specified in cinfo
453      */
454     bool inherits(const ClassInfo *cinfo) const;
455
456     // internal properties (ECMA 262-3 8.6.2)
457
458     /**
459      * Implementation of the [[Prototype]] internal property (implemented by
460      * all Objects)
461      *
462      * @see Object::prototype()
463      */
464     Value prototype() const;
465     void setPrototype(const Value &proto);
466
467     /**
468      * Implementation of the [[Class]] internal property (implemented by all
469      * Objects)
470      *
471      * The default implementation uses classInfo().
472      * You should either implement @ref classInfo(), or
473      * if you simply need a classname, you can reimplement @ref className()
474      * instead.
475      *
476      * @see Object::className()
477      */
478     virtual UString className() const;
479
480     /**
481      * Implementation of the [[Get]] internal property (implemented by all
482      * Objects)
483      *
484      * @see Object::get()
485      */
486     // [[Get]] - must be implemented by all Objects
487     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
488     virtual Value get(ExecState *exec, unsigned propertyName) const;
489
490     /**
491      * Implementation of the [[Put]] internal property (implemented by all
492      * Objects)
493      *
494      * @see Object::put()
495      */
496     virtual void put(ExecState *exec, const Identifier &propertyName,
497                      const Value &value, int attr = None);
498     virtual void put(ExecState *exec, unsigned propertyName,
499                      const Value &value, int attr = None);
500
501     /**
502      * Implementation of the [[CanPut]] internal property (implemented by all
503      * Objects)
504      *
505      * @see Object::canPut()
506      */
507     virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
508
509     /**
510      * Implementation of the [[HasProperty]] internal property (implemented by
511      * all Objects)
512      *
513      * @see Object::hasProperty()
514      */
515     virtual bool hasProperty(ExecState *exec,
516                              const Identifier &propertyName) const;
517     virtual bool hasProperty(ExecState *exec, unsigned propertyName) const;
518
519     /**
520      * Implementation of the [[Delete]] internal property (implemented by all
521      * Objects)
522      *
523      * @see Object::deleteProperty()
524      */
525     virtual bool deleteProperty(ExecState *exec,
526                                 const Identifier &propertyName);
527     virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
528
529     /**
530      * Remove all properties from this object.
531      * This doesn't take DontDelete into account, and isn't in the ECMA spec.
532      * It's simply a quick way to remove everything before destroying.
533      */
534     void deleteAllProperties(ExecState *);
535
536     /**
537      * Implementation of the [[DefaultValue]] internal property (implemented by
538      * all Objects)
539      *
540      * @see Object::defaultValue()
541      */
542     virtual Value defaultValue(ExecState *exec, Type hint) const;
543
544     virtual bool implementsConstruct() const;
545     /**
546      * Implementation of the [[Construct]] internal property
547      *
548      * @see Object::construct()
549      */
550     virtual Object construct(ExecState *exec, const List &args);
551     virtual Object construct(ExecState *exec, const List &args, const UString &sourceURL, int lineNumber);
552
553     virtual bool implementsCall() const;
554     /**
555      * Implementation of the [[Call]] internal property
556      *
557      * @see Object::call()
558      */
559     virtual Value call(ExecState *exec, Object &thisObj,
560                        const List &args);
561
562     virtual bool implementsHasInstance() const;
563     /**
564      * Implementation of the [[HasInstance]] internal property
565      *
566      * @see Object::hasInstance()
567      */
568     virtual Boolean hasInstance(ExecState *exec, const Value &value);
569
570     /**
571      * Implementation of the [[Scope]] internal property
572      *
573      * @see Object::scope()
574      */
575     const ScopeChain &scope() const { return _scope; }
576     void setScope(const ScopeChain &s) { _scope = s; }
577
578     virtual ReferenceList propList(ExecState *exec, bool recursive = true);
579
580     Value internalValue() const;
581     void setInternalValue(const Value &v);
582     void setInternalValue(ValueImp *v);
583
584     Value toPrimitive(ExecState *exec,
585                       Type preferredType = UnspecifiedType) const;
586     bool toBoolean(ExecState *exec) const;
587     double toNumber(ExecState *exec) const;
588     UString toString(ExecState *exec) const;
589     Object toObject(ExecState *exec) const;
590
591     // This get method only looks at the property map.
592     // A bit like hasProperty(recursive=false), this doesn't go to the prototype.
593     // This is used e.g. by lookupOrCreateFunction (to cache a function, we don't want
594     // to look up in the prototype, it might already exist there)
595     ValueImp *getDirect(const Identifier& propertyName) const
596         { return _prop.get(propertyName); }
597     void putDirect(const Identifier &propertyName, ValueImp *value, int attr = 0);
598     void putDirect(const Identifier &propertyName, int value, int attr = 0);
599     
600     void saveProperties(SavedProperties &p) const { _prop.save(p); }
601     void restoreProperties(const SavedProperties &p) { _prop.restore(p); }
602
603 #if APPLE_CHANGES
604     bool forwardingScriptMessage() const { return _forwardingScriptMessage; }
605     void setForwardingScriptMessage(bool f) { _forwardingScriptMessage = f; }
606 #endif
607
608   protected:
609     PropertyMap _prop;
610   private:
611     const HashEntry* findPropertyHashEntry( const Identifier& propertyName ) const;
612     ValueImp *_proto;
613     ValueImp *_internalValue;
614     ScopeChain _scope;
615
616 #if APPLE_CHANGES
617     bool _forwardingScriptMessage;
618 #endif    
619   };
620
621   /**
622    * Types of Native Errors available. For custom errors, GeneralError
623    * should be used.
624    */
625   enum ErrorType { GeneralError   = 0,
626                    EvalError      = 1,
627                    RangeError     = 2,
628                    ReferenceError = 3,
629                    SyntaxError    = 4,
630                    TypeError      = 5,
631                    URIError       = 6};
632
633   /**
634    * @short Factory methods for error objects.
635    */
636   class Error {
637   public:
638     /**
639      * Factory method for error objects.
640      *
641      * @param exec The current execution state
642      * @param errtype Type of error.
643      * @param message Optional error message.
644      * @param lineno Optional line number.
645      * @param lineno Optional source id.
646      */
647     static Object create(ExecState *exec, ErrorType errtype = GeneralError,
648                          const char *message = 0, int lineno = -1,
649                          int sourceId = -1, const UString *sourceURL = 0);
650
651     /**
652      * Array of error names corresponding to @ref ErrorType
653      */
654     static const char * const * const errorNames;
655   };
656
657   inline Object::Object(ObjectImp *v) : Value(v) { }
658
659   inline ObjectImp *Object::imp() const { return static_cast<ObjectImp*>(rep); }
660
661   inline const ClassInfo *Object::classInfo() const
662     { return imp()->classInfo(); }
663
664   inline bool Object::inherits(const ClassInfo *cinfo) const
665     { return imp()->inherits(cinfo); }
666
667   inline Value Object::prototype() const
668     { return Value(imp()->prototype()); }
669
670   inline UString Object::className() const
671     { return imp()->className(); }
672
673   inline Value Object::get(ExecState *exec, const Identifier &propertyName) const
674     { return imp()->get(exec,propertyName); }
675
676   inline Value Object::get(ExecState *exec, unsigned propertyName) const
677     { return imp()->get(exec,propertyName); }
678
679   inline void Object::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
680     { imp()->put(exec,propertyName,value,attr); }
681
682   inline void Object::put(ExecState *exec, unsigned propertyName, const Value &value, int attr)
683     { imp()->put(exec,propertyName,value,attr); }
684
685   inline bool Object::canPut(ExecState *exec, const Identifier &propertyName) const
686     { return imp()->canPut(exec,propertyName); }
687
688   inline bool Object::hasProperty(ExecState *exec, const Identifier &propertyName) const
689     { return imp()->hasProperty(exec, propertyName); }
690
691   inline bool Object::hasProperty(ExecState *exec, unsigned propertyName) const
692     { return imp()->hasProperty(exec, propertyName); }
693
694   inline bool Object::deleteProperty(ExecState *exec, const Identifier &propertyName)
695     { return imp()->deleteProperty(exec,propertyName); }
696
697   inline bool Object::deleteProperty(ExecState *exec, unsigned propertyName)
698     { return imp()->deleteProperty(exec,propertyName); }
699
700   inline Value Object::defaultValue(ExecState *exec, Type hint) const
701     { return imp()->defaultValue(exec,hint); }
702
703   inline bool Object::implementsConstruct() const
704     { return imp()->implementsConstruct(); }
705
706   inline Object Object::construct(ExecState *exec, const List &args)
707     { return imp()->construct(exec,args); }
708   
709   inline Object Object::construct(ExecState *exec, const List &args, const UString &sourceURL, int lineNumber)
710   { return imp()->construct(exec,args,sourceURL,lineNumber); }
711
712   inline bool Object::implementsCall() const
713     { return imp()->implementsCall(); }
714
715   inline bool Object::implementsHasInstance() const
716     { return imp()->implementsHasInstance(); }
717
718   inline Boolean Object::hasInstance(ExecState *exec, const Value &value)
719     { return imp()->hasInstance(exec,value); }
720
721   inline const ScopeChain &Object::scope() const
722     { return imp()->scope(); }
723
724   inline void Object::setScope(const ScopeChain &s)
725     { imp()->setScope(s); }
726
727   inline ReferenceList Object::propList(ExecState *exec, bool recursive)
728     { return imp()->propList(exec,recursive); }
729
730   inline Value Object::internalValue() const
731     { return imp()->internalValue(); }
732
733   inline void Object::setInternalValue(const Value &v)
734     { imp()->setInternalValue(v); }
735
736   inline void Object::saveProperties(SavedProperties &p) const
737     { imp()->saveProperties(p); }
738   inline void Object::restoreProperties(const SavedProperties &p)
739     { imp()->restoreProperties(p); }
740
741 }; // namespace
742
743 #endif // _KJS_OBJECT_H_