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