KJS

object.h
1 /*
2  * This file is part of the KDE libraries
3  * Copyright (C) 1999-2001 Harri Porten ([email protected])
4  * Copyright (C) 2001 Peter Kelly ([email protected])
5  * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
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., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #ifndef KJS_OBJECT_H
25 #define KJS_OBJECT_H
26 
27 #include "global.h"
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 #include "propertydescriptor.h"
35 
36 namespace KJS
37 {
38 
39 struct HashTable;
40 struct HashEntry;
41 struct ListImp;
42 class InternalFunctionImp;
43 class PropertyNameArray;
44 
48 struct ClassInfo {
52  const char *className;
65  void *dummy;
66 };
67 
68 // This is an internal value object which stores getter and setter functions
69 // for a property.
70 class GetterSetterImp : public JSCell
71 {
72 public:
73  JSType type() const
74  {
75  return GetterSetterType;
76  }
77 
78  GetterSetterImp() : getter(nullptr), setter(nullptr) { }
79 
80  virtual JSValue *toPrimitive(ExecState *exec, JSType preferred = UnspecifiedType) const;
81  virtual bool getPrimitiveNumber(ExecState *, double &number, JSValue *&value);
82  virtual bool toBoolean(ExecState *exec) const;
83  virtual double toNumber(ExecState *exec) const;
84  virtual UString toString(ExecState *exec) const;
85  virtual JSObject *toObject(ExecState *exec) const;
86 
87  virtual void mark();
88 
89  JSObject *getGetter()
90  {
91  return getter;
92  }
93  void setGetter(JSObject *g)
94  {
95  getter = g;
96  }
97  JSObject *getSetter()
98  {
99  return setter;
100  }
101  void setSetter(JSObject *s)
102  {
103  setter = s;
104  }
105 
106 private:
107  JSObject *getter;
108  JSObject *setter;
109 };
110 
111 class KJS_EXPORT JSObject : public JSCell
112 {
113 public:
119  explicit JSObject(JSValue *proto);
120 
125  explicit JSObject();
126 
127  virtual void mark();
128  virtual JSType type() const;
129 
167  virtual const ClassInfo *classInfo() const;
168 
195  bool inherits(const ClassInfo *cinfo) const;
196 
197  // internal properties (ECMA 262-3 8.6.2)
198 
207  JSValue *prototype() const;
208  void setPrototype(JSValue *proto);
209 
226  virtual UString className() const;
227 
240  JSValue *get(ExecState *exec, const Identifier &propertyName) const;
241  JSValue *get(ExecState *exec, unsigned propertyName) const;
242 
243  bool getPropertySlot(ExecState *, const Identifier &, PropertySlot &);
244  bool getPropertySlot(ExecState *, unsigned, PropertySlot &);
245  // Fills the PropertyDescriptor looking the ownPropertys and all prototypes until found.
246  bool getPropertyDescriptor(ExecState *, const Identifier &propertyName, PropertyDescriptor &);
247 
248  virtual bool getOwnPropertySlot(ExecState *, const Identifier &, PropertySlot &);
249  virtual bool getOwnPropertySlot(ExecState *, unsigned index, PropertySlot &);
250  virtual bool getOwnPropertyDescriptor(ExecState *, const Identifier &, PropertyDescriptor &);
251 
262  virtual void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None);
263  virtual void put(ExecState *exec, unsigned propertyName, JSValue *value, int attr = None);
264 
279  virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
280 
290  bool propertyIsEnumerable(ExecState *exec, const Identifier &propertyName) const;
291 
302  bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
303  bool hasProperty(ExecState *exec, unsigned propertyName) const;
304 
316  virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
317  virtual bool deleteProperty(ExecState *exec, unsigned propertyName);
318 
335  virtual JSValue *defaultValue(ExecState *exec, JSType hint) const;
336 
345  virtual bool implementsConstruct() const;
346 
375  virtual JSObject *construct(ExecState *exec, const List &args);
376  virtual JSObject *construct(ExecState *exec, const List &args, const Identifier &functionName, const UString &sourceURL, int lineNumber);
377 
385  virtual JSObject *valueClone(Interpreter *targetCtx) const;
386 
395  virtual bool isFunctionType() const;
396 
414  JSValue *call(ExecState *exec, JSObject *thisObj, const List &args); // ### TODO: consolidate with below
415  virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args);
416 
425  virtual bool implementsHasInstance() const;
426 
436  virtual bool hasInstance(ExecState *exec, JSValue *value);
437 
438  void getPropertyNames(ExecState *, PropertyNameArray &, PropertyMap::PropertyMode mode = PropertyMap::ExcludeDontEnumProperties);
439  virtual void getOwnPropertyNames(ExecState *, PropertyNameArray &, PropertyMap::PropertyMode mode);
440 
441  virtual JSValue *toPrimitive(ExecState *exec, JSType preferredType = UnspecifiedType) const;
442  virtual bool getPrimitiveNumber(ExecState *, double &number, JSValue *&value);
443  virtual bool toBoolean(ExecState *exec) const;
444  virtual double toNumber(ExecState *exec) const;
445  virtual UString toString(ExecState *exec) const;
446  virtual JSObject *toObject(ExecState *exec) const;
447 
448  virtual bool getPropertyAttributes(const Identifier &propertyName, unsigned &attributes) const;
449 
450  // Returns whether the object should be treated as undefined when doing equality comparisons
451  virtual bool masqueradeAsUndefined() const
452  {
453  return false;
454  }
455 
456  // This get function only looks at the property map for Object.
457  // It is virtual because for all custom-data classes we want to by-pass
458  // the prototype and get it directly. For example called from
459  // Object::defineOwnProperty to directly get GetterSetterImp and update it.
460  // This is used e.g. by lookupOrCreateFunction (to cache a function, we don't want
461  // to look up in the prototype, it might already exist there)
462  virtual JSValue *getDirect(const Identifier &propertyName) const
463  {
464  return _prop.get(propertyName);
465  }
466  JSValue **getDirectLocation(const Identifier &propertyName)
467  {
468  return _prop.getLocation(propertyName);
469  }
470 
471  // If this method returns non-0, there is already a property
472  // with name propertyName that's not readonly and not a setter-getter
473  // which can be updated via the returned pointer.
474  JSValue **getDirectWriteLocation(const Identifier &propertyName)
475  {
476  return _prop.getWriteLocation(propertyName);
477  }
478 
479  // This function is virtual to directly store, by-pass the prototype, values
480  // for all custom-data classes like the Array. For example an Array with a prototype
481  // to store values via getter/setter. It would be impossible to store a value
482  // by-passing the getter/setter prototype.
483  // This is for example called in Object::defineOwnProperty to directly store the values.
484  // Same for removeDirect.
485  virtual void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0)
486  {
487  _prop.put(propertyName, value, attr);
488  }
489  virtual void putDirect(const Identifier &propertyName, int value, int attr = 0);
490  virtual void removeDirect(const Identifier &propertyName);
491 
492  // convenience to add a function property under the function's own built-in name
493  void putDirectFunction(InternalFunctionImp *, int attr = 0);
494 
495  void fillGetterPropertySlot(PropertySlot &slot, JSValue **location);
496  void fillDirectLocationSlot(PropertySlot &slot, JSValue **location);
497 
498  void defineGetter(ExecState *exec, const Identifier &propertyName, JSObject *getterFunc);
499  void defineSetter(ExecState *exec, const Identifier &propertyName, JSObject *setterFunc);
500 
501  virtual bool defineOwnProperty(ExecState *exec, const Identifier &propertyName, PropertyDescriptor &desc, bool shouldThrow);
502 
503  void preventExtensions();
504  bool isExtensible()
505  {
506  return _prop.isExtensible();
507  }
508 
514  void clearProperties()
515  {
516  _prop.clear();
517  }
518 
519  void saveProperties(SavedProperties &p) const
520  {
521  _prop.save(p);
522  }
523  void restoreProperties(const SavedProperties &p)
524  {
525  _prop.restore(p);
526  }
527 
528  virtual bool isActivation() const
529  {
530  return false;
531  }
532  virtual bool isGlobalObject() const
533  {
534  return false;
535  }
536 
537  // This is used to keep track of whether scope object have local
538  // variables introduced by something other than 'var'
539  bool isLocalInjected() const
540  {
541  return _prop.m_objLocalInjected;
542  }
543  void setLocalInjected()
544  {
545  _prop.m_objLocalInjected = true;
546  }
547 
548 protected:
549  PropertyMap _prop;
550 private:
551 
552  const HashEntry *findPropertyHashEntry(const Identifier &propertyName) const;
553  JSValue *_proto;
554 #ifdef _WIN32
555  JSObject(const JSObject &);
556  JSObject &operator=(const JSObject &);
557 #endif
558 };
559 
564 enum ErrorType { GeneralError = 0,
565  EvalError = 1,
566  RangeError = 2,
567  ReferenceError = 3,
568  SyntaxError = 4,
569  TypeError = 5,
570  URIError = 6
571  };
572 
576 class KJS_EXPORT Error
577 {
578 public:
589  static JSObject *create(ExecState *, ErrorType, const UString &message, int lineNumber, int sourceId, const UString &sourceURL);
590  static JSObject *create(ExecState *, ErrorType, const char *message);
591 
595  static const char *const *const errorNames;
596 };
597 
598 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const UString &message, int lineNumber, int sourceId, const UString &sourceURL);
599 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const UString &message);
600 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType, const char *message);
601 KJS_EXPORT JSObject *throwError(ExecState *, ErrorType);
602 
603 inline JSObject::JSObject(JSValue *proto)
604  : _proto(proto)
605 {
606  assert(proto);
607 }
608 
609 inline JSObject::JSObject()
610  : _proto(jsNull())
611 {}
612 
613 inline JSValue *JSObject::prototype() const
614 {
615  return _proto;
616 }
617 
618 inline void JSObject::setPrototype(JSValue *proto)
619 {
620  assert(proto);
621  _proto = proto;
622 }
623 
624 inline bool JSObject::inherits(const ClassInfo *info) const
625 {
626  for (const ClassInfo *ci = classInfo(); ci; ci = ci->parentClass)
627  if (ci == info) {
628  return true;
629  }
630  return false;
631 }
632 
633 inline void JSObject::fillDirectLocationSlot(PropertySlot &slot,
634  JSValue **location)
635 {
636  if (_prop.hasGetterSetterProperties() &&
637  (*location)->type() == GetterSetterType) {
638  fillGetterPropertySlot(slot, location);
639  } else {
640  slot.setValueSlot(this, location);
641  }
642 }
643 
644 // this method is here to be after the inline declaration of JSObject::inherits
645 inline bool JSCell::isObject(const ClassInfo *info) const
646 {
647  return isObject() && static_cast<const JSObject *>(this)->inherits(info);
648 }
649 
650 // this method is here to be after the inline declaration of JSCell::isObject
651 inline bool JSValue::isObject(const ClassInfo *c) const
652 {
653  return !JSImmediate::isImmediate(this) && asCell()->isObject(c);
654 }
655 
656 // It may seem crazy to inline a function this large but it makes a big difference
657 // since this is function very hot in variable lookup
658 inline bool JSObject::getPropertySlot(ExecState *exec, const Identifier &propertyName, PropertySlot &slot)
659 {
660  JSObject *object = this;
661  while (true) {
662  if (object->getOwnPropertySlot(exec, propertyName, slot)) {
663  return true;
664  }
665 
666  JSValue *proto = object->_proto;
667  if (!proto->isObject()) {
668  return false;
669  }
670 
671  object = static_cast<JSObject *>(proto);
672  }
673 }
674 
675 inline void JSObject::getPropertyNames(ExecState *exec, PropertyNameArray &propertyNames, PropertyMap::PropertyMode mode)
676 {
677  for (JSObject *cur = this; cur; cur = cur->_proto->getObject()) {
678  cur->getOwnPropertyNames(exec, propertyNames, mode);
679  }
680 }
681 
682 inline JSValue *JSObject::toPrimitive(ExecState *exec, JSType preferredType) const
683 {
684  return defaultValue(exec, preferredType);
685 }
686 
687 inline JSValue *JSObject::call(ExecState *exec, JSObject *thisObj, const List &args)
688 {
689  return callAsFunction(exec, thisObj, args);
690 }
691 
692 } // namespace
693 
694 #endif // KJS_OBJECT_H
Factory methods for error objects.
Definition: object.h:576
const ClassInfo * parentClass
Pointer to the class information of the base class.
Definition: object.h:57
void * dummy
Reserved for future extension.
Definition: object.h:65
An entry in a hash table.
Definition: lookup.h:38
Interpreter objects can be used to evaluate ECMAScript code.
Definition: interpreter.h:56
A hash table Usually the hashtable is generated by the create_hash_table script, from a ...
Definition: lookup.h:74
const char * className
A string denoting the class name.
Definition: object.h:52
static const char *const *const errorNames
Array of error names corresponding to ErrorType.
Definition: object.h:595
Unicode string class.
Definition: ustring.h:153
JSValue is the base type for all primitives (Undefined, Null, Boolean, String, Number) and objects in...
Definition: value.h:58
const HashTable * propHashTable
Static hash-table of properties.
Definition: object.h:61
Native list type.
Definition: list.h:52
Class Information.
Definition: object.h:48
Represents the current state of script execution.
Definition: ExecState.h:53
Represents an Identifier for a Javascript object.
Definition: identifier.h:36
Javascript Property Map.
Definition: property_map.h:81
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Jun 4 2020 22:48:42 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.