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

Last change on this file since 1881 was 1837, checked in by mjs, 23 years ago

Phase 1 of optimization to stop allocating references through the
collector. This step clearly splits evaluating to a reference and
evaluating to a value, and moves all of the reference-specific
operations from Value to Reference. A special ConstReference class
helps out for the one case where you need special reference
operations if the result is a reference, and not otherwise.

Also, Reference now inherits privately from Value, and there is a
new ReferenceList class that inherits privately from List, so the
uses of Reference and Value are now completely orthogonal. This
means that as the next step, their implementations can be
completely disentangled.

This step has no actual performance impact.

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