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