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