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
#ifndef NDEBUG
00029
#include <strings.h>
00030
#endif
00031
00032
#include "array_object.h"
00033
#include "bool_object.h"
00034
#include "collector.h"
00035
#include "context.h"
00036
#include "date_object.h"
00037
#include "debugger.h"
00038
#include "error_object.h"
00039
#include "function_object.h"
00040
#include "internal.h"
00041
#include "lexer.h"
00042
#include "math_object.h"
00043
#include "nodes.h"
00044
#include "number_object.h"
00045
#include "object.h"
00046
#include "object_object.h"
00047
#include "operations.h"
00048
#include "regexp_object.h"
00049
#include "string_object.h"
00050
00051
#define I18N_NOOP(s) s
00052
00053
extern int kjsyyparse();
00054
00055
using namespace KJS;
00056
00057
namespace KJS {
00058
00059
00060
typedef union {
unsigned char b[8];
double d; } kjs_double_t;
00061
00062
#ifdef WORDS_BIGENDIAN
00063
static const kjs_double_t NaN_Bytes = { { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 } };
00064
static const kjs_double_t Inf_Bytes = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
00065
#elif defined(arm)
00066
static const kjs_double_t NaN_Bytes = { { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 } };
00067
static const kjs_double_t Inf_Bytes = { { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } };
00068
#else
00069
static const kjs_double_t NaN_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f } };
00070
static const kjs_double_t Inf_Bytes = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
00071
#endif
00072
00073
const double NaN = NaN_Bytes.d;
00074
const double Inf = Inf_Bytes.d;
00075 }
00076
00077
#ifdef KJS_THREADSUPPORT
00078
static pthread_once_t interpreterLockOnce = PTHREAD_ONCE_INIT;
00079
static pthread_mutex_t interpreterLock;
00080
00081
static void initializeInterpreterLock()
00082 {
00083 pthread_mutexattr_t attr;
00084
00085 pthread_mutexattr_init(&attr);
00086 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
00087
00088 pthread_mutex_init(&interpreterLock, &attr);
00089 }
00090
#endif
00091
00092
static inline void lockInterpreter()
00093 {
00094
#ifdef KJS_THREADSUPPORT
00095
pthread_once(&interpreterLockOnce, initializeInterpreterLock);
00096 pthread_mutex_lock(&interpreterLock);
00097
#endif
00098
}
00099
00100
static inline void unlockInterpreter()
00101 {
00102
#ifdef KJS_THREADSUPPORT
00103
pthread_mutex_unlock(&interpreterLock);
00104
#endif
00105
}
00106
00107
00108
00109 UndefinedImp *UndefinedImp::staticUndefined = 0;
00110
00111
Value UndefinedImp::toPrimitive(
ExecState* , Type)
const
00112
{
00113
return Value((
ValueImp*)
this);
00114 }
00115
00116
bool UndefinedImp::toBoolean(
ExecState* )
const
00117
{
00118
return false;
00119 }
00120
00121
double UndefinedImp::toNumber(
ExecState* )
const
00122
{
00123
return NaN;
00124 }
00125
00126
UString UndefinedImp::toString(
ExecState* )
const
00127
{
00128
return "undefined";
00129 }
00130
00131
Object UndefinedImp::toObject(
ExecState *exec)
const
00132
{
00133
Object err =
Error::create(exec, TypeError, I18N_NOOP(
"Undefined value"));
00134 exec->
setException(err);
00135
return err;
00136 }
00137
00138
00139
00140 NullImp *NullImp::staticNull = 0;
00141
00142
Value NullImp::toPrimitive(
ExecState* , Type)
const
00143
{
00144
return Value((
ValueImp*)
this);
00145 }
00146
00147
bool NullImp::toBoolean(
ExecState* )
const
00148
{
00149
return false;
00150 }
00151
00152
double NullImp::toNumber(
ExecState* )
const
00153
{
00154
return 0.0;
00155 }
00156
00157
UString NullImp::toString(
ExecState* )
const
00158
{
00159
return "null";
00160 }
00161
00162
Object NullImp::toObject(
ExecState *exec)
const
00163
{
00164
Object err =
Error::create(exec, TypeError, I18N_NOOP(
"Null value"));
00165 exec->
setException(err);
00166
return err;
00167 }
00168
00169
00170
00171 BooleanImp* BooleanImp::staticTrue = 0;
00172 BooleanImp* BooleanImp::staticFalse = 0;
00173
00174
Value BooleanImp::toPrimitive(
ExecState* , Type)
const
00175
{
00176
return Value((
ValueImp*)
this);
00177 }
00178
00179
bool BooleanImp::toBoolean(
ExecState* )
const
00180
{
00181
return val;
00182 }
00183
00184
double BooleanImp::toNumber(
ExecState* )
const
00185
{
00186
return val ? 1.0 : 0.0;
00187 }
00188
00189
UString BooleanImp::toString(
ExecState* )
const
00190
{
00191
return val ?
"true" :
"false";
00192 }
00193
00194
Object BooleanImp::toObject(
ExecState *exec)
const
00195
{
00196
List args;
00197 args.
append(const_cast<BooleanImp*>(
this));
00198
return Object::dynamicCast(exec->
interpreter()->
builtinBoolean().
construct(exec,args));
00199 }
00200
00201
00202
00203
Value StringImp::toPrimitive(
ExecState* , Type)
const
00204
{
00205
return Value((
ValueImp*)
this);
00206 }
00207
00208
bool StringImp::toBoolean(
ExecState* )
const
00209
{
00210
return (val.size() > 0);
00211 }
00212
00213
double StringImp::toNumber(
ExecState* )
const
00214
{
00215
return val.toDouble();
00216 }
00217
00218
UString StringImp::toString(
ExecState* )
const
00219
{
00220
return val;
00221 }
00222
00223
Object StringImp::toObject(
ExecState *exec)
const
00224
{
00225
List args;
00226 args.
append(const_cast<StringImp*>(
this));
00227
return Object::dynamicCast(exec->
interpreter()->
builtinString().
construct(exec,args));
00228 }
00229
00230
00231
00232 NumberImp *NumberImp::staticNaN;
00233
00234
ValueImp *NumberImp::create(
int i)
00235 {
00236
if (SimpleNumber::fits(i))
00237
return SimpleNumber::make(i);
00238 NumberImp *imp =
new NumberImp(static_cast<double>(i));
00239 imp->setGcAllowedFast();
00240
return imp;
00241 }
00242
00243
ValueImp *NumberImp::create(
double d)
00244 {
00245
if (SimpleNumber::fits(d))
00246
return SimpleNumber::make((
int)d);
00247
if (isNaN(d))
00248
return staticNaN;
00249 NumberImp *imp =
new NumberImp(d);
00250 imp->setGcAllowedFast();
00251
return imp;
00252 }
00253
00254
Value NumberImp::toPrimitive(
ExecState *, Type)
const
00255
{
00256
return Number((NumberImp*)
this);
00257 }
00258
00259
bool NumberImp::toBoolean(
ExecState *)
const
00260
{
00261
return !((val == 0) || isNaN(val));
00262 }
00263
00264
double NumberImp::toNumber(
ExecState *)
const
00265
{
00266
return val;
00267 }
00268
00269
UString NumberImp::toString(
ExecState *)
const
00270
{
00271
if (val == 0.0)
00272
return "0";
00273
return UString::from(val);
00274 }
00275
00276
Object NumberImp::toObject(
ExecState *exec)
const
00277
{
00278
List args;
00279 args.
append(const_cast<NumberImp*>(
this));
00280
return Object::dynamicCast(exec->
interpreter()->
builtinNumber().
construct(exec,args));
00281 }
00282
00283
bool NumberImp::toUInt32(
unsigned& uint32)
const
00284
{
00285 uint32 = (
unsigned)val;
00286
return (
double)uint32 == val;
00287 }
00288
00289
double SimpleNumber::negZero = -0.0;
00290
00291
00292
00293 LabelStack::LabelStack(
const LabelStack &other)
00294 {
00295 tos = 0;
00296 *
this = other;
00297 }
00298
00299
LabelStack &LabelStack::operator=(
const LabelStack &other)
00300 {
00301 clear();
00302 tos = 0;
00303 StackElem *cur = 0;
00304 StackElem *se = other.
tos;
00305
while (se) {
00306 StackElem *newPrev =
new StackElem;
00307 newPrev->prev = 0;
00308 newPrev->id = se->id;
00309
if (cur)
00310 cur->prev = newPrev;
00311
else
00312 tos = newPrev;
00313 cur = newPrev;
00314 se = se->prev;
00315 }
00316
return *
this;
00317 }
00318
00319 bool LabelStack::push(
const Identifier &
id)
00320 {
00321
if (
id.isEmpty() ||
contains(
id))
00322
return false;
00323
00324 StackElem *newtos =
new StackElem;
00325 newtos->id =
id;
00326 newtos->prev = tos;
00327 tos = newtos;
00328
return true;
00329 }
00330
00331 bool LabelStack::contains(
const Identifier &
id)
const
00332
{
00333
if (
id.isEmpty())
00334
return true;
00335
00336
for (StackElem *curr = tos; curr; curr = curr->prev)
00337
if (curr->id ==
id)
00338
return true;
00339
00340
return false;
00341 }
00342
00343 void LabelStack::pop()
00344 {
00345
if (tos) {
00346 StackElem *prev = tos->prev;
00347
delete tos;
00348 tos = prev;
00349 }
00350 }
00351
00352 LabelStack::~LabelStack()
00353 {
00354 clear();
00355 }
00356
00357
void LabelStack::clear()
00358 {
00359 StackElem *prev;
00360
00361
while (tos) {
00362 prev = tos->prev;
00363
delete tos;
00364 tos = prev;
00365 }
00366 }
00367
00368
00369
00370
00371
00372 ContextImp::ContextImp(
Object &glob, InterpreterImp *interpreter,
Object &thisV,
int _sourceId, CodeType type,
00373
ContextImp *callingCon,
FunctionImp *func,
const List *args)
00374 : _interpreter(interpreter), _function(func), _arguments(args)
00375 {
00376 codeType = type;
00377 _callingContext = callingCon;
00378 tryCatch = 0;
00379
00380 sourceId = _sourceId;
00381 line0 = 1;
00382 line1 = 1;
00383
00384
if (func && func->inherits(&DeclaredFunctionImp::info))
00385 functionName = static_cast<DeclaredFunctionImp*>(func)->name();
00386
else
00387 functionName =
Identifier::null();
00388
00389
00390
if (type == FunctionCode) {
00391 activation =
Object(
new ActivationImp(func,*args));
00392 variable = activation;
00393 }
else {
00394 activation =
Object();
00395 variable = glob;
00396 }
00397
00398
00399
switch(type) {
00400
case EvalCode:
00401
if (_callingContext) {
00402 scope = _callingContext->scopeChain();
00403
#ifndef KJS_PURE_ECMA
00404
if (thisV.
imp() != glob.
imp())
00405 scope.push(thisV.
imp());
00406
#endif
00407
variable = _callingContext->variableObject();
00408 thisVal = _callingContext->thisValue();
00409
break;
00410 }
00411
case GlobalCode:
00412 scope.clear();
00413 scope.push(glob.
imp());
00414
#ifndef KJS_PURE_ECMA
00415
if (thisV.
isValid())
00416 thisVal = thisV;
00417
else
00418
#endif
00419
thisVal = glob;
00420
break;
00421
case FunctionCode:
00422 scope = func->scope();
00423 scope.push(activation.imp());
00424 variable = activation;
00425 thisVal = thisV;
00426
break;
00427 }
00428
00429 _interpreter->setContext(
this);
00430 }
00431
00432 ContextImp::~ContextImp()
00433 {
00434 _interpreter->setContext(_callingContext);
00435 }
00436
00437
void ContextImp::mark()
00438 {
00439
for (
ContextImp *context =
this; context; context = context->
_callingContext) {
00440 context->
scope.
mark();
00441 }
00442 }
00443
00444
bool ContextImp::inTryCatch()
const
00445
{
00446
const ContextImp *c =
this;
00447
while (c && !c->
tryCatch)
00448 c = c->
_callingContext;
00449
return (c && c->
tryCatch);
00450 }
00451
00452
00453
00454
void SourceCode::cleanup()
00455 {
00456
if (interpreter && interpreter->debugger())
00457 interpreter->debugger()->sourceUnused(interpreter->globalExec(),sid);
00458
if (interpreter)
00459 interpreter->removeSourceCode(
this);
00460
delete this;
00461 }
00462
00463
00464
00465 FunctionBodyNode *Parser::progNode = 0;
00466
int Parser::sid = 0;
00467 SourceCode *Parser::source = 0;
00468
00469 FunctionBodyNode *Parser::parse(
const UChar *code,
unsigned int length, SourceCode **src,
00470
int *errLine,
UString *errMsg)
00471 {
00472
if (errLine)
00473 *errLine = -1;
00474
if (errMsg)
00475 *errMsg = 0;
00476
00477 Lexer::curr()->setCode(code, length);
00478 progNode = 0;
00479 sid++;
00480
00481 source =
new SourceCode(sid);
00482 source->ref();
00483 *src = source;
00484
00485
00486
00487
00488
int parseError = kjsyyparse();
00489
if (Lexer::curr()->hadError())
00490 parseError = 1;
00491 Lexer::curr()->doneParsing();
00492 FunctionBodyNode *prog = progNode;
00493 progNode = 0;
00494
00495 source = 0;
00496
00497
if (parseError) {
00498
int eline = Lexer::curr()->lineNo();
00499
if (errLine)
00500 *errLine = eline;
00501
if (errMsg)
00502 *errMsg =
"Parse error at line " +
UString::from(eline);
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
01030
UString name;
01031
switch ( v.
type() ) {
01032
case UnspecifiedType:
01033
name =
"Unspecified";
01034
break;
01035
case UndefinedType:
01036
name =
"Undefined";
01037
break;
01038
case NullType:
01039
name =
"Null";
01040
break;
01041
case BooleanType:
01042
name =
"Boolean";
01043
break;
01044
case StringType:
01045
name =
"String";
01046
break;
01047
case NumberType:
01048
name =
"Number";
01049
break;
01050
case ObjectType:
01051
name =
Object::dynamicCast(v).
className();
01052
if (
name.isNull())
01053
name =
"(unknown class)";
01054
break;
01055 }
01056
bool hadExcep = exec->
hadException();
01057
UString vString = v.
toString(exec);
01058
if ( !hadExcep )
01059 exec->
clearException();
01060
if ( vString.
size() > 50 )
01061 vString = vString.
substr( 0, 50 ) +
"...";
01062
01063
CString tempString( vString.
cstring() );
01064
01065 fprintf(stderr,
"KJS: %s: %s : %s (%p)",
01066 s, tempString.c_str(),
name.ascii(), (
void*)v.
imp());
01067
01068
if (lineno >= 0)
01069 fprintf(stderr,
", line %d\n",lineno);
01070
else
01071 fprintf(stderr,
"\n");
01072 }
01073 }
01074
#endif