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