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