blob: 7daee7e2460a2fb50231e9f6826fe4da781f2270 [file] [log] [blame]
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _KJS_OBJECT_H_
#define _KJS_OBJECT_H_
#include <stdlib.h>
#include "ustring.h"
/**
* @short Main namespace
*/
namespace KJS {
/**
* Types of classes derived from KJSO
*/
enum Type { // main types
AbstractType = 1,
UndefinedType,
NullType,
BooleanType,
NumberType,
StringType,
ObjectType,
HostType,
ReferenceType,
CompletionType,
// extended types
FunctionType,
InternalFunctionType,
DeclaredFunctionType,
AnonymousFunctionType,
ConstructorType,
ActivationType
};
/**
* Property attributes.
*/
enum Attribute { None = 0,
ReadOnly = 1 << 1,
DontEnum = 1 << 2,
DontDelete = 1 << 3,
Internal = 1 << 4 };
/**
* Types of classes derived from @ref Object.
*/
enum Class { UndefClass,
ArrayClass,
StringClass,
BooleanClass,
NumberClass,
ObjectClass,
DateClass,
RegExpClass,
ErrorClass,
FunctionClass };
/**
* Completion types.
*/
enum Compl { Normal, Break, Continue, ReturnValue, Throw };
/**
* Error codes.
*/
enum ErrorType { NoError = 0,
GeneralError,
EvalError,
RangeError,
ReferenceError,
SyntaxError,
TypeError,
URIError };
extern const double NaN;
extern const double Inf;
// forward declarations
class Imp;
class Boolean;
class Number;
class String;
class Object;
struct Property;
class PropList;
class List;
/**
* @short Type information.
*/
struct TypeInfo {
/**
* A string denoting the type name. Example: "Number".
*/
const char *name;
/**
* One of the @ref KJS::Type enums.
*/
Type type;
/**
* Pointer to the type information of the base class.
* NULL if there is none.
*/
const TypeInfo *base;
/**
* Additional specifier for your own use.
*/
int extra;
/**
* Reserved for future extensions (internal).
*/
void *dummy;
};
/**
* @short Main base class for every KJS object.
*/
class KJSO {
friend class ElementNode;
public:
/**
* Constructor.
*/
KJSO();
/**
* @internal
*/
KJSO(Imp *d);
/**
* Copy constructor.
*/
KJSO(const KJSO &);
/*
* Assignment operator
*/
KJSO& operator=(const KJSO &);
/**
* Destructor.
*/
virtual ~KJSO();
/**
* @return True if this object is null, i.e. if there is no data attached
* to this object. Don't confuse this with the Null object.
*/
bool isNull() const;
/**
* @return True if this objects is of any other value than Undefined.
*/
bool isDefined() const;
/**
* @return the type of the object. One of the @ref KJS::Type enums.
*/
Type type() const;
/**
* Check whether object is of a certain type
* @param t type to check for
*/
bool isA(Type t) const { return (type() == t); }
/**
* Check whether object is of a certain type. Allows checking of
* host objects, too.
* @param type name (Number, Boolean etc.)
*/
bool isA(const char *s) const;
/**
* Use this method when checking for objects. It's safer than checking
* for a single object type with @ref isA().
*/
bool isObject() const;
/**
* Examine the inheritance structure of this object.
* @param t Name of the base class.
* @return True if object is of type t or a derived from such a type.
*/
bool derivedFrom(const char *s) const;
/**
* @return Conversion to primitive type (Undefined, Boolean, Number
* or String)
* @param preferred Optional hint. Either StringType or NumberType.
*/
KJSO toPrimitive(Type preferred = UndefinedType) const; // ECMA 9.1
/**
* @return Conversion to Boolean type.
*/
Boolean toBoolean() const; // ECMA 9.2
/**
* @return Conversion to Number type.
*/
Number toNumber() const; // ECMA 9.3
/**
* @return Conversion to double. 0.0 if conversion failed.
*/
double round() const;
/**
* @return Conversion to Number type containing an integer value.
*/
Number toInteger() const; // ECMA 9.4
/**
* @return Conversion to signed integer value.
*/
int toInt32() const; // ECMA 9.5
/**
* @return Conversion to unsigned integer value.
*/
unsigned int toUInt32() const; // ECMA 9.6
/**
* @return Conversion to unsigned short value.
*/
unsigned short toUInt16() const; // ECMA 9.7
/**
* @return Conversion to String type.
*/
String toString() const; // ECMA 9.8
/**
* @return Conversion to Object type.
*/
Object toObject() const; // ECMA 9.9
// Properties
/**
* Set the internal [[Prototype]] property of this object.
* @param p A prototype object.
*/
void setPrototype(const KJSO &p);
/**
* Set the "prototype" property of this object. Different from
* the internal [[Prototype]] property.
* @param p A prototype object.
*/
void setPrototypeProperty(const KJSO &p);
/**
* @return The internal [[prototype]] property.
*/
KJSO prototype() const;
/**
* The internal [[Get]] method.
* @return The value of property p.
*/
KJSO get(const UString &p) const;
/**
* The internal [[HasProperty]] method.
* @param p Property name.
* @param recursive Indicates whether prototypes are searched as well.
* @return Boolean value indicating whether the object already has a
* member with the given name p.
*/
bool hasProperty(const UString &p, bool recursive = true) const;
/**
* The internal [[Put]] method. Sets the specified property to the value v.
* @param p Property name.
* @param v Value.
*/
void put(const UString &p, const KJSO& v);
/**
* The internal [[CanPut]] method.
* @param p Property name.
* @return A boolean value indicating whether a [[Put]] operation with
* p succeed.
*/
bool canPut(const UString &p) const;
/**
* The internal [[Delete]] method. Removes the specified property from
* the object.
* @param p Property name.
* @return True if the property was deleted successfully or didn't exist
* in the first place. False if the DontDelete attribute was set.
*/
bool deleteProperty(const UString &p);
/**
* Same as above put() method except the additional attribute. Right now,
* this only works with native types as Host Objects don't reimplement
* this method.
* @param attr One of @ref KJS::Attribute.
*/
void put(const UString &p, const KJSO& v, int attr);
/**
* Convenience function for adding a Number property constructed from
* a double value.
*/
void put(const UString &p, double d, int attr = None);
/**
* Convenience function for adding a Number property constructed from
* an integer value.
*/
void put(const UString &p, int i, int attr = None);
/**
* Convenience function for adding a Number property constructed from
* an unsigned integer value.
*/
void put(const UString &p, unsigned int u, int attr = None);
/**
* Reference method.
* @return Reference base if object is a reference. Throws
* a ReferenceError otherwise.
*/
KJSO getBase() const;
/**
* Reference method.
* @return Property name of a reference. Null string if object is not
* a reference.
*/
UString getPropertyName() const;
/**
* Reference method.
* @return Referenced value. This object if no reference.
*/
KJSO getValue() const;
KJSO getValue(); /* TODO: remove in next version */
/**
* Reference method. Set referenced value to v.
*/
ErrorType putValue(const KJSO& v);
/**
* @return True if object supports @ref executeCall() method. That's the
* case for all objects derived from FunctionType.
*/
bool implementsCall() const;
/**
* Execute function implemented via the @ref Function::execute() method.
*
* Note: check availability via @ref implementsCall() beforehand.
* @param thisV Object serving as the 'this' value.
* @param args Pointer to the list of arguments or null.
* @return Result of the function call.
*/
KJSO executeCall(const KJSO &thisV, const List *args);
KJSO executeCall(const KJSO &thisV, const List *args, const List *extraScope) const;
/**
* Set this object's constructor.
*/
void setConstructor(KJSO c);
/**
* @return A Pointer to the internal implementation.
*/
Imp *imp() const { return rep; }
#ifdef KJS_DEBUG_MEM
/**
* @internal
*/
static int count;
#endif
protected:
/**
* Pointer to the internal implementation.
*/
Imp *rep;
private:
void putArrayElement(const UString &p, const KJSO &v);
}; // end of KJSO
/**
* @short Base for all implementation classes.
*/
class Imp {
friend class KJSO;
friend class Collector;
friend class ForInNode;
friend class Debugger;
public:
Imp();
public:
virtual KJSO toPrimitive(Type preferred = UndefinedType) const; // ECMA 9.1
virtual Boolean toBoolean() const; // ECMA 9.2
virtual Number toNumber() const; // ECMA 9.3
virtual String toString() const; // ECMA 9.8
virtual Object toObject() const; // ECMA 9.9
// properties
virtual KJSO get(const UString &p) const;
virtual bool hasProperty(const UString &p, bool recursive = true) const;
virtual void put(const UString &p, const KJSO& v);
void put(const UString &p, const KJSO& v, int attr);
virtual bool canPut(const UString &p) const;
virtual bool deleteProperty(const UString &p);
virtual KJSO defaultValue(Type hint) const;
bool implementsCall() const;
/**
* @internal Reserved for mark & sweep garbage collection
*/
virtual void mark(Imp *imp = 0L);
bool marked() const;
Type type() const { return typeInfo()->type; }
/**
* @return The TypeInfo struct describing this object.
*/
virtual const TypeInfo* typeInfo() const { return &info; }
void setPrototype(const KJSO& p);
Imp* prototype() const { return proto; }
void setPrototypeProperty(const KJSO &p);
void setConstructor(const KJSO& c);
void* operator new(size_t);
void operator delete(void*);
/**
* @deprecated
*/
void operator delete(void*, size_t);
#ifdef KJS_DEBUG_MEM
/**
* @internal
*/
static int count;
#endif
protected:
virtual ~Imp();
private:
Imp(const Imp&);
Imp& operator=(const Imp&);
void putArrayElement(const UString &p, const KJSO& v);
/**
* Get the property names for this object. To be used by for .. in loops
* @return The (pointer to the) first element of a PropList, to be deleted
* by the caller, or 0 if there are no enumerable properties
*/
PropList *propList(PropList *first = 0L, PropList *last = 0L,
bool recursive = true) const;
public:
// reference counting mechanism
inline Imp* ref() { refcount++; return this; }
inline bool deref() { return (!--refcount); }
unsigned int refcount;
private:
Property *prop;
Imp *proto;
static const TypeInfo info;
// reserved for memory managment - currently used as flags for garbage collection
// (prev != 0) = marked, (next != 0) = created, (next != this) = created and gc allowed
Imp *prev, *next;
// for future extensions
class ImpInternal;
ImpInternal *internal;
void setMarked(bool m);
void setGcAllowed(bool a);
bool gcAllowed() const;
void setCreated(bool c);
bool created() const;
};
/**
* @short General implementation class for Objects
*/
class ObjectImp : public Imp {
friend class Object;
public:
ObjectImp(Class c);
ObjectImp(Class c, const KJSO &v);
ObjectImp(Class c, const KJSO &v, const KJSO &p);
virtual ~ObjectImp();
virtual KJSO toPrimitive(Type preferred = UndefinedType) const;
virtual Boolean toBoolean() const;
virtual Number toNumber() const;
virtual String toString() const;
virtual Object toObject() const;
virtual const TypeInfo* typeInfo() const { return &info; }
static const TypeInfo info;
/**
* @internal Reimplemenation of @ref Imp::mark().
*/
virtual void mark(Imp *imp = 0L);
private:
Class cl;
Imp *val;
};
/**
* @short Object class encapsulating an internal value.
*/
class Object : public KJSO {
public:
Object(Imp *d);
Object(Class c = UndefClass);
Object(Class c, const KJSO& v);
Object(Class c, const KJSO& v, const Object& p);
virtual ~Object();
void setClass(Class c);
Class getClass() const;
void setInternalValue(const KJSO& v);
KJSO internalValue();
static Object create(Class c);
static Object create(Class c, const KJSO& val);
static Object create(Class c, const KJSO& val, const Object &p);
static Object dynamicCast(const KJSO &obj);
};
/**
* @short Implementation base class for Host Objects.
*/
class HostImp : public Imp {
public:
HostImp();
virtual ~HostImp();
virtual const TypeInfo* typeInfo() const { return &info; }
virtual Boolean toBoolean() const;
virtual String toString() const;
static const TypeInfo info;
};
class KJScriptImp;
/**
* The Global object represents the global namespace. It holds the native
* objects like String and functions like eval().
*
* It also serves as a container for variables created by the user, i.e.
* the statement
* <pre>
* var i = 2;
* </pre>
* will basically perform a Global::current().put("i", Number(2)); operation.
*
* @short Unique global object containing initial native properties.
*/
class Global : public Object {
friend class KJScriptImp;
public:
/**
* Constructs a Global object. This is done by the interpreter once and
* there should be no need to create an instance on your own. Usually,
* you'll just want to access the current instance.
* For example like this:
* <pre>
* Global global(Global::current());
* KJSO proto = global.objectPrototype();
* </pre>
*/
Global();
/**
* Destruct the Global object.
*/
virtual ~Global();
/**
* @return A reference to the Global object belonging to the current
* interpreter instance.
*/
static Global current();
/**
* @return A handle to Object.prototype.
*/
KJSO objectPrototype() const;
/**
* @return A handle to Function.prototype.
*/
KJSO functionPrototype() const;
/**
* Set a filter object that will intercept all put() and get() calls
* to the global object. If this object returns Undefined on get() the
* request will be passed on the global object.
* @deprecated
*/
void setFilter(const KJSO &f);
/**
* Return a handle to the filter object (see @ref setFilter()).
* Null if no filter has been installed.
* @deprecated
*/
KJSO filter() const;
/**
* Returns the extra user data set for this global object. Null by default.
* Typical usage if you need to query any info related to the currently
* running interpreter:
*
* MyMainWindow *m = (MyMainWindow*)Global::current().extra();
*/
void *extra() const;
/**
* Set the extra user data for this global object. It's not used by the
* interpreter itself and can therefore be used to bind arbitrary data
* to each interpreter instance.
*/
void setExtra(void *e);
private:
Global(void *);
void init();
void clear();
};
/**
* @short Factory methods for error objects.
*/
class Error {
public:
/**
* Factory method for error objects. The error will be registered globally
* and the execution will continue as if a "throw" statement was
* encountered.
* @param e Type of error.
* @param m Optional error message.
* @param l Optional line number.
*/
static KJSO create(ErrorType e, const char *m = 0, int l = -1);
/**
* Same as above except the different return type (which is not casted
* here).
*/
static Object createObject(ErrorType e, const char *m = 0, int l = -1);
};
}; // namespace
#endif