00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "value.h"
00023 #include "object.h"
00024 #include "types.h"
00025 #include "interpreter.h"
00026 #include "operations.h"
00027 #include "object_object.h"
00028 #include "function_object.h"
00029 #include "lookup.h"
00030 #include <stdio.h>
00031 #include <assert.h>
00032
00033 using namespace KJS;
00034
00035
00036
00037 ObjectPrototypeImp::ObjectPrototypeImp(ExecState *exec,
00038 FunctionPrototypeImp *funcProto)
00039 : ObjectImp()
00040 {
00041 Value protect(this);
00042 putDirect(toStringPropertyName, new ObjectProtoFuncImp(exec,funcProto,ObjectProtoFuncImp::ToString,
00043 0, toStringPropertyName), DontEnum);
00044 putDirect(toLocaleStringPropertyName, new ObjectProtoFuncImp(exec,funcProto,ObjectProtoFuncImp::ToLocaleString,
00045 0, toLocaleStringPropertyName), DontEnum);
00046 putDirect(valueOfPropertyName, new ObjectProtoFuncImp(exec,funcProto,ObjectProtoFuncImp::ValueOf,
00047 0, valueOfPropertyName), DontEnum);
00048 putDirect("hasOwnProperty", new ObjectProtoFuncImp(exec,funcProto,ObjectProtoFuncImp::HasOwnProperty,
00049 1,"hasOwnProperty"),DontEnum);
00050 putDirect("isPrototypeOf", new ObjectProtoFuncImp(exec,funcProto,ObjectProtoFuncImp::IsPrototypeOf,
00051 1,"isPrototypeOf"),DontEnum);
00052 putDirect("propertyIsEnumerable", new ObjectProtoFuncImp(exec,funcProto,ObjectProtoFuncImp::PropertyIsEnumerable,
00053 1,"propertyIsEnumerable"),DontEnum);
00054
00055 #ifndef KJS_PURE_ECMA // standard compliance location is the Global object
00056
00057 put(exec, "eval",
00058 Object(new GlobalFuncImp(exec, funcProto,GlobalFuncImp::Eval, 1, "eval")),
00059 DontEnum);
00060 #endif
00061 }
00062
00063
00064
00065 ObjectProtoFuncImp::ObjectProtoFuncImp(ExecState * ,
00066 FunctionPrototypeImp *funcProto,
00067 int i, int len, const Identifier &_ident)
00068 : InternalFunctionImp(funcProto), id(i)
00069 {
00070 Value protect(this);
00071 putDirect(lengthPropertyName, len, DontDelete|ReadOnly|DontEnum);
00072 ident = _ident;
00073 }
00074
00075
00076 bool ObjectProtoFuncImp::implementsCall() const
00077 {
00078 return true;
00079 }
00080
00081
00082
00083 Value ObjectProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
00084 {
00085 switch (id) {
00086 case ToString:
00087
00088 case ToLocaleString:
00089 return String("[object "+thisObj.className()+"]");
00090 case ValueOf:
00091 return thisObj;
00092 case HasOwnProperty: {
00093
00094 Identifier propertyName(args[0].toString(exec));
00095 Value tempProto(thisObj.imp()->prototype());
00096 thisObj.imp()->setPrototype(Value());
00097 bool exists = thisObj.hasProperty(exec,propertyName);
00098 thisObj.imp()->setPrototype(tempProto);
00099 return Value(exists ? BooleanImp::staticTrue : BooleanImp::staticFalse);
00100 }
00101 case IsPrototypeOf: {
00102 Value v = args[0];
00103 for (; v.isValid() && v.isA(ObjectType); v = Object::dynamicCast(v).prototype()) {
00104 if (v.imp() == thisObj.imp())
00105 return Value(BooleanImp::staticTrue);
00106 }
00107 return Value(BooleanImp::staticFalse);
00108 }
00109 case PropertyIsEnumerable: {
00110 Identifier propertyName(args[0].toString(exec));
00111 ObjectImp *obj = static_cast<ObjectImp*>(thisObj.imp());
00112
00113 int attributes;
00114 ValueImp *v = obj->_prop.get(propertyName,attributes);
00115 if (v)
00116 return Value((attributes & DontEnum) ?
00117 BooleanImp::staticFalse : BooleanImp::staticTrue);
00118
00119 if (propertyName == specialPrototypePropertyName)
00120 return Value(BooleanImp::staticFalse);
00121
00122 const HashEntry *entry = obj->findPropertyHashEntry(propertyName);
00123 return Value((entry && !(entry->attr & DontEnum)) ?
00124 BooleanImp::staticTrue : BooleanImp::staticFalse);
00125 }
00126 }
00127
00128 return Undefined();
00129 }
00130
00131
00132
00133 ObjectObjectImp::ObjectObjectImp(ExecState * ,
00134 ObjectPrototypeImp *objProto,
00135 FunctionPrototypeImp *funcProto)
00136 : InternalFunctionImp(funcProto)
00137 {
00138 Value protect(this);
00139
00140 putDirect(prototypePropertyName, objProto, DontEnum|DontDelete|ReadOnly);
00141
00142
00143 putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
00144 }
00145
00146
00147 bool ObjectObjectImp::implementsConstruct() const
00148 {
00149 return true;
00150 }
00151
00152
00153 Object ObjectObjectImp::construct(ExecState *exec, const List &args)
00154 {
00155
00156 if (args.isEmpty()) {
00157 Object proto = exec->lexicalInterpreter()->builtinObjectPrototype();
00158 Object result(new ObjectImp(proto));
00159 return result;
00160 }
00161
00162 Value arg = *(args.begin());
00163 Object obj = Object::dynamicCast(arg);
00164 if (obj.isValid())
00165 return obj;
00166
00167 switch (arg.type()) {
00168 case StringType:
00169 case BooleanType:
00170 case NumberType:
00171 return arg.toObject(exec);
00172 default:
00173 assert(!"unhandled switch case in ObjectConstructor");
00174 case NullType:
00175 case UndefinedType:
00176 Object proto = exec->lexicalInterpreter()->builtinObjectPrototype();
00177 return Object(new ObjectImp(proto));
00178 }
00179 }
00180
00181 bool ObjectObjectImp::implementsCall() const
00182 {
00183 return true;
00184 }
00185
00186 Value ObjectObjectImp::call(ExecState *exec, Object &, const List &args)
00187 {
00188 Value result;
00189
00190 List argList;
00191
00192 if (args.isEmpty()) {
00193 result = construct(exec,argList);
00194 } else {
00195 Value arg = args[0];
00196 if (arg.type() == NullType || arg.type() == UndefinedType) {
00197 argList.append(arg);
00198 result = construct(exec,argList);
00199 } else
00200 result = arg.toObject(exec);
00201 }
00202 return result;
00203 }
00204