summaryrefslogtreecommitdiffstats
path: root/kjs/object.h
diff options
context:
space:
mode:
Diffstat (limited to 'kjs/object.h')
-rw-r--r--kjs/object.h726
1 files changed, 726 insertions, 0 deletions
diff --git a/kjs/object.h b/kjs/object.h
new file mode 100644
index 000000000..ca795460c
--- /dev/null
+++ b/kjs/object.h
@@ -0,0 +1,726 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#ifndef _KJS_OBJECT_H_
+#define _KJS_OBJECT_H_
+
+// Objects
+
+#include "value.h"
+#include "types.h"
+#include "reference_list.h"
+#include "identifier.h"
+#include "property_map.h"
+#include "scope_chain.h"
+
+namespace KJS {
+
+ class ObjectImpPrivate;
+ class PropertyMap;
+ class HashTable;
+ struct HashEntry;
+ class ListImp;
+
+ /** Attributes (only applicable to the Object type).
+ * See ECMA 262-3 8.6.1
+ */
+ enum Attribute { None = 0,
+ ReadOnly = 1 << 1, ///< property can be only read, not written
+ DontEnum = 1 << 2, ///< property doesn't appear in (for .. in ..)
+ DontDelete = 1 << 3, ///< property can't be deleted
+ Internal = 1 << 4, ///< an internal property, set to by pass checks
+ Function = 1 << 5 }; ///< property is a function - only used by static hashtables
+
+ /**
+ * Class Information
+ */
+ struct ClassInfo {
+ /**
+ * A string denoting the class name. Example: "Window".
+ */
+ const char* className;
+ /**
+ * Pointer to the class information of the base class.
+ * 0L if there is none.
+ */
+ const ClassInfo *parentClass;
+ /**
+ * Static hash-table of properties.
+ */
+ const HashTable *propHashTable;
+ /**
+ * Reserved for future extension.
+ */
+ void *dummy;
+ };
+
+ /**
+ * Represents an Object. This is a wrapper for ObjectImp
+ */
+ class KJS_EXPORT Object : public Value {
+ public:
+ Object() { }
+ explicit Object(ObjectImp *v);
+
+ ObjectImp *imp() const;
+
+ const ClassInfo *classInfo() const;
+ bool inherits(const ClassInfo *cinfo) const;
+
+ /**
+ * Converts a Value into an Object. If the value's type is not ObjectType,
+ * a null object will be returned (i.e. one with it's internal pointer set
+ * to 0). If you do not know for sure whether the value is of type
+ * ObjectType, you should check the isValid() methods afterwards before
+ * calling any methods on the Object.
+ *
+ * @return The value converted to an object
+ */
+ static Object dynamicCast(const Value &v);
+
+ /**
+ * Returns the prototype of this object. Note that this is not the same as
+ * the "prototype" property.
+ *
+ * See ECMA 8.6.2
+ *
+ * @return The object's prototype
+ */
+ Value prototype() const;
+
+ /**
+ * Returns the class name of the object
+ *
+ * See ECMA 8.6.2
+ *
+ * @return The object's class name
+ */
+ UString className() const;
+
+ /**
+ * Retrieves the specified property from the object. If neither the object
+ * or any other object in it's prototype chain have the property, this
+ * function will return Undefined.
+ *
+ * See ECMA 8.6.2.1
+ *
+ * @param exec The current execution state
+ * @param propertyName The name of the property to retrieve
+ *
+ * @return The specified property, or Undefined
+ */
+ Value get(ExecState *exec, const Identifier &propertyName) const;
+ Value get(ExecState *exec, unsigned propertyName) const;
+
+ /**
+ * Sets the specified property.
+ *
+ * See ECMA 8.6.2.2
+ *
+ * @param exec The current execution state
+ * @param propertyName The name of the property to set
+ * @param value The value to set
+ * @param attr The Attribute value for the property
+ */
+ void put(ExecState *exec, const Identifier &propertyName,
+ const Value &value, int attr = None);
+ void put(ExecState *exec, unsigned propertyName,
+ const Value &value, int attr = None);
+
+ /**
+ * Used to check whether or not a particular property is allowed to be set
+ * on an object
+ *
+ * See ECMA 8.6.2.3
+ *
+ * @param exec The current execution state
+ * @param propertyName The name of the property
+ * @return true if the property can be set, otherwise false
+ */
+ bool canPut(ExecState *exec, const Identifier &propertyName) const;
+
+ /**
+ * Checks to see whether the object (or any object in it's prototype chain)
+ * has a property with the specified name.
+ *
+ * See ECMA 8.6.2.4
+ *
+ * @param exec The current execution state
+ * @param propertyName The name of the property to check for
+ * @return true if the object has the property, otherwise false
+ */
+ bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
+ bool hasProperty(ExecState *exec, unsigned propertyName) const;
+
+ /**
+ * Removes the specified property from the object.
+ *
+ * See ECMA 8.6.2.5
+ *
+ * @param exec The current execution state
+ * @param propertyName The name of the property to delete
+ * @return true if the property was successfully deleted or did not
+ * exist on the object. false if deleting the specified property is not
+ * allowed.
+ */
+ bool deleteProperty(ExecState *exec, const Identifier &propertyName);
+ bool deleteProperty(ExecState *exec, unsigned propertyName);
+
+ /**
+ * Converts the object into a primitive value. The value return may differ
+ * depending on the supplied hint
+ *
+ * See ECMA 8.6.2.6
+ *
+ * @param exec The current execution state
+ * @param hint The desired primitive type to convert to
+ * @return A primitive value converted from the objetc. Note that the
+ * type of primitive value returned may not be the same as the requested
+ * hint.
+ */
+ Value defaultValue(ExecState *exec, Type hint) const;
+
+ /**
+ * Whether or not the object implements the construct() method. If this
+ * returns false you should not call the construct() method on this
+ * object (typically, an assertion will fail to indicate this).
+ *
+ * @return true if this object implements the construct() method, otherwise
+ * false
+ */
+ bool implementsConstruct() const;
+
+ /**
+ * Creates a new object based on this object. Typically this means the
+ * following:
+ * 1. A new object is created
+ * 2. The prototype of the new object is set to the value of this object's
+ * "prototype" property
+ * 3. The call() method of this object is called, with the new object
+ * passed as the this value
+ * 4. The new object is returned
+ *
+ * In some cases, Host objects may differ from these semantics, although
+ * this is discouraged.
+ *
+ * If an error occurs during construction, the execution state's exception
+ * will be set. This can be tested for with ExecState::hadException().
+ * Under some circumstances, the exception object may also be returned.
+ *
+ * Note: This function should not be called if implementsConstruct() returns
+ * false, in which case it will result in an assertion failure.
+ *
+ * @param exec The current execution state
+ * @param args The arguments to be passed to call() once the new object has
+ * been created
+ * @return The newly created &amp; initialized object
+ */
+ Object construct(ExecState *exec, const List &args);
+
+ /**
+ * Whether or not the object implements the call() method. If this returns
+ * false you should not call the call() method on this object (typically,
+ * an assertion will fail to indicate this).
+ *
+ * @return true if this object implements the call() method, otherwise
+ * false
+ */
+ bool implementsCall() const;
+
+
+ /**
+ * Calls this object as if it is a function.
+ *
+ * Note: This function should not be called if implementsCall() returns
+ * false, in which case it will result in an assertion failure.
+ *
+ * See ECMA 8.6.2.3
+ *
+ * @param exec The current execution state
+ * @param thisObj The obj to be used as "this" within function execution.
+ * Note that in most cases this will be different from the C++ "this"
+ * object. For example, if the ECMAScript code "window.location.toString()"
+ * is executed, call() will be invoked on the C++ object which implements
+ * the toString method, with the thisObj being window.location
+ * @param args List of arguments to be passed to the function
+ * @return The return value from the function
+ */
+ Value call(ExecState *exec, Object &thisObj, const List &args);
+
+ /**
+ * Whether or not the object implements the hasInstance() method. If this
+ * returns false you should not call the hasInstance() method on this
+ * object (typically, an assertion will fail to indicate this).
+ *
+ * @return true if this object implements the hasInstance() method,
+ * otherwise false
+ */
+ bool implementsHasInstance() const;
+
+ /**
+ * Checks whether value delegates behavior to this object. Used by the
+ * instanceof operator.
+ *
+ * @param exec The current execution state
+ * @param value The value to check
+ * @return true if value delegates behavior to this object, otherwise
+ * false
+ */
+ Boolean hasInstance(ExecState *exec, const Value &value);
+
+ /**
+ * Returns the scope of this object. This is used when execution declared
+ * functions - the execution context for the function is initialized with
+ * extra object in it's scope. An example of this is functions declared
+ * inside other functions:
+ *
+ * \code
+ * function f() {
+ *
+ * function b() {
+ * return prototype;
+ * }
+ *
+ * var x = 4;
+ * // do some stuff
+ * }
+ * f.prototype = new String();
+ * \endcode
+ *
+ * When the function f.b is executed, its scope will include properties of
+ * f. So in the example above the return value of f.b() would be the new
+ * String object that was assigned to f.prototype.
+ *
+ * @return The function's scope
+ */
+ const ScopeChain &scope() const;
+ void setScope(const ScopeChain &s);
+
+ /**
+ * Returns a List of References to all the properties of the object. Used
+ * in "for x in y" statements. The list is created new, so it can be freely
+ * modified without affecting the object's properties. It should be deleted
+ * by the caller.
+ *
+ * Subclasses can override this method in ObjectImpl to provide the
+ * appearance of
+ * having extra properties other than those set specifically with put().
+ *
+ * @param exec The current execution state
+ * @param recursive Whether or not properties in the object's prototype
+ * chain should be
+ * included in the list.
+ * @return A List of References to properties of the object.
+ **/
+ ReferenceList propList(ExecState *exec, bool recursive = true);
+
+ /**
+ * Returns the internal value of the object. This is used for objects such
+ * as String and Boolean which are wrappers for native types. The interal
+ * value is the actual value represented by the wrapper objects.
+ *
+ * @see ECMA 8.6.2
+ * @return The internal value of the object
+ */
+ Value internalValue() const;
+
+ /**
+ * Sets the internal value of the object
+ *
+ * @see internalValue()
+ *
+ * @param v The new internal value
+ */
+ void setInternalValue(const Value &v);
+ };
+
+ inline Object Value::toObject(ExecState *exec) const { return rep->dispatchToObject(exec); }
+
+ class KJS_EXPORT ObjectImp : public ValueImp {
+ friend class ObjectProtoFuncImp;
+ public:
+ /**
+ * Creates a new ObjectImp with the specified prototype
+ *
+ * @param proto The prototype
+ */
+ ObjectImp(const Object &proto);
+ ObjectImp(ObjectImp *proto);
+
+ /**
+ * Creates a new ObjectImp with a prototype of Null()
+ * (that is, the ECMAScript "null" value, not a null Object).
+ *
+ */
+ ObjectImp();
+
+ virtual ~ObjectImp();
+
+ virtual void mark();
+
+ Type type() const;
+
+ /**
+ * A pointer to a ClassInfo struct for this class. This provides a basic
+ * facility for run-time type information, and can be used to check an
+ * object's class an inheritance (see inherits()). This should
+ * always return a statically declared pointer, or 0 to indicate that
+ * there is no class information.
+ *
+ * This is primarily useful if you have application-defined classes that you
+ * wish to check against for casting purposes.
+ *
+ * For example, to specify the class info for classes FooImp and BarImp,
+ * where FooImp inherits from BarImp, you would add the following in your
+ * class declarations:
+ *
+ * \code
+ * class BarImp : public ObjectImp {
+ * virtual const ClassInfo *classInfo() const { return &info; }
+ * static const ClassInfo info;
+ * // ...
+ * };
+ *
+ * class FooImp : public ObjectImp {
+ * virtual const ClassInfo *classInfo() const { return &info; }
+ * static const ClassInfo info;
+ * // ...
+ * };
+ * \endcode
+ *
+ * And in your source file:
+ *
+ * \code
+ * const ClassInfo BarImp::info = {0, 0, 0}; // no parent class
+ * const ClassInfo FooImp::info = {&BarImp::info, 0, 0};
+ * \endcode
+ *
+ * @see inherits()
+ */
+ virtual const ClassInfo *classInfo() const;
+
+ /**
+ * Checks whether this object inherits from the class with the specified
+ * classInfo() pointer. This requires that both this class and the other
+ * class return a non-NULL pointer for their classInfo() methods (otherwise
+ * it will return false).
+ *
+ * For example, for two ObjectImp pointers obj1 and obj2, you can check
+ * if obj1's class inherits from obj2's class using the following:
+ *
+ * if (obj1->inherits(obj2->classInfo())) {
+ * // ...
+ * }
+ *
+ * If you have a handle to a statically declared ClassInfo, such as in the
+ * classInfo() example, you can check for inheritance without needing
+ * an instance of the other class:
+ *
+ * if (obj1->inherits(FooImp::info)) {
+ * // ...
+ * }
+ *
+ * @param cinfo The ClassInfo pointer for the class you want to check
+ * inheritance against.
+ * @return true if this object's class inherits from class with the
+ * ClassInfo pointer specified in cinfo
+ */
+ bool inherits(const ClassInfo *cinfo) const;
+
+ // internal properties (ECMA 262-3 8.6.2)
+
+ /**
+ * Implementation of the [[Prototype]] internal property (implemented by
+ * all Objects)
+ *
+ * @see Object::prototype()
+ */
+ Value prototype() const;
+ void setPrototype(const Value &proto);
+
+ /**
+ * Implementation of the [[Class]] internal property (implemented by all
+ * Objects)
+ *
+ * The default implementation uses classInfo().
+ * You should either implement classInfo(), or
+ * if you simply need a classname, you can reimplement className()
+ * instead.
+ *
+ * @see Object::className()
+ */
+ virtual UString className() const;
+
+ /**
+ * Implementation of the [[Get]] internal property (implemented by all
+ * Objects)
+ *
+ * @see Object::get()
+ */
+ // [[Get]] - must be implemented by all Objects
+ virtual Value get(ExecState *exec, const Identifier &propertyName) const;
+ virtual Value getPropertyByIndex(ExecState *exec,
+ unsigned propertyName) const;
+
+ /**
+ * Implementation of the [[Put]] internal property (implemented by all
+ * Objects)
+ *
+ * @see Object::put()
+ */
+ virtual void put(ExecState *exec, const Identifier &propertyName,
+ const Value &value, int attr = None);
+ virtual void putPropertyByIndex(ExecState *exec, unsigned propertyName,
+ const Value &value, int attr = None);
+
+ /**
+ * Implementation of the [[CanPut]] internal property (implemented by all
+ * Objects)
+ *
+ * @see Object::canPut()
+ */
+ virtual bool canPut(ExecState *exec, const Identifier &propertyName) const;
+
+ /**
+ * Implementation of the [[HasProperty]] internal property (implemented by
+ * all Objects)
+ *
+ * @see Object::hasProperty()
+ */
+ virtual bool hasProperty(ExecState *exec,
+ const Identifier &propertyName) const;
+ virtual bool hasPropertyByIndex(ExecState *exec, unsigned propertyName) const;
+
+ /**
+ * Implementation of the [[Delete]] internal property (implemented by all
+ * Objects)
+ *
+ * @see Object::deleteProperty()
+ */
+ virtual bool deleteProperty(ExecState *exec,
+ const Identifier &propertyName);
+ virtual bool deletePropertyByIndex(ExecState *exec, unsigned propertyName);
+
+ /**
+ * Remove all properties from this object.
+ * This doesn't take DontDelete into account, and isn't in the ECMA spec.
+ * It's simply a quick way to remove everything before destroying.
+ */
+ void deleteAllProperties(ExecState *);
+
+ /**
+ * Implementation of the [[DefaultValue]] internal property (implemented by
+ * all Objects)
+ *
+ * @see Object::defaultValue()
+ */
+ virtual Value defaultValue(ExecState *exec, Type hint) const;
+
+ virtual bool implementsConstruct() const;
+ /**
+ * Implementation of the [[Construct]] internal property
+ *
+ * @see Object::construct()
+ */
+ virtual Object construct(ExecState *exec, const List &args);
+
+ virtual bool implementsCall() const;
+ /**
+ * Implementation of the [[Call]] internal property
+ *
+ * @see Object::call()
+ */
+ virtual Value call(ExecState *exec, Object &thisObj,
+ const List &args);
+
+ virtual bool implementsHasInstance() const;
+ /**
+ * Implementation of the [[HasInstance]] internal property
+ *
+ * @see Object::hasInstance()
+ */
+ virtual Boolean hasInstance(ExecState *exec, const Value &value);
+
+ /**
+ * Implementation of the [[Scope]] internal property
+ *
+ * @see Object::scope()
+ */
+ const ScopeChain &scope() const { return _scope; }
+ void setScope(const ScopeChain &s) { _scope = s; }
+
+ virtual ReferenceList propList(ExecState *exec, bool recursive = true);
+
+ Value internalValue() const;
+ void setInternalValue(const Value &v);
+ void setInternalValue(ValueImp *v);
+
+ Value toPrimitive(ExecState *exec,
+ Type preferredType = UnspecifiedType) const;
+ bool toBoolean(ExecState *exec) const;
+ double toNumber(ExecState *exec) const;
+ UString toString(ExecState *exec) const;
+ Object toObject(ExecState *exec) const;
+
+ // This get method only looks at the property map.
+ // A bit like hasProperty(recursive=false), this doesn't go to the prototype.
+ // This is used e.g. by lookupOrCreateFunction (to cache a function, we don't want
+ // to look up in the prototype, it might already exist there)
+ ValueImp *getDirect(const Identifier& propertyName) const
+ { return _prop.get(propertyName); }
+ void putDirect(const Identifier &propertyName, ValueImp *value, int attr = 0);
+ void putDirect(const Identifier &propertyName, int value, int attr = 0);
+
+ /**
+ * Sets the name of the function, if this is an InternalFunctionImp object.
+ * (calling InternalFunctionImp::setName)
+ */
+ void setFunctionName(const Identifier &propertyName);
+
+ protected:
+ PropertyMap _prop;
+ private:
+ const HashEntry* findPropertyHashEntry( const Identifier& propertyName ) const;
+ ObjectImpPrivate *_od;
+ ValueImp *_proto;
+ ValueImp *_internalValue;
+ ScopeChain _scope;
+ };
+
+ /**
+ * Types of Native Errors available. For custom errors, GeneralError
+ * should be used.
+ */
+ enum ErrorType { GeneralError = 0,
+ EvalError = 1,
+ RangeError = 2,
+ ReferenceError = 3,
+ SyntaxError = 4,
+ TypeError = 5,
+ URIError = 6};
+
+ /**
+ * @short Factory methods for error objects.
+ */
+ class KJS_EXPORT Error {
+ public:
+ /**
+ * Factory method for error objects.
+ *
+ * @param exec The current execution state
+ * @param errtype Type of error.
+ * @param message Optional error message.
+ * @param lineno Optional line number.
+ * @param sourceId Optional source id.
+ */
+ static Object create(ExecState *exec, ErrorType errtype = GeneralError,
+ const char *message = 0, int lineno = -1,
+ int sourceId = -1);
+
+ /**
+ * Array of error names corresponding to ErrorType
+ */
+ static const char * const * const errorNames;
+ };
+
+ inline Object::Object(ObjectImp *v) : Value(v) { }
+
+ inline ObjectImp *Object::imp() const { return static_cast<ObjectImp*>(rep); }
+
+ inline const ClassInfo *Object::classInfo() const
+ { return imp()->classInfo(); }
+
+ inline bool Object::inherits(const ClassInfo *cinfo) const
+ { return imp()->inherits(cinfo); }
+
+ inline Value Object::prototype() const
+ { return Value(imp()->prototype()); }
+
+ inline UString Object::className() const
+ { return imp()->className(); }
+
+ inline Value Object::get(ExecState *exec, const Identifier &propertyName) const
+ { return imp()->get(exec,propertyName); }
+
+ inline Value Object::get(ExecState *exec, unsigned propertyName) const
+ { return imp()->getPropertyByIndex(exec, propertyName); }
+
+ inline void Object::put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr)
+ { imp()->put(exec,propertyName,value,attr); }
+
+ inline void Object::put(ExecState *exec, unsigned propertyName, const Value &value, int attr)
+ { imp()->putPropertyByIndex(exec, propertyName, value, attr); }
+
+ inline bool Object::canPut(ExecState *exec, const Identifier &propertyName) const
+ { return imp()->canPut(exec,propertyName); }
+
+ inline bool Object::hasProperty(ExecState *exec, const Identifier &propertyName) const
+ { return imp()->hasProperty(exec, propertyName); }
+
+ inline bool Object::hasProperty(ExecState *exec, unsigned propertyName) const
+ { return imp()->hasPropertyByIndex(exec, propertyName); }
+
+ inline bool Object::deleteProperty(ExecState *exec, const Identifier &propertyName)
+ { return imp()->deleteProperty(exec,propertyName); }
+
+ inline bool Object::deleteProperty(ExecState *exec, unsigned propertyName)
+ { return imp()->deletePropertyByIndex(exec, propertyName); }
+
+ inline Value Object::defaultValue(ExecState *exec, Type hint) const
+ { return imp()->defaultValue(exec,hint); }
+
+ inline bool Object::implementsConstruct() const
+ { return imp()->implementsConstruct(); }
+
+ inline Object Object::construct(ExecState *exec, const List &args)
+ { return imp()->construct(exec,args); }
+
+ inline bool Object::implementsCall() const
+ { return imp()->implementsCall(); }
+
+ inline bool Object::implementsHasInstance() const
+ { return imp()->implementsHasInstance(); }
+
+ inline Boolean Object::hasInstance(ExecState *exec, const Value &value)
+ { return imp()->hasInstance(exec,value); }
+
+ inline const ScopeChain &Object::scope() const
+ { return imp()->scope(); }
+
+ inline void Object::setScope(const ScopeChain &s)
+ { imp()->setScope(s); }
+
+ inline ReferenceList Object::propList(ExecState *exec, bool recursive)
+ { return imp()->propList(exec,recursive); }
+
+ inline Value Object::internalValue() const
+ { return imp()->internalValue(); }
+
+ inline void Object::setInternalValue(const Value &v)
+ { imp()->setInternalValue(v); }
+
+} // namespace
+
+#endif // _KJS_OBJECT_H_