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->interpreter()->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->interpreter()->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