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