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