00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "value.h"
00026 #include "object.h"
00027 #include "types.h"
00028 #include "interpreter.h"
00029 #include "lookup.h"
00030 #include "reference_list.h"
00031
00032 #include <assert.h>
00033 #include <math.h>
00034 #include <stdio.h>
00035
00036 #include "internal.h"
00037 #include "collector.h"
00038 #include "operations.h"
00039 #include "error_object.h"
00040 #include "nodes.h"
00041
00042 using namespace KJS;
00043
00044
00045
00046 Object Object::dynamicCast(const Value &v)
00047 {
00048 if (!v.isValid() || v.type() != ObjectType)
00049 return Object(0);
00050
00051 return Object(static_cast<ObjectImp*>(v.imp()));
00052 }
00053
00054 Value Object::call(ExecState *exec, Object &thisObj, const List &args)
00055 {
00056 #if KJS_MAX_STACK > 0
00057 static int depth = 0;
00058 if (++depth > KJS_MAX_STACK) {
00059 #ifndef NDEBUG
00060 fprintf(stderr, "Exceeded maximum function call depth\n");
00061 #endif
00062 --depth;
00063 Object err = Error::create(exec, RangeError,
00064 "Exceeded maximum function call depth.");
00065 exec->setException(err);
00066 return err;
00067 }
00068 #endif
00069
00070 Value ret = static_cast<ObjectImp*>(rep)->call(exec,thisObj,args);
00071
00072 #if KJS_MAX_STACK > 0
00073 --depth;
00074 #endif
00075
00076 return ret;
00077 }
00078
00079
00080
00081 ObjectImp::ObjectImp(const Object &proto)
00082 : _proto(static_cast<ObjectImp*>(proto.imp())), _internalValue(0L)
00083 {
00084
00085 }
00086
00087 ObjectImp::ObjectImp(ObjectImp *proto)
00088 : _proto(proto), _internalValue(0L)
00089 {
00090 }
00091
00092 ObjectImp::ObjectImp()
00093 {
00094
00095 _proto = NullImp::staticNull;
00096 _internalValue = 0L;
00097 }
00098
00099 ObjectImp::~ObjectImp()
00100 {
00101
00102 }
00103
00104 void ObjectImp::mark()
00105 {
00106
00107 ValueImp::mark();
00108
00109 if (_proto && !_proto->marked())
00110 _proto->mark();
00111
00112 _prop.mark();
00113
00114 if (_internalValue && !_internalValue->marked())
00115 _internalValue->mark();
00116
00117 _scope.mark();
00118 }
00119
00120 const ClassInfo *ObjectImp::classInfo() const
00121 {
00122 return 0;
00123 }
00124
00125 bool ObjectImp::inherits(const ClassInfo *info) const
00126 {
00127 if (!info)
00128 return false;
00129
00130 const ClassInfo *ci = classInfo();
00131 if (!ci)
00132 return false;
00133
00134 while (ci && ci != info)
00135 ci = ci->parentClass;
00136
00137 return (ci == info);
00138 }
00139
00140 Type ObjectImp::type() const
00141 {
00142 return ObjectType;
00143 }
00144
00145 Value ObjectImp::prototype() const
00146 {
00147 return Value(_proto);
00148 }
00149
00150 void ObjectImp::setPrototype(const Value &proto)
00151 {
00152 _proto = proto.imp();
00153 }
00154
00155 UString ObjectImp::className() const
00156 {
00157 const ClassInfo *ci = classInfo();
00158 if ( ci )
00159 return ci->className;
00160 return "Object";
00161 }
00162
00163 Value ObjectImp::get(ExecState *exec, const Identifier &propertyName) const
00164 {
00165 ValueImp *imp = getDirect(propertyName);
00166 if (imp)
00167 return Value(imp);
00168
00169 Object proto = Object::dynamicCast(prototype());
00170
00171
00172 if (propertyName == specialPrototypePropertyName) {
00173 if (!proto.isValid())
00174 return Null();
00175 else
00176 return Value(proto);
00177 }
00178
00179 if (proto.isNull())
00180 return Undefined();
00181
00182 return proto.get(exec,propertyName);
00183 }
00184
00185 Value ObjectImp::getPropertyByIndex(ExecState *exec,
00186 unsigned propertyName) const
00187 {
00188 return get(exec, Identifier::from(propertyName));
00189 }
00190
00191
00192 void ObjectImp::put(ExecState *exec, const Identifier &propertyName,
00193 const Value &value, int attr)
00194 {
00195 assert(!value.isNull());
00196
00197
00198 if (propertyName == specialPrototypePropertyName) {
00199 setPrototype(value);
00200 return;
00201 }
00202
00203
00204
00205
00206
00207
00208 if ((attr == None || attr == DontDelete) && !canPut(exec,propertyName)) {
00209 #ifdef KJS_VERBOSE
00210 fprintf( stderr, "WARNING: canPut %s said NO\n", propertyName.ascii() );
00211 #endif
00212 return;
00213 }
00214
00215 _prop.put(propertyName,value.imp(),attr);
00216 }
00217
00218
00219 void ObjectImp::putPropertyByIndex(ExecState *exec, unsigned propertyName,
00220 const Value &value, int attr)
00221 {
00222 put(exec, Identifier::from(propertyName), value, attr);
00223 }
00224
00225
00226 bool ObjectImp::canPut(ExecState *, const Identifier &propertyName) const
00227 {
00228 int attributes;
00229 ValueImp *v = _prop.get(propertyName, attributes);
00230 if (v)
00231 return!(attributes & ReadOnly);
00232
00233
00234 const HashEntry* e = findPropertyHashEntry(propertyName);
00235 if (e)
00236 return !(e->attr & ReadOnly);
00237
00238
00239
00240 return true;
00241 }
00242
00243
00244 bool ObjectImp::hasProperty(ExecState *exec, const Identifier &propertyName) const
00245 {
00246 if (_prop.get(propertyName))
00247 return true;
00248
00249
00250 if (findPropertyHashEntry(propertyName))
00251 return true;
00252
00253
00254 if (propertyName == specialPrototypePropertyName)
00255 return true;
00256
00257
00258 Object proto = Object::dynamicCast(prototype());
00259 return !proto.isNull() && proto.hasProperty(exec,propertyName);
00260 }
00261
00262 bool ObjectImp::hasPropertyByIndex(ExecState *exec, unsigned propertyName) const
00263 {
00264 return hasProperty(exec, Identifier::from(propertyName));
00265 }
00266
00267
00268 bool ObjectImp::deleteProperty(ExecState *, const Identifier &propertyName)
00269 {
00270 int attributes;
00271 ValueImp *v = _prop.get(propertyName, attributes);
00272 if (v) {
00273 if ((attributes & DontDelete))
00274 return false;
00275 _prop.remove(propertyName);
00276 return true;
00277 }
00278
00279
00280 const HashEntry* entry = findPropertyHashEntry(propertyName);
00281 if (entry && entry->attr & DontDelete)
00282 return false;
00283 return true;
00284 }
00285
00286 bool ObjectImp::deletePropertyByIndex(ExecState *exec, unsigned propertyName)
00287 {
00288 return deleteProperty(exec, Identifier::from(propertyName));
00289 }
00290
00291 void ObjectImp::deleteAllProperties( ExecState * )
00292 {
00293 _prop.clear();
00294 }
00295
00296
00297 Value ObjectImp::defaultValue(ExecState *exec, Type hint) const
00298 {
00299 if (hint != StringType && hint != NumberType) {
00300
00301 if (_proto == exec->interpreter()->builtinDatePrototype().imp())
00302 hint = StringType;
00303 else
00304 hint = NumberType;
00305 }
00306
00307 Value v;
00308 if (hint == StringType)
00309 v = get(exec,toStringPropertyName);
00310 else
00311 v = get(exec,valueOfPropertyName);
00312
00313 if (v.type() == ObjectType) {
00314 Object o = Object(static_cast<ObjectImp*>(v.imp()));
00315 if (o.implementsCall()) {
00316 Object thisObj = Object(const_cast<ObjectImp*>(this));
00317 Value def = o.call(exec,thisObj,List::empty());
00318 Type defType = def.type();
00319 if (defType == UnspecifiedType || defType == UndefinedType ||
00320 defType == NullType || defType == BooleanType ||
00321 defType == StringType || defType == NumberType) {
00322 return def;
00323 }
00324 }
00325 }
00326
00327 if (hint == StringType)
00328 v = get(exec,valueOfPropertyName);
00329 else
00330 v = get(exec,toStringPropertyName);
00331
00332 if (v.type() == ObjectType) {
00333 Object o = Object(static_cast<ObjectImp*>(v.imp()));
00334 if (o.implementsCall()) {
00335 Object thisObj = Object(const_cast<ObjectImp*>(this));
00336 Value def = o.call(exec,thisObj,List::empty());
00337 Type defType = def.type();
00338 if (defType == UnspecifiedType || defType == UndefinedType ||
00339 defType == NullType || defType == BooleanType ||
00340 defType == StringType || defType == NumberType) {
00341 return def;
00342 }
00343 }
00344 }
00345
00346 Object err = Error::create(exec, TypeError, I18N_NOOP("No default value"));
00347 exec->setException(err);
00348 return err;
00349 }
00350
00351 const HashEntry* ObjectImp::findPropertyHashEntry( const Identifier& propertyName ) const
00352 {
00353 const ClassInfo *info = classInfo();
00354 while (info) {
00355 if (info->propHashTable) {
00356 const HashEntry *e = Lookup::findEntry(info->propHashTable, propertyName);
00357 if (e)
00358 return e;
00359 }
00360 info = info->parentClass;
00361 }
00362 return 0L;
00363 }
00364
00365 bool ObjectImp::implementsConstruct() const
00366 {
00367 return false;
00368 }
00369
00370 Object ObjectImp::construct(ExecState* , const List &)
00371 {
00372 assert(false);
00373 return Object(0);
00374 }
00375
00376 bool ObjectImp::implementsCall() const
00377 {
00378 return false;
00379 }
00380
00381 Value ObjectImp::call(ExecState* , Object &, const List &)
00382 {
00383 assert(false);
00384 return Object(0);
00385 }
00386
00387 bool ObjectImp::implementsHasInstance() const
00388 {
00389 return false;
00390 }
00391
00392 Boolean ObjectImp::hasInstance(ExecState* , const Value &)
00393 {
00394 assert(false);
00395 return Boolean(false);
00396 }
00397
00398 ReferenceList ObjectImp::propList(ExecState *exec, bool recursive)
00399 {
00400 ReferenceList list;
00401 if (_proto && _proto->dispatchType() == ObjectType && recursive)
00402 list = static_cast<ObjectImp*>(_proto)->propList(exec,recursive);
00403
00404 _prop.addEnumerablesToReferenceList(list, Object(this));
00405
00406
00407 const ClassInfo *info = classInfo();
00408 while (info) {
00409 if (info->propHashTable) {
00410 int size = info->propHashTable->size;
00411 const HashEntry *e = info->propHashTable->entries;
00412 for (int i = 0; i < size; ++i, ++e) {
00413 if ( e->soffset && !(e->attr & DontEnum) )
00414 list.append(Reference(this, &info->propHashTable->sbase[e->soffset]));
00415 }
00416 }
00417 info = info->parentClass;
00418 }
00419
00420 return list;
00421 }
00422
00423 Value ObjectImp::internalValue() const
00424 {
00425 return Value(_internalValue);
00426 }
00427
00428 void ObjectImp::setInternalValue(const Value &v)
00429 {
00430 _internalValue = v.imp();
00431 }
00432
00433 void ObjectImp::setInternalValue(ValueImp *v)
00434 {
00435 v->setGcAllowed();
00436 _internalValue = v;
00437 }
00438
00439 Value ObjectImp::toPrimitive(ExecState *exec, Type preferredType) const
00440 {
00441 return defaultValue(exec,preferredType);
00442 }
00443
00444 bool ObjectImp::toBoolean(ExecState* ) const
00445 {
00446 return true;
00447 }
00448
00449 double ObjectImp::toNumber(ExecState *exec) const
00450 {
00451 Value prim = toPrimitive(exec,NumberType);
00452 if (exec->hadException())
00453 return 0.0;
00454 return prim.toNumber(exec);
00455 }
00456
00457 UString ObjectImp::toString(ExecState *exec) const
00458 {
00459 Value prim = toPrimitive(exec,StringType);
00460 if (exec->hadException())
00461 return "";
00462 return prim.toString(exec);
00463 }
00464
00465 Object ObjectImp::toObject(ExecState *) const
00466 {
00467 return Object(const_cast<ObjectImp*>(this));
00468 }
00469
00470 void ObjectImp::putDirect(const Identifier &propertyName, ValueImp *value, int attr)
00471 {
00472 value->setGcAllowed();
00473 _prop.put(propertyName, value, attr);
00474 }
00475
00476 void ObjectImp::putDirect(const Identifier &propertyName, int value, int attr)
00477 {
00478 _prop.put(propertyName, NumberImp::create(value), attr);
00479 }
00480
00481 void ObjectImp::setFunctionName(const Identifier &propertyName)
00482 {
00483 if (inherits(&InternalFunctionImp::info))
00484 static_cast<InternalFunctionImp*>(this)->setName(propertyName);
00485 }
00486
00487
00488
00489 const char * const errorNamesArr[] = {
00490 I18N_NOOP("Error"),
00491 I18N_NOOP("Evaluation error"),
00492 I18N_NOOP("Range error"),
00493 I18N_NOOP("Reference error"),
00494 I18N_NOOP("Syntax error"),
00495 I18N_NOOP("Type error"),
00496 I18N_NOOP("URI error"),
00497 };
00498
00499 const char * const * const Error::errorNames = errorNamesArr;
00500
00501 Object Error::create(ExecState *exec, ErrorType errtype, const char *message,
00502 int lineno, int sourceId)
00503 {
00504 #ifdef KJS_VERBOSE
00505
00506 fprintf(stderr, "WARNING: KJS %s: %s\n", errorNames[errtype], message);
00507 #endif
00508
00509 Object cons;
00510
00511 switch (errtype) {
00512 case EvalError:
00513 cons = exec->interpreter()->builtinEvalError();
00514 break;
00515 case RangeError:
00516 cons = exec->interpreter()->builtinRangeError();
00517 break;
00518 case ReferenceError:
00519 cons = exec->interpreter()->builtinReferenceError();
00520 break;
00521 case SyntaxError:
00522 cons = exec->interpreter()->builtinSyntaxError();
00523 break;
00524 case TypeError:
00525 cons = exec->interpreter()->builtinTypeError();
00526 break;
00527 case URIError:
00528 cons = exec->interpreter()->builtinURIError();
00529 break;
00530 default:
00531 cons = exec->interpreter()->builtinError();
00532 break;
00533 }
00534
00535 if (!message)
00536 message = errorNames[errtype];
00537 List args;
00538 args.append(String(message));
00539 Object err = Object::dynamicCast(cons.construct(exec,args));
00540
00541 if (lineno != -1)
00542 err.put(exec, "line", Number(lineno));
00543 if (sourceId != -1)
00544 err.put(exec, "sourceId", Number(sourceId));
00545
00546 return err;
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 }
00560