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 <stdio.h>
00026
#include <math.h>
00027
#include <assert.h>
00028
00029
#include "array_object.h"
00030
#include "bool_object.h"
00031
#include "collector.h"
00032
#include "context.h"
00033
#include "date_object.h"
00034
#include "debugger.h"
00035
#include "error_object.h"
00036
#include "function_object.h"
00037
#include "internal.h"
00038
#include "lexer.h"
00039
#include "math_object.h"
00040
#include "nodes.h"
00041
#include "number_object.h"
00042
#include "object.h"
00043
#include "object_object.h"
00044
#include "operations.h"
00045
#include "regexp_object.h"
00046
#include "string_object.h"
00047
00048
#define I18N_NOOP(s) s
00049
00050
extern int kjsyyparse();
00051
00052
using namespace KJS;
00053
00054
namespace KJS {
00055
00056
00057
typedef union {
unsigned char b[8];
double d; } kjs_double_t;
00058
00059
#ifdef WORDS_BIGENDIAN
00060
static const kjs_double_t NaN_Bytes = { { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 } };
00061
static const kjs_double_t Inf_Bytes = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
00062
#elif defined(arm)
00063
static const kjs_double_t NaN_Bytes = { { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 } };
00064
static const kjs_double_t Inf_Bytes = { { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } };
00065
#else
00066
static const kjs_double_t NaN_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } };
00067
static const kjs_double_t Inf_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
00068
#endif
00069
00070
const double NaN = NaN_Bytes.d;
00071
const double Inf = Inf_Bytes.d;
00072 }
00073
00074
#ifdef KJS_THREADSUPPORT
00075
static pthread_once_t interpreterLockOnce = PTHREAD_ONCE_INIT;
00076
static pthread_mutex_t interpreterLock;
00077
00078
static void initializeInterpreterLock()
00079 {
00080 pthread_mutexattr_t attr;
00081
00082 pthread_mutexattr_init(&attr);
00083 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
00084
00085 pthread_mutex_init(&interpreterLock, &attr);
00086 }
00087
#endif
00088
00089
static inline void lockInterpreter()
00090 {
00091
#ifdef KJS_THREADSUPPORT
00092
pthread_once(&interpreterLockOnce, initializeInterpreterLock);
00093 pthread_mutex_lock(&interpreterLock);
00094
#endif
00095
}
00096
00097
static inline void unlockInterpreter()
00098 {
00099
#ifdef KJS_THREADSUPPORT
00100
pthread_mutex_unlock(&interpreterLock);
00101
#endif
00102
}
00103
00104
00105
00106 UndefinedImp *UndefinedImp::staticUndefined = 0;
00107
00108
Value UndefinedImp::toPrimitive(
ExecState* , Type)
const
00109
{
00110
return Value((
ValueImp*)
this);
00111 }
00112
00113
bool UndefinedImp::toBoolean(
ExecState* )
const
00114
{
00115
return false;
00116 }
00117
00118
double UndefinedImp::toNumber(
ExecState* )
const
00119
{
00120
return NaN;
00121 }
00122
00123
UString UndefinedImp::toString(
ExecState* )
const
00124
{
00125
return "undefined";
00126 }
00127
00128
Object UndefinedImp::toObject(
ExecState *exec)
const
00129
{
00130
Object err = Error::create(exec, TypeError, I18N_NOOP(
"Undefined value"));
00131 exec->
setException(err);
00132
return err;
00133 }
00134
00135
00136
00137 NullImp *NullImp::staticNull = 0;
00138
00139
Value NullImp::toPrimitive(
ExecState* , Type)
const
00140
{
00141
return Value((
ValueImp*)
this);
00142 }
00143
00144
bool NullImp::toBoolean(
ExecState* )
const
00145
{
00146
return false;
00147 }
00148
00149
double NullImp::toNumber(
ExecState* )
const
00150
{
00151
return 0.0;
00152 }
00153
00154
UString NullImp::toString(
ExecState* )
const
00155
{
00156
return "null";
00157 }
00158
00159
Object NullImp::toObject(
ExecState *exec)
const
00160
{
00161
Object err = Error::create(exec, TypeError, I18N_NOOP(
"Null value"));
00162 exec->
setException(err);
00163
return err;
00164 }
00165
00166
00167
00168 BooleanImp* BooleanImp::staticTrue = 0;
00169 BooleanImp* BooleanImp::staticFalse = 0;
00170
00171
Value BooleanImp::toPrimitive(
ExecState* , Type)
const
00172
{
00173
return Value((
ValueImp*)
this);
00174 }
00175
00176
bool BooleanImp::toBoolean(
ExecState* )
const
00177
{
00178
return val;
00179 }
00180
00181
double BooleanImp::toNumber(
ExecState* )
const
00182
{
00183
return val ? 1.0 : 0.0;
00184 }
00185
00186
UString BooleanImp::toString(
ExecState* )
const
00187
{
00188
return val ?
"true" :
"false";
00189 }
00190
00191
Object BooleanImp::toObject(
ExecState *exec)
const
00192
{
00193
List args;
00194 args.
append(const_cast<BooleanImp*>(
this));
00195
return Object::dynamicCast(exec->
interpreter()->
builtinBoolean().
construct(exec,args));
00196 }
00197
00198
00199
00200
Value StringImp::toPrimitive(
ExecState* , Type)
const
00201
{
00202
return Value((
ValueImp*)
this);
00203 }
00204
00205
bool StringImp::toBoolean(
ExecState* )
const
00206
{
00207
return (val.size() > 0);
00208 }
00209
00210
double StringImp::toNumber(
ExecState* )
const
00211
{
00212
return val.toDouble();
00213 }
00214
00215
UString StringImp::toString(
ExecState* )
const
00216
{
00217
return val;
00218 }
00219
00220
Object StringImp::toObject(
ExecState *exec)
const
00221
{
00222
List args;
00223 args.
append(const_cast<StringImp*>(
this));
00224
return Object::dynamicCast(exec->
interpreter()->
builtinString().
construct(exec,args));
00225 }
00226
00227
00228
00229 NumberImp *NumberImp::staticNaN;
00230
00231
ValueImp *NumberImp::create(
int i)
00232 {
00233
if (SimpleNumber::fits(i))
00234
return SimpleNumber::make(i);
00235 NumberImp *imp =
new NumberImp(static_cast<double>(i));
00236 imp->setGcAllowedFast();
00237
return imp;
00238 }
00239
00240
ValueImp *NumberImp::create(
double d)
00241 {
00242
if (SimpleNumber::fits(d))
00243
return SimpleNumber::make((
int)d);
00244
if (isNaN(d))
00245
return staticNaN;
00246 NumberImp *imp =
new NumberImp(d);
00247 imp->setGcAllowedFast();
00248
return imp;
00249 }
00250
00251
Value NumberImp::toPrimitive(
ExecState *, Type)
const
00252
{
00253
return Number((NumberImp*)
this);
00254 }
00255
00256
bool NumberImp::toBoolean(
ExecState *)
const
00257
{
00258
return !((val == 0) || isNaN(val));
00259 }
00260
00261
double NumberImp::toNumber(
ExecState *)
const
00262
{
00263
return val;
00264 }
00265
00266
UString NumberImp::toString(
ExecState *)
const
00267
{
00268
if (val == 0.0)
00269
return "0";
00270
return UString::from(val);
00271 }
00272
00273
Object NumberImp::toObject(
ExecState *exec)
const
00274
{
00275
List args;
00276 args.
append(const_cast<NumberImp*>(
this));
00277
return Object::dynamicCast(exec->
interpreter()->
builtinNumber().
construct(exec,args));
00278 }
00279
00280
bool NumberImp::toUInt32(
unsigned& uint32)
const
00281
{
00282 uint32 = (
unsigned)val;
00283
return (
double)uint32 == val;
00284 }
00285
00286
double SimpleNumber::negZero = -0.0;
00287
00288
00289
00290 LabelStack::LabelStack(
const LabelStack &other)
00291 {
00292 tos = 0;
00293 *
this = other;
00294 }
00295
00296
LabelStack &LabelStack::operator=(
const LabelStack &other)
00297 {
00298 clear();
00299 tos = 0;
00300 StackElem *cur = 0;
00301 StackElem *se = other.
tos;
00302
while (se) {
00303 StackElem *newPrev =
new StackElem;
00304 newPrev->prev = 0;
00305 newPrev->id = se->id;
00306
if (cur)
00307 cur->prev = newPrev;
00308
else
00309 tos = newPrev;
00310 cur = newPrev;
00311 se = se->prev;
00312 }
00313
return *
this;
00314 }
00315
00316 bool LabelStack::push(
const Identifier &
id)
00317 {
00318
if (
id.isEmpty() ||
contains(
id))
00319
return false;
00320
00321 StackElem *newtos =
new StackElem;
00322 newtos->id =
id;
00323 newtos->prev = tos;
00324 tos = newtos;
00325
return true;
00326 }
00327
00328 bool LabelStack::contains(
const Identifier &
id)
const
00329
{
00330
if (
id.isEmpty())
00331
return true;
00332
00333
for (StackElem *curr = tos; curr; curr = curr->prev)
00334
if (curr->id ==
id)
00335
return true;
00336
00337
return false;
00338 }
00339
00340 void LabelStack::pop()
00341 {
00342
if (tos) {
00343 StackElem *prev = tos->prev;
00344
delete tos;
00345 tos = prev;
00346 }
00347 }
00348
00349 LabelStack::~LabelStack()
00350 {
00351 clear();
00352 }
00353
00354
void LabelStack::clear()
00355 {
00356 StackElem *prev;
00357
00358
while (tos) {
00359 prev = tos->prev;
00360
delete tos;
00361 tos = prev;
00362 }
00363 }
00364
00365
00366
00367
00368
00369 ContextImp::ContextImp(
Object &glob, InterpreterImp *interpreter,
Object &thisV,
int _sourceId, CodeType type,
00370
ContextImp *callingCon,
FunctionImp *func,
const List *args)
00371 : _interpreter(interpreter), _function(func), _arguments(args)
00372 {
00373 codeType = type;
00374 _callingContext = callingCon;
00375 tryCatch = 0;
00376
00377 sourceId = _sourceId;
00378 line0 = 1;
00379 line1 = 1;
00380
00381
if (func && func->inherits(&DeclaredFunctionImp::info))
00382 functionName = static_cast<DeclaredFunctionImp*>(func)->name();
00383
else
00384 functionName =
Identifier::null();
00385
00386
00387
if (type == FunctionCode) {
00388 activation =
Object(
new ActivationImp(func,*args));
00389 variable = activation;
00390 }
else {
00391 activation = Object();
00392 variable = glob;
00393 }
00394
00395
00396
switch(type) {
00397
case EvalCode:
00398
if (_callingContext) {
00399 scope = _callingContext->scopeChain();
00400
#ifndef KJS_PURE_ECMA
00401
if (thisV.
imp() != glob.
imp())
00402 scope.push(thisV.
imp());
00403
#endif
00404
variable = _callingContext->variableObject();
00405 thisVal = _callingContext->thisValue();
00406
break;
00407 }
00408
case GlobalCode:
00409 scope.clear();
00410 scope.push(glob.
imp());
00411
#ifndef KJS_PURE_ECMA
00412
if (thisV.
isValid())
00413 thisVal = thisV;
00414
else
00415
#endif
00416
thisVal = glob;
00417
break;
00418
case FunctionCode:
00419 scope = func->scope();
00420 scope.push(activation.imp());
00421 variable = activation;
00422 thisVal = thisV;
00423
break;
00424 }
00425
00426 _interpreter->setContext(
this);
00427 }
00428
00429 ContextImp::~ContextImp()
00430 {
00431 _interpreter->setContext(_callingContext);
00432 }
00433
00434
void ContextImp::mark()
00435 {
00436
for (
ContextImp *context =
this; context; context = context->
_callingContext) {
00437 context->
scope.
mark();
00438 }
00439 }
00440
00441
bool ContextImp::inTryCatch()
const
00442
{
00443
const ContextImp *c =
this;
00444
while (c && !c->
tryCatch)
00445 c = c->
_callingContext;
00446
return (c && c->
tryCatch);
00447 }
00448
00449
00450
00451
void SourceCode::cleanup()
00452 {
00453
if (interpreter && interpreter->debugger())
00454 interpreter->debugger()->sourceUnused(interpreter->globalExec(),sid);
00455
if (interpreter)
00456 interpreter->removeSourceCode(
this);
00457
delete this;
00458 }
00459
00460
00461
00462 FunctionBodyNode *Parser::progNode = 0;
00463
int Parser::sid = 0;
00464 SourceCode *Parser::source = 0;
00465
00466 FunctionBodyNode *Parser::parse(
const UChar *code,
unsigned int length, SourceCode **src,
00467
int *errLine,
UString *errMsg)
00468 {
00469
if (errLine)
00470 *errLine = -1;
00471
if (errMsg)
00472 *errMsg = 0;
00473
00474 Lexer::curr()->setCode(code, length);
00475 progNode = 0;
00476 sid++;
00477
00478 source =
new SourceCode(sid);
00479 source->ref();
00480 *src = source;
00481
00482
00483
00484
00485
int parseError = kjsyyparse();
00486
if (Lexer::curr()->hadError())
00487 parseError = 1;
00488 Lexer::curr()->doneParsing();
00489 FunctionBodyNode *prog = progNode;
00490 progNode = 0;
00491
00492 source = 0;
00493
00494
if (parseError) {
00495
int eline = Lexer::curr()->lineNo();
00496
if (errLine)
00497 *errLine = eline;
00498
if (errMsg)
00499 *errMsg =
"Parse error at line " + UString::from(eline);
00500
#ifdef KJS_VERBOSE
00501
fprintf( stderr,
"%s\n",
UString(code,length).ascii() );
00502
#endif
00503
#ifndef NDEBUG
00504
fprintf(stderr,
"KJS: JavaScript parse error at line %d.\n", eline);
00505
#endif
00506
delete prog;
00507
return 0;
00508 }
00509
#ifdef KJS_VERBOSE
00510
fprintf( stderr,
"%s\n", prog->toCode().ascii() );
00511
#endif
00512
00513
return prog;
00514 }
00515
00516
00517
00518 InterpreterImp* InterpreterImp::s_hook = 0L;
00519
00520
void InterpreterImp::globalInit()
00521 {
00522
00523 UndefinedImp::staticUndefined =
new UndefinedImp();
00524 UndefinedImp::staticUndefined->ref();
00525 NullImp::staticNull =
new NullImp();
00526 NullImp::staticNull->ref();
00527 BooleanImp::staticTrue =
new BooleanImp(
true);
00528 BooleanImp::staticTrue->ref();
00529 BooleanImp::staticFalse =
new BooleanImp(
false);
00530 BooleanImp::staticFalse->ref();
00531 NumberImp::staticNaN =
new NumberImp(NaN);
00532 NumberImp::staticNaN->ref();
00533 }
00534
00535
void InterpreterImp::globalClear()
00536 {
00537
00538 UndefinedImp::staticUndefined->deref();
00539 UndefinedImp::staticUndefined->setGcAllowed();
00540 UndefinedImp::staticUndefined = 0L;
00541 NullImp::staticNull->deref();
00542 NullImp::staticNull->setGcAllowed();
00543 NullImp::staticNull = 0L;
00544 BooleanImp::staticTrue->deref();
00545 BooleanImp::staticTrue->setGcAllowed();
00546 BooleanImp::staticTrue = 0L;
00547 BooleanImp::staticFalse->deref();
00548 BooleanImp::staticFalse->setGcAllowed();
00549 BooleanImp::staticFalse = 0L;
00550 NumberImp::staticNaN->deref();
00551 NumberImp::staticNaN->setGcAllowed();
00552 NumberImp::staticNaN = 0;
00553 }
00554
00555 InterpreterImp::InterpreterImp(
Interpreter *interp,
const Object &glob)
00556 : m_interpreter(interp),
00557 global(glob),
00558 dbg(0),
00559 m_compatMode(
Interpreter::NativeMode),
00560 _context(0),
00561 recursion(0),
00562 sources(0)
00563 {
00564
00565
00566 lockInterpreter();
00567
if (s_hook) {
00568 prev = s_hook;
00569
next = s_hook->next;
00570 s_hook->next->prev =
this;
00571 s_hook->next =
this;
00572 }
else {
00573
00574 s_hook =
next = prev =
this;
00575 globalInit();
00576 }
00577 unlockInterpreter();
00578
00579 globExec =
new ExecState(m_interpreter,0);
00580
00581
00582 initGlobalObject();
00583 }
00584
00585
void InterpreterImp::lock()
00586 {
00587 lockInterpreter();
00588 }
00589
00590
void InterpreterImp::unlock()
00591 {
00592 unlockInterpreter();
00593 }
00594
00595
void InterpreterImp::initGlobalObject()
00596 {
00597
00598
00599
FunctionPrototypeImp *funcProto =
new FunctionPrototypeImp(globExec);
00600 b_FunctionPrototype =
Object(funcProto);
00601 ObjectPrototypeImp *objProto =
new ObjectPrototypeImp(globExec,funcProto);
00602 b_ObjectPrototype = Object(objProto);
00603 funcProto->setPrototype(b_ObjectPrototype);
00604
00605 ArrayPrototypeImp *arrayProto =
new ArrayPrototypeImp(globExec,objProto);
00606 b_ArrayPrototype = Object(arrayProto);
00607 StringPrototypeImp *stringProto =
new StringPrototypeImp(globExec,objProto);
00608 b_StringPrototype = Object(stringProto);
00609 BooleanPrototypeImp *booleanProto =
new BooleanPrototypeImp(globExec,objProto,funcProto);
00610 b_BooleanPrototype = Object(booleanProto);
00611 NumberPrototypeImp *numberProto =
new NumberPrototypeImp(globExec,objProto,funcProto);
00612 b_NumberPrototype = Object(numberProto);
00613 DatePrototypeImp *dateProto =
new DatePrototypeImp(globExec,objProto);
00614 b_DatePrototype = Object(dateProto);
00615 RegExpPrototypeImp *regexpProto =
new RegExpPrototypeImp(globExec,objProto,funcProto);
00616 b_RegExpPrototype = Object(regexpProto);
00617 ErrorPrototypeImp *errorProto =
new ErrorPrototypeImp(globExec,objProto,funcProto);
00618 b_ErrorPrototype = Object(errorProto);
00619
00620 static_cast<ObjectImp*>(global.imp())->setPrototype(b_ObjectPrototype);
00621
00622
00623
00624 b_Object = Object(
new ObjectObjectImp(globExec, objProto, funcProto));
00625 b_Function = Object(
new FunctionObjectImp(globExec, funcProto));
00626 b_Array = Object(
new ArrayObjectImp(globExec, funcProto, arrayProto));
00627 b_String = Object(
new StringObjectImp(globExec, funcProto, stringProto));
00628 b_Boolean = Object(
new BooleanObjectImp(globExec, funcProto, booleanProto));
00629 b_Number = Object(
new NumberObjectImp(globExec, funcProto, numberProto));
00630 b_Date = Object(
new DateObjectImp(globExec, funcProto, dateProto));
00631 b_RegExp = Object(
new RegExpObjectImp(globExec, funcProto, regexpProto));
00632 b_Error = Object(
new ErrorObjectImp(globExec, funcProto, errorProto));
00633
00634
00635 b_evalErrorPrototype = Object(
new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
00636
"EvalError",
"EvalError"));
00637 b_rangeErrorPrototype = Object(
new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
00638
"RangeError",
"RangeError"));
00639 b_referenceErrorPrototype = Object(
new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
00640
"ReferenceError",
"ReferenceError"));
00641 b_syntaxErrorPrototype = Object(
new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
00642
"SyntaxError",
"SyntaxError"));
00643 b_typeErrorPrototype = Object(
new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
00644
"TypeError",
"TypeError"));
00645 b_uriErrorPrototype = Object(
new NativeErrorPrototypeImp(globExec,errorProto,URIError,
00646
"URIError",
"URIError"));
00647
00648
00649 b_evalError = Object(
new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
00650 b_rangeError = Object(
new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
00651 b_referenceError = Object(
new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
00652 b_syntaxError = Object(
new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
00653 b_typeError = Object(
new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
00654 b_uriError = Object(
new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
00655
00656
00657 funcProto->put(globExec,constructorPropertyName, b_Function, DontEnum);
00658
00659 global.put(globExec,
"Object", b_Object, DontEnum);
00660 global.put(globExec,
"Function", b_Function, DontEnum);
00661 global.put(globExec,
"Array", b_Array, DontEnum);
00662 global.put(globExec,
"Boolean", b_Boolean, DontEnum);
00663 global.put(globExec,
"String", b_String, DontEnum);
00664 global.put(globExec,
"Number", b_Number, DontEnum);
00665 global.put(globExec,
"Date", b_Date, DontEnum);
00666 global.put(globExec,
"RegExp", b_RegExp, DontEnum);
00667 global.put(globExec,
"Error", b_Error, DontEnum);
00668
00669
00670 global.put(globExec,
"EvalError",b_evalError, Internal);
00671 global.put(globExec,
"RangeError",b_rangeError, Internal);
00672 global.put(globExec,
"ReferenceError",b_referenceError, Internal);
00673 global.put(globExec,
"SyntaxError",b_syntaxError, Internal);
00674 global.put(globExec,
"TypeError",b_typeError, Internal);
00675 global.put(globExec,
"URIError",b_uriError, Internal);
00676
00677
00678 objProto->put(globExec, constructorPropertyName, b_Object, DontEnum | DontDelete | ReadOnly);
00679 funcProto->put(globExec, constructorPropertyName, b_Function, DontEnum | DontDelete | ReadOnly);
00680 arrayProto->put(globExec, constructorPropertyName, b_Array, DontEnum | DontDelete | ReadOnly);
00681 booleanProto->put(globExec, constructorPropertyName, b_Boolean, DontEnum | DontDelete | ReadOnly);
00682 stringProto->put(globExec, constructorPropertyName, b_String, DontEnum | DontDelete | ReadOnly);
00683 numberProto->put(globExec, constructorPropertyName, b_Number, DontEnum | DontDelete | ReadOnly);
00684 dateProto->put(globExec, constructorPropertyName, b_Date, DontEnum | DontDelete | ReadOnly);
00685 regexpProto->put(globExec, constructorPropertyName, b_RegExp, DontEnum | DontDelete | ReadOnly);
00686 errorProto->put(globExec, constructorPropertyName, b_Error, DontEnum | DontDelete | ReadOnly);
00687 b_evalErrorPrototype.put(globExec, constructorPropertyName, b_evalError, DontEnum | DontDelete | ReadOnly);
00688 b_rangeErrorPrototype.put(globExec, constructorPropertyName, b_rangeError, DontEnum | DontDelete | ReadOnly);
00689 b_referenceErrorPrototype.put(globExec, constructorPropertyName, b_referenceError, DontEnum | DontDelete | ReadOnly);
00690 b_syntaxErrorPrototype.put(globExec, constructorPropertyName, b_syntaxError, DontEnum | DontDelete | ReadOnly);
00691 b_typeErrorPrototype.put(globExec, constructorPropertyName, b_typeError, DontEnum | DontDelete | ReadOnly);
00692 b_uriErrorPrototype.put(globExec, constructorPropertyName, b_uriError, DontEnum | DontDelete | ReadOnly);
00693
00694
00695 global.put(globExec,
"NaN",
Number(NaN), DontEnum|DontDelete);
00696 global.put(globExec,
"Infinity",
Number(Inf), DontEnum|DontDelete);
00697 global.put(globExec,
"undefined",
Undefined(), DontEnum|DontDelete);
00698
00699
00700
#ifdef KJS_PURE_ECMA // otherwise as deprecated Object.prototype property
00701
global.put(globExec,
"eval",
00702 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval,1,
"eval")), DontEnum);
00703
#endif
00704
global.put(globExec,
"parseInt",
00705 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt,2,
"parseInt")), DontEnum);
00706 global.put(globExec,
"parseFloat",
00707 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat,1,
"parseFloat")), DontEnum);
00708 global.put(globExec,
"isNaN",
00709 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN,1,
"isNaN")), DontEnum);
00710 global.put(globExec,
"isFinite",
00711 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite,1,
"isFinite")), DontEnum);
00712 global.put(globExec,
"decodeURI",
00713 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURI,1,
"decodeURI")),
00714 DontEnum);
00715 global.put(globExec,
"decodeURIComponent",
00716 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::DecodeURIComponent,1,
"decodeURIComponent")),
00717 DontEnum);
00718 global.put(globExec,
"encodeURI",
00719 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURI,1,
"encodeURI")),
00720 DontEnum);
00721 global.put(globExec,
"encodeURIComponent",
00722 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::EncodeURIComponent,1,
"encodeURIComponent")),
00723 DontEnum);
00724 global.put(globExec,
"escape",
00725 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape,1,
"escape")), DontEnum);
00726 global.put(globExec,
"unescape",
00727 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape,1,
"unescape")), DontEnum);
00728
#ifndef NDEBUG
00729
global.put(globExec,
"kjsprint",
00730 Object(
new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::KJSPrint,1,
"kjsprint")), DontEnum);
00731
#endif
00732
00733
00734 global.put(globExec,
"Math", Object(
new MathObjectImp(globExec,objProto)), DontEnum);
00735 }
00736
00737 InterpreterImp::~InterpreterImp()
00738 {
00739
if (dbg)
00740 dbg->detach(m_interpreter);
00741
for (SourceCode *s = sources; s; s = s->next)
00742 s->interpreter = 0;
00743
delete globExec;
00744 globExec = 0L;
00745 clear();
00746 }
00747
00748
void InterpreterImp::clear()
00749 {
00750
00751
00752 lockInterpreter();
00753
next->prev = prev;
00754 prev->next =
next;
00755 s_hook =
next;
00756
if (s_hook ==
this)
00757 {
00758
00759 s_hook = 0L;
00760 globalClear();
00761 }
00762 unlockInterpreter();
00763 }
00764
00765
void InterpreterImp::mark()
00766 {
00767
00768
00769
00770
00771
if (UndefinedImp::staticUndefined && !UndefinedImp::staticUndefined->marked())
00772 UndefinedImp::staticUndefined->mark();
00773
if (NullImp::staticNull && !NullImp::staticNull->marked())
00774 NullImp::staticNull->mark();
00775
if (BooleanImp::staticTrue && !BooleanImp::staticTrue->marked())
00776 BooleanImp::staticTrue->mark();
00777
if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
00778 BooleanImp::staticFalse->mark();
00779
00780
if (global.imp())
00781 global.imp()->mark();
00782
if (m_interpreter)
00783 m_interpreter->mark();
00784
if (_context)
00785 _context->mark();
00786 }
00787
00788
bool InterpreterImp::checkSyntax(
const UString &code,
int *errLine,
UString *errMsg)
00789 {
00790
00791 SourceCode *source;
00792 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,errLine,errMsg);
00793 source->deref();
00794
bool ok = (progNode != 0);
00795
delete progNode;
00796
return ok;
00797 }
00798
00799
bool InterpreterImp::checkSyntax(
const UString &code)
00800 {
00801
00802 SourceCode *source;
00803 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,0,0);
00804 source->deref();
00805
bool ok = (progNode != 0);
00806
delete progNode;
00807
return ok;
00808 }
00809
00810
Completion InterpreterImp::evaluate(
const UString &code,
const Value &thisV)
00811 {
00812 lockInterpreter();
00813
00814
00815
if (recursion >= 20) {
00816
Completion result =
Completion(Throw,Error::create(globExec,GeneralError,
"Recursion too deep"));
00817 unlockInterpreter();
00818
return result;
00819 }
00820
00821
00822
int errLine;
00823
UString errMsg;
00824 SourceCode *source;
00825 FunctionBodyNode *progNode = Parser::parse(code.
data(),code.
size(),&source,&errLine,&errMsg);
00826
if (progNode)
00827 progNode->setProgram(
true);
00828
00829
00830
if (dbg) {
00831
bool cont = dbg->sourceParsed(globExec,source->sid,code,errLine);
00832
if (!cont) {
00833 source->deref();
00834
if (progNode)
00835
delete progNode;
00836 unlockInterpreter();
00837
return Completion(Break);
00838 }
00839 }
00840
00841 addSourceCode(source);
00842
00843
00844
if (!progNode) {
00845 Object err = Error::create(globExec,SyntaxError,errMsg.
ascii(),errLine);
00846 err.
put(globExec,
"sid",
Number(source->sid));
00847 globExec->setException(err);
00848 globExec->clearException();
00849 source->deref();
00850 unlockInterpreter();
00851
return Completion(Throw,err);
00852 }
00853 source->deref();
00854
00855 globExec->clearException();
00856
00857 recursion++;
00858 progNode->ref();
00859
00860 Object &globalObj = globalObject();
00861 Object thisObj = globalObject();
00862
00863
if (thisV.
isValid()) {
00864
00865
if (thisV.
isA(NullType) || thisV.
isA(UndefinedType))
00866 thisObj = globalObject();
00867
else {
00868 thisObj = thisV.
toObject(globExec);
00869 }
00870 }
00871
00872 Completion res;
00873
if (globExec->hadException()) {
00874
00875
00876 res = Completion(Throw,globExec->exception());
00877 }
00878
else {
00879
00880
ContextImp ctx(globalObj,
this, thisObj, source->sid);
00881
ExecState newExec(m_interpreter,&ctx);
00882
00883
00884
00885 progNode->processVarDecls(&newExec);
00886
00887 ctx.
setLines(progNode->firstLine(),progNode->firstLine());
00888
bool abort =
false;
00889
if (dbg) {
00890
if (!dbg->enterContext(&newExec)) {
00891
00892 dbg->imp()->abort();
00893 abort =
true;
00894 }
00895 }
00896
00897
if (!abort) {
00898 ctx.
setLines(progNode->lastLine(),progNode->lastLine());
00899 res = progNode->execute(&newExec);
00900
if (dbg && !dbg->exitContext(&newExec,res)) {
00901
00902 dbg->imp()->abort();
00903 unlockInterpreter();
00904 res = Completion(ReturnValue,
Undefined());
00905 }
00906 }
00907 }
00908
00909
if (progNode->deref())
00910
delete progNode;
00911 recursion--;
00912
00913
if (globExec->hadException()) {
00914 res = Completion(Throw,globExec->exception());
00915 globExec->clearException();
00916 }
00917
00918 unlockInterpreter();
00919
return res;
00920 }
00921
00922
void InterpreterImp::setDebugger(Debugger *d)
00923 {
00924
if (d == dbg)
00925
return;
00926
00927 Debugger *old = dbg;
00928 dbg = d;
00929
if ( old )
00930 old->detach(m_interpreter);
00931 }
00932
00933
void InterpreterImp::addSourceCode(SourceCode *code)
00934 {
00935 assert(!code->next);
00936 assert(!code->interpreter);
00937 code->next = sources;
00938 code->interpreter =
this;
00939 sources = code;
00940 }
00941
00942
void InterpreterImp::removeSourceCode(SourceCode *code)
00943 {
00944 assert(code);
00945 assert(sources);
00946
00947
if (code == sources) {
00948 sources = sources->next;
00949
return;
00950 }
00951
00952 SourceCode *prev = sources;
00953 SourceCode *cur = sources->next;
00954
while (cur != code) {
00955 assert(cur);
00956 prev = cur;
00957 cur = cur->next;
00958 }
00959
00960 prev->next = cur->next;
00961 }
00962
00963
00964
00965
const ClassInfo InternalFunctionImp::info = {
"Function", 0, 0, 0};
00966
00967 InternalFunctionImp::InternalFunctionImp(FunctionPrototypeImp *funcProto)
00968 : ObjectImp(funcProto)
00969 {
00970 }
00971
00972 InternalFunctionImp::InternalFunctionImp(
ExecState *exec)
00973 : ObjectImp(static_cast<FunctionPrototypeImp*>(exec->interpreter()->builtinFunctionPrototype().imp()))
00974 {
00975 }
00976
00977
bool InternalFunctionImp::implementsHasInstance()
const
00978
{
00979
return true;
00980 }
00981
00982
Boolean InternalFunctionImp::hasInstance(
ExecState *exec,
const Value &value)
00983 {
00984
if (value.
type() != ObjectType)
00985
return Boolean(
false);
00986
00987
Value prot = get(exec,prototypePropertyName);
00988
if (prot.
type() != ObjectType && prot.
type() != NullType) {
00989 Object err = Error::create(exec, TypeError,
"Invalid prototype encountered "
00990
"in instanceof operation.");
00991 exec->
setException(err);
00992
return Boolean(
false);
00993 }
00994
00995 Object v = Object(static_cast<ObjectImp*>(value.
imp()));
00996
while ((v = Object::dynamicCast(v.
prototype())).imp()) {
00997
if (v.
imp() == prot.
imp())
00998
return Boolean(
true);
00999 }
01000
return Boolean(
false);
01001 }
01002
01003
01004
01005
double KJS::roundValue(
ExecState *exec,
const Value &v)
01006 {
01007
if (v.
type() == UndefinedType)
01008
return 0.0;
01009
double n = v.
toNumber(exec);
01010
if (isNaN(n))
01011
return NaN;
01012
if (n == 0.0)
01013
return 0.0;
01014
double d = floor(fabs(n));
01015
if (n < 0)
01016 d *= -1;
01017
01018
return d;
01019 }
01020
01021
#ifndef NDEBUG
01022
#include <stdio.h>
01023
void KJS::printInfo(
ExecState *exec,
const char *s,
const Value &o,
int lineno)
01024 {
01025
if (!o.
isValid())
01026 fprintf(stderr,
"KJS: %s: (null)", s);
01027
else {
01028
Value v = o;
01029
unsigned int arrayLength = 0;
01030
bool hadExcep = exec->
hadException();
01031
01032
UString name;
01033
switch ( v.
type() ) {
01034
case UnspecifiedType:
01035
name =
"Unspecified";
01036
break;
01037
case UndefinedType:
01038
name =
"Undefined";
01039
break;
01040
case NullType:
01041
name =
"Null";
01042
break;
01043
case BooleanType:
01044
name =
"Boolean";
01045
break;
01046
case StringType:
01047
name =
"String";
01048
break;
01049
case NumberType:
01050
name =
"Number";
01051
break;
01052
case ObjectType: {
01053 Object obj = Object::dynamicCast(v);
01054
name = obj.
className();
01055
if (
name.
isNull())
01056
name =
"(unknown class)";
01057
if ( obj.
inherits(&ArrayInstanceImp::info) )
01058 arrayLength = obj.
get(exec,lengthPropertyName).
toUInt32(exec);
01059 }
01060
break;
01061 }
01062
UString vString;
01063
01064
if ( arrayLength > 100 )
01065 vString =
UString(
"[ Array with " ) + UString::from( arrayLength ) +
" elements ]";
01066
else
01067 vString = v.
toString(exec);
01068
if ( !hadExcep )
01069 exec->
clearException();
01070
if ( vString.
size() > 50 )
01071 vString = vString.
substr( 0, 50 ) +
"...";
01072
01073
CString tempString( vString.
cstring() );
01074
01075 fprintf(stderr,
"KJS: %s: %s : %s (%p)",
01076 s, tempString.
c_str(),
name.
ascii(), (
void*)v.
imp());
01077
01078
if (lineno >= 0)
01079 fprintf(stderr,
", line %d\n",lineno);
01080
else
01081 fprintf(stderr,
"\n");
01082 }
01083 }
01084
#endif