source: webkit/trunk/JavaScriptCore/kjs/object.h@ 2779

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