nodes.cpp
00001 // -*- c-basic-offset: 2 -*- 00002 /* 00003 * This file is part of the KDE libraries 00004 * Copyright (C) 1999-2002, 2003 Harri Porten (porten@kde.org) 00005 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 00006 * Copyright (C) 2003 Apple Computer, Inc. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Library General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Library General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Library General Public License 00019 * along with this library; see the file COPYING.LIB. If not, write to 00020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00021 * Boston, MA 02110-1301, USA. 00022 * 00023 */ 00024 00025 #include "nodes.h" 00026 00027 #include <math.h> 00028 #include <assert.h> 00029 #ifdef KJS_DEBUG_MEM 00030 #include <stdio.h> 00031 #include <typeinfo> 00032 #endif 00033 #ifdef KJS_VERBOSE 00034 #include <iostream> 00035 using namespace std; 00036 #endif 00037 00038 #include "collector.h" 00039 #include "context.h" 00040 #include "debugger.h" 00041 #include "function_object.h" 00042 #include "internal.h" 00043 #include "value.h" 00044 #include "object.h" 00045 #include "types.h" 00046 #include "interpreter.h" 00047 #include "lexer.h" 00048 #include "operations.h" 00049 #include "ustring.h" 00050 00051 using namespace KJS; 00052 00053 #define KJS_BREAKPOINT \ 00054 if (!hitStatement(exec)) \ 00055 return Completion(Normal); 00056 00057 #define KJS_ABORTPOINT \ 00058 if (exec->dynamicInterpreter()->imp()->debugger() && \ 00059 exec->dynamicInterpreter()->imp()->debugger()->imp()->aborted()) \ 00060 return Completion(Normal); 00061 00062 #define KJS_CHECKEXCEPTION \ 00063 if (exec->hadException()) { \ 00064 setExceptionDetailsIfNeeded(exec); \ 00065 return Completion(Throw, exec->exception()); \ 00066 } \ 00067 if (Collector::outOfMemory()) \ 00068 return Completion(Throw, Error::create(exec,GeneralError,"Out of memory")); 00069 00070 #define KJS_CHECKEXCEPTIONVALUE \ 00071 if (exec->hadException()) { \ 00072 setExceptionDetailsIfNeeded(exec); \ 00073 return exec->exception(); \ 00074 } \ 00075 if (Collector::outOfMemory()) \ 00076 return Undefined(); // will be picked up by KJS_CHECKEXCEPTION 00077 00078 #define KJS_CHECKEXCEPTIONREFERENCE \ 00079 if (exec->hadException()) { \ 00080 setExceptionDetailsIfNeeded(exec); \ 00081 return Reference::makeValueReference(Undefined()); \ 00082 } \ 00083 if (Collector::outOfMemory()) \ 00084 return Reference::makeValueReference(Undefined()); // will be picked up by KJS_CHECKEXCEPTION 00085 00086 #define KJS_CHECKEXCEPTIONLIST \ 00087 if (exec->hadException()) { \ 00088 setExceptionDetailsIfNeeded(exec); \ 00089 return List(); \ 00090 } \ 00091 if (Collector::outOfMemory()) \ 00092 return List(); // will be picked up by KJS_CHECKEXCEPTION 00093 00094 #ifdef KJS_DEBUG_MEM 00095 std::list<Node *> * Node::s_nodes = 0L; 00096 #endif 00097 00098 // ----------------------------- Node ----------------------------------------- 00099 00100 Node::Node() 00101 { 00102 line = Lexer::curr()->lineNo(); 00103 refcount = 0; 00104 #ifdef KJS_DEBUG_MEM 00105 if (!s_nodes) 00106 s_nodes = new std::list<Node *>; 00107 s_nodes->push_back(this); 00108 #endif 00109 } 00110 00111 Node::~Node() 00112 { 00113 #ifdef KJS_DEBUG_MEM 00114 s_nodes->remove( this ); 00115 #endif 00116 } 00117 00118 Reference Node::evaluateReference(ExecState *exec) const 00119 { 00120 Value v = evaluate(exec); 00121 KJS_CHECKEXCEPTIONREFERENCE 00122 return Reference::makeValueReference(v); 00123 } 00124 00125 // fallback for those nodes without a evaluate() reimplementation 00126 // TODO: reimplemint in each sub class, make Node::evaluate() pure virtual 00127 Value Node::evaluate(ExecState *exec) const 00128 { 00129 // fprintf(stderr, "%s::evaluate()\n", typeid(*this).name()); 00130 return evaluateReference(exec).getValue(exec); 00131 } 00132 00133 bool Node::toBoolean(ExecState *exec) const 00134 { 00135 // fprintf(stderr, "Node(%s)::toBoolean()\n", typeid(*this).name()); 00136 return evaluate(exec).toBoolean(exec); 00137 } 00138 00139 double Node::toNumber(ExecState *exec) const 00140 { 00141 // fprintf(stderr, "Node(%s)::toNumber()\n", typeid(*this).name()); 00142 return evaluate(exec).toNumber(exec); 00143 } 00144 00145 UString Node::toString(ExecState *exec) const 00146 { 00147 return evaluate(exec).toString(exec); 00148 } 00149 00150 #ifdef KJS_DEBUG_MEM 00151 void Node::finalCheck() 00152 { 00153 if (!s_nodes) { 00154 fprintf(stderr, "Node::finalCheck(): list 0\n"); 00155 return; 00156 } 00157 fprintf( stderr, "[nodes] Node::finalCheck(): list count : %d\n", (int)s_nodes->size() ); 00158 std::list<Node *>::iterator it = s_nodes->begin(); 00159 for ( uint i = 0; it != s_nodes->end() ; ++it, ++i ) 00160 fprintf( stderr, "[nodes] [%d] Still having node %p (%s) (refcount %d)\n", i, (void*)*it, typeid( **it ).name(), (*it)->refcount ); 00161 delete s_nodes; 00162 s_nodes = 0L; 00163 } 00164 #endif 00165 00166 Value Node::throwError(ExecState *exec, ErrorType e, const char *msg) const 00167 { 00168 Object err = Error::create(exec, e, msg, lineNo(), sourceId()); 00169 exec->setException(err); 00170 return err; 00171 } 00172 00173 Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, 00174 const Value &v, const Node *expr) const 00175 { 00176 char *vStr = strdup(v.toString(exec).ascii()); 00177 char *exprStr = strdup(expr->toCode().ascii()); 00178 00179 int length = strlen(msg) - 4 /* two %s */ + strlen(vStr) + strlen(exprStr) + 1 /* null terminator */; 00180 char *str = new char[length]; 00181 sprintf(str, msg, vStr, exprStr); 00182 free(vStr); 00183 free(exprStr); 00184 00185 Value result = throwError(exec, e, str); 00186 delete [] str; 00187 00188 return result; 00189 } 00190 00191 Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Identifier label) const 00192 { 00193 const char *l = label.ascii(); 00194 int length = strlen(msg) - 2 /* %s */ + strlen(l) + 1 /* null terminator */; 00195 char *message = new char[length]; 00196 sprintf(message, msg, l); 00197 00198 Value result = throwError(exec, e, message); 00199 delete [] message; 00200 00201 return result; 00202 } 00203 00204 00205 void Node::setExceptionDetailsIfNeeded(ExecState *exec) const 00206 { 00207 if (exec->hadException()) { 00208 Object exception = exec->exception().toObject(exec); 00209 if (!exception.hasProperty(exec, "line") /* && 00210 !exception.hasProperty(exec, "sourceURL")*/ ) { 00211 exception.put(exec, "line", Number(line)); 00212 // exception.put(exec, "sourceURL", String(sourceURL)); 00213 } 00214 } 00215 } 00216 00217 // ----------------------------- StatementNode -------------------------------- 00218 StatementNode::StatementNode() : l0(-1), l1(-1), sourceCode(0), breakPoint(false) 00219 { 00220 } 00221 00222 StatementNode::~StatementNode() 00223 { 00224 if (sourceCode) 00225 sourceCode->deref(); 00226 } 00227 00228 void StatementNode::setLoc(int line0, int line1, SourceCode *src) 00229 { 00230 // ### require these to be passed to the constructor 00231 l0 = line0; 00232 l1 = line1; 00233 if (sourceCode != src) { 00234 if (sourceCode) 00235 sourceCode->deref(); 00236 sourceCode = src; 00237 sourceCode->ref(); 00238 } 00239 } 00240 00241 // return true if the debugger wants us to stop at this point 00242 bool StatementNode::hitStatement(ExecState *exec) 00243 { 00244 assert(sourceCode); 00245 assert(exec->context().imp()->sourceId == sourceCode->sid); 00246 exec->context().imp()->setLines(l0,l1); 00247 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger(); 00248 if (dbg) 00249 return dbg->atStatement(exec); 00250 else 00251 return true; // continue 00252 } 00253 00254 // return true if the debugger wants us to stop at this point 00255 bool StatementNode::abortStatement(ExecState *exec) 00256 { 00257 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger(); 00258 if (dbg) 00259 return dbg->imp()->aborted(); 00260 else 00261 return false; 00262 } 00263 00264 void StatementNode::processFuncDecl(ExecState *) 00265 { 00266 } 00267 00268 // ----------------------------- NullNode ------------------------------------- 00269 00270 Value NullNode::evaluate(ExecState *) const 00271 { 00272 return Null(); 00273 } 00274 00275 bool NullNode::toBoolean(ExecState *) const 00276 { 00277 return false; 00278 } 00279 00280 double NullNode::toNumber(ExecState *) const 00281 { 00282 return 0.0; 00283 } 00284 00285 UString NullNode::toString(ExecState *) const 00286 { 00287 return "null"; 00288 } 00289 00290 // ----------------------------- BooleanNode ---------------------------------- 00291 00292 Value BooleanNode::evaluate(ExecState *) const 00293 { 00294 return Boolean(val); 00295 } 00296 00297 bool BooleanNode::toBoolean(ExecState *) const 00298 { 00299 return val; 00300 } 00301 00302 double BooleanNode::toNumber(ExecState *) const 00303 { 00304 return val ? 1.0 : 0.0; 00305 } 00306 00307 UString BooleanNode::toString(ExecState *) const 00308 { 00309 return val ? "true" : "false"; 00310 } 00311 00312 // ----------------------------- NumberNode ----------------------------------- 00313 00314 Value NumberNode::evaluate(ExecState *) const 00315 { 00316 return Number(val); 00317 } 00318 00319 bool NumberNode::toBoolean(ExecState *) const 00320 { 00321 return !((val == 0) /* || (iVal() == N0) */ || isNaN(val)); 00322 } 00323 00324 double NumberNode::toNumber(ExecState *) const 00325 { 00326 return val; 00327 } 00328 00329 UString NumberNode::toString(ExecState *) const 00330 { 00331 return UString::from(val); 00332 } 00333 00334 // ----------------------------- StringNode ----------------------------------- 00335 00336 Value StringNode::evaluate(ExecState *) const 00337 { 00338 return String(val); 00339 } 00340 00341 bool StringNode::toBoolean(ExecState *) const 00342 { 00343 return !val.isEmpty(); 00344 } 00345 00346 double StringNode::toNumber(ExecState *) const 00347 { 00348 return val.toDouble(); 00349 } 00350 00351 UString StringNode::toString(ExecState *) const 00352 { 00353 return val; 00354 } 00355 00356 // ----------------------------- RegExpNode ----------------------------------- 00357 00358 Value RegExpNode::evaluate(ExecState *exec) const 00359 { 00360 List list; 00361 String p(pattern); 00362 String f(flags); 00363 list.append(p); 00364 list.append(f); 00365 00366 Object reg = exec->lexicalInterpreter()->imp()->builtinRegExp(); 00367 return reg.construct(exec,list); 00368 } 00369 00370 bool RegExpNode::toBoolean(ExecState *) const 00371 { 00372 return true; 00373 } 00374 00375 // ----------------------------- ThisNode ------------------------------------- 00376 00377 // ECMA 11.1.1 00378 Value ThisNode::evaluate(ExecState *exec) const 00379 { 00380 return exec->context().imp()->thisValue(); 00381 } 00382 00383 // ----------------------------- ResolveNode ---------------------------------- 00384 00385 // ECMA 11.1.2 & 10.1.4 00386 Value ResolveNode::evaluate(ExecState *exec) const 00387 { 00388 return evaluateReference(exec).getValue(exec); 00389 } 00390 00391 Reference ResolveNode::evaluateReference(ExecState *exec) const 00392 { 00393 ScopeChain chain = exec->context().imp()->scopeChain(); 00394 00395 while (!chain.isEmpty()) { 00396 ObjectImp *o = chain.top(); 00397 00398 //cerr << "Resolve: looking at '" << ident.ascii() << "'" 00399 // << " in " << (void*)o << " " << o->classInfo()->className << endl; 00400 if (o->hasProperty(exec,ident)) { 00401 //cerr << "Resolve: FOUND '" << ident.ascii() << "'" 00402 // << " in " << (void*)o << " " << o->classInfo()->className << endl; 00403 return Reference(o, ident); 00404 } 00405 00406 chain.pop(); 00407 } 00408 00409 // identifier not found 00410 #ifdef KJS_VERBOSE 00411 cerr << "Resolve::evaluateReference: didn't find '" << ident.ustring().ascii() << "'" << endl; 00412 #endif 00413 return Reference(Null(), ident); 00414 } 00415 00416 // ----------------------------- GroupNode ------------------------------------ 00417 00418 void GroupNode::ref() 00419 { 00420 Node::ref(); 00421 if ( group ) 00422 group->ref(); 00423 } 00424 00425 bool GroupNode::deref() 00426 { 00427 if ( group && group->deref() ) 00428 delete group; 00429 return Node::deref(); 00430 } 00431 00432 // ECMA 11.1.6 00433 Value GroupNode::evaluate(ExecState *exec) const 00434 { 00435 return group->evaluate(exec); 00436 } 00437 00438 Reference GroupNode::evaluateReference(ExecState *exec) const 00439 { 00440 return group->evaluateReference(exec); 00441 } 00442 00443 // ----------------------------- ElementNode ---------------------------------- 00444 00445 void ElementNode::ref() 00446 { 00447 for (ElementNode *n = this; n; n = n->list) { 00448 n->Node::ref(); 00449 if (n->node) 00450 n->node->ref(); 00451 } 00452 } 00453 00454 bool ElementNode::deref() 00455 { 00456 ElementNode *next; 00457 for (ElementNode *n = this; n; n = next) { 00458 next = n->list; 00459 if (n->node && n->node->deref()) 00460 delete n->node; 00461 if (n != this && n->Node::deref()) 00462 delete n; 00463 } 00464 return Node::deref(); 00465 } 00466 00467 // ECMA 11.1.4 00468 Value ElementNode::evaluate(ExecState *exec) const 00469 { 00470 Object array = exec->lexicalInterpreter()->builtinArray().construct(exec, List::empty()); 00471 int length = 0; 00472 for (const ElementNode *n = this; n; n = n->list) { 00473 Value val = n->node->evaluate(exec); 00474 KJS_CHECKEXCEPTIONVALUE 00475 length += n->elision; 00476 array.put(exec, length++, val); 00477 } 00478 return array; 00479 } 00480 00481 // ----------------------------- ArrayNode ------------------------------------ 00482 00483 void ArrayNode::ref() 00484 { 00485 Node::ref(); 00486 if ( element ) 00487 element->ref(); 00488 } 00489 00490 bool ArrayNode::deref() 00491 { 00492 if ( element && element->deref() ) 00493 delete element; 00494 return Node::deref(); 00495 } 00496 00497 // ECMA 11.1.4 00498 Value ArrayNode::evaluate(ExecState *exec) const 00499 { 00500 Object array; 00501 int length; 00502 00503 if (element) { 00504 array = Object(static_cast<ObjectImp*>(element->evaluate(exec).imp())); 00505 KJS_CHECKEXCEPTIONVALUE 00506 length = opt ? array.get(exec,lengthPropertyName).toInt32(exec) : 0; 00507 } else { 00508 Value newArr = exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty()); 00509 array = Object(static_cast<ObjectImp*>(newArr.imp())); 00510 length = 0; 00511 } 00512 00513 if (opt) 00514 array.put(exec,lengthPropertyName, Number(elision + length), DontEnum | DontDelete); 00515 00516 return array; 00517 } 00518 00519 // ----------------------------- ObjectLiteralNode ---------------------------- 00520 00521 void ObjectLiteralNode::ref() 00522 { 00523 Node::ref(); 00524 if ( list ) 00525 list->ref(); 00526 } 00527 00528 bool ObjectLiteralNode::deref() 00529 { 00530 if ( list && list->deref() ) 00531 delete list; 00532 return Node::deref(); 00533 } 00534 00535 // ECMA 11.1.5 00536 Value ObjectLiteralNode::evaluate(ExecState *exec) const 00537 { 00538 if (list) 00539 return list->evaluate(exec); 00540 00541 return exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty()); 00542 } 00543 00544 // ----------------------------- PropertyValueNode ---------------------------- 00545 00546 void PropertyValueNode::ref() 00547 { 00548 for (PropertyValueNode *n = this; n; n = n->list) { 00549 n->Node::ref(); 00550 if (n->name) 00551 n->name->ref(); 00552 if (n->assign) 00553 n->assign->ref(); 00554 } 00555 } 00556 00557 bool PropertyValueNode::deref() 00558 { 00559 PropertyValueNode *next; 00560 for (PropertyValueNode *n = this; n; n = next) { 00561 next = n->list; 00562 if ( n->name && n->name->deref() ) 00563 delete n->name; 00564 if ( n->assign && n->assign->deref() ) 00565 delete n->assign; 00566 if (n != this && n->Node::deref() ) 00567 delete n; 00568 } 00569 return Node::deref(); 00570 } 00571 00572 // ECMA 11.1.5 00573 Value PropertyValueNode::evaluate(ExecState *exec) const 00574 { 00575 Object obj = exec->lexicalInterpreter()->builtinObject().construct(exec, List::empty()); 00576 00577 for (const PropertyValueNode *p = this; p; p = p->list) { 00578 Value n = p->name->evaluate(exec); 00579 KJS_CHECKEXCEPTIONVALUE 00580 Value v = p->assign->evaluate(exec); 00581 KJS_CHECKEXCEPTIONVALUE 00582 00583 obj.put(exec, Identifier(n.toString(exec)), v); 00584 } 00585 00586 return obj; 00587 } 00588 00589 // ----------------------------- PropertyNode --------------------------------- 00590 00591 // ECMA 11.1.5 00592 Value PropertyNode::evaluate(ExecState * /*exec*/) const 00593 { 00594 Value s; 00595 00596 if (str.isNull()) { 00597 s = String(UString::from(numeric)); 00598 } else { 00599 s = String(str.ustring()); 00600 } 00601 00602 return s; 00603 } 00604 00605 // ----------------------------- AccessorNode1 -------------------------------- 00606 00607 void AccessorNode1::ref() 00608 { 00609 Node::ref(); 00610 if ( expr1 ) 00611 expr1->ref(); 00612 if ( expr2 ) 00613 expr2->ref(); 00614 } 00615 00616 bool AccessorNode1::deref() 00617 { 00618 if ( expr1 && expr1->deref() ) 00619 delete expr1; 00620 if ( expr2 && expr2->deref() ) 00621 delete expr2; 00622 return Node::deref(); 00623 } 00624 00625 // ECMA 11.2.1a 00626 Reference AccessorNode1::evaluateReference(ExecState *exec) const 00627 { 00628 Value v1 = expr1->evaluate(exec); 00629 KJS_CHECKEXCEPTIONREFERENCE 00630 Value v2 = expr2->evaluate(exec); 00631 KJS_CHECKEXCEPTIONREFERENCE 00632 #ifndef NDEBUG 00633 // catch errors before being caught in toObject(). better error message. 00634 if (v1.isA(UndefinedType) || v1.isA(NullType)) { 00635 UString s = "Attempted to access property on %s object " 00636 "(result of expression %s)"; 00637 (void)throwError(exec, TypeError, s.cstring().c_str(), v1, this); 00638 return Reference::makeValueReference(Undefined()); 00639 } 00640 #endif 00641 Object o = v1.toObject(exec); 00642 unsigned i; 00643 if (v2.toUInt32(i)) 00644 return Reference(o, i); 00645 UString s = v2.toString(exec); 00646 return Reference(o, Identifier(s)); 00647 } 00648 00649 // ----------------------------- AccessorNode2 -------------------------------- 00650 00651 void AccessorNode2::ref() 00652 { 00653 Node::ref(); 00654 if ( expr ) 00655 expr->ref(); 00656 } 00657 00658 bool AccessorNode2::deref() 00659 { 00660 if ( expr && expr->deref() ) 00661 delete expr; 00662 return Node::deref(); 00663 } 00664 00665 // ECMA 11.2.1b 00666 Reference AccessorNode2::evaluateReference(ExecState *exec) const 00667 { 00668 Value v = expr->evaluate(exec); 00669 KJS_CHECKEXCEPTIONREFERENCE 00670 assert(v.isValid()); 00671 #ifndef NDEBUG 00672 // catch errors before being caught in toObject(). better error message. 00673 if (v.isA(UndefinedType) || v.isA(NullType)) { 00674 UString s = "Attempted to access '" + ident.ustring() + 00675 "' property on %s object (result of expression %s)"; 00676 (void)throwError(exec, TypeError, s.cstring().c_str(), v, this); 00677 return Reference::makeValueReference(Undefined()); 00678 } 00679 #endif 00680 Object o = v.toObject(exec); 00681 return Reference(o, ident); 00682 } 00683 00684 // ----------------------------- ArgumentListNode ----------------------------- 00685 00686 void ArgumentListNode::ref() 00687 { 00688 for (ArgumentListNode *n = this; n; n = n->list) { 00689 n->Node::ref(); 00690 if (n->expr) 00691 n->expr->ref(); 00692 } 00693 } 00694 00695 bool ArgumentListNode::deref() 00696 { 00697 ArgumentListNode *next; 00698 for (ArgumentListNode *n = this; n; n = next) { 00699 next = n->list; 00700 if (n->expr && n->expr->deref()) 00701 delete n->expr; 00702 if (n != this && n->Node::deref()) 00703 delete n; 00704 } 00705 return Node::deref(); 00706 } 00707 00708 Value ArgumentListNode::evaluate(ExecState * /*exec*/) const 00709 { 00710 assert(0); 00711 return Value(); // dummy, see evaluateList() 00712 } 00713 00714 // ECMA 11.2.4 00715 List ArgumentListNode::evaluateList(ExecState *exec) const 00716 { 00717 List l; 00718 00719 for (const ArgumentListNode *n = this; n; n = n->list) { 00720 Value v = n->expr->evaluate(exec); 00721 KJS_CHECKEXCEPTIONLIST 00722 l.append(v); 00723 } 00724 00725 return l; 00726 } 00727 00728 // ----------------------------- ArgumentsNode -------------------------------- 00729 00730 void ArgumentsNode::ref() 00731 { 00732 Node::ref(); 00733 if ( list ) 00734 list->ref(); 00735 } 00736 00737 bool ArgumentsNode::deref() 00738 { 00739 if ( list && list->deref() ) 00740 delete list; 00741 return Node::deref(); 00742 } 00743 00744 Value ArgumentsNode::evaluate(ExecState * /*exec*/) const 00745 { 00746 assert(0); 00747 return Value(); // dummy, see evaluateList() 00748 } 00749 00750 // ECMA 11.2.4 00751 List ArgumentsNode::evaluateList(ExecState *exec) const 00752 { 00753 if (!list) 00754 return List(); 00755 00756 return list->evaluateList(exec); 00757 } 00758 00759 // ----------------------------- NewExprNode ---------------------------------- 00760 00761 // ECMA 11.2.2 00762 00763 void NewExprNode::ref() 00764 { 00765 Node::ref(); 00766 if ( expr ) 00767 expr->ref(); 00768 if ( args ) 00769 args->ref(); 00770 } 00771 00772 bool NewExprNode::deref() 00773 { 00774 if ( expr && expr->deref() ) 00775 delete expr; 00776 if ( args && args->deref() ) 00777 delete args; 00778 return Node::deref(); 00779 } 00780 00781 Value NewExprNode::evaluate(ExecState *exec) const 00782 { 00783 Value v = expr->evaluate(exec); 00784 KJS_CHECKEXCEPTIONVALUE 00785 00786 List argList; 00787 if (args) { 00788 argList = args->evaluateList(exec); 00789 KJS_CHECKEXCEPTIONVALUE 00790 } 00791 00792 if (v.type() != ObjectType) { 00793 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr); 00794 } 00795 00796 Object constr = Object(static_cast<ObjectImp*>(v.imp())); 00797 if (!constr.implementsConstruct()) { 00798 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr); 00799 } 00800 00801 Value res = constr.construct(exec,argList); 00802 00803 return res; 00804 } 00805 00806 // ----------------------------- FunctionCallNode ----------------------------- 00807 00808 void FunctionCallNode::ref() 00809 { 00810 Node::ref(); 00811 if ( expr ) 00812 expr->ref(); 00813 if ( args ) 00814 args->ref(); 00815 } 00816 00817 bool FunctionCallNode::deref() 00818 { 00819 if ( expr && expr->deref() ) 00820 delete expr; 00821 if ( args && args->deref() ) 00822 delete args; 00823 return Node::deref(); 00824 } 00825 00826 // ECMA 11.2.3 00827 Value FunctionCallNode::evaluate(ExecState *exec) const 00828 { 00829 Reference ref = expr->evaluateReference(exec); 00830 KJS_CHECKEXCEPTIONVALUE 00831 00832 List argList = args->evaluateList(exec); 00833 KJS_CHECKEXCEPTIONVALUE 00834 00835 Value v = ref.getValue(exec); 00836 KJS_CHECKEXCEPTIONVALUE 00837 00838 if (v.type() != ObjectType) { 00839 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be called.", v, expr); 00840 } 00841 00842 Object func = Object(static_cast<ObjectImp*>(v.imp())); 00843 00844 if (!func.implementsCall()) { 00845 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr); 00846 } 00847 00848 Value thisVal; 00849 if (ref.isMutable()) 00850 thisVal = ref.getBase(exec); 00851 else 00852 thisVal = Null(); 00853 00854 if (thisVal.type() == ObjectType && 00855 Object::dynamicCast(thisVal).inherits(&ActivationImp::info)) 00856 thisVal = Null(); 00857 00858 if (thisVal.type() != ObjectType) { 00859 // ECMA 11.2.3 says that in this situation the this value should be null. 00860 // However, section 10.2.3 says that in the case where the value provided 00861 // by the caller is null, the global object should be used. It also says 00862 // that the section does not apply to interal functions, but for simplicity 00863 // of implementation we use the global object anyway here. This guarantees 00864 // that in host objects you always get a valid object for this. 00865 // thisVal = Null(); 00866 thisVal = exec->dynamicInterpreter()->globalObject(); 00867 } 00868 00869 Object thisObj = Object::dynamicCast(thisVal); 00870 Value result = func.call(exec,thisObj, argList); 00871 00872 return result; 00873 } 00874 00875 // ----------------------------- PostfixNode ---------------------------------- 00876 00877 void PostfixNode::ref() 00878 { 00879 Node::ref(); 00880 if ( expr ) 00881 expr->ref(); 00882 } 00883 00884 bool PostfixNode::deref() 00885 { 00886 if ( expr && expr->deref() ) 00887 delete expr; 00888 return Node::deref(); 00889 } 00890 00891 // ECMA 11.3 00892 Value PostfixNode::evaluate(ExecState *exec) const 00893 { 00894 Reference ref = expr->evaluateReference(exec); 00895 KJS_CHECKEXCEPTIONVALUE 00896 Value v = ref.getValue(exec); 00897 double n = v.toNumber(exec); 00898 00899 double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1; 00900 00901 ref.putValue(exec, Number(newValue)); 00902 00903 return Number(n); 00904 } 00905 00906 // ----------------------------- DeleteNode ----------------------------------- 00907 00908 void DeleteNode::ref() 00909 { 00910 Node::ref(); 00911 if ( expr ) 00912 expr->ref(); 00913 } 00914 00915 bool DeleteNode::deref() 00916 { 00917 if ( expr && expr->deref() ) 00918 delete expr; 00919 return Node::deref(); 00920 } 00921 00922 // ECMA 11.4.1 00923 Value DeleteNode::evaluate(ExecState *exec) const 00924 { 00925 Reference ref = expr->evaluateReference(exec); 00926 KJS_CHECKEXCEPTIONVALUE 00927 return Boolean(ref.deleteValue(exec)); 00928 } 00929 00930 // ----------------------------- VoidNode ------------------------------------- 00931 00932 void VoidNode::ref() 00933 { 00934 Node::ref(); 00935 if ( expr ) 00936 expr->ref(); 00937 } 00938 00939 bool VoidNode::deref() 00940 { 00941 if ( expr && expr->deref() ) 00942 delete expr; 00943 return Node::deref(); 00944 } 00945 00946 // ECMA 11.4.2 00947 Value VoidNode::evaluate(ExecState *exec) const 00948 { 00949 Value dummy1 = expr->evaluate(exec); 00950 KJS_CHECKEXCEPTIONVALUE 00951 00952 return Undefined(); 00953 } 00954 00955 // ----------------------------- TypeOfNode ----------------------------------- 00956 00957 void TypeOfNode::ref() 00958 { 00959 Node::ref(); 00960 if ( expr ) 00961 expr->ref(); 00962 } 00963 00964 bool TypeOfNode::deref() 00965 { 00966 if ( expr && expr->deref() ) 00967 delete expr; 00968 return Node::deref(); 00969 } 00970 00971 // ECMA 11.4.3 00972 Value TypeOfNode::evaluate(ExecState *exec) const 00973 { 00974 const char *s = 0L; 00975 Reference ref = expr->evaluateReference(exec); 00976 KJS_CHECKEXCEPTIONVALUE 00977 if (ref.isMutable()) { 00978 Value b = ref.getBase(exec); 00979 if (b.type() == NullType) 00980 return String("undefined"); 00981 } 00982 Value v = ref.getValue(exec); 00983 switch (v.type()) 00984 { 00985 case UndefinedType: 00986 s = "undefined"; 00987 break; 00988 case NullType: 00989 s = "object"; 00990 break; 00991 case BooleanType: 00992 s = "boolean"; 00993 break; 00994 case NumberType: 00995 s = "number"; 00996 break; 00997 case StringType: 00998 s = "string"; 00999 break; 01000 default: 01001 if (v.type() == ObjectType && static_cast<ObjectImp*>(v.imp())->implementsCall()) 01002 s = "function"; 01003 else 01004 s = "object"; 01005 break; 01006 } 01007 01008 return String(s); 01009 } 01010 01011 // ----------------------------- PrefixNode ----------------------------------- 01012 01013 void PrefixNode::ref() 01014 { 01015 Node::ref(); 01016 if ( expr ) 01017 expr->ref(); 01018 } 01019 01020 bool PrefixNode::deref() 01021 { 01022 if ( expr && expr->deref() ) 01023 delete expr; 01024 return Node::deref(); 01025 } 01026 01027 // ECMA 11.4.4 and 11.4.5 01028 Value PrefixNode::evaluate(ExecState *exec) const 01029 { 01030 Reference ref = expr->evaluateReference(exec); 01031 KJS_CHECKEXCEPTIONVALUE 01032 Value v = ref.getValue(exec); 01033 double n = v.toNumber(exec); 01034 01035 double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1; 01036 Value n2 = Number(newValue); 01037 01038 ref.putValue(exec,n2); 01039 01040 return n2; 01041 } 01042 01043 // ----------------------------- UnaryPlusNode -------------------------------- 01044 01045 void UnaryPlusNode::ref() 01046 { 01047 Node::ref(); 01048 if ( expr ) 01049 expr->ref(); 01050 } 01051 01052 bool UnaryPlusNode::deref() 01053 { 01054 if ( expr && expr->deref() ) 01055 delete expr; 01056 return Node::deref(); 01057 } 01058 01059 // ECMA 11.4.6 01060 double UnaryPlusNode::toNumber(ExecState *exec) const 01061 { 01062 return expr->toNumber(exec); 01063 } 01064 01065 // could go 01066 Value UnaryPlusNode::evaluate(ExecState *exec) const 01067 { 01068 Value v = expr->evaluate(exec); 01069 KJS_CHECKEXCEPTIONVALUE 01070 01071 return Number(v.toNumber(exec)); /* TODO: optimize */ 01072 } 01073 01074 // ----------------------------- NegateNode ----------------------------------- 01075 01076 void NegateNode::ref() 01077 { 01078 Node::ref(); 01079 if ( expr ) 01080 expr->ref(); 01081 } 01082 01083 bool NegateNode::deref() 01084 { 01085 if ( expr && expr->deref() ) 01086 delete expr; 01087 return Node::deref(); 01088 } 01089 01090 // ECMA 11.4.7 01091 double NegateNode::toNumber(ExecState *exec) const 01092 { 01093 return -expr->toNumber(exec); 01094 } 01095 01096 Value NegateNode::evaluate(ExecState *exec) const 01097 { 01098 Value v = expr->evaluate(exec); 01099 KJS_CHECKEXCEPTIONVALUE 01100 double d = -v.toNumber(exec); 01101 01102 return Number(d); 01103 } 01104 01105 // ----------------------------- BitwiseNotNode ------------------------------- 01106 01107 void BitwiseNotNode::ref() 01108 { 01109 Node::ref(); 01110 if ( expr ) 01111 expr->ref(); 01112 } 01113 01114 bool BitwiseNotNode::deref() 01115 { 01116 if ( expr && expr->deref() ) 01117 delete expr; 01118 return Node::deref(); 01119 } 01120 01121 // ECMA 11.4.8 01122 Value BitwiseNotNode::evaluate(ExecState *exec) const 01123 { 01124 Value v = expr->evaluate(exec); 01125 KJS_CHECKEXCEPTIONVALUE 01126 int i32 = v.toInt32(exec); 01127 01128 return Number(~i32); 01129 } 01130 01131 // ----------------------------- LogicalNotNode ------------------------------- 01132 01133 void LogicalNotNode::ref() 01134 { 01135 Node::ref(); 01136 if ( expr ) 01137 expr->ref(); 01138 } 01139 01140 bool LogicalNotNode::deref() 01141 { 01142 if ( expr && expr->deref() ) 01143 delete expr; 01144 return Node::deref(); 01145 } 01146 01147 // ECMA 11.4.9 01148 bool LogicalNotNode::toBoolean(ExecState *exec) const 01149 { 01150 return !expr->toBoolean(exec); 01151 } 01152 01153 // could remove this 01154 Value LogicalNotNode::evaluate(ExecState *exec) const 01155 { 01156 bool b = expr->toBoolean(exec); 01157 KJS_CHECKEXCEPTIONVALUE 01158 01159 return Boolean(!b); 01160 } 01161 01162 // ----------------------------- MultNode ------------------------------------- 01163 01164 void MultNode::ref() 01165 { 01166 Node::ref(); 01167 if ( term1 ) 01168 term1->ref(); 01169 if ( term2 ) 01170 term2->ref(); 01171 } 01172 01173 bool MultNode::deref() 01174 { 01175 if ( term1 && term1->deref() ) 01176 delete term1; 01177 if ( term2 && term2->deref() ) 01178 delete term2; 01179 return Node::deref(); 01180 } 01181 01182 // ECMA 11.5 01183 Value MultNode::evaluate(ExecState *exec) const 01184 { 01185 Value v1 = term1->evaluate(exec); 01186 KJS_CHECKEXCEPTIONVALUE 01187 01188 Value v2 = term2->evaluate(exec); 01189 KJS_CHECKEXCEPTIONVALUE 01190 01191 return mult(exec,v1, v2, oper); 01192 } 01193 01194 // ----------------------------- AddNode -------------------------------------- 01195 01196 // factory for an appropriate addition or substraction node 01197 Node* AddNode::create(Node *t1, Node *t2, char op) 01198 { 01199 // ### many more combinations to check for 01200 // fold constants 01201 if ((t1->type() == NumberType || t1->type() == BooleanType) && 01202 (t2->type() == NumberType || t2->type() == BooleanType)) { 01203 double d = t2->toNumber(0); 01204 Node* n = new NumberNode(t1->toNumber(0) + (op == '+' ? d : -d)); 01205 delete t1; 01206 delete t2; 01207 return n; 01208 } 01209 01210 if (op == '+' && t2->type() == StringType) 01211 return new AppendStringNode(t1, t2->toString(0)); 01212 01213 // fall back to generic node 01214 return new AddNode(t1, t2, op); 01215 } 01216 01217 void AddNode::ref() 01218 { 01219 Node::ref(); 01220 if ( term1 ) 01221 term1->ref(); 01222 if ( term2 ) 01223 term2->ref(); 01224 } 01225 01226 bool AddNode::deref() 01227 { 01228 if ( term1 && term1->deref() ) 01229 delete term1; 01230 if ( term2 && term2->deref() ) 01231 delete term2; 01232 return Node::deref(); 01233 } 01234 01235 // ECMA 11.6 01236 Value AddNode::evaluate(ExecState *exec) const 01237 { 01238 Value v1 = term1->evaluate(exec); 01239 KJS_CHECKEXCEPTIONVALUE 01240 01241 Value v2 = term2->evaluate(exec); 01242 KJS_CHECKEXCEPTIONVALUE 01243 01244 return add(exec,v1, v2, oper); 01245 } 01246 01247 // ------------------------ AddNumberNode ------------------------------------ 01248 01249 void AppendStringNode::ref() 01250 { 01251 Node::ref(); 01252 term->ref(); 01253 } 01254 01255 bool AppendStringNode::deref() 01256 { 01257 if (term->deref()) 01258 delete term; 01259 return Node::deref(); 01260 } 01261 01262 // ECMA 11.6 (special case of string appending) 01263 Value AppendStringNode::evaluate(ExecState *exec) const 01264 { 01265 UString s = term->toString(exec); 01266 KJS_CHECKEXCEPTIONVALUE 01267 01268 return String(s + str); 01269 } 01270 01271 // ----------------------------- ShiftNode ------------------------------------ 01272 01273 void ShiftNode::ref() 01274 { 01275 Node::ref(); 01276 if ( term1 ) 01277 term1->ref(); 01278 if ( term2 ) 01279 term2->ref(); 01280 } 01281 01282 bool ShiftNode::deref() 01283 { 01284 if ( term1 && term1->deref() ) 01285 delete term1; 01286 if ( term2 && term2->deref() ) 01287 delete term2; 01288 return Node::deref(); 01289 } 01290 01291 // ECMA 11.7 01292 Value ShiftNode::evaluate(ExecState *exec) const 01293 { 01294 Value v1 = term1->evaluate(exec); 01295 KJS_CHECKEXCEPTIONVALUE 01296 Value v2 = term2->evaluate(exec); 01297 KJS_CHECKEXCEPTIONVALUE 01298 unsigned int i2 = v2.toUInt32(exec); 01299 i2 &= 0x1f; 01300 01301 switch (oper) { 01302 case OpLShift: 01303 return Number(v1.toInt32(exec) << i2); 01304 case OpRShift: 01305 return Number(v1.toInt32(exec) >> i2); 01306 case OpURShift: 01307 return Number(v1.toUInt32(exec) >> i2); 01308 default: 01309 assert(!"ShiftNode: unhandled switch case"); 01310 return Undefined(); 01311 } 01312 } 01313 01314 // ----------------------------- RelationalNode ------------------------------- 01315 01316 void RelationalNode::ref() 01317 { 01318 Node::ref(); 01319 if ( expr1 ) 01320 expr1->ref(); 01321 if ( expr2 ) 01322 expr2->ref(); 01323 } 01324 01325 bool RelationalNode::deref() 01326 { 01327 if ( expr1 && expr1->deref() ) 01328 delete expr1; 01329 if ( expr2 && expr2->deref() ) 01330 delete expr2; 01331 return Node::deref(); 01332 } 01333 01334 // ECMA 11.8 01335 Value RelationalNode::evaluate(ExecState *exec) const 01336 { 01337 Value v1 = expr1->evaluate(exec); 01338 KJS_CHECKEXCEPTIONVALUE 01339 Value v2 = expr2->evaluate(exec); 01340 KJS_CHECKEXCEPTIONVALUE 01341 01342 bool b; 01343 if (oper == OpLess || oper == OpGreaterEq) { 01344 int r = relation(exec, v1, v2); 01345 if (r < 0) 01346 b = false; 01347 else 01348 b = (oper == OpLess) ? (r == 1) : (r == 0); 01349 } else if (oper == OpGreater || oper == OpLessEq) { 01350 int r = relation(exec, v2, v1); 01351 if (r < 0) 01352 b = false; 01353 else 01354 b = (oper == OpGreater) ? (r == 1) : (r == 0); 01355 } else if (oper == OpIn) { 01356 // Is all of this OK for host objects? 01357 if (v2.type() != ObjectType) 01358 return throwError(exec, TypeError, 01359 "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2); 01360 Object o2(static_cast<ObjectImp*>(v2.imp())); 01361 b = o2.hasProperty(exec,Identifier(v1.toString(exec))); 01362 } else { 01363 if (v2.type() != ObjectType) 01364 return throwError(exec, TypeError, 01365 "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2); 01366 01367 Object o2(static_cast<ObjectImp*>(v2.imp())); 01368 if (!o2.implementsHasInstance()) { 01369 // According to the spec, only some types of objects "imlement" the [[HasInstance]] property. 01370 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]] 01371 // property. It seems that all object have the property, but not all implement it, so in this 01372 // case we return false (consistent with mozilla) 01373 return Boolean(false); 01374 // return throwError(exec, TypeError, 01375 // "Object does not implement the [[HasInstance]] method." ); 01376 } 01377 return o2.hasInstance(exec, v1); 01378 } 01379 01380 return Boolean(b); 01381 } 01382 01383 // ----------------------------- EqualNode ------------------------------------ 01384 01385 void EqualNode::ref() 01386 { 01387 Node::ref(); 01388 if ( expr1 ) 01389 expr1->ref(); 01390 if ( expr2 ) 01391 expr2->ref(); 01392 } 01393 01394 bool EqualNode::deref() 01395 { 01396 if ( expr1 && expr1->deref() ) 01397 delete expr1; 01398 if ( expr2 && expr2->deref() ) 01399 delete expr2; 01400 return Node::deref(); 01401 } 01402 01403 // ECMA 11.9 01404 Value EqualNode::evaluate(ExecState *exec) const 01405 { 01406 Value v1 = expr1->evaluate(exec); 01407 KJS_CHECKEXCEPTIONVALUE 01408 Value v2 = expr2->evaluate(exec); 01409 KJS_CHECKEXCEPTIONVALUE 01410 01411 bool result; 01412 if (oper == OpEqEq || oper == OpNotEq) { 01413 // == and != 01414 bool eq = equal(exec,v1, v2); 01415 result = oper == OpEqEq ? eq : !eq; 01416 } else { 01417 // === and !== 01418 bool eq = strictEqual(exec,v1, v2); 01419 result = oper == OpStrEq ? eq : !eq; 01420 } 01421 return Boolean(result); 01422 } 01423 01424 // ----------------------------- BitOperNode ---------------------------------- 01425 01426 void BitOperNode::ref() 01427 { 01428 Node::ref(); 01429 if ( expr1 ) 01430 expr1->ref(); 01431 if ( expr2 ) 01432 expr2->ref(); 01433 } 01434 01435 bool BitOperNode::deref() 01436 { 01437 if ( expr1 && expr1->deref() ) 01438 delete expr1; 01439 if ( expr2 && expr2->deref() ) 01440 delete expr2; 01441 return Node::deref(); 01442 } 01443 01444 // ECMA 11.10 01445 Value BitOperNode::evaluate(ExecState *exec) const 01446 { 01447 Value v1 = expr1->evaluate(exec); 01448 KJS_CHECKEXCEPTIONVALUE 01449 Value v2 = expr2->evaluate(exec); 01450 KJS_CHECKEXCEPTIONVALUE 01451 int i1 = v1.toInt32(exec); 01452 int i2 = v2.toInt32(exec); 01453 int result; 01454 if (oper == OpBitAnd) 01455 result = i1 & i2; 01456 else if (oper == OpBitXOr) 01457 result = i1 ^ i2; 01458 else 01459 result = i1 | i2; 01460 01461 return Number(result); 01462 } 01463 01464 // ----------------------------- BinaryLogicalNode ---------------------------- 01465 01466 void BinaryLogicalNode::ref() 01467 { 01468 Node::ref(); 01469 if ( expr1 ) 01470 expr1->ref(); 01471 if ( expr2 ) 01472 expr2->ref(); 01473 } 01474 01475 bool BinaryLogicalNode::deref() 01476 { 01477 if ( expr1 && expr1->deref() ) 01478 delete expr1; 01479 if ( expr2 && expr2->deref() ) 01480 delete expr2; 01481 return Node::deref(); 01482 } 01483 01484 // ECMA 11.11 01485 Value BinaryLogicalNode::evaluate(ExecState *exec) const 01486 { 01487 Value v1 = expr1->evaluate(exec); 01488 KJS_CHECKEXCEPTIONVALUE 01489 bool b1 = v1.toBoolean(exec); 01490 if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr)) 01491 return v1; 01492 01493 Value v2 = expr2->evaluate(exec); 01494 KJS_CHECKEXCEPTIONVALUE 01495 01496 return v2; 01497 } 01498 01499 // ----------------------------- ConditionalNode ------------------------------ 01500 01501 void ConditionalNode::ref() 01502 { 01503 Node::ref(); 01504 if ( expr1 ) 01505 expr1->ref(); 01506 if ( expr2 ) 01507 expr2->ref(); 01508 if ( logical ) 01509 logical->ref(); 01510 } 01511 01512 bool ConditionalNode::deref() 01513 { 01514 if ( expr1 && expr1->deref() ) 01515 delete expr1; 01516 if ( expr2 && expr2->deref() ) 01517 delete expr2; 01518 if ( logical && logical->deref() ) 01519 delete logical; 01520 return Node::deref(); 01521 } 01522 01523 // ECMA 11.12 01524 Value ConditionalNode::evaluate(ExecState *exec) const 01525 { 01526 bool b = logical->toBoolean(exec); 01527 KJS_CHECKEXCEPTIONVALUE 01528 01529 Value v = b ? expr1->evaluate(exec) : expr2->evaluate(exec); 01530 KJS_CHECKEXCEPTIONVALUE 01531 01532 return v; 01533 } 01534 01535 // ----------------------------- AssignNode ----------------------------------- 01536 01537 void AssignNode::ref() 01538 { 01539 Node::ref(); 01540 if ( left ) 01541 left->ref(); 01542 if ( expr ) 01543 expr->ref(); 01544 } 01545 01546 bool AssignNode::deref() 01547 { 01548 if ( left && left->deref() ) 01549 delete left; 01550 if ( expr && expr->deref() ) 01551 delete expr; 01552 return Node::deref(); 01553 } 01554 01555 // ECMA 11.13 01556 Value AssignNode::evaluate(ExecState *exec) const 01557 { 01558 Reference l = left->evaluateReference(exec); 01559 KJS_CHECKEXCEPTIONVALUE 01560 Value v; 01561 if (oper == OpEqual) { 01562 v = expr->evaluate(exec); 01563 KJS_CHECKEXCEPTIONVALUE 01564 } else { 01565 Value v1 = l.getValue(exec); 01566 Value v2 = expr->evaluate(exec); 01567 KJS_CHECKEXCEPTIONVALUE 01568 int i1; 01569 int i2; 01570 unsigned int ui; 01571 switch (oper) { 01572 case OpMultEq: 01573 v = mult(exec, v1, v2, '*'); 01574 break; 01575 case OpDivEq: 01576 v = mult(exec, v1, v2, '/'); 01577 break; 01578 case OpPlusEq: 01579 v = add(exec, v1, v2, '+'); 01580 break; 01581 case OpMinusEq: 01582 v = add(exec, v1, v2, '-'); 01583 break; 01584 case OpLShift: 01585 i1 = v1.toInt32(exec); 01586 i2 = v2.toInt32(exec); 01587 v = Number(i1 << i2); 01588 break; 01589 case OpRShift: 01590 i1 = v1.toInt32(exec); 01591 i2 = v2.toInt32(exec); 01592 v = Number(i1 >> i2); 01593 break; 01594 case OpURShift: 01595 ui = v1.toUInt32(exec); 01596 i2 = v2.toInt32(exec); 01597 v = Number(ui >> i2); 01598 break; 01599 case OpAndEq: 01600 i1 = v1.toInt32(exec); 01601 i2 = v2.toInt32(exec); 01602 v = Number(i1 & i2); 01603 break; 01604 case OpXOrEq: 01605 i1 = v1.toInt32(exec); 01606 i2 = v2.toInt32(exec); 01607 v = Number(i1 ^ i2); 01608 break; 01609 case OpOrEq: 01610 i1 = v1.toInt32(exec); 01611 i2 = v2.toInt32(exec); 01612 v = Number(i1 | i2); 01613 break; 01614 case OpModEq: { 01615 double d1 = v1.toNumber(exec); 01616 double d2 = v2.toNumber(exec); 01617 v = Number(fmod(d1,d2)); 01618 } 01619 break; 01620 default: 01621 v = Undefined(); 01622 } 01623 }; 01624 l.putValue(exec,v); 01625 01626 KJS_CHECKEXCEPTIONVALUE 01627 01628 return v; 01629 } 01630 01631 // ----------------------------- CommaNode ------------------------------------ 01632 01633 void CommaNode::ref() 01634 { 01635 Node::ref(); 01636 if ( expr1 ) 01637 expr1->ref(); 01638 if ( expr2 ) 01639 expr2->ref(); 01640 } 01641 01642 bool CommaNode::deref() 01643 { 01644 if ( expr1 && expr1->deref() ) 01645 delete expr1; 01646 if ( expr2 && expr2->deref() ) 01647 delete expr2; 01648 return Node::deref(); 01649 } 01650 01651 // ECMA 11.14 01652 Value CommaNode::evaluate(ExecState *exec) const 01653 { 01654 (void) expr1->evaluate(exec); // ignore return value 01655 KJS_CHECKEXCEPTIONVALUE 01656 Value v = expr2->evaluate(exec); 01657 KJS_CHECKEXCEPTIONVALUE 01658 01659 return v; 01660 } 01661 01662 // ----------------------------- StatListNode --------------------------------- 01663 01664 StatListNode::StatListNode(StatementNode *s) 01665 : statement(s), list(this) 01666 { 01667 setLoc(s->firstLine(), s->lastLine(), s->code()); 01668 } 01669 01670 StatListNode::StatListNode(StatListNode *l, StatementNode *s) 01671 : statement(s), list(l->list) 01672 { 01673 l->list = this; 01674 setLoc(l->firstLine(),s->lastLine(),l->code()); 01675 } 01676 01677 void StatListNode::ref() 01678 { 01679 for (StatListNode *n = this; n; n = n->list) { 01680 n->Node::ref(); 01681 if (n->statement) 01682 n->statement->ref(); 01683 } 01684 } 01685 01686 bool StatListNode::deref() 01687 { 01688 StatListNode *next; 01689 for (StatListNode *n = this; n; n = next) { 01690 next = n->list; 01691 if (n->statement && n->statement->deref()) 01692 delete n->statement; 01693 if (n != this && n->Node::deref()) 01694 delete n; 01695 } 01696 return StatementNode::deref(); 01697 } 01698 01699 // ECMA 12.1 01700 Completion StatListNode::execute(ExecState *exec) 01701 { 01702 Completion c = statement->execute(exec); 01703 KJS_ABORTPOINT 01704 if (exec->hadException()) { 01705 Value ex = exec->exception(); 01706 exec->clearException(); 01707 return Completion(Throw, ex); 01708 } 01709 01710 if (c.complType() != Normal) 01711 return c; 01712 01713 Value v = c.value(); 01714 01715 for (StatListNode *n = list; n; n = n->list) { 01716 Completion c2 = n->statement->execute(exec); 01717 KJS_ABORTPOINT 01718 if (c2.complType() != Normal) 01719 return c2; 01720 01721 if (exec->hadException()) { 01722 Value ex = exec->exception(); 01723 exec->clearException(); 01724 return Completion(Throw, ex); 01725 } 01726 01727 if (c2.isValueCompletion()) 01728 v = c2.value(); 01729 c = c2; 01730 } 01731 01732 return Completion(c.complType(), v, c.target()); 01733 } 01734 01735 void StatListNode::processVarDecls(ExecState *exec) 01736 { 01737 for (StatListNode *n = this; n; n = n->list) 01738 n->statement->processVarDecls(exec); 01739 } 01740 01741 // ----------------------------- AssignExprNode ------------------------------- 01742 01743 void AssignExprNode::ref() 01744 { 01745 Node::ref(); 01746 if ( expr ) 01747 expr->ref(); 01748 } 01749 01750 bool AssignExprNode::deref() 01751 { 01752 if ( expr && expr->deref() ) 01753 delete expr; 01754 return Node::deref(); 01755 } 01756 01757 // ECMA 12.2 01758 Value AssignExprNode::evaluate(ExecState *exec) const 01759 { 01760 return expr->evaluate(exec); 01761 } 01762 01763 // ----------------------------- VarDeclNode ---------------------------------- 01764 01765 VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t) 01766 : varType(t), ident(id), init(in) 01767 { 01768 } 01769 01770 void VarDeclNode::ref() 01771 { 01772 Node::ref(); 01773 if ( init ) 01774 init->ref(); 01775 } 01776 01777 bool VarDeclNode::deref() 01778 { 01779 if ( init && init->deref() ) 01780 delete init; 01781 return Node::deref(); 01782 } 01783 01784 // ECMA 12.2 01785 Value VarDeclNode::evaluate(ExecState *exec) const 01786 { 01787 Object variable = Object::dynamicCast(exec->context().imp()->variableObject()); 01788 01789 Value val; 01790 if (init) { 01791 val = init->evaluate(exec); 01792 KJS_CHECKEXCEPTIONVALUE 01793 } else { 01794 // ### check attributes? reuse check done in processVarDecls()? 01795 if (variable.imp()->getDirect(ident)) // already declared ? 01796 return Value(); 01797 val = Undefined(); 01798 } 01799 01800 #ifdef KJS_VERBOSE 01801 printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val); 01802 #endif 01803 // We use Internal to bypass all checks in derived objects, e.g. so that 01804 // "var location" creates a dynamic property instead of activating window.location. 01805 int flags = Internal; 01806 if (exec->context().imp()->codeType() != EvalCode) 01807 flags |= DontDelete; 01808 if (varType == VarDeclNode::Constant) 01809 flags |= ReadOnly; 01810 variable.put(exec, ident, val, flags); 01811 01812 // the spec wants us to return the name of the identifier here 01813 // but we'll save the construction and copying as the return 01814 // value isn't used by the caller 01815 return Value(); 01816 } 01817 01818 void VarDeclNode::processVarDecls(ExecState *exec) 01819 { 01820 Object variable = exec->context().variableObject(); 01821 // ### use getDirect()? Check attributes? 01822 // ### avoid duplication with actions performed in evaluate()? 01823 if ( !variable.hasProperty( exec, ident ) ) { // already declared ? 01824 int flags = None; 01825 if (exec->_context->codeType() != EvalCode) 01826 flags |= DontDelete; 01827 if (varType == VarDeclNode::Constant) 01828 flags |= ReadOnly; 01829 // TODO: check for forbidden redeclaration of consts 01830 variable.put(exec, ident, Undefined(), flags); 01831 } 01832 } 01833 01834 // ----------------------------- VarDeclListNode ------------------------------ 01835 01836 void VarDeclListNode::ref() 01837 { 01838 for (VarDeclListNode *n = this; n; n = n->list) { 01839 n->Node::ref(); 01840 if (n->var) 01841 n->var->ref(); 01842 } 01843 } 01844 01845 bool VarDeclListNode::deref() 01846 { 01847 VarDeclListNode *next; 01848 for (VarDeclListNode *n = this; n; n = next) { 01849 next = n->list; 01850 if (n->var && n->var->deref()) 01851 delete n->var; 01852 if (n != this && n->Node::deref()) 01853 delete n; 01854 } 01855 return Node::deref(); 01856 } 01857 01858 01859 // ECMA 12.2 01860 Value VarDeclListNode::evaluate(ExecState *exec) const 01861 { 01862 for (const VarDeclListNode *n = this; n; n = n->list) { 01863 (void)n->var->evaluate(exec); 01864 KJS_CHECKEXCEPTIONVALUE 01865 } 01866 return Undefined(); 01867 } 01868 01869 void VarDeclListNode::processVarDecls(ExecState *exec) 01870 { 01871 for (VarDeclListNode *n = this; n; n = n->list) 01872 n->var->processVarDecls(exec); 01873 } 01874 01875 // ----------------------------- VarStatementNode ----------------------------- 01876 01877 void VarStatementNode::ref() 01878 { 01879 StatementNode::ref(); 01880 if ( list ) 01881 list->ref(); 01882 } 01883 01884 bool VarStatementNode::deref() 01885 { 01886 if ( list && list->deref() ) 01887 delete list; 01888 return StatementNode::deref(); 01889 } 01890 01891 // ECMA 12.2 01892 Completion VarStatementNode::execute(ExecState *exec) 01893 { 01894 KJS_BREAKPOINT; 01895 01896 (void) list->evaluate(exec); 01897 KJS_CHECKEXCEPTION 01898 01899 return Completion(Normal); 01900 } 01901 01902 void VarStatementNode::processVarDecls(ExecState *exec) 01903 { 01904 list->processVarDecls(exec); 01905 } 01906 01907 // ----------------------------- BlockNode ------------------------------------ 01908 01909 BlockNode::BlockNode(SourceElementsNode *s) 01910 { 01911 if (s) { 01912 source = s->elements; 01913 s->elements = 0; 01914 setLoc(s->firstLine(), s->lastLine(), s->code()); 01915 } else { 01916 source = 0; 01917 } 01918 } 01919 01920 void BlockNode::ref() 01921 { 01922 StatementNode::ref(); 01923 if ( source ) 01924 source->ref(); 01925 } 01926 01927 bool BlockNode::deref() 01928 { 01929 if ( source && source->deref() ) 01930 delete source; 01931 return StatementNode::deref(); 01932 } 01933 01934 // ECMA 12.1 01935 Completion BlockNode::execute(ExecState *exec) 01936 { 01937 if (!source) 01938 return Completion(Normal); 01939 01940 source->processFuncDecl(exec); 01941 01942 return source->execute(exec); 01943 } 01944 01945 void BlockNode::processVarDecls(ExecState *exec) 01946 { 01947 if (source) 01948 source->processVarDecls(exec); 01949 } 01950 01951 // ----------------------------- EmptyStatementNode --------------------------- 01952 01953 // ECMA 12.3 01954 Completion EmptyStatementNode::execute(ExecState * /*exec*/) 01955 { 01956 return Completion(Normal); 01957 } 01958 01959 // ----------------------------- ExprStatementNode ---------------------------- 01960 01961 void ExprStatementNode::ref() 01962 { 01963 StatementNode::ref(); 01964 if ( expr ) 01965 expr->ref(); 01966 } 01967 01968 bool ExprStatementNode::deref() 01969 { 01970 if ( expr && expr->deref() ) 01971 delete expr; 01972 return StatementNode::deref(); 01973 } 01974 01975 // ECMA 12.4 01976 Completion ExprStatementNode::execute(ExecState *exec) 01977 { 01978 KJS_BREAKPOINT; 01979 01980 Value v = expr->evaluate(exec); 01981 KJS_CHECKEXCEPTION 01982 01983 return Completion(Normal, v); 01984 } 01985 01986 // ----------------------------- IfNode --------------------------------------- 01987 01988 void IfNode::ref() 01989 { 01990 StatementNode::ref(); 01991 if ( statement1 ) 01992 statement1->ref(); 01993 if ( statement2 ) 01994 statement2->ref(); 01995 if ( expr ) 01996 expr->ref(); 01997 } 01998 01999 bool IfNode::deref() 02000 { 02001 if ( statement1 && statement1->deref() ) 02002 delete statement1; 02003 if ( statement2 && statement2->deref() ) 02004 delete statement2; 02005 if ( expr && expr->deref() ) 02006 delete expr; 02007 return StatementNode::deref(); 02008 } 02009 02010 // ECMA 12.5 02011 Completion IfNode::execute(ExecState *exec) 02012 { 02013 KJS_BREAKPOINT; 02014 02015 assert(expr); 02016 bool b = expr->toBoolean(exec); 02017 KJS_CHECKEXCEPTION 02018 02019 // if ... then 02020 if (b) 02021 return statement1->execute(exec); 02022 02023 // no else 02024 if (!statement2) 02025 return Completion(Normal); 02026 02027 // else 02028 return statement2->execute(exec); 02029 } 02030 02031 void IfNode::processVarDecls(ExecState *exec) 02032 { 02033 statement1->processVarDecls(exec); 02034 02035 if (statement2) 02036 statement2->processVarDecls(exec); 02037 } 02038 02039 // ----------------------------- DoWhileNode ---------------------------------- 02040 02041 void DoWhileNode::ref() 02042 { 02043 StatementNode::ref(); 02044 if ( statement ) 02045 statement->ref(); 02046 if ( expr ) 02047 expr->ref(); 02048 } 02049 02050 bool DoWhileNode::deref() 02051 { 02052 if ( statement && statement->deref() ) 02053 delete statement; 02054 if ( expr && expr->deref() ) 02055 delete expr; 02056 return StatementNode::deref(); 02057 } 02058 02059 // ECMA 12.6.1 02060 Completion DoWhileNode::execute(ExecState *exec) 02061 { 02062 KJS_BREAKPOINT; 02063 02064 Completion c; 02065 Value value; 02066 bool b; 02067 02068 do { 02069 // bail out on error 02070 KJS_CHECKEXCEPTION 02071 02072 exec->context().imp()->seenLabels()->pushIteration(); 02073 c = statement->execute(exec); 02074 exec->context().imp()->seenLabels()->popIteration(); 02075 if (!((c.complType() == Continue) && ls.contains(c.target()))) { 02076 if ((c.complType() == Break) && ls.contains(c.target())) 02077 return Completion(Normal, value); 02078 if (c.complType() != Normal) 02079 return c; 02080 } 02081 b = expr->toBoolean(exec); 02082 KJS_CHECKEXCEPTION 02083 } while (b); 02084 02085 return Completion(Normal, value); 02086 } 02087 02088 void DoWhileNode::processVarDecls(ExecState *exec) 02089 { 02090 statement->processVarDecls(exec); 02091 } 02092 02093 // ----------------------------- WhileNode ------------------------------------ 02094 02095 void WhileNode::ref() 02096 { 02097 StatementNode::ref(); 02098 if ( statement ) 02099 statement->ref(); 02100 if ( expr ) 02101 expr->ref(); 02102 } 02103 02104 bool WhileNode::deref() 02105 { 02106 if ( statement && statement->deref() ) 02107 delete statement; 02108 if ( expr && expr->deref() ) 02109 delete expr; 02110 return StatementNode::deref(); 02111 } 02112 02113 // ECMA 12.6.2 02114 Completion WhileNode::execute(ExecState *exec) 02115 { 02116 KJS_BREAKPOINT; 02117 02118 Completion c; 02119 Value value; 02120 02121 while (1) { 02122 bool b = expr->toBoolean(exec); 02123 KJS_CHECKEXCEPTION 02124 02125 // bail out on error 02126 KJS_CHECKEXCEPTION 02127 02128 if (!b) 02129 return Completion(Normal, value); 02130 02131 exec->context().imp()->seenLabels()->pushIteration(); 02132 c = statement->execute(exec); 02133 exec->context().imp()->seenLabels()->popIteration(); 02134 if (c.isValueCompletion()) 02135 value = c.value(); 02136 02137 if ((c.complType() == Continue) && ls.contains(c.target())) 02138 continue; 02139 if ((c.complType() == Break) && ls.contains(c.target())) 02140 return Completion(Normal, value); 02141 if (c.complType() != Normal) 02142 return c; 02143 } 02144 } 02145 02146 void WhileNode::processVarDecls(ExecState *exec) 02147 { 02148 statement->processVarDecls(exec); 02149 } 02150 02151 // ----------------------------- ForNode -------------------------------------- 02152 02153 void ForNode::ref() 02154 { 02155 StatementNode::ref(); 02156 if ( statement ) 02157 statement->ref(); 02158 if ( expr1 ) 02159 expr1->ref(); 02160 if ( expr2 ) 02161 expr2->ref(); 02162 if ( expr3 ) 02163 expr3->ref(); 02164 } 02165 02166 bool ForNode::deref() 02167 { 02168 if ( statement && statement->deref() ) 02169 delete statement; 02170 if ( expr1 && expr1->deref() ) 02171 delete expr1; 02172 if ( expr2 && expr2->deref() ) 02173 delete expr2; 02174 if ( expr3 && expr3->deref() ) 02175 delete expr3; 02176 return StatementNode::deref(); 02177 } 02178 02179 // ECMA 12.6.3 02180 Completion ForNode::execute(ExecState *exec) 02181 { 02182 Value v, cval; 02183 02184 if (expr1) { 02185 v = expr1->evaluate(exec); 02186 KJS_CHECKEXCEPTION 02187 } 02188 for (;;) { 02189 if (expr2) { 02190 bool b = expr2->toBoolean(exec); 02191 KJS_CHECKEXCEPTION 02192 if (!b) 02193 return Completion(Normal, cval); 02194 } 02195 // bail out on error 02196 KJS_CHECKEXCEPTION 02197 02198 exec->context().imp()->seenLabels()->pushIteration(); 02199 Completion c = statement->execute(exec); 02200 exec->context().imp()->seenLabels()->popIteration(); 02201 if (c.isValueCompletion()) 02202 cval = c.value(); 02203 if (!((c.complType() == Continue) && ls.contains(c.target()))) { 02204 if ((c.complType() == Break) && ls.contains(c.target())) 02205 return Completion(Normal, cval); 02206 if (c.complType() != Normal) 02207 return c; 02208 } 02209 if (expr3) { 02210 v = expr3->evaluate(exec); 02211 KJS_CHECKEXCEPTION 02212 } 02213 } 02214 } 02215 02216 void ForNode::processVarDecls(ExecState *exec) 02217 { 02218 if (expr1) 02219 expr1->processVarDecls(exec); 02220 02221 statement->processVarDecls(exec); 02222 } 02223 02224 // ----------------------------- ForInNode ------------------------------------ 02225 02226 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s) 02227 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s) 02228 { 02229 } 02230 02231 ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s) 02232 : ident(i), init(in), expr(e), statement(s) 02233 { 02234 // for( var foo = bar in baz ) 02235 varDecl = new VarDeclNode(ident, init, VarDeclNode::Variable); 02236 lexpr = new ResolveNode(ident); 02237 } 02238 02239 void ForInNode::ref() 02240 { 02241 StatementNode::ref(); 02242 if ( statement ) 02243 statement->ref(); 02244 if ( expr ) 02245 expr->ref(); 02246 if ( lexpr ) 02247 lexpr->ref(); 02248 if ( init ) 02249 init->ref(); 02250 if ( varDecl ) 02251 varDecl->ref(); 02252 } 02253 02254 bool ForInNode::deref() 02255 { 02256 if ( statement && statement->deref() ) 02257 delete statement; 02258 if ( expr && expr->deref() ) 02259 delete expr; 02260 if ( lexpr && lexpr->deref() ) 02261 delete lexpr; 02262 if ( init && init->deref() ) 02263 delete init; 02264 if ( varDecl && varDecl->deref() ) 02265 delete varDecl; 02266 return StatementNode::deref(); 02267 } 02268 02269 // ECMA 12.6.4 02270 Completion ForInNode::execute(ExecState *exec) 02271 { 02272 Value retval; 02273 Completion c; 02274 02275 if ( varDecl ) { 02276 (void)varDecl->evaluate(exec); 02277 KJS_CHECKEXCEPTION 02278 } 02279 02280 Value v = expr->evaluate(exec); 02281 // for Null and Undefined, we want to make sure not to go through 02282 // the loop at all, because their object wrappers will have a 02283 // property list but will throw an exception if you attempt to 02284 // access any property. 02285 if (v.isA(NullType) || v.isA(UndefinedType)) 02286 return Completion(Normal, retval); 02287 02288 Object o = v.toObject(exec); 02289 KJS_CHECKEXCEPTION 02290 ReferenceList propList = o.propList(exec); 02291 02292 ReferenceListIterator propIt = propList.begin(); 02293 02294 while (propIt != propList.end()) { 02295 Identifier name = propIt->getPropertyName(exec); 02296 if (!o.hasProperty(exec,name)) { 02297 propIt++; 02298 continue; 02299 } 02300 02301 Reference ref = lexpr->evaluateReference(exec); 02302 KJS_CHECKEXCEPTION 02303 ref.putValue(exec, String(name.ustring())); 02304 02305 exec->context().imp()->seenLabels()->pushIteration(); 02306 c = statement->execute(exec); 02307 exec->context().imp()->seenLabels()->popIteration(); 02308 if (c.isValueCompletion()) 02309 retval = c.value(); 02310 02311 if (!((c.complType() == Continue) && ls.contains(c.target()))) { 02312 if ((c.complType() == Break) && ls.contains(c.target())) 02313 break; 02314 if (c.complType() != Normal) { 02315 return c; 02316 } 02317 } 02318 02319 propIt++; 02320 } 02321 02322 // bail out on error 02323 KJS_CHECKEXCEPTION 02324 02325 return Completion(Normal, retval); 02326 } 02327 02328 void ForInNode::processVarDecls(ExecState *exec) 02329 { 02330 statement->processVarDecls(exec); 02331 } 02332 02333 // ----------------------------- ContinueNode --------------------------------- 02334 02335 // ECMA 12.7 02336 Completion ContinueNode::execute(ExecState *exec) 02337 { 02338 KJS_BREAKPOINT; 02339 02340 Value dummy; 02341 02342 if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration()) 02343 return Completion(Throw, 02344 throwError(exec, SyntaxError, "continue used outside of iteration statement")); 02345 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident)) 02346 return Completion(Throw, 02347 throwError(exec, SyntaxError, "Label %s not found in containing block. Can't continue.", ident)); 02348 else 02349 return Completion(Continue, dummy, ident); 02350 } 02351 02352 // ----------------------------- BreakNode ------------------------------------ 02353 02354 // ECMA 12.8 02355 Completion BreakNode::execute(ExecState *exec) 02356 { 02357 KJS_BREAKPOINT; 02358 02359 Value dummy; 02360 02361 if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration() && 02362 !exec->context().imp()->seenLabels()->inSwitch()) 02363 return Completion(Throw, 02364 throwError(exec, SyntaxError, "break used outside of iteration or switch statement")); 02365 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident)) 02366 return Completion(Throw, 02367 throwError(exec, SyntaxError, "Label %s not found in containing block. Can't break.", ident)); 02368 else 02369 return Completion(Break, dummy, ident); 02370 } 02371 02372 // ----------------------------- ReturnNode ----------------------------------- 02373 02374 void ReturnNode::ref() 02375 { 02376 StatementNode::ref(); 02377 if ( value ) 02378 value->ref(); 02379 } 02380 02381 bool ReturnNode::deref() 02382 { 02383 if ( value && value->deref() ) 02384 delete value; 02385 return StatementNode::deref(); 02386 } 02387 02388 // ECMA 12.9 02389 Completion ReturnNode::execute(ExecState *exec) 02390 { 02391 KJS_BREAKPOINT; 02392 02393 CodeType codeType = exec->context().imp()->codeType(); 02394 if (codeType != FunctionCode) { 02395 return Completion(Throw, throwError(exec, SyntaxError, "Invalid return statement.")); 02396 } 02397 02398 if (!value) 02399 return Completion(ReturnValue, Undefined()); 02400 02401 Value v = value->evaluate(exec); 02402 KJS_CHECKEXCEPTION 02403 02404 return Completion(ReturnValue, v); 02405 } 02406 02407 // ----------------------------- WithNode ------------------------------------- 02408 02409 void WithNode::ref() 02410 { 02411 StatementNode::ref(); 02412 if ( statement ) 02413 statement->ref(); 02414 if ( expr ) 02415 expr->ref(); 02416 } 02417 02418 bool WithNode::deref() 02419 { 02420 if ( statement && statement->deref() ) 02421 delete statement; 02422 if ( expr && expr->deref() ) 02423 delete expr; 02424 return StatementNode::deref(); 02425 } 02426 02427 // ECMA 12.10 02428 Completion WithNode::execute(ExecState *exec) 02429 { 02430 KJS_BREAKPOINT; 02431 02432 Value v = expr->evaluate(exec); 02433 KJS_CHECKEXCEPTION 02434 Object o = v.toObject(exec); 02435 KJS_CHECKEXCEPTION 02436 exec->context().imp()->pushScope(o); 02437 Completion res = statement->execute(exec); 02438 exec->context().imp()->popScope(); 02439 02440 return res; 02441 } 02442 02443 void WithNode::processVarDecls(ExecState *exec) 02444 { 02445 statement->processVarDecls(exec); 02446 } 02447 02448 // ----------------------------- CaseClauseNode ------------------------------- 02449 02450 void CaseClauseNode::ref() 02451 { 02452 Node::ref(); 02453 if ( expr ) 02454 expr->ref(); 02455 if ( list ) 02456 list->ref(); 02457 } 02458 02459 bool CaseClauseNode::deref() 02460 { 02461 if ( expr && expr->deref() ) 02462 delete expr; 02463 if ( list && list->deref() ) 02464 delete list; 02465 return Node::deref(); 02466 } 02467 02468 // ECMA 12.11 02469 Value CaseClauseNode::evaluate(ExecState *exec) const 02470 { 02471 Value v = expr->evaluate(exec); 02472 KJS_CHECKEXCEPTIONVALUE 02473 02474 return v; 02475 } 02476 02477 // ECMA 12.11 02478 Completion CaseClauseNode::evalStatements(ExecState *exec) const 02479 { 02480 if (list) 02481 return list->execute(exec); 02482 else 02483 return Completion(Normal, Undefined()); 02484 } 02485 02486 void CaseClauseNode::processVarDecls(ExecState *exec) 02487 { 02488 if (list) 02489 list->processVarDecls(exec); 02490 } 02491 02492 // ----------------------------- ClauseListNode ------------------------------- 02493 02494 void ClauseListNode::ref() 02495 { 02496 for (ClauseListNode *n = this; n; n = n->nx) { 02497 n->Node::ref(); 02498 if (n->cl) 02499 n->cl->ref(); 02500 } 02501 } 02502 02503 bool ClauseListNode::deref() 02504 { 02505 ClauseListNode *next; 02506 for (ClauseListNode *n = this; n; n = next) { 02507 next = n->nx; 02508 if (n->cl && n->cl->deref()) 02509 delete n->cl; 02510 if (n != this && n->Node::deref()) 02511 delete n; 02512 } 02513 return Node::deref(); 02514 } 02515 02516 Value ClauseListNode::evaluate(ExecState * /*exec*/) const 02517 { 02518 /* should never be called */ 02519 assert(false); 02520 return Value(); 02521 } 02522 02523 // ECMA 12.11 02524 void ClauseListNode::processVarDecls(ExecState *exec) 02525 { 02526 for (ClauseListNode *n = this; n; n = n->nx) 02527 if (n->cl) 02528 n->cl->processVarDecls(exec); 02529 } 02530 02531 // ----------------------------- CaseBlockNode -------------------------------- 02532 02533 CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, 02534 ClauseListNode *l2) 02535 { 02536 def = d; 02537 if (l1) { 02538 list1 = l1->nx; 02539 l1->nx = 0; 02540 } else { 02541 list1 = 0; 02542 } 02543 if (l2) { 02544 list2 = l2->nx; 02545 l2->nx = 0; 02546 } else { 02547 list2 = 0; 02548 } 02549 } 02550 02551 void CaseBlockNode::ref() 02552 { 02553 Node::ref(); 02554 if ( def ) 02555 def->ref(); 02556 if ( list1 ) 02557 list1->ref(); 02558 if ( list2 ) 02559 list2->ref(); 02560 } 02561 02562 bool CaseBlockNode::deref() 02563 { 02564 if ( def && def->deref() ) 02565 delete def; 02566 if ( list1 && list1->deref() ) 02567 delete list1; 02568 if ( list2 && list2->deref() ) 02569 delete list2; 02570 return Node::deref(); 02571 } 02572 02573 Value CaseBlockNode::evaluate(ExecState * /*exec*/) const 02574 { 02575 /* should never be called */ 02576 assert(false); 02577 return Value(); 02578 } 02579 02580 // ECMA 12.11 02581 Completion CaseBlockNode::evalBlock(ExecState *exec, const Value& input) const 02582 { 02583 Value v; 02584 Completion res; 02585 ClauseListNode *a = list1, *b = list2; 02586 CaseClauseNode *clause; 02587 02588 while (a) { 02589 clause = a->clause(); 02590 a = a->next(); 02591 v = clause->evaluate(exec); 02592 KJS_CHECKEXCEPTION 02593 if (strictEqual(exec, input, v)) { 02594 res = clause->evalStatements(exec); 02595 if (res.complType() != Normal) 02596 return res; 02597 while (a) { 02598 res = a->clause()->evalStatements(exec); 02599 if (res.complType() != Normal) 02600 return res; 02601 a = a->next(); 02602 } 02603 break; 02604 } 02605 } 02606 02607 while (b) { 02608 clause = b->clause(); 02609 b = b->next(); 02610 v = clause->evaluate(exec); 02611 KJS_CHECKEXCEPTION 02612 if (strictEqual(exec, input, v)) { 02613 res = clause->evalStatements(exec); 02614 if (res.complType() != Normal) 02615 return res; 02616 goto step18; 02617 } 02618 } 02619 02620 // default clause 02621 if (def) { 02622 res = def->evalStatements(exec); 02623 if (res.complType() != Normal) 02624 return res; 02625 } 02626 b = list2; 02627 step18: 02628 while (b) { 02629 clause = b->clause(); 02630 res = clause->evalStatements(exec); 02631 if (res.complType() != Normal) 02632 return res; 02633 b = b->next(); 02634 } 02635 02636 // bail out on error 02637 KJS_CHECKEXCEPTION 02638 02639 return Completion(Normal); 02640 } 02641 02642 void CaseBlockNode::processVarDecls(ExecState *exec) 02643 { 02644 if (list1) 02645 list1->processVarDecls(exec); 02646 if (def) 02647 def->processVarDecls(exec); 02648 if (list2) 02649 list2->processVarDecls(exec); 02650 } 02651 02652 // ----------------------------- SwitchNode ----------------------------------- 02653 02654 void SwitchNode::ref() 02655 { 02656 StatementNode::ref(); 02657 if ( expr ) 02658 expr->ref(); 02659 if ( block ) 02660 block->ref(); 02661 } 02662 02663 bool SwitchNode::deref() 02664 { 02665 if ( expr && expr->deref() ) 02666 delete expr; 02667 if ( block && block->deref() ) 02668 delete block; 02669 return StatementNode::deref(); 02670 } 02671 02672 // ECMA 12.11 02673 Completion SwitchNode::execute(ExecState *exec) 02674 { 02675 KJS_BREAKPOINT; 02676 02677 Value v = expr->evaluate(exec); 02678 KJS_CHECKEXCEPTION 02679 exec->context().imp()->seenLabels()->pushSwitch(); 02680 Completion res = block->evalBlock(exec,v); 02681 exec->context().imp()->seenLabels()->popSwitch(); 02682 02683 if ((res.complType() == Break) && ls.contains(res.target())) 02684 return Completion(Normal, res.value()); 02685 else 02686 return res; 02687 } 02688 02689 void SwitchNode::processVarDecls(ExecState *exec) 02690 { 02691 block->processVarDecls(exec); 02692 } 02693 02694 // ----------------------------- LabelNode ------------------------------------ 02695 02696 void LabelNode::ref() 02697 { 02698 StatementNode::ref(); 02699 if ( statement ) 02700 statement->ref(); 02701 } 02702 02703 bool LabelNode::deref() 02704 { 02705 if ( statement && statement->deref() ) 02706 delete statement; 02707 return StatementNode::deref(); 02708 } 02709 02710 // ECMA 12.12 02711 Completion LabelNode::execute(ExecState *exec) 02712 { 02713 Completion e; 02714 02715 if (!exec->context().imp()->seenLabels()->push(label)) { 02716 return Completion( Throw, 02717 throwError(exec, SyntaxError, "Duplicated label %s found.", label)); 02718 }; 02719 e = statement->execute(exec); 02720 exec->context().imp()->seenLabels()->pop(); 02721 02722 if ((e.complType() == Break) && (e.target() == label)) 02723 return Completion(Normal, e.value()); 02724 else 02725 return e; 02726 } 02727 02728 void LabelNode::processVarDecls(ExecState *exec) 02729 { 02730 statement->processVarDecls(exec); 02731 } 02732 02733 // ----------------------------- ThrowNode ------------------------------------ 02734 02735 void ThrowNode::ref() 02736 { 02737 StatementNode::ref(); 02738 if ( expr ) 02739 expr->ref(); 02740 } 02741 02742 bool ThrowNode::deref() 02743 { 02744 if ( expr && expr->deref() ) 02745 delete expr; 02746 return StatementNode::deref(); 02747 } 02748 02749 // ECMA 12.13 02750 Completion ThrowNode::execute(ExecState *exec) 02751 { 02752 KJS_BREAKPOINT; 02753 02754 Value v = expr->evaluate(exec); 02755 KJS_CHECKEXCEPTION 02756 02757 // bail out on error 02758 KJS_CHECKEXCEPTION 02759 02760 Debugger *dbg = exec->interpreter()->imp()->debugger(); 02761 if (dbg) 02762 dbg->exception(exec,v,exec->context().imp()->inTryCatch()); 02763 02764 return Completion(Throw, v); 02765 } 02766 02767 // ----------------------------- CatchNode ------------------------------------ 02768 02769 void CatchNode::ref() 02770 { 02771 StatementNode::ref(); 02772 if ( block ) 02773 block->ref(); 02774 } 02775 02776 bool CatchNode::deref() 02777 { 02778 if ( block && block->deref() ) 02779 delete block; 02780 return StatementNode::deref(); 02781 } 02782 02783 Completion CatchNode::execute(ExecState * /*exec*/) 02784 { 02785 // should never be reached. execute(exec, arg) is used instead 02786 assert(0L); 02787 return Completion(); 02788 } 02789 02790 // ECMA 12.14 02791 Completion CatchNode::execute(ExecState *exec, const Value &arg) 02792 { 02793 /* TODO: correct ? Not part of the spec */ 02794 02795 exec->clearException(); 02796 02797 Object obj(new ObjectImp()); 02798 obj.put(exec, ident, arg, DontDelete); 02799 exec->context().imp()->pushScope(obj); 02800 Completion c = block->execute(exec); 02801 exec->context().imp()->popScope(); 02802 02803 return c; 02804 } 02805 02806 void CatchNode::processVarDecls(ExecState *exec) 02807 { 02808 block->processVarDecls(exec); 02809 } 02810 02811 // ----------------------------- FinallyNode ---------------------------------- 02812 02813 void FinallyNode::ref() 02814 { 02815 StatementNode::ref(); 02816 if ( block ) 02817 block->ref(); 02818 } 02819 02820 bool FinallyNode::deref() 02821 { 02822 if ( block && block->deref() ) 02823 delete block; 02824 return StatementNode::deref(); 02825 } 02826 02827 // ECMA 12.14 02828 Completion FinallyNode::execute(ExecState *exec) 02829 { 02830 return block->execute(exec); 02831 } 02832 02833 void FinallyNode::processVarDecls(ExecState *exec) 02834 { 02835 block->processVarDecls(exec); 02836 } 02837 02838 // ----------------------------- TryNode -------------------------------------- 02839 02840 void TryNode::ref() 02841 { 02842 StatementNode::ref(); 02843 if ( block ) 02844 block->ref(); 02845 if ( _final ) 02846 _final->ref(); 02847 if ( _catch ) 02848 _catch->ref(); 02849 } 02850 02851 bool TryNode::deref() 02852 { 02853 if ( block && block->deref() ) 02854 delete block; 02855 if ( _final && _final->deref() ) 02856 delete _final; 02857 if ( _catch && _catch->deref() ) 02858 delete _catch; 02859 return StatementNode::deref(); 02860 } 02861 02862 // ECMA 12.14 02863 Completion TryNode::execute(ExecState *exec) 02864 { 02865 KJS_BREAKPOINT; 02866 02867 Completion c, c2; 02868 02869 if (_catch) 02870 exec->context().imp()->pushTryCatch(); 02871 c = block->execute(exec); 02872 if (_catch) 02873 exec->context().imp()->popTryCatch(); 02874 02875 if (!_final) { 02876 if (c.complType() != Throw) 02877 return c; 02878 return _catch->execute(exec,c.value()); 02879 } 02880 02881 if (!_catch) { 02882 Value exception = exec->_exception; 02883 exec->_exception = Value(); 02884 02885 c2 = _final->execute(exec); 02886 02887 if (!exec->hadException() && c2.complType() != Throw) 02888 exec->_exception = exception; 02889 02890 return (c2.complType() == Normal) ? c : c2; 02891 } 02892 02893 if (c.complType() == Throw) 02894 c = _catch->execute(exec,c.value()); 02895 02896 c2 = _final->execute(exec); 02897 return (c2.complType() == Normal) ? c : c2; 02898 } 02899 02900 void TryNode::processVarDecls(ExecState *exec) 02901 { 02902 block->processVarDecls(exec); 02903 if (_final) 02904 _final->processVarDecls(exec); 02905 if (_catch) 02906 _catch->processVarDecls(exec); 02907 } 02908 02909 // ----------------------------- ParameterNode -------------------------------- 02910 02911 void ParameterNode::ref() 02912 { 02913 for (ParameterNode *n = this; n; n = n->next) 02914 n->Node::ref(); 02915 } 02916 02917 bool ParameterNode::deref() 02918 { 02919 ParameterNode *next; 02920 for (ParameterNode *n = this; n; n = next) { 02921 next = n->next; 02922 if (n != this && n->Node::deref()) 02923 delete n; 02924 } 02925 return Node::deref(); 02926 } 02927 02928 // ECMA 13 02929 Value ParameterNode::evaluate(ExecState * /*exec*/) const 02930 { 02931 return Undefined(); 02932 } 02933 02934 // ----------------------------- FunctionBodyNode ----------------------------- 02935 02936 02937 FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s) 02938 : BlockNode(s) 02939 { 02940 //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this); 02941 } 02942 02943 void FunctionBodyNode::processFuncDecl(ExecState *exec) 02944 { 02945 if (source) 02946 source->processFuncDecl(exec); 02947 } 02948 02949 // ----------------------------- FuncDeclNode --------------------------------- 02950 02951 void FuncDeclNode::ref() 02952 { 02953 StatementNode::ref(); 02954 if ( param ) 02955 param->ref(); 02956 if ( body ) 02957 body->ref(); 02958 } 02959 02960 bool FuncDeclNode::deref() 02961 { 02962 if ( param && param->deref() ) 02963 delete param; 02964 if ( body && body->deref() ) 02965 delete body; 02966 return StatementNode::deref(); 02967 } 02968 02969 // ECMA 13 02970 void FuncDeclNode::processFuncDecl(ExecState *exec) 02971 { 02972 ContextImp *ctx = exec->context().imp(); 02973 // TODO: let this be an object with [[Class]] property "Function" 02974 FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain()); 02975 Object func(fimp); // protect from GC 02976 02977 // Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty()); 02978 List empty; 02979 Object proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty); 02980 proto.put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum); 02981 func.put(exec, prototypePropertyName, proto, Internal|DontDelete); 02982 02983 int plen = 0; 02984 for(const ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++) 02985 fimp->addParameter(p->ident()); 02986 02987 func.put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum); 02988 02989 #ifdef KJS_VERBOSE 02990 fprintf(stderr,"KJS: new function %s in %p\n", ident.ustring().cstring().c_str(), ctx->variableObject().imp()); 02991 #endif 02992 if (exec->_context->codeType() == EvalCode) { 02993 // ECMA 10.2.2 02994 ctx->variableObject().put(exec, ident, func, Internal); 02995 } else { 02996 ctx->variableObject().put(exec, ident, func, DontDelete | Internal); 02997 } 02998 02999 if (body) { 03000 // hack the scope so that the function gets put as a property of func, and it's scope 03001 // contains the func as well as our current scope 03002 Object oldVar = ctx->variableObject(); 03003 ctx->setVariableObject(func); 03004 ctx->pushScope(func); 03005 body->processFuncDecl(exec); 03006 ctx->popScope(); 03007 ctx->setVariableObject(oldVar); 03008 } 03009 } 03010 03011 // ----------------------------- FuncExprNode --------------------------------- 03012 03013 void FuncExprNode::ref() 03014 { 03015 Node::ref(); 03016 if ( param ) 03017 param->ref(); 03018 if ( body ) 03019 body->ref(); 03020 } 03021 03022 bool FuncExprNode::deref() 03023 { 03024 if ( param && param->deref() ) 03025 delete param; 03026 if ( body && body->deref() ) 03027 delete body; 03028 return Node::deref(); 03029 } 03030 03031 03032 // ECMA 13 03033 Value FuncExprNode::evaluate(ExecState *exec) const 03034 { 03035 ContextImp *context = exec->context().imp(); 03036 bool named = !ident.isNull(); 03037 Object functionScopeObject; 03038 03039 if (named) { 03040 // named FunctionExpressions can recursively call themselves, 03041 // but they won't register with the current scope chain and should 03042 // be contained as single property in an anonymous object. 03043 functionScopeObject = Object(new ObjectImp()); 03044 context->pushScope(functionScopeObject); 03045 } 03046 03047 FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), body, exec->context().imp()->scopeChain()); 03048 Value ret(fimp); 03049 List empty; 03050 Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty); 03051 fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete); 03052 03053 for(const ParameterNode *p = param; p != 0L; p = p->nextParam()) 03054 fimp->addParameter(p->ident()); 03055 03056 if (named) { 03057 functionScopeObject.put(exec, ident, Value(fimp), ReadOnly|DontDelete); 03058 context->popScope(); 03059 } 03060 03061 return ret; 03062 } 03063 03064 // ----------------------------- SourceElementsNode --------------------------- 03065 03066 SourceElementsNode::SourceElementsNode(StatementNode *s1) 03067 { 03068 element = s1; 03069 elements = this; 03070 setLoc(s1->firstLine(), s1->lastLine(), s1->code()); 03071 } 03072 03073 SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2) 03074 { 03075 elements = s1->elements; 03076 s1->elements = this; 03077 element = s2; 03078 setLoc(s1->firstLine(), s2->lastLine(), s1->code()); 03079 } 03080 03081 void SourceElementsNode::ref() 03082 { 03083 for (SourceElementsNode *n = this; n; n = n->elements) { 03084 n->Node::ref(); 03085 if (n->element) 03086 n->element->ref(); 03087 } 03088 } 03089 03090 bool SourceElementsNode::deref() 03091 { 03092 SourceElementsNode *next; 03093 for (SourceElementsNode *n = this; n; n = next) { 03094 next = n->elements; 03095 if (n->element && n->element->deref()) 03096 delete n->element; 03097 if (n != this && n->Node::deref()) 03098 delete n; 03099 } 03100 return StatementNode::deref(); 03101 } 03102 03103 // ECMA 14 03104 Completion SourceElementsNode::execute(ExecState *exec) 03105 { 03106 KJS_CHECKEXCEPTION 03107 03108 Completion c1 = element->execute(exec); 03109 KJS_CHECKEXCEPTION; 03110 if (c1.complType() != Normal) 03111 return c1; 03112 03113 for (SourceElementsNode *n = elements; n; n = n->elements) { 03114 Completion c2 = n->element->execute(exec); 03115 if (c2.complType() != Normal) 03116 return c2; 03117 // The spec says to return c2 here, but it seems that mozilla returns c1 if 03118 // c2 doesn't have a value 03119 if (c2.value().isValid()) 03120 c1 = c2; 03121 } 03122 03123 return c1; 03124 } 03125 03126 // ECMA 14 03127 void SourceElementsNode::processFuncDecl(ExecState *exec) 03128 { 03129 for (SourceElementsNode *n = this; n; n = n->elements) 03130 n->element->processFuncDecl(exec); 03131 } 03132 03133 void SourceElementsNode::processVarDecls(ExecState *exec) 03134 { 03135 for (SourceElementsNode *n = this; n; n = n->elements) 03136 n->element->processVarDecls(exec); 03137 }