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