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

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