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