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 #ifdef KJS_VERBOSE
00260 printInfo(exec, (UString("setting property ")+
00261 propertyName()).cstring().c_str(), w);
00262 #endif
00263 if (bs.type() == NullType)
00264 exec->interpreter()->globalObject().put(exec, propertyName(), w);
00265 else
00266 static_cast<ObjectImp*>(bs.imp())->put(exec, propertyName(), w);
00267 }
00268
00269
00270
00271 ReferenceImp::ReferenceImp(const Value& v, const UString& p)
00272 : base(v.imp()), prop(p)
00273 {
00274 }
00275
00276 void ReferenceImp::mark()
00277 {
00278 ValueImp::mark();
00279 if (base && !base->marked())
00280 base->mark();
00281 }
00282
00283 Value ReferenceImp::toPrimitive(ExecState *, Type ) const
00284 {
00285
00286 assert(false);
00287 return Value();
00288 }
00289
00290 bool ReferenceImp::toBoolean(ExecState *) const
00291 {
00292
00293 assert(false);
00294 return false;
00295 }
00296
00297 double ReferenceImp::toNumber(ExecState *) const
00298 {
00299
00300 assert(false);
00301 return 0;
00302 }
00303
00304 UString ReferenceImp::toString(ExecState *) const
00305 {
00306
00307 assert(false);
00308 return UString::null;
00309 }
00310
00311 Object ReferenceImp::toObject(ExecState *) const
00312 {
00313
00314 assert(false);
00315 return Object();
00316 }
00317
00318
00319
00320 LabelStack::LabelStack(const LabelStack &other)
00321 {
00322 tos = 0;
00323 *this = other;
00324 }
00325
00326 LabelStack &LabelStack::operator=(const LabelStack &other)
00327 {
00328 clear();
00329 tos = 0;
00330 StackElem *cur = 0;
00331 StackElem *se = other.tos;
00332 while (se) {
00333 StackElem *newPrev = new StackElem;
00334 newPrev->prev = 0;
00335 newPrev->id = se->id;
00336 if (cur)
00337 cur->prev = newPrev;
00338 else
00339 tos = newPrev;
00340 cur = newPrev;
00341 se = se->prev;
00342 }
00343 return *this;
00344 }
00345
00346 bool LabelStack::push(const UString &id)
00347 {
00348 if (id.isEmpty() || contains(id))
00349 return false;
00350
00351 StackElem *newtos = new StackElem;
00352 newtos->id = id;
00353 newtos->prev = tos;
00354 tos = newtos;
00355 return true;
00356 }
00357
00358 bool LabelStack::contains(const UString &id) const
00359 {
00360 if (id.isEmpty())
00361 return true;
00362
00363 for (StackElem *curr = tos; curr; curr = curr->prev)
00364 if (curr->id == id)
00365 return true;
00366
00367 return false;
00368 }
00369
00370 void LabelStack::pop()
00371 {
00372 if (tos) {
00373 StackElem *prev = tos->prev;
00374 delete tos;
00375 tos = prev;
00376 }
00377 }
00378
00379 LabelStack::~LabelStack()
00380 {
00381 clear();
00382 }
00383
00384 void LabelStack::clear()
00385 {
00386 StackElem *prev;
00387
00388 while (tos) {
00389 prev = tos->prev;
00390 delete tos;
00391 tos = prev;
00392 }
00393 }
00394
00395
00396
00397 CompletionImp::CompletionImp(ComplType c, const Value& v, const UString& t)
00398 : comp(c), val(v.imp()), tar(t)
00399 {
00400 }
00401
00402 CompletionImp::~CompletionImp()
00403 {
00404 }
00405
00406 void CompletionImp::mark()
00407 {
00408 ValueImp::mark();
00409
00410 if (val && !val->marked())
00411 val->mark();
00412 }
00413
00414 Value CompletionImp::toPrimitive(ExecState *, Type ) const
00415 {
00416
00417 assert(false);
00418 return Value();
00419 }
00420
00421 bool CompletionImp::toBoolean(ExecState *) const
00422 {
00423
00424 assert(false);
00425 return false;
00426 }
00427
00428 double CompletionImp::toNumber(ExecState *) const
00429 {
00430
00431 assert(false);
00432 return 0;
00433 }
00434
00435 UString CompletionImp::toString(ExecState *) const
00436 {
00437
00438 assert(false);
00439 return UString::null;
00440 }
00441
00442 Object CompletionImp::toObject(ExecState *) const
00443 {
00444
00445 assert(false);
00446 return Object();
00447 }
00448
00449
00450
00451 #ifdef KJS_DEBUG_MEM
00452 int ListImp::count = 0;
00453 #endif
00454
00455 Value ListImp::toPrimitive(ExecState *, Type ) const
00456 {
00457
00458 assert(false);
00459 return Value();
00460 }
00461
00462 bool ListImp::toBoolean(ExecState *) const
00463 {
00464
00465 assert(false);
00466 return false;
00467 }
00468
00469 double ListImp::toNumber(ExecState *) const
00470 {
00471
00472 assert(false);
00473 return 0;
00474 }
00475
00476 UString ListImp::toString(ExecState *) const
00477 {
00478
00479 assert(false);
00480 return UString::null;
00481 }
00482
00483 Object ListImp::toObject(ExecState *) const
00484 {
00485
00486 assert(false);
00487 return Object();
00488 }
00489
00490 ListImp::ListImp()
00491 {
00492 #ifdef KJS_DEBUG_MEM
00493 count++;
00494 #endif
00495
00496 hook = new ListNode(Null(), 0L, 0L);
00497 hook->next = hook;
00498 hook->prev = hook;
00499
00500 }
00501
00502 ListImp::~ListImp()
00503 {
00504
00505 #ifdef KJS_DEBUG_MEM
00506 count--;
00507 #endif
00508
00509 clear();
00510 delete hook;
00511
00512 if ( emptyList == this )
00513 emptyList = 0L;
00514 }
00515
00516 void ListImp::mark()
00517 {
00518 ListNode *n = hook->next;
00519 while (n != hook) {
00520 if (!n->member->marked())
00521 n->member->mark();
00522 n = n->next;
00523 }
00524 ValueImp::mark();
00525 }
00526
00527 void ListImp::append(const Value& obj)
00528 {
00529 ListNode *n = new ListNode(obj, hook->prev, hook);
00530 hook->prev->next = n;
00531 hook->prev = n;
00532 }
00533
00534 void ListImp::prepend(const Value& obj)
00535 {
00536 ListNode *n = new ListNode(obj, hook, hook->next);
00537 hook->next->prev = n;
00538 hook->next = n;
00539 }
00540
00541 void ListImp::appendList(const List& lst)
00542 {
00543 ListIterator it = lst.begin();
00544 ListIterator e = lst.end();
00545 while(it != e) {
00546 append(*it);
00547 ++it;
00548 }
00549 }
00550
00551 void ListImp::prependList(const List& lst)
00552 {
00553 ListIterator it = lst.end();
00554 ListIterator e = lst.begin();
00555 while(it != e) {
00556 --it;
00557 prepend(*it);
00558 }
00559 }
00560
00561 void ListImp::removeFirst()
00562 {
00563 erase(hook->next);
00564 }
00565
00566 void ListImp::removeLast()
00567 {
00568 erase(hook->prev);
00569 }
00570
00571 void ListImp::remove(const Value &obj)
00572 {
00573 if (obj.isNull())
00574 return;
00575 ListNode *n = hook->next;
00576 while (n != hook) {
00577 if (n->member == obj.imp()) {
00578 erase(n);
00579 return;
00580 }
00581 n = n->next;
00582 }
00583 }
00584
00585 void ListImp::clear()
00586 {
00587 ListNode *n = hook->next;
00588 while (n != hook) {
00589 n = n->next;
00590 delete n->prev;
00591 }
00592
00593 hook->next = hook;
00594 hook->prev = hook;
00595 }
00596
00597 ListImp *ListImp::copy() const
00598 {
00599 ListImp* newList = new ListImp;
00600
00601 ListIterator e = end();
00602 ListIterator it = begin();
00603
00604 while(it != e) {
00605 newList->append(*it);
00606 ++it;
00607 }
00608
00609
00610 return newList;
00611 }
00612
00613 void ListImp::erase(ListNode *n)
00614 {
00615 if (n != hook) {
00616 n->next->prev = n->prev;
00617 n->prev->next = n->next;
00618 delete n;
00619 }
00620 }
00621
00622 bool ListImp::isEmpty() const
00623 {
00624 return (hook->prev == hook);
00625 }
00626
00627 int ListImp::size() const
00628 {
00629 int s = 0;
00630 ListNode *node = hook;
00631 while ((node = node->next) != hook)
00632 s++;
00633
00634 return s;
00635 }
00636
00637 Value ListImp::at(int i) const
00638 {
00639 if (i < 0 || i >= size())
00640 return Undefined();
00641
00642 ListIterator it = begin();
00643 int j = 0;
00644 while ((j++ < i))
00645 it++;
00646
00647 return *it;
00648 }
00649
00650 ListImp *ListImp::emptyList = 0L;
00651
00652 ListImp *ListImp::empty()
00653 {
00654 if (!emptyList)
00655 emptyList = new ListImp();
00656 return emptyList;
00657 }
00658
00659
00660
00661
00662
00663 ContextImp::ContextImp(Object &glob, ExecState *exec, Object &thisV, CodeType type,
00664 ContextImp *_callingContext, FunctionImp *func, const List &args)
00665 {
00666 codeType = type;
00667 callingCon = _callingContext;
00668
00669
00670 if (type == FunctionCode || type == AnonymousCode ) {
00671 activation = Object(new ActivationImp(exec,func,args));
00672 variable = activation;
00673 } else {
00674 activation = Object();
00675 variable = glob;
00676 }
00677
00678
00679 switch(type) {
00680 case EvalCode:
00681 if (callingCon) {
00682 scope = callingCon->scopeChain().copy();
00683 #ifndef KJS_PURE_ECMA
00684 if (thisV.imp() != glob.imp())
00685 scope.prepend(thisV);
00686 #endif
00687 variable = callingCon->variableObject();
00688 thisVal = callingCon->thisValue();
00689 break;
00690 }
00691 case GlobalCode:
00692 scope = List();
00693 scope.append(glob);
00694 thisVal = Object(static_cast<ObjectImp*>(glob.imp()));
00695 break;
00696 case FunctionCode:
00697 case AnonymousCode:
00698 if (type == FunctionCode) {
00699 scope = func->scope().copy();
00700 scope.prepend(activation);
00701 } else {
00702 scope = List();
00703 scope.append(activation);
00704 scope.append(glob);
00705 }
00706 variable = activation;
00707 thisVal = thisV;
00708 break;
00709 }
00710
00711 }
00712
00713 ContextImp::~ContextImp()
00714 {
00715 }
00716
00717 void ContextImp::pushScope(const Object &s)
00718 {
00719 scope.prepend(s);
00720 }
00721
00722 void ContextImp::popScope()
00723 {
00724 scope.removeFirst();
00725 }
00726
00727
00728
00729 ProgramNode *Parser::progNode = 0;
00730 int Parser::sid = 0;
00731
00732 ProgramNode *Parser::parse(const UChar *code, unsigned int length, int *sourceId,
00733 int *errLine, UString *errMsg)
00734 {
00735 if (errLine)
00736 *errLine = -1;
00737 if (errMsg)
00738 *errMsg = 0;
00739
00740 Lexer::curr()->setCode(code, length);
00741 progNode = 0;
00742 sid++;
00743 if (sourceId)
00744 *sourceId = sid;
00745
00746
00747
00748 int parseError = kjsyyparse();
00749 ProgramNode *prog = progNode;
00750 progNode = 0;
00751
00752
00753 if (parseError) {
00754 int eline = Lexer::curr()->lineNo();
00755 if (errLine)
00756 *errLine = eline;
00757 if (errMsg)
00758 *errMsg = "Parse error at line " + UString::from(eline);
00759 #ifndef NDEBUG
00760 fprintf(stderr, "KJS: JavaScript parse error at line %d.\n", eline);
00761 #endif
00762 delete prog;
00763 return 0;
00764 }
00765
00766 return prog;
00767 }
00768
00769
00770
00771 InterpreterImp* InterpreterImp::s_hook = 0L;
00772
00773 void InterpreterImp::globalInit()
00774 {
00775
00776 UndefinedImp::staticUndefined = new UndefinedImp();
00777 UndefinedImp::staticUndefined->ref();
00778 NullImp::staticNull = new NullImp();
00779 NullImp::staticNull->ref();
00780 BooleanImp::staticTrue = new BooleanImp(true);
00781 BooleanImp::staticTrue->ref();
00782 BooleanImp::staticFalse = new BooleanImp(false);
00783 BooleanImp::staticFalse->ref();
00784 }
00785
00786 void InterpreterImp::globalClear()
00787 {
00788
00789 UndefinedImp::staticUndefined->deref();
00790 UndefinedImp::staticUndefined->setGcAllowed();
00791 UndefinedImp::staticUndefined = 0L;
00792 NullImp::staticNull->deref();
00793 NullImp::staticNull->setGcAllowed();
00794 NullImp::staticNull = 0L;
00795 BooleanImp::staticTrue->deref();
00796 BooleanImp::staticTrue->setGcAllowed();
00797 BooleanImp::staticTrue = 0L;
00798 BooleanImp::staticFalse->deref();
00799 BooleanImp::staticFalse->setGcAllowed();
00800 BooleanImp::staticFalse = 0L;
00801 }
00802
00803 InterpreterImp::InterpreterImp(Interpreter *interp, const Object &glob)
00804 : m_interpreter(interp),
00805 global(glob),
00806 dbg(0),
00807 m_compatMode(Interpreter::NativeMode),
00808 recursion(0)
00809 {
00810
00811
00812 if (s_hook) {
00813 prev = s_hook;
00814 next = s_hook->next;
00815 s_hook->next->prev = this;
00816 s_hook->next = this;
00817 } else {
00818
00819 s_hook = next = prev = this;
00820 globalInit();
00821 }
00822
00823 globExec = new ExecState(m_interpreter,0);
00824
00825
00826 initGlobalObject();
00827 }
00828
00829 void InterpreterImp::initGlobalObject()
00830 {
00831
00832
00833 FunctionPrototypeImp *funcProto = new FunctionPrototypeImp(globExec);
00834 b_FunctionPrototype = Object(funcProto);
00835 ObjectPrototypeImp *objProto = new ObjectPrototypeImp(globExec,funcProto);
00836 b_ObjectPrototype = Object(objProto);
00837 funcProto->setPrototype(b_ObjectPrototype);
00838
00839 ArrayPrototypeImp *arrayProto = new ArrayPrototypeImp(globExec,objProto);
00840 b_ArrayPrototype = Object(arrayProto);
00841 StringPrototypeImp *stringProto = new StringPrototypeImp(globExec,objProto);
00842 b_StringPrototype = Object(stringProto);
00843 BooleanPrototypeImp *booleanProto = new BooleanPrototypeImp(globExec,objProto,funcProto);
00844 b_BooleanPrototype = Object(booleanProto);
00845 NumberPrototypeImp *numberProto = new NumberPrototypeImp(globExec,objProto,funcProto);
00846 b_NumberPrototype = Object(numberProto);
00847 DatePrototypeImp *dateProto = new DatePrototypeImp(globExec,objProto);
00848 b_DatePrototype = Object(dateProto);
00849 RegExpPrototypeImp *regexpProto = new RegExpPrototypeImp(globExec,objProto,funcProto);
00850 b_RegExpPrototype = Object(regexpProto);
00851 ErrorPrototypeImp *errorProto = new ErrorPrototypeImp(globExec,objProto,funcProto);
00852 b_ErrorPrototype = Object(errorProto);
00853
00854 static_cast<ObjectImp*>(global.imp())->setPrototype(b_ObjectPrototype);
00855
00856
00857
00858 b_Object = Object(new ObjectObjectImp(globExec, objProto, funcProto));
00859 b_Function = Object(new FunctionObjectImp(globExec, funcProto));
00860 b_Array = Object(new ArrayObjectImp(globExec, funcProto, arrayProto));
00861 b_String = Object(new StringObjectImp(globExec, funcProto, stringProto));
00862 b_Boolean = Object(new BooleanObjectImp(globExec, funcProto, booleanProto));
00863 b_Number = Object(new NumberObjectImp(globExec, funcProto, numberProto));
00864 b_Date = Object(new DateObjectImp(globExec,funcProto,dateProto));
00865 b_RegExp = Object(new RegExpObjectImp(globExec, funcProto, regexpProto));
00866 b_Error = Object(new ErrorObjectImp(globExec, funcProto, errorProto));
00867
00868
00869 b_evalErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,EvalError,
00870 "EvalError","EvalError"));
00871 b_rangeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,RangeError,
00872 "RangeError","RangeError"));
00873 b_referenceErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,ReferenceError,
00874 "ReferenceError","ReferenceError"));
00875 b_syntaxErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,SyntaxError,
00876 "SyntaxError","SyntaxError"));
00877 b_typeErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,TypeError,
00878 "TypeError","TypeError"));
00879 b_uriErrorPrototype = Object(new NativeErrorPrototypeImp(globExec,errorProto,URIError,
00880 "URIError","URIError"));
00881
00882
00883 b_evalError = Object(new NativeErrorImp(globExec,funcProto,b_evalErrorPrototype));
00884 b_rangeError = Object(new NativeErrorImp(globExec,funcProto,b_rangeErrorPrototype));
00885 b_referenceError = Object(new NativeErrorImp(globExec,funcProto,b_referenceErrorPrototype));
00886 b_syntaxError = Object(new NativeErrorImp(globExec,funcProto,b_syntaxErrorPrototype));
00887 b_typeError = Object(new NativeErrorImp(globExec,funcProto,b_typeErrorPrototype));
00888 b_uriError = Object(new NativeErrorImp(globExec,funcProto,b_uriErrorPrototype));
00889
00890
00891 funcProto->put(globExec,"constructor", b_Function, DontEnum);
00892
00893 global.put(globExec,"Object", b_Object, DontEnum);
00894 global.put(globExec,"Function", b_Function, DontEnum);
00895 global.put(globExec,"Array", b_Array, DontEnum);
00896 global.put(globExec,"Boolean", b_Boolean, DontEnum);
00897 global.put(globExec,"String", b_String, DontEnum);
00898 global.put(globExec,"Number", b_Number, DontEnum);
00899 global.put(globExec,"Date", b_Date, DontEnum);
00900 global.put(globExec,"RegExp", b_RegExp, DontEnum);
00901 global.put(globExec,"Error", b_Error, DontEnum);
00902
00903
00904 global.put(globExec,"EvalError",b_evalError, Internal);
00905 global.put(globExec,"RangeError",b_rangeError, Internal);
00906 global.put(globExec,"ReferenceError",b_referenceError, Internal);
00907 global.put(globExec,"SyntaxError",b_syntaxError, Internal);
00908 global.put(globExec,"TypeError",b_typeError, Internal);
00909 global.put(globExec,"URIError",b_uriError, Internal);
00910
00911
00912 objProto->put(globExec, "constructor", b_Object, DontEnum | DontDelete | ReadOnly);
00913 funcProto->put(globExec, "constructor", b_Function, DontEnum | DontDelete | ReadOnly);
00914 arrayProto->put(globExec, "constructor", b_Array, DontEnum | DontDelete | ReadOnly);
00915 booleanProto->put(globExec, "constructor", b_Boolean, DontEnum | DontDelete | ReadOnly);
00916 stringProto->put(globExec, "constructor", b_String, DontEnum | DontDelete | ReadOnly);
00917 numberProto->put(globExec, "constructor", b_Number, DontEnum | DontDelete | ReadOnly);
00918 dateProto->put(globExec, "constructor", b_Date, DontEnum | DontDelete | ReadOnly);
00919 regexpProto->put(globExec, "constructor", b_RegExp, DontEnum | DontDelete | ReadOnly);
00920 errorProto->put(globExec, "constructor", b_Error, DontEnum | DontDelete | ReadOnly);
00921 b_evalErrorPrototype.put(globExec, "constructor", b_evalError, DontEnum | DontDelete | ReadOnly);
00922 b_rangeErrorPrototype.put(globExec, "constructor", b_rangeError, DontEnum | DontDelete | ReadOnly);
00923 b_referenceErrorPrototype.put(globExec, "constructor", b_referenceError, DontEnum | DontDelete | ReadOnly);
00924 b_syntaxErrorPrototype.put(globExec, "constructor", b_syntaxError, DontEnum | DontDelete | ReadOnly);
00925 b_typeErrorPrototype.put(globExec, "constructor", b_typeError, DontEnum | DontDelete | ReadOnly);
00926 b_uriErrorPrototype.put(globExec, "constructor", b_uriError, DontEnum | DontDelete | ReadOnly);
00927
00928
00929 global.put(globExec, "NaN", Number(NaN), DontEnum|DontDelete);
00930 global.put(globExec, "Infinity", Number(Inf), DontEnum|DontDelete);
00931 global.put(globExec, "undefined", Undefined(), DontEnum|DontDelete);
00932
00933
00934 #ifdef KJS_PURE_ECMA // otherwise as deprecated Object.prototype property
00935 global.put(globExec,"eval", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Eval, 1)), DontEnum);
00936 #endif
00937 global.put(globExec,"parseInt", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseInt, 2)), DontEnum);
00938 global.put(globExec,"parseFloat", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::ParseFloat, 1)), DontEnum);
00939 global.put(globExec,"isNaN", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsNaN, 1)), DontEnum);
00940 global.put(globExec,"isFinite", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::IsFinite, 1)), DontEnum);
00941 global.put(globExec,"escape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::Escape, 1)), DontEnum);
00942 global.put(globExec,"unescape", Object(new GlobalFuncImp(globExec,funcProto,GlobalFuncImp::UnEscape, 1)), DontEnum);
00943
00944
00945 global.put(globExec,"Math", Object(new MathObjectImp(globExec,objProto)), DontEnum);
00946 }
00947
00948 InterpreterImp::~InterpreterImp()
00949 {
00950 if (dbg)
00951 dbg->detach(m_interpreter);
00952 delete globExec;
00953 globExec = 0L;
00954 clear();
00955 }
00956
00957 void InterpreterImp::clear()
00958 {
00959
00960
00961 next->prev = prev;
00962 prev->next = next;
00963 s_hook = next;
00964 if (s_hook == this)
00965 {
00966
00967 s_hook = 0L;
00968 globalClear();
00969 }
00970 }
00971
00972 void InterpreterImp::mark()
00973 {
00974
00975
00976
00977
00978 if (UndefinedImp::staticUndefined && !UndefinedImp::staticUndefined->marked())
00979 UndefinedImp::staticUndefined->mark();
00980 if (NullImp::staticNull && !NullImp::staticNull->marked())
00981 NullImp::staticNull->mark();
00982 if (BooleanImp::staticTrue && !BooleanImp::staticTrue->marked())
00983 BooleanImp::staticTrue->mark();
00984 if (BooleanImp::staticFalse && !BooleanImp::staticFalse->marked())
00985 BooleanImp::staticFalse->mark();
00986 if (ListImp::emptyList && !ListImp::emptyList->marked())
00987 ListImp::emptyList->mark();
00988
00989 if (global.imp())
00990 global.imp()->mark();
00991 if (m_interpreter)
00992 m_interpreter->mark();
00993 }
00994
00995 bool InterpreterImp::checkSyntax(const UString &code)
00996 {
00997
00998 ProgramNode *progNode = Parser::parse(code.data(),code.size(),0,0,0);
00999 bool ok = (progNode != 0);
01000 delete progNode;
01001 return ok;
01002 }
01003
01004 Completion InterpreterImp::evaluate(const UString &code, const Value &thisV)
01005 {
01006
01007 if (recursion >= 20) {
01008 return Completion(Throw,Error::create(globExec,GeneralError,"Recursion too deep"));
01009 }
01010
01011
01012 int sid;
01013 int errLine;
01014 UString errMsg;
01015 ProgramNode *progNode = Parser::parse(code.data(),code.size(),&sid,&errLine,&errMsg);
01016
01017
01018 if (dbg) {
01019 bool cont = dbg->sourceParsed(globExec,sid,code,errLine);
01020 if (!cont)
01021 return Completion(Break);
01022 }
01023
01024
01025 if (!progNode) {
01026 Object err = Error::create(globExec,SyntaxError,errMsg.ascii(),errLine);
01027 err.put(globExec,"sid",Number(sid));
01028 return Completion(Throw,err);
01029 }
01030
01031 globExec->clearException();
01032
01033 recursion++;
01034 progNode->ref();
01035
01036 Object globalObj = globalObject();
01037 Object thisObj = globalObject();
01038
01039 if (!thisV.isNull()) {
01040
01041 if (thisV.isA(NullType) || thisV.isA(UndefinedType))
01042 thisObj = globalObject();
01043 else {
01044 thisObj = thisV.toObject(globExec);
01045 }
01046 }
01047
01048 Completion res;
01049 if (globExec->hadException()) {
01050
01051
01052 res = Completion(Throw,globExec->exception());
01053 }
01054 else {
01055
01056 ExecState *exec1 = 0;
01057 ContextImp *ctx = new ContextImp(globalObj, exec1, thisObj);
01058 ExecState *newExec = new ExecState(m_interpreter,ctx);
01059
01060 res = progNode->execute(newExec);
01061
01062 delete newExec;
01063 delete ctx;
01064 }
01065
01066 if (progNode->deref())
01067 delete progNode;
01068 recursion--;
01069
01070 return res;
01071 }
01072
01073 void InterpreterImp::setDebugger(Debugger *d)
01074 {
01075 if (d == dbg)
01076 return;
01077
01078 Debugger *old = dbg;
01079 dbg = d;
01080 if ( old )
01081 old->detach(m_interpreter);
01082 }
01083
01084
01085
01086 const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
01087
01088 InternalFunctionImp::InternalFunctionImp(FunctionPrototypeImp *funcProto)
01089 : ObjectImp(Object(funcProto))
01090 {
01091 }
01092
01093 bool InternalFunctionImp::implementsHasInstance() const
01094 {
01095 return true;
01096 }
01097
01098 Boolean InternalFunctionImp::hasInstance(ExecState *exec, const Value &value)
01099 {
01100 if (value.type() != ObjectType)
01101 return Boolean(false);
01102
01103 Value prot = get(exec,"prototype");
01104 if (prot.type() != ObjectType && prot.type() != NullType) {
01105 Object err = Error::create(exec, TypeError, "Invalid prototype encountered "
01106 "in instanceof operation.");
01107 exec->setException(err);
01108 return Boolean(false);
01109 }
01110
01111 Object v = Object(static_cast<ObjectImp*>(value.imp()));
01112 while ((v = Object::dynamicCast(v.prototype())).imp()) {
01113 if (v.imp() == prot.imp())
01114 return Boolean(true);
01115 }
01116 return Boolean(false);
01117 }
01118
01119
01120
01121 double KJS::roundValue(ExecState *exec, const Value &v)
01122 {
01123 if (v.type() == UndefinedType)
01124 return 0.0;
01125 double n = v.toNumber(exec);
01126 if (n == 0.0)
01127 return 0.0;
01128 double d = floor(fabs(n));
01129 if (n < 0)
01130 d *= -1;
01131
01132 return d;
01133 }
01134
01135 #ifndef NDEBUG
01136 #include <stdio.h>
01137 void KJS::printInfo(ExecState *exec, const char *s, const Value &o, int lineno)
01138 {
01139 if (o.isNull())
01140 fprintf(stderr, "KJS: %s: (null)", s);
01141 else {
01142 Value v = o;
01143 if (o.isA(ReferenceType))
01144 v = o.getValue(exec);
01145
01146 UString name;
01147 switch ( v.type() ) {
01148 case UnspecifiedType:
01149 name = "Unspecified";
01150 break;
01151 case UndefinedType:
01152 name = "Undefined";
01153 break;
01154 case NullType:
01155 name = "Null";
01156 break;
01157 case BooleanType:
01158 name = "Boolean";
01159 break;
01160 case StringType:
01161 name = "String";
01162 break;
01163 case NumberType:
01164 name = "Number";
01165 break;
01166 case ObjectType:
01167 name = Object::dynamicCast(v).className();
01168 if (name.isNull())
01169 name = "(unknown class)";
01170 break;
01171 case ReferenceType:
01172 name = "Reference";
01173 break;
01174 case ListType:
01175 name = "List";
01176 break;
01177 case CompletionType:
01178 name = "Completion";
01179 break;
01180 default:
01181 break;
01182 }
01183 bool hadExcep = exec->hadException();
01184 UString vString = v.toString(exec);
01185 if ( !hadExcep )
01186 exec->clearException();
01187 if ( vString.size() > 50 )
01188 vString = vString.substr( 0, 50 ) + "...";
01189
01190 CString tempString( vString.cstring() );
01191
01192 fprintf(stderr, "KJS: %s: %s : %s (%p)",
01193 s, tempString.c_str(), name.ascii(), (void*)v.imp());
01194
01195 if (lineno >= 0)
01196 fprintf(stderr, ", line %d\n",lineno);
01197 else
01198 fprintf(stderr, "\n");
01199 if (!o.isNull())
01200 if (o.isA(ReferenceType)) {
01201 fprintf(stderr, "KJS: Was property '%s'\n", o.getPropertyName(exec).ascii());
01202 printInfo(exec,"of", o.getBase(exec));
01203 }
01204 }
01205 }
01206 #endif