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

Last change on this file since 15385 was 15385, checked in by ggaren, 19 years ago

Reviewed by Maciej.


  • Removed context and exception parameters from JSObjectGetPropertyEnumerator, removing the spurious use of ExecState inside JavaScriptCore that made us think this was necessary in the first place.

(StringInstance::getPropertyList): Use getString instead of toString because
we know we're dealing with a string -- we put it there in the first place.
While we're at it, store the string's size instead of retrieving it each time
through the loop, to avoid the unnecessary killing of puppies.

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