kjs Library API Documentation

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