object_object.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Lesser General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Lesser General Public
00017  *  License along with this library; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
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 // ------------------------------ ObjectPrototypeImp --------------------------------
00036 
00037 ObjectPrototypeImp::ObjectPrototypeImp(ExecState *exec,
00038                                        FunctionPrototypeImp *funcProto)
00039   : ObjectImp() // [[Prototype]] is Null()
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   // see http://www.devguru.com/Technologies/ecmascript/quickref/object.html
00057   put(exec, "eval",
00058       Object(new GlobalFuncImp(exec, funcProto,GlobalFuncImp::Eval, 1, "eval")),
00059       DontEnum);
00060 #endif
00061 }
00062 
00063 // ------------------------------ ObjectProtoFuncImp --------------------------------
00064 
00065 ObjectProtoFuncImp::ObjectProtoFuncImp(ExecState * /*exec*/,
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 // ECMA 15.2.4.2 + 15.2.4.3
00082 
00083 Value ObjectProtoFuncImp::call(ExecState *exec, Object &thisObj, const List &args)
00084 {
00085   switch (id) {
00086   case ToString:
00087     // fall through
00088   case ToLocaleString:
00089     return String("[object "+thisObj.className()+"]");
00090   case ValueOf:
00091     return thisObj;
00092   case HasOwnProperty: {
00093     // Same as hasProperty() but without checking the prototype
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 // ------------------------------ ObjectObjectImp --------------------------------
00132 
00133 ObjectObjectImp::ObjectObjectImp(ExecState * /*exec*/,
00134                                  ObjectPrototypeImp *objProto,
00135                                  FunctionPrototypeImp *funcProto)
00136   : InternalFunctionImp(funcProto)
00137 {
00138   Value protect(this);
00139   // ECMA 15.2.3.1
00140   putDirect(prototypePropertyName, objProto, DontEnum|DontDelete|ReadOnly);
00141 
00142   // no. of arguments for constructor
00143   putDirect(lengthPropertyName, NumberImp::one(), ReadOnly|DontDelete|DontEnum);
00144 }
00145 
00146 
00147 bool ObjectObjectImp::implementsConstruct() const
00148 {
00149   return true;
00150 }
00151 
00152 // ECMA 15.2.2
00153 Object ObjectObjectImp::construct(ExecState *exec, const List &args)
00154 {
00155   // if no arguments have been passed ...
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 &/*thisObj*/, const List &args)
00187 {
00188   Value result;
00189 
00190   List argList;
00191   // Construct a new Object
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 
KDE Home | KDE Accessibility Home | Description of Access Keys