source: webkit/trunk/JavaScriptCore/kjs/nodes.cpp@ 7239

Last change on this file since 7239 was 7239, checked in by darin, 21 years ago

Reviewed by Ken.

  • fixed 43 Mozilla JavaScript tests
  • kjs/date_object.h: Change parseDate and timeClip to take and return doubles.
  • kjs/date_object.cpp: (DateObjectImp::construct): Change to use a timeClip function that takes and returns a double rather than constructing a number object to pass to it. (DateObjectFuncImp::call): Change to use a parseDate function that returns a double. (KJS::parseDate): Change to return a double instead of creating the Number object here. (KJS::timeClip): Implement this as specified in the language standard.
  • kjs/error_object.cpp: (NativeErrorImp::NativeErrorImp): Set the DontDelete, ReadOnly, and DontEnum flags on the prototype property.
  • kjs/function.cpp: (KJS::FunctionImp::get): Return null rather than undefined for arguments when the function is not currently in scope. (KJS::isStrWhiteSpace): Added. Matches specification for StrWhiteSpace. Could move it to some utility file later. (KJS::parseDigit): Added. Helper function for parseInt. (KJS::parseInt): Added. Integer parser that puts result in a double so we're not limited to what strtoll can handle. Also matches standard more closely. (KJS::parseFloat): Added. Handles "0x" properly and passes flag to make empty string turn into NaN instead of 0. (KJS::GlobalFuncImp::call): Use the new parseInt and parseFloat.
  • kjs/function_object.cpp: (FunctionPrototypeImp::FunctionPrototypeImp): Add a length property.
  • kjs/lexer.h: Added error flag and sawError() function for detecting errors.
  • kjs/lexer.cpp: (Lexer::setCode): Clear error state. (Lexer::lex): Set error state if the lexer encounters an error
  • kjs/internal.cpp: (NumberImp::toString): Roll in change from KDE version to special case 0 so we handle -0 correctly. (Parser::parse): Use new lexer error method so those errors are treated like parser errors.
  • kjs/math_object.cpp: (MathFuncImp::call): Change min and max to treat -0 as less than +0. Change round to round values between -0.5 and -0 to -0 instead of +0.
  • kjs/nodes.h: Add evaluateReference function to GroupNode.
  • kjs/nodes.cpp: (GroupNode::evaluateReference): Pass references through groups (parenthesized expressions) properly so that expressions like "delete (x.y)" work. Before, the parentheses would change x.y into a value that can't be deleted as a side effect.
  • kjs/string_object.cpp: Change parameter count for indexOf and lastIndexOf from 2 to 1 to match the specification.
  • kjs/testkjs.cpp: Rolled in changes from KDE to add a "quit" function to the test tool and get rid of the fixed size limit for code.
  • kjs/ustring.cpp: (KJS::UString::substr): Added optimized case for substr(0, length) so it just returns the string without creating a new Rep, since I'm using substr in a place where it will often be passed a 0.
  • tests/mozilla/ecma/String/15.5.4.11-1.js: Fixed one wrong entry in the Unicode table I added to the other day that was making a couple tests fail.
  • tests/mozilla/ecma/String/15.5.4.12-1.js: Ditto.
  • tests/mozilla/ecma/String/15.5.4.12-2.js: Ditto.
  • tests/mozilla/ecma/String/15.5.4.12-3.js: Ditto.
  • tests/mozilla/ecma/String/15.5.4.12-4.js: Ditto.
  • tests/mozilla/ecma/String/15.5.4.12-5.js: Ditto.
  • kjs/string_object.lut.h: Regenerated.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.6 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2002 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
6 * Copyright (C) 2003 Apple Computer, Inc.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 *
23 */
24
25#include "nodes.h"
26
27//#include <iostream>
28#include <math.h>
29#include <assert.h>
30#ifdef KJS_DEBUG_MEM
31#include <stdio.h>
32#include <typeinfo>
33#endif
34
35#include "collector.h"
36#include "context.h"
37#include "debugger.h"
38#include "function_object.h"
39#include "internal.h"
40#include "value.h"
41#include "object.h"
42#include "types.h"
43#include "interpreter.h"
44#include "lexer.h"
45#include "operations.h"
46#include "ustring.h"
47
48using namespace KJS;
49
50#define KJS_BREAKPOINT \
51 if (!hitStatement(exec)) \
52 return Completion(Normal);
53
54#define KJS_ABORTPOINT \
55 if (exec->dynamicInterpreter()->imp()->debugger() && \
56 exec->dynamicInterpreter()->imp()->debugger()->imp()->aborted()) \
57 return Completion(Normal);
58
59#define KJS_CHECKEXCEPTION \
60 if (exec->hadException()) \
61 return Completion(Throw, exec->exception()); \
62 if (Collector::outOfMemory()) \
63 return Completion(Throw, Error::create(exec,GeneralError,"Out of memory"));
64
65#define KJS_CHECKEXCEPTIONVALUE \
66 if (exec->hadException()) \
67 return exec->exception(); \
68 if (Collector::outOfMemory()) \
69 return Undefined(); // will be picked up by KJS_CHECKEXCEPTION
70
71#define KJS_CHECKEXCEPTIONREFERENCE \
72 if (exec->hadException()) \
73 return Reference::makeValueReference(Undefined());; \
74 if (Collector::outOfMemory()) \
75 return Reference::makeValueReference(Undefined()); // will be picked up by KJS_CHECKEXCEPTION
76
77#define KJS_CHECKEXCEPTIONLIST \
78 if (exec->hadException()) \
79 return List(); \
80 if (Collector::outOfMemory()) \
81 return List(); // will be picked up by KJS_CHECKEXCEPTION
82
83#ifdef KJS_DEBUG_MEM
84std::list<Node *> * Node::s_nodes = 0L;
85#endif
86
87// ------------------------------ Node -----------------------------------------
88
89Node::Node()
90{
91 line = Lexer::curr()->lineNo();
92 sourceURL = Lexer::curr()->sourceURL();
93 refcount = 0;
94#ifdef KJS_DEBUG_MEM
95 if (!s_nodes)
96 s_nodes = new std::list<Node *>;
97 s_nodes->push_back(this);
98#endif
99}
100
101Node::~Node()
102{
103#ifdef KJS_DEBUG_MEM
104 s_nodes->remove( this );
105#endif
106}
107
108Reference Node::evaluateReference(ExecState *exec)
109{
110 Value v = evaluate(exec);
111 KJS_CHECKEXCEPTIONREFERENCE
112 return Reference::makeValueReference(v);
113}
114
115#ifdef KJS_DEBUG_MEM
116void Node::finalCheck()
117{
118 fprintf( stderr, "Node::finalCheck(): list count : %d\n", (int)s_nodes.size() );
119 std::list<Node *>::iterator it = s_nodes->begin();
120 for ( uint i = 0; it != s_nodes->end() ; ++it, ++i )
121 fprintf( stderr, "[%d] Still having node %p (%s) (refcount %d)\n", i, (void*)*it, typeid( **it ).name(), (*it)->refcount );
122 delete s_nodes;
123 s_nodes = 0L;
124}
125#endif
126
127Value Node::throwError(ExecState *exec, ErrorType e, const char *msg)
128{
129 Object err = Error::create(exec, e, msg, lineNo(), sourceId(), &sourceURL);
130 exec->setException(err);
131 return err;
132}
133
134Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Value v, Node *expr)
135{
136 char *vStr = strdup(v.toString(exec).ascii());
137 char *exprStr = strdup(expr->toString().ascii());
138
139 int length = strlen(msg) - 4 /* two %s */ + strlen(vStr) + strlen(exprStr) + 1 /* null terminator */;
140 char *str = new char[length];
141 sprintf(str, msg, vStr, exprStr);
142 free(vStr);
143 free(exprStr);
144
145 Value result = throwError(exec, e, str);
146 delete [] str;
147
148 return result;
149}
150
151
152Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Identifier label)
153{
154 const char *l = label.ascii();
155 int length = strlen(msg) - 2 /* %s */ + strlen(l) + 1 /* null terminator */;
156 char *message = new char[length];
157 sprintf(message, msg, l);
158
159 Value result = throwError(exec, e, message);
160 delete [] message;
161
162 return result;
163}
164
165// ------------------------------ StatementNode --------------------------------
166StatementNode::StatementNode() : l0(-1), l1(-1), sid(-1), breakPoint(false)
167{
168}
169
170void StatementNode::setLoc(int line0, int line1, int sourceId)
171{
172 l0 = line0;
173 l1 = line1;
174 sid = sourceId;
175}
176
177// return true if the debugger wants us to stop at this point
178bool StatementNode::hitStatement(ExecState *exec)
179{
180 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
181 if (dbg)
182 return dbg->atStatement(exec,sid,l0,l1);
183 else
184 return true; // continue
185}
186
187// return true if the debugger wants us to stop at this point
188bool StatementNode::abortStatement(ExecState *exec)
189{
190 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
191 if (dbg)
192 return dbg->imp()->aborted();
193 else
194 return false;
195}
196
197void StatementNode::processFuncDecl(ExecState *exec)
198{
199}
200
201// ------------------------------ NullNode -------------------------------------
202
203Value NullNode::evaluate(ExecState */*exec*/)
204{
205 return Null();
206}
207
208// ------------------------------ BooleanNode ----------------------------------
209
210Value BooleanNode::evaluate(ExecState */*exec*/)
211{
212 return Boolean(value);
213}
214
215// ------------------------------ NumberNode -----------------------------------
216
217Value NumberNode::evaluate(ExecState */*exec*/)
218{
219 return Number(value);
220}
221
222// ------------------------------ StringNode -----------------------------------
223
224Value StringNode::evaluate(ExecState */*exec*/)
225{
226 return String(value);
227}
228
229// ------------------------------ RegExpNode -----------------------------------
230
231Value RegExpNode::evaluate(ExecState *exec)
232{
233 List list;
234 String p(pattern);
235 String f(flags);
236 list.append(p);
237 list.append(f);
238
239 Object reg = exec->lexicalInterpreter()->imp()->builtinRegExp();
240 return reg.construct(exec,list);
241}
242
243// ------------------------------ ThisNode -------------------------------------
244
245// ECMA 11.1.1
246Value ThisNode::evaluate(ExecState *exec)
247{
248 return exec->context().imp()->thisValue();
249}
250
251// ------------------------------ ResolveNode ----------------------------------
252
253// ECMA 11.1.2 & 10.1.4
254Value ResolveNode::evaluate(ExecState *exec)
255{
256 return evaluateReference(exec).getValue(exec);
257}
258
259Reference ResolveNode::evaluateReference(ExecState *exec)
260{
261 ScopeChain chain = exec->context().imp()->scopeChain();
262
263 while (!chain.isEmpty()) {
264 ObjectImp *o = chain.top();
265
266 //cout << "Resolve: looking at '" << ident.ascii() << "'"
267 // << " in " << (void*)o << " " << o->classInfo()->className << endl;
268 if (o->hasProperty(exec,ident)) {
269 //cout << "Resolve: FOUND '" << ident.ascii() << "'"
270 // << " in " << (void*)o << " " << o->classInfo()->className << endl;
271 return Reference(o, ident);
272 }
273
274 chain.pop();
275 }
276
277 // identifier not found
278 //cout << "Resolve: didn't find '" << ident.ascii() << "'" << endl;
279 return Reference(Null(), ident);
280}
281
282
283// ------------------------------ GroupNode ------------------------------------
284
285void GroupNode::ref()
286{
287 Node::ref();
288 if ( group )
289 group->ref();
290}
291
292bool GroupNode::deref()
293{
294 if ( group && group->deref() )
295 delete group;
296 return Node::deref();
297}
298
299// ECMA 11.1.6
300Value GroupNode::evaluate(ExecState *exec)
301{
302 return group->evaluate(exec);
303}
304
305Reference GroupNode::evaluateReference(ExecState *exec)
306{
307 return group->evaluateReference(exec);
308}
309
310// ------------------------------ ElementNode ----------------------------------
311
312void ElementNode::ref()
313{
314 for (ElementNode *n = this; n; n = n->list) {
315 n->Node::ref();
316 if (n->node)
317 n->node->ref();
318 }
319}
320
321bool ElementNode::deref()
322{
323 ElementNode *next;
324 for (ElementNode *n = this; n; n = next) {
325 next = n->list;
326 if (n->node && n->node->deref())
327 delete n->node;
328 if (n != this && n->Node::deref())
329 delete n;
330 }
331 return Node::deref();
332}
333
334// ECMA 11.1.4
335Value ElementNode::evaluate(ExecState *exec)
336{
337 Object array = exec->lexicalInterpreter()->builtinArray().construct(exec, List::empty());
338 int length = 0;
339 for (ElementNode *n = this; n; n = n->list) {
340 Value val = n->node->evaluate(exec);
341 KJS_CHECKEXCEPTIONVALUE
342 length += n->elision;
343 array.put(exec, length++, val);
344 }
345 return array;
346}
347
348// ------------------------------ ArrayNode ------------------------------------
349
350void ArrayNode::ref()
351{
352 Node::ref();
353 if ( element )
354 element->ref();
355}
356
357bool ArrayNode::deref()
358{
359 if ( element && element->deref() )
360 delete element;
361 return Node::deref();
362}
363
364// ECMA 11.1.4
365Value ArrayNode::evaluate(ExecState *exec)
366{
367 Object array;
368 int length;
369
370 if (element) {
371 array = Object(static_cast<ObjectImp*>(element->evaluate(exec).imp()));
372 KJS_CHECKEXCEPTIONVALUE
373 length = opt ? array.get(exec,lengthPropertyName).toInt32(exec) : 0;
374 } else {
375 Value newArr = exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty());
376 array = Object(static_cast<ObjectImp*>(newArr.imp()));
377 length = 0;
378 }
379
380 if (opt)
381 array.put(exec,lengthPropertyName, Number(elision + length), DontEnum | DontDelete);
382
383 return array;
384}
385
386// ------------------------------ ObjectLiteralNode ----------------------------
387
388void ObjectLiteralNode::ref()
389{
390 Node::ref();
391 if ( list )
392 list->ref();
393}
394
395bool ObjectLiteralNode::deref()
396{
397 if ( list && list->deref() )
398 delete list;
399 return Node::deref();
400}
401
402// ECMA 11.1.5
403Value ObjectLiteralNode::evaluate(ExecState *exec)
404{
405 if (list)
406 return list->evaluate(exec);
407
408 return exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty());
409}
410
411// ------------------------------ PropertyValueNode ----------------------------
412
413void PropertyValueNode::ref()
414{
415 for (PropertyValueNode *n = this; n; n = n->list) {
416 n->Node::ref();
417 if (n->name)
418 n->name->ref();
419 if (n->assign)
420 n->assign->ref();
421 }
422}
423
424bool PropertyValueNode::deref()
425{
426 PropertyValueNode *next;
427 for (PropertyValueNode *n = this; n; n = next) {
428 next = n->list;
429 if ( n->name && n->name->deref() )
430 delete n->name;
431 if ( n->assign && n->assign->deref() )
432 delete n->assign;
433 if (n != this && n->Node::deref() )
434 delete n;
435 }
436 return Node::deref();
437}
438
439// ECMA 11.1.5
440Value PropertyValueNode::evaluate(ExecState *exec)
441{
442 Object obj = exec->lexicalInterpreter()->builtinObject().construct(exec, List::empty());
443
444 for (PropertyValueNode *p = this; p; p = p->list) {
445 Value n = p->name->evaluate(exec);
446 KJS_CHECKEXCEPTIONVALUE
447 Value v = p->assign->evaluate(exec);
448 KJS_CHECKEXCEPTIONVALUE
449
450 obj.put(exec, Identifier(n.toString(exec)), v);
451 }
452
453 return obj;
454}
455
456// ------------------------------ PropertyNode ---------------------------------
457
458// ECMA 11.1.5
459Value PropertyNode::evaluate(ExecState */*exec*/)
460{
461 Value s;
462
463 if (str.isNull()) {
464 s = String(UString::from(numeric));
465 } else {
466 s = String(str.ustring());
467 }
468
469 return s;
470}
471
472// ------------------------------ AccessorNode1 --------------------------------
473
474void AccessorNode1::ref()
475{
476 Node::ref();
477 if ( expr1 )
478 expr1->ref();
479 if ( expr2 )
480 expr2->ref();
481}
482
483bool AccessorNode1::deref()
484{
485 if ( expr1 && expr1->deref() )
486 delete expr1;
487 if ( expr2 && expr2->deref() )
488 delete expr2;
489 return Node::deref();
490}
491
492// ECMA 11.2.1a
493Value AccessorNode1::evaluate(ExecState *exec)
494{
495 return evaluateReference(exec).getValue(exec);
496}
497
498Reference AccessorNode1::evaluateReference(ExecState *exec)
499{
500 Value v1 = expr1->evaluate(exec);
501 KJS_CHECKEXCEPTIONREFERENCE
502 Value v2 = expr2->evaluate(exec);
503 KJS_CHECKEXCEPTIONREFERENCE
504 Object o = v1.toObject(exec);
505 unsigned i;
506 if (v2.toUInt32(i))
507 return Reference(o, i);
508 String s = v2.toString(exec);
509 return Reference(o, Identifier(s.value()));
510}
511
512
513// ------------------------------ AccessorNode2 --------------------------------
514
515void AccessorNode2::ref()
516{
517 Node::ref();
518 if ( expr )
519 expr->ref();
520}
521
522bool AccessorNode2::deref()
523{
524 if ( expr && expr->deref() )
525 delete expr;
526 return Node::deref();
527}
528
529// ECMA 11.2.1b
530Value AccessorNode2::evaluate(ExecState *exec)
531{
532 return evaluateReference(exec).getValue(exec);
533}
534
535Reference AccessorNode2::evaluateReference(ExecState *exec)
536{
537 Value v = expr->evaluate(exec);
538 KJS_CHECKEXCEPTIONREFERENCE
539 Object o = v.toObject(exec);
540 return Reference(o, ident);
541}
542
543// ------------------------------ ArgumentListNode -----------------------------
544
545void ArgumentListNode::ref()
546{
547 for (ArgumentListNode *n = this; n; n = n->list) {
548 n->Node::ref();
549 if (n->expr)
550 n->expr->ref();
551 }
552}
553
554bool ArgumentListNode::deref()
555{
556 ArgumentListNode *next;
557 for (ArgumentListNode *n = this; n; n = next) {
558 next = n->list;
559 if (n->expr && n->expr->deref())
560 delete n->expr;
561 if (n != this && n->Node::deref())
562 delete n;
563 }
564 return Node::deref();
565}
566
567Value ArgumentListNode::evaluate(ExecState */*exec*/)
568{
569 assert(0);
570 return Value(); // dummy, see evaluateList()
571}
572
573// ECMA 11.2.4
574List ArgumentListNode::evaluateList(ExecState *exec)
575{
576 List l;
577
578 for (ArgumentListNode *n = this; n; n = n->list) {
579 Value v = n->expr->evaluate(exec);
580 KJS_CHECKEXCEPTIONLIST
581 l.append(v);
582 }
583
584 return l;
585}
586
587// ------------------------------ ArgumentsNode --------------------------------
588
589void ArgumentsNode::ref()
590{
591 Node::ref();
592 if ( list )
593 list->ref();
594}
595
596bool ArgumentsNode::deref()
597{
598 if ( list && list->deref() )
599 delete list;
600 return Node::deref();
601}
602
603Value ArgumentsNode::evaluate(ExecState */*exec*/)
604{
605 assert(0);
606 return Value(); // dummy, see evaluateList()
607}
608
609// ECMA 11.2.4
610List ArgumentsNode::evaluateList(ExecState *exec)
611{
612 if (!list)
613 return List();
614
615 return list->evaluateList(exec);
616}
617
618// ------------------------------ NewExprNode ----------------------------------
619
620// ECMA 11.2.2
621
622void NewExprNode::ref()
623{
624 Node::ref();
625 if ( expr )
626 expr->ref();
627 if ( args )
628 args->ref();
629}
630
631bool NewExprNode::deref()
632{
633 if ( expr && expr->deref() )
634 delete expr;
635 if ( args && args->deref() )
636 delete args;
637 return Node::deref();
638}
639
640Value NewExprNode::evaluate(ExecState *exec)
641{
642 Value v = expr->evaluate(exec);
643 KJS_CHECKEXCEPTIONVALUE
644
645 List argList;
646 if (args) {
647 argList = args->evaluateList(exec);
648 KJS_CHECKEXCEPTIONVALUE
649 }
650
651 if (v.type() != ObjectType) {
652 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr);
653 }
654
655 Object constr = Object(static_cast<ObjectImp*>(v.imp()));
656 if (!constr.implementsConstruct()) {
657 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr);
658 }
659
660 Value res = constr.construct(exec,argList);
661
662 return res;
663}
664
665// ------------------------------ FunctionCallNode -----------------------------
666
667void FunctionCallNode::ref()
668{
669 Node::ref();
670 if ( expr )
671 expr->ref();
672 if ( args )
673 args->ref();
674}
675
676bool FunctionCallNode::deref()
677{
678 if ( expr && expr->deref() )
679 delete expr;
680 if ( args && args->deref() )
681 delete args;
682 return Node::deref();
683}
684
685// ECMA 11.2.3
686Value FunctionCallNode::evaluate(ExecState *exec)
687{
688 Reference ref = expr->evaluateReference(exec);
689 KJS_CHECKEXCEPTIONVALUE
690
691 List argList = args->evaluateList(exec);
692
693 KJS_CHECKEXCEPTIONVALUE
694
695 Value v = ref.getValue(exec);
696
697 if (v.type() != ObjectType) {
698 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, expr);
699 }
700
701 Object func = Object(static_cast<ObjectImp*>(v.imp()));
702
703 if (!func.implementsCall()) {
704 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr);
705 }
706
707 Value thisVal;
708 if (ref.isMutable())
709 thisVal = ref.getBase(exec);
710 else
711 thisVal = Null();
712
713 if (thisVal.type() == ObjectType &&
714 Object::dynamicCast(thisVal).inherits(&ActivationImp::info))
715 thisVal = Null();
716
717 if (thisVal.type() != ObjectType) {
718 // ECMA 11.2.3 says that in this situation the this value should be null.
719 // However, section 10.2.3 says that in the case where the value provided
720 // by the caller is null, the global object should be used. It also says
721 // that the section does not apply to interal functions, but for simplicity
722 // of implementation we use the global object anyway here. This guarantees
723 // that in host objects you always get a valid object for this.
724 // thisVal = Null();
725 thisVal = exec->dynamicInterpreter()->globalObject();
726 }
727
728 Object thisObj = Object::dynamicCast(thisVal);
729 Value result = func.call(exec,thisObj, argList);
730
731 return result;
732}
733
734// ------------------------------ PostfixNode ----------------------------------
735
736void PostfixNode::ref()
737{
738 Node::ref();
739 if ( expr )
740 expr->ref();
741}
742
743bool PostfixNode::deref()
744{
745 if ( expr && expr->deref() )
746 delete expr;
747 return Node::deref();
748}
749
750// ECMA 11.3
751Value PostfixNode::evaluate(ExecState *exec)
752{
753 Reference ref = expr->evaluateReference(exec);
754 KJS_CHECKEXCEPTIONVALUE
755 Value v = ref.getValue(exec);
756 Number n = v.toNumber(exec);
757
758 double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
759 Value n2 = Number(newValue);
760
761 ref.putValue(exec,n2);
762
763 return n;
764}
765
766// ------------------------------ DeleteNode -----------------------------------
767
768void DeleteNode::ref()
769{
770 Node::ref();
771 if ( expr )
772 expr->ref();
773}
774
775bool DeleteNode::deref()
776{
777 if ( expr && expr->deref() )
778 delete expr;
779 return Node::deref();
780}
781
782// ECMA 11.4.1
783Value DeleteNode::evaluate(ExecState *exec)
784{
785 Reference ref = expr->evaluateReference(exec);
786 KJS_CHECKEXCEPTIONVALUE
787 return Boolean(ref.deleteValue(exec));
788}
789
790// ------------------------------ VoidNode -------------------------------------
791
792void VoidNode::ref()
793{
794 Node::ref();
795 if ( expr )
796 expr->ref();
797}
798
799bool VoidNode::deref()
800{
801 if ( expr && expr->deref() )
802 delete expr;
803 return Node::deref();
804}
805
806// ECMA 11.4.2
807Value VoidNode::evaluate(ExecState *exec)
808{
809 Value dummy1 = expr->evaluate(exec);
810 KJS_CHECKEXCEPTIONVALUE
811
812 return Undefined();
813}
814
815// ------------------------------ TypeOfNode -----------------------------------
816
817void TypeOfNode::ref()
818{
819 Node::ref();
820 if ( expr )
821 expr->ref();
822}
823
824bool TypeOfNode::deref()
825{
826 if ( expr && expr->deref() )
827 delete expr;
828 return Node::deref();
829}
830
831// ECMA 11.4.3
832Value TypeOfNode::evaluate(ExecState *exec)
833{
834 const char *s = 0L;
835 Reference ref = expr->evaluateReference(exec);
836 KJS_CHECKEXCEPTIONVALUE
837 if (ref.isMutable()) {
838 Value b = ref.getBase(exec);
839 if (b.type() == NullType)
840 return String("undefined");
841 }
842 Value v = ref.getValue(exec);
843 switch (v.type())
844 {
845 case UndefinedType:
846 s = "undefined";
847 break;
848 case NullType:
849 s = "object";
850 break;
851 case BooleanType:
852 s = "boolean";
853 break;
854 case NumberType:
855 s = "number";
856 break;
857 case StringType:
858 s = "string";
859 break;
860 default:
861 if (v.type() == ObjectType && static_cast<ObjectImp*>(v.imp())->implementsCall())
862 s = "function";
863 else
864 s = "object";
865 break;
866 }
867
868 return String(s);
869}
870
871// ------------------------------ PrefixNode -----------------------------------
872
873void PrefixNode::ref()
874{
875 Node::ref();
876 if ( expr )
877 expr->ref();
878}
879
880bool PrefixNode::deref()
881{
882 if ( expr && expr->deref() )
883 delete expr;
884 return Node::deref();
885}
886
887// ECMA 11.4.4 and 11.4.5
888Value PrefixNode::evaluate(ExecState *exec)
889{
890 Reference ref = expr->evaluateReference(exec);
891 KJS_CHECKEXCEPTIONVALUE
892 Value v = ref.getValue(exec);
893 Number n = v.toNumber(exec);
894
895 double newValue = (oper == OpPlusPlus) ? n.value() + 1 : n.value() - 1;
896 Value n2 = Number(newValue);
897
898 ref.putValue(exec,n2);
899
900 return n2;
901}
902
903// ------------------------------ UnaryPlusNode --------------------------------
904
905void UnaryPlusNode::ref()
906{
907 Node::ref();
908 if ( expr )
909 expr->ref();
910}
911
912bool UnaryPlusNode::deref()
913{
914 if ( expr && expr->deref() )
915 delete expr;
916 return Node::deref();
917}
918
919// ECMA 11.4.6
920Value UnaryPlusNode::evaluate(ExecState *exec)
921{
922 Value v = expr->evaluate(exec);
923 KJS_CHECKEXCEPTIONVALUE
924
925 return Number(v.toNumber(exec)); /* TODO: optimize */
926}
927
928// ------------------------------ NegateNode -----------------------------------
929
930void NegateNode::ref()
931{
932 Node::ref();
933 if ( expr )
934 expr->ref();
935}
936
937bool NegateNode::deref()
938{
939 if ( expr && expr->deref() )
940 delete expr;
941 return Node::deref();
942}
943
944// ECMA 11.4.7
945Value NegateNode::evaluate(ExecState *exec)
946{
947 Value v = expr->evaluate(exec);
948 KJS_CHECKEXCEPTIONVALUE
949 Number n = v.toNumber(exec);
950
951 double d = -n.value();
952
953 return Number(d);
954}
955
956// ------------------------------ BitwiseNotNode -------------------------------
957
958void BitwiseNotNode::ref()
959{
960 Node::ref();
961 if ( expr )
962 expr->ref();
963}
964
965bool BitwiseNotNode::deref()
966{
967 if ( expr && expr->deref() )
968 delete expr;
969 return Node::deref();
970}
971
972// ECMA 11.4.8
973Value BitwiseNotNode::evaluate(ExecState *exec)
974{
975 Value v = expr->evaluate(exec);
976 KJS_CHECKEXCEPTIONVALUE
977 int i32 = v.toInt32(exec);
978
979 return Number(~i32);
980}
981
982// ------------------------------ LogicalNotNode -------------------------------
983
984void LogicalNotNode::ref()
985{
986 Node::ref();
987 if ( expr )
988 expr->ref();
989}
990
991bool LogicalNotNode::deref()
992{
993 if ( expr && expr->deref() )
994 delete expr;
995 return Node::deref();
996}
997
998// ECMA 11.4.9
999Value LogicalNotNode::evaluate(ExecState *exec)
1000{
1001 Value v = expr->evaluate(exec);
1002 KJS_CHECKEXCEPTIONVALUE
1003 bool b = v.toBoolean(exec);
1004
1005 return Boolean(!b);
1006}
1007
1008// ------------------------------ MultNode -------------------------------------
1009
1010void MultNode::ref()
1011{
1012 Node::ref();
1013 if ( term1 )
1014 term1->ref();
1015 if ( term2 )
1016 term2->ref();
1017}
1018
1019bool MultNode::deref()
1020{
1021 if ( term1 && term1->deref() )
1022 delete term1;
1023 if ( term2 && term2->deref() )
1024 delete term2;
1025 return Node::deref();
1026}
1027
1028// ECMA 11.5
1029Value MultNode::evaluate(ExecState *exec)
1030{
1031 Value v1 = term1->evaluate(exec);
1032 KJS_CHECKEXCEPTIONVALUE
1033
1034 Value v2 = term2->evaluate(exec);
1035 KJS_CHECKEXCEPTIONVALUE
1036
1037 return mult(exec,v1, v2, oper);
1038}
1039
1040// ------------------------------ AddNode --------------------------------------
1041
1042void AddNode::ref()
1043{
1044 Node::ref();
1045 if ( term1 )
1046 term1->ref();
1047 if ( term2 )
1048 term2->ref();
1049}
1050
1051bool AddNode::deref()
1052{
1053 if ( term1 && term1->deref() )
1054 delete term1;
1055 if ( term2 && term2->deref() )
1056 delete term2;
1057 return Node::deref();
1058}
1059
1060// ECMA 11.6
1061Value AddNode::evaluate(ExecState *exec)
1062{
1063 Value v1 = term1->evaluate(exec);
1064 KJS_CHECKEXCEPTIONVALUE
1065
1066 Value v2 = term2->evaluate(exec);
1067 KJS_CHECKEXCEPTIONVALUE
1068
1069 return add(exec,v1, v2, oper);
1070}
1071
1072// ------------------------------ ShiftNode ------------------------------------
1073
1074void ShiftNode::ref()
1075{
1076 Node::ref();
1077 if ( term1 )
1078 term1->ref();
1079 if ( term2 )
1080 term2->ref();
1081}
1082
1083bool ShiftNode::deref()
1084{
1085 if ( term1 && term1->deref() )
1086 delete term1;
1087 if ( term2 && term2->deref() )
1088 delete term2;
1089 return Node::deref();
1090}
1091
1092// ECMA 11.7
1093Value ShiftNode::evaluate(ExecState *exec)
1094{
1095 Value v1 = term1->evaluate(exec);
1096 KJS_CHECKEXCEPTIONVALUE
1097 Value v2 = term2->evaluate(exec);
1098 KJS_CHECKEXCEPTIONVALUE
1099 unsigned int i2 = v2.toUInt32(exec);
1100 i2 &= 0x1f;
1101
1102 double result;
1103 switch (oper) {
1104 case OpLShift:
1105 result = v1.toInt32(exec) << i2;
1106 break;
1107 case OpRShift:
1108 result = v1.toInt32(exec) >> i2;
1109 break;
1110 case OpURShift:
1111 result = v1.toUInt32(exec) >> i2;
1112 break;
1113 default:
1114 assert(!"ShiftNode: unhandled switch case");
1115 result = 0;
1116 }
1117
1118 return Number(result);
1119}
1120
1121// ------------------------------ RelationalNode -------------------------------
1122
1123void RelationalNode::ref()
1124{
1125 Node::ref();
1126 if ( expr1 )
1127 expr1->ref();
1128 if ( expr2 )
1129 expr2->ref();
1130}
1131
1132bool RelationalNode::deref()
1133{
1134 if ( expr1 && expr1->deref() )
1135 delete expr1;
1136 if ( expr2 && expr2->deref() )
1137 delete expr2;
1138 return Node::deref();
1139}
1140
1141// ECMA 11.8
1142Value RelationalNode::evaluate(ExecState *exec)
1143{
1144 Value v1 = expr1->evaluate(exec);
1145 KJS_CHECKEXCEPTIONVALUE
1146 Value v2 = expr2->evaluate(exec);
1147 KJS_CHECKEXCEPTIONVALUE
1148
1149 bool b;
1150 if (oper == OpLess || oper == OpGreaterEq) {
1151 int r = relation(exec, v1, v2);
1152 if (r < 0)
1153 b = false;
1154 else
1155 b = (oper == OpLess) ? (r == 1) : (r == 0);
1156 } else if (oper == OpGreater || oper == OpLessEq) {
1157 int r = relation(exec, v2, v1);
1158 if (r < 0)
1159 b = false;
1160 else
1161 b = (oper == OpGreater) ? (r == 1) : (r == 0);
1162 } else if (oper == OpIn) {
1163 // Is all of this OK for host objects?
1164 if (v2.type() != ObjectType)
1165 return throwError(exec, TypeError,
1166 "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2);
1167 Object o2(static_cast<ObjectImp*>(v2.imp()));
1168 b = o2.hasProperty(exec, Identifier(v1.toString(exec)));
1169 } else {
1170 if (v2.type() != ObjectType)
1171 return throwError(exec, TypeError,
1172 "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2);
1173
1174 Object o2(static_cast<ObjectImp*>(v2.imp()));
1175 if (!o2.implementsHasInstance()) {
1176 // According to the spec, only some types of objects "imlement" the [[HasInstance]] property.
1177 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
1178 // property. It seems that all object have the property, but not all implement it, so in this
1179 // case we return false (consistent with mozilla)
1180 return Boolean(false);
1181 // return throwError(exec, TypeError,
1182 // "Object does not implement the [[HasInstance]] method." );
1183 }
1184 return o2.hasInstance(exec, v1);
1185 }
1186
1187 return Boolean(b);
1188}
1189
1190// ------------------------------ EqualNode ------------------------------------
1191
1192void EqualNode::ref()
1193{
1194 Node::ref();
1195 if ( expr1 )
1196 expr1->ref();
1197 if ( expr2 )
1198 expr2->ref();
1199}
1200
1201bool EqualNode::deref()
1202{
1203 if ( expr1 && expr1->deref() )
1204 delete expr1;
1205 if ( expr2 && expr2->deref() )
1206 delete expr2;
1207 return Node::deref();
1208}
1209
1210// ECMA 11.9
1211Value EqualNode::evaluate(ExecState *exec)
1212{
1213 Value v1 = expr1->evaluate(exec);
1214 KJS_CHECKEXCEPTIONVALUE
1215 Value v2 = expr2->evaluate(exec);
1216 KJS_CHECKEXCEPTIONVALUE
1217
1218 bool result;
1219 if (oper == OpEqEq || oper == OpNotEq) {
1220 // == and !=
1221 bool eq = equal(exec,v1, v2);
1222 result = oper == OpEqEq ? eq : !eq;
1223 } else {
1224 // === and !==
1225 bool eq = strictEqual(exec,v1, v2);
1226 result = oper == OpStrEq ? eq : !eq;
1227 }
1228 return Boolean(result);
1229}
1230
1231// ------------------------------ BitOperNode ----------------------------------
1232
1233void BitOperNode::ref()
1234{
1235 Node::ref();
1236 if ( expr1 )
1237 expr1->ref();
1238 if ( expr2 )
1239 expr2->ref();
1240}
1241
1242bool BitOperNode::deref()
1243{
1244 if ( expr1 && expr1->deref() )
1245 delete expr1;
1246 if ( expr2 && expr2->deref() )
1247 delete expr2;
1248 return Node::deref();
1249}
1250
1251// ECMA 11.10
1252Value BitOperNode::evaluate(ExecState *exec)
1253{
1254 Value v1 = expr1->evaluate(exec);
1255 KJS_CHECKEXCEPTIONVALUE
1256 Value v2 = expr2->evaluate(exec);
1257 KJS_CHECKEXCEPTIONVALUE
1258 int i1 = v1.toInt32(exec);
1259 int i2 = v2.toInt32(exec);
1260 int result;
1261 if (oper == OpBitAnd)
1262 result = i1 & i2;
1263 else if (oper == OpBitXOr)
1264 result = i1 ^ i2;
1265 else
1266 result = i1 | i2;
1267
1268 return Number(result);
1269}
1270
1271// ------------------------------ BinaryLogicalNode ----------------------------
1272
1273void BinaryLogicalNode::ref()
1274{
1275 Node::ref();
1276 if ( expr1 )
1277 expr1->ref();
1278 if ( expr2 )
1279 expr2->ref();
1280}
1281
1282bool BinaryLogicalNode::deref()
1283{
1284 if ( expr1 && expr1->deref() )
1285 delete expr1;
1286 if ( expr2 && expr2->deref() )
1287 delete expr2;
1288 return Node::deref();
1289}
1290
1291// ECMA 11.11
1292Value BinaryLogicalNode::evaluate(ExecState *exec)
1293{
1294 Value v1 = expr1->evaluate(exec);
1295 KJS_CHECKEXCEPTIONVALUE
1296 bool b1 = v1.toBoolean(exec);
1297 if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
1298 return v1;
1299
1300 Value v2 = expr2->evaluate(exec);
1301 KJS_CHECKEXCEPTIONVALUE
1302
1303 return v2;
1304}
1305
1306// ------------------------------ ConditionalNode ------------------------------
1307
1308void ConditionalNode::ref()
1309{
1310 Node::ref();
1311 if ( expr1 )
1312 expr1->ref();
1313 if ( expr2 )
1314 expr2->ref();
1315 if ( logical )
1316 logical->ref();
1317}
1318
1319bool ConditionalNode::deref()
1320{
1321 if ( expr1 && expr1->deref() )
1322 delete expr1;
1323 if ( expr2 && expr2->deref() )
1324 delete expr2;
1325 if ( logical && logical->deref() )
1326 delete logical;
1327 return Node::deref();
1328}
1329
1330// ECMA 11.12
1331Value ConditionalNode::evaluate(ExecState *exec)
1332{
1333 Value v = logical->evaluate(exec);
1334 KJS_CHECKEXCEPTIONVALUE
1335 bool b = v.toBoolean(exec);
1336
1337 if (b)
1338 v = expr1->evaluate(exec);
1339 else
1340 v = expr2->evaluate(exec);
1341 KJS_CHECKEXCEPTIONVALUE
1342
1343 return v;
1344}
1345
1346// ------------------------------ AssignNode -----------------------------------
1347
1348void AssignNode::ref()
1349{
1350 Node::ref();
1351 if ( left )
1352 left->ref();
1353 if ( expr )
1354 expr->ref();
1355}
1356
1357bool AssignNode::deref()
1358{
1359 if ( left && left->deref() )
1360 delete left;
1361 if ( expr && expr->deref() )
1362 delete expr;
1363 return Node::deref();
1364}
1365
1366// ECMA 11.13
1367Value AssignNode::evaluate(ExecState *exec)
1368{
1369 Reference l = left->evaluateReference(exec);
1370 KJS_CHECKEXCEPTIONVALUE
1371 Value e, v;
1372 if (oper == OpEqual) {
1373 v = expr->evaluate(exec);
1374 KJS_CHECKEXCEPTIONVALUE
1375 } else {
1376 Value v1 = l.getValue(exec);
1377 Value v2 = expr->evaluate(exec);
1378 KJS_CHECKEXCEPTIONVALUE
1379 int i1;
1380 int i2;
1381 unsigned int ui;
1382 switch (oper) {
1383 case OpMultEq:
1384 v = mult(exec, v1, v2, '*');
1385 break;
1386 case OpDivEq:
1387 v = mult(exec, v1, v2, '/');
1388 break;
1389 case OpPlusEq:
1390 v = add(exec, v1, v2, '+');
1391 break;
1392 case OpMinusEq:
1393 v = add(exec, v1, v2, '-');
1394 break;
1395 case OpLShift:
1396 i1 = v1.toInt32(exec);
1397 i2 = v2.toInt32(exec);
1398 v = Number(i1 <<= i2);
1399 break;
1400 case OpRShift:
1401 i1 = v1.toInt32(exec);
1402 i2 = v2.toInt32(exec);
1403 v = Number(i1 >>= i2);
1404 break;
1405 case OpURShift:
1406 ui = v1.toUInt32(exec);
1407 i2 = v2.toInt32(exec);
1408 v = Number(ui >>= i2);
1409 break;
1410 case OpAndEq:
1411 i1 = v1.toInt32(exec);
1412 i2 = v2.toInt32(exec);
1413 v = Number(i1 &= i2);
1414 break;
1415 case OpXOrEq:
1416 i1 = v1.toInt32(exec);
1417 i2 = v2.toInt32(exec);
1418 v = Number(i1 ^= i2);
1419 break;
1420 case OpOrEq:
1421 i1 = v1.toInt32(exec);
1422 i2 = v2.toInt32(exec);
1423 v = Number(i1 |= i2);
1424 break;
1425 case OpModEq: {
1426 double d1 = v1.toNumber(exec);
1427 double d2 = v2.toNumber(exec);
1428 v = Number(fmod(d1,d2));
1429 }
1430 break;
1431 default:
1432 v = Undefined();
1433 }
1434 };
1435 l.putValue(exec,v);
1436
1437 KJS_CHECKEXCEPTIONVALUE
1438
1439 return v;
1440}
1441
1442// ------------------------------ CommaNode ------------------------------------
1443
1444void CommaNode::ref()
1445{
1446 Node::ref();
1447 if ( expr1 )
1448 expr1->ref();
1449 if ( expr2 )
1450 expr2->ref();
1451}
1452
1453bool CommaNode::deref()
1454{
1455 if ( expr1 && expr1->deref() )
1456 delete expr1;
1457 if ( expr2 && expr2->deref() )
1458 delete expr2;
1459 return Node::deref();
1460}
1461
1462// ECMA 11.14
1463Value CommaNode::evaluate(ExecState *exec)
1464{
1465 Value dummy = expr1->evaluate(exec);
1466 KJS_CHECKEXCEPTIONVALUE
1467 Value v = expr2->evaluate(exec);
1468 KJS_CHECKEXCEPTIONVALUE
1469
1470 return v;
1471}
1472
1473// ------------------------------ StatListNode ---------------------------------
1474
1475StatListNode::StatListNode(StatementNode *s)
1476 : statement(s), list(this)
1477{
1478 setLoc(s->firstLine(), s->lastLine(), s->sourceId());
1479}
1480
1481StatListNode::StatListNode(StatListNode *l, StatementNode *s)
1482 : statement(s), list(l->list)
1483{
1484 l->list = this;
1485 setLoc(l->firstLine(), s->lastLine(), l->sourceId());
1486}
1487
1488void StatListNode::ref()
1489{
1490 for (StatListNode *n = this; n; n = n->list) {
1491 n->Node::ref();
1492 if (n->statement)
1493 n->statement->ref();
1494 }
1495}
1496
1497bool StatListNode::deref()
1498{
1499 StatListNode *next;
1500 for (StatListNode *n = this; n; n = next) {
1501 next = n->list;
1502 if (n->statement && n->statement->deref())
1503 delete n->statement;
1504 if (n != this && n->Node::deref())
1505 delete n;
1506 }
1507 return Node::deref();
1508}
1509
1510// ECMA 12.1
1511Completion StatListNode::execute(ExecState *exec)
1512{
1513 Completion c = statement->execute(exec);
1514 KJS_ABORTPOINT
1515 if (exec->hadException()) {
1516 Value ex = exec->exception();
1517 exec->clearException();
1518 return Completion(Throw, ex);
1519 }
1520
1521 if (c.complType() != Normal)
1522 return c;
1523
1524 Value v = c.value();
1525
1526 for (StatListNode *n = list; n; n = n->list) {
1527 Completion c2 = n->statement->execute(exec);
1528 KJS_ABORTPOINT
1529 if (c2.complType() != Normal)
1530 return c2;
1531
1532 if (exec->hadException()) {
1533 Value ex = exec->exception();
1534 exec->clearException();
1535 return Completion(Throw, ex);
1536 }
1537
1538 if (c2.isValueCompletion())
1539 v = c2.value();
1540 c = c2;
1541 }
1542
1543 return Completion(c.complType(), v, c.target());
1544}
1545
1546void StatListNode::processVarDecls(ExecState *exec)
1547{
1548 for (StatListNode *n = this; n; n = n->list)
1549 n->statement->processVarDecls(exec);
1550}
1551
1552// ------------------------------ AssignExprNode -------------------------------
1553
1554void AssignExprNode::ref()
1555{
1556 Node::ref();
1557 if ( expr )
1558 expr->ref();
1559}
1560
1561bool AssignExprNode::deref()
1562{
1563 if ( expr && expr->deref() )
1564 delete expr;
1565 return Node::deref();
1566}
1567
1568// ECMA 12.2
1569Value AssignExprNode::evaluate(ExecState *exec)
1570{
1571 return expr->evaluate(exec);
1572}
1573
1574// ------------------------------ VarDeclNode ----------------------------------
1575
1576VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in)
1577 : ident(id), init(in)
1578{
1579}
1580
1581void VarDeclNode::ref()
1582{
1583 Node::ref();
1584 if ( init )
1585 init->ref();
1586}
1587
1588bool VarDeclNode::deref()
1589{
1590 if ( init && init->deref() )
1591 delete init;
1592 return Node::deref();
1593}
1594
1595// ECMA 12.2
1596Value VarDeclNode::evaluate(ExecState *exec)
1597{
1598 Object variable = Object::dynamicCast(exec->context().imp()->variableObject());
1599
1600 Value val;
1601 if (init) {
1602 val = init->evaluate(exec);
1603 KJS_CHECKEXCEPTIONVALUE
1604 } else {
1605 // already declared? - check with getDirect so you can override
1606 // built-in properties of the global object with var declarations.
1607 if ( variable.imp()->getDirect(ident) )
1608 return Value();
1609 val = Undefined();
1610 }
1611
1612#ifdef KJS_VERBOSE
1613 printInfo(exec,(UString("new variable ")+ident).cstring().c_str(),val);
1614#endif
1615 // We use Internal to bypass all checks in derived objects, e.g. so that
1616 // "var location" creates a dynamic property instead of activating window.location.
1617 variable.put(exec, ident, val, DontDelete | Internal);
1618
1619 return String(ident.ustring());
1620}
1621
1622void VarDeclNode::processVarDecls(ExecState *exec)
1623{
1624 Object variable = exec->context().imp()->variableObject();
1625
1626 // If a variable by this name already exists, don't clobber it -
1627 // it might be a function parameter
1628 if (!variable.hasProperty(exec, ident)) {
1629 variable.put(exec,ident, Undefined(), DontDelete);
1630 }
1631}
1632
1633// ------------------------------ VarDeclListNode ------------------------------
1634
1635void VarDeclListNode::ref()
1636{
1637 for (VarDeclListNode *n = this; n; n = n->list) {
1638 n->Node::ref();
1639 if (n->var)
1640 n->var->ref();
1641 }
1642}
1643
1644bool VarDeclListNode::deref()
1645{
1646 VarDeclListNode *next;
1647 for (VarDeclListNode *n = this; n; n = next) {
1648 next = n->list;
1649 if (n->var && n->var->deref())
1650 delete n->var;
1651 if (n != this && n->Node::deref())
1652 delete n;
1653 }
1654 return Node::deref();
1655}
1656
1657
1658// ECMA 12.2
1659Value VarDeclListNode::evaluate(ExecState *exec)
1660{
1661 for (VarDeclListNode *n = this; n; n = n->list) {
1662 n->var->evaluate(exec);
1663 KJS_CHECKEXCEPTIONVALUE
1664 }
1665 return Undefined();
1666}
1667
1668void VarDeclListNode::processVarDecls(ExecState *exec)
1669{
1670 for (VarDeclListNode *n = this; n; n = n->list)
1671 n->var->processVarDecls(exec);
1672}
1673
1674// ------------------------------ VarStatementNode -----------------------------
1675
1676void VarStatementNode::ref()
1677{
1678 Node::ref();
1679 if ( list )
1680 list->ref();
1681}
1682
1683bool VarStatementNode::deref()
1684{
1685 if ( list && list->deref() )
1686 delete list;
1687 return Node::deref();
1688}
1689
1690// ECMA 12.2
1691Completion VarStatementNode::execute(ExecState *exec)
1692{
1693 KJS_BREAKPOINT;
1694
1695 (void) list->evaluate(exec); // returns 0L
1696 KJS_CHECKEXCEPTION
1697
1698 return Completion(Normal);
1699}
1700
1701void VarStatementNode::processVarDecls(ExecState *exec)
1702{
1703 list->processVarDecls(exec);
1704}
1705
1706// ------------------------------ BlockNode ------------------------------------
1707
1708BlockNode::BlockNode(SourceElementsNode *s)
1709{
1710 if (s) {
1711 source = s->elements;
1712 s->elements = 0;
1713 setLoc(s->firstLine(), s->lastLine(), s->sourceId());
1714 } else {
1715 source = 0;
1716 }
1717}
1718
1719void BlockNode::ref()
1720{
1721 Node::ref();
1722 if ( source )
1723 source->ref();
1724}
1725
1726bool BlockNode::deref()
1727{
1728 if ( source && source->deref() )
1729 delete source;
1730 return Node::deref();
1731}
1732
1733// ECMA 12.1
1734Completion BlockNode::execute(ExecState *exec)
1735{
1736 if (!source)
1737 return Completion(Normal);
1738
1739 source->processFuncDecl(exec);
1740
1741 return source->execute(exec);
1742}
1743
1744void BlockNode::processVarDecls(ExecState *exec)
1745{
1746 if (source)
1747 source->processVarDecls(exec);
1748}
1749
1750// ------------------------------ EmptyStatementNode ---------------------------
1751
1752// ECMA 12.3
1753Completion EmptyStatementNode::execute(ExecState */*exec*/)
1754{
1755 return Completion(Normal);
1756}
1757
1758// ------------------------------ ExprStatementNode ----------------------------
1759
1760void ExprStatementNode::ref()
1761{
1762 Node::ref();
1763 if ( expr )
1764 expr->ref();
1765}
1766
1767bool ExprStatementNode::deref()
1768{
1769 if ( expr && expr->deref() )
1770 delete expr;
1771 return Node::deref();
1772}
1773
1774// ECMA 12.4
1775Completion ExprStatementNode::execute(ExecState *exec)
1776{
1777 KJS_BREAKPOINT;
1778
1779 Value v = expr->evaluate(exec);
1780 KJS_CHECKEXCEPTION
1781
1782 return Completion(Normal, v);
1783}
1784
1785// ------------------------------ IfNode ---------------------------------------
1786
1787void IfNode::ref()
1788{
1789 Node::ref();
1790 if ( statement1 )
1791 statement1->ref();
1792 if ( statement2 )
1793 statement2->ref();
1794 if ( expr )
1795 expr->ref();
1796}
1797
1798bool IfNode::deref()
1799{
1800 if ( statement1 && statement1->deref() )
1801 delete statement1;
1802 if ( statement2 && statement2->deref() )
1803 delete statement2;
1804 if ( expr && expr->deref() )
1805 delete expr;
1806 return Node::deref();
1807}
1808
1809// ECMA 12.5
1810Completion IfNode::execute(ExecState *exec)
1811{
1812 KJS_BREAKPOINT;
1813
1814 Value v = expr->evaluate(exec);
1815 KJS_CHECKEXCEPTION
1816 bool b = v.toBoolean(exec);
1817
1818 // if ... then
1819 if (b)
1820 return statement1->execute(exec);
1821
1822 // no else
1823 if (!statement2)
1824 return Completion(Normal);
1825
1826 // else
1827 return statement2->execute(exec);
1828}
1829
1830void IfNode::processVarDecls(ExecState *exec)
1831{
1832 statement1->processVarDecls(exec);
1833
1834 if (statement2)
1835 statement2->processVarDecls(exec);
1836}
1837
1838// ------------------------------ DoWhileNode ----------------------------------
1839
1840void DoWhileNode::ref()
1841{
1842 Node::ref();
1843 if ( statement )
1844 statement->ref();
1845 if ( expr )
1846 expr->ref();
1847}
1848
1849bool DoWhileNode::deref()
1850{
1851 if ( statement && statement->deref() )
1852 delete statement;
1853 if ( expr && expr->deref() )
1854 delete expr;
1855 return Node::deref();
1856}
1857
1858// ECMA 12.6.1
1859Completion DoWhileNode::execute(ExecState *exec)
1860{
1861 KJS_BREAKPOINT;
1862
1863 Value be, bv;
1864 Completion c;
1865 Value value;
1866
1867 do {
1868 // bail out on error
1869 KJS_CHECKEXCEPTION
1870
1871 c = statement->execute(exec);
1872 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1873 if ((c.complType() == Break) && ls.contains(c.target()))
1874 return Completion(Normal, value);
1875 if (c.complType() != Normal)
1876 return c;
1877 }
1878 bv = expr->evaluate(exec);
1879 KJS_CHECKEXCEPTION
1880 } while (bv.toBoolean(exec));
1881
1882 return Completion(Normal, value);
1883}
1884
1885void DoWhileNode::processVarDecls(ExecState *exec)
1886{
1887 statement->processVarDecls(exec);
1888}
1889
1890// ------------------------------ WhileNode ------------------------------------
1891
1892void WhileNode::ref()
1893{
1894 Node::ref();
1895 if ( statement )
1896 statement->ref();
1897 if ( expr )
1898 expr->ref();
1899}
1900
1901bool WhileNode::deref()
1902{
1903 if ( statement && statement->deref() )
1904 delete statement;
1905 if ( expr && expr->deref() )
1906 delete expr;
1907 return Node::deref();
1908}
1909
1910// ECMA 12.6.2
1911Completion WhileNode::execute(ExecState *exec)
1912{
1913 KJS_BREAKPOINT;
1914
1915 Value be, bv;
1916 Completion c;
1917 bool b(false);
1918 Value value;
1919
1920 while (1) {
1921 bv = expr->evaluate(exec);
1922 KJS_CHECKEXCEPTION
1923 b = bv.toBoolean(exec);
1924
1925 // bail out on error
1926 KJS_CHECKEXCEPTION
1927
1928 if (!b)
1929 return Completion(Normal, value);
1930
1931 c = statement->execute(exec);
1932 if (c.isValueCompletion())
1933 value = c.value();
1934
1935 if ((c.complType() == Continue) && ls.contains(c.target()))
1936 continue;
1937 if ((c.complType() == Break) && ls.contains(c.target()))
1938 return Completion(Normal, value);
1939 if (c.complType() != Normal)
1940 return c;
1941 }
1942}
1943
1944void WhileNode::processVarDecls(ExecState *exec)
1945{
1946 statement->processVarDecls(exec);
1947}
1948
1949// ------------------------------ ForNode --------------------------------------
1950
1951void ForNode::ref()
1952{
1953 Node::ref();
1954 if ( statement )
1955 statement->ref();
1956 if ( expr1 )
1957 expr1->ref();
1958 if ( expr2 )
1959 expr2->ref();
1960 if ( expr3 )
1961 expr3->ref();
1962}
1963
1964bool ForNode::deref()
1965{
1966 if ( statement && statement->deref() )
1967 delete statement;
1968 if ( expr1 && expr1->deref() )
1969 delete expr1;
1970 if ( expr2 && expr2->deref() )
1971 delete expr2;
1972 if ( expr3 && expr3->deref() )
1973 delete expr3;
1974 return Node::deref();
1975}
1976
1977// ECMA 12.6.3
1978Completion ForNode::execute(ExecState *exec)
1979{
1980 Value e, v, cval;
1981 bool b;
1982
1983 if (expr1) {
1984 v = expr1->evaluate(exec);
1985 KJS_CHECKEXCEPTION
1986 }
1987 while (1) {
1988 if (expr2) {
1989 v = expr2->evaluate(exec);
1990 KJS_CHECKEXCEPTION
1991 b = v.toBoolean(exec);
1992 if (b == false)
1993 return Completion(Normal, cval);
1994 }
1995 // bail out on error
1996 KJS_CHECKEXCEPTION
1997
1998 Completion c = statement->execute(exec);
1999 if (c.isValueCompletion())
2000 cval = c.value();
2001 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2002 if ((c.complType() == Break) && ls.contains(c.target()))
2003 return Completion(Normal, cval);
2004 if (c.complType() != Normal)
2005 return c;
2006 }
2007 if (expr3) {
2008 v = expr3->evaluate(exec);
2009 KJS_CHECKEXCEPTION
2010 }
2011 }
2012}
2013
2014void ForNode::processVarDecls(ExecState *exec)
2015{
2016 if (expr1)
2017 expr1->processVarDecls(exec);
2018
2019 statement->processVarDecls(exec);
2020}
2021
2022// ------------------------------ ForInNode ------------------------------------
2023
2024ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
2025 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
2026{
2027}
2028
2029ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
2030 : ident(i), init(in), expr(e), statement(s)
2031{
2032 // for( var foo = bar in baz )
2033 varDecl = new VarDeclNode(ident, init);
2034 lexpr = new ResolveNode(ident);
2035}
2036
2037void ForInNode::ref()
2038{
2039 Node::ref();
2040 if ( statement )
2041 statement->ref();
2042 if ( expr )
2043 expr->ref();
2044 if ( lexpr )
2045 lexpr->ref();
2046 if ( init )
2047 init->ref();
2048 if ( varDecl )
2049 varDecl->ref();
2050}
2051
2052bool ForInNode::deref()
2053{
2054 if ( statement && statement->deref() )
2055 delete statement;
2056 if ( expr && expr->deref() )
2057 delete expr;
2058 if ( lexpr && lexpr->deref() )
2059 delete lexpr;
2060 if ( init && init->deref() )
2061 delete init;
2062 if ( varDecl && varDecl->deref() )
2063 delete varDecl;
2064 return Node::deref();
2065}
2066
2067// ECMA 12.6.4
2068Completion ForInNode::execute(ExecState *exec)
2069{
2070 Value e, retval;
2071 Object v;
2072 Completion c;
2073 ReferenceList propList;
2074
2075 if ( varDecl ) {
2076 varDecl->evaluate(exec);
2077 KJS_CHECKEXCEPTION
2078 }
2079
2080 e = expr->evaluate(exec);
2081
2082 // for Null and Undefined, we want to make sure not to go through
2083 // the loop at all, because their object wrappers will have a
2084 // property list but will throw an exception if you attempt to
2085 // access any property.
2086 if (e.type() == UndefinedType || e.type() == NullType) {
2087 return Completion(Normal, retval);
2088 }
2089
2090 KJS_CHECKEXCEPTION
2091 v = e.toObject(exec);
2092 propList = v.propList(exec);
2093
2094 ReferenceListIterator propIt = propList.begin();
2095
2096 while (propIt != propList.end()) {
2097 Identifier name = propIt->getPropertyName(exec);
2098 if (!v.hasProperty(exec,name)) {
2099 propIt++;
2100 continue;
2101 }
2102
2103 Reference ref = lexpr->evaluateReference(exec);
2104 KJS_CHECKEXCEPTION
2105 ref.putValue(exec, String(name.ustring()));
2106
2107 c = statement->execute(exec);
2108 if (c.isValueCompletion())
2109 retval = c.value();
2110
2111 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2112 if ((c.complType() == Break) && ls.contains(c.target()))
2113 break;
2114 if (c.complType() != Normal) {
2115 return c;
2116 }
2117 }
2118
2119 propIt++;
2120 }
2121
2122 // bail out on error
2123 KJS_CHECKEXCEPTION
2124
2125 return Completion(Normal, retval);
2126}
2127
2128void ForInNode::processVarDecls(ExecState *exec)
2129{
2130 statement->processVarDecls(exec);
2131}
2132
2133// ------------------------------ ContinueNode ---------------------------------
2134
2135// ECMA 12.7
2136Completion ContinueNode::execute(ExecState *exec)
2137{
2138 KJS_BREAKPOINT;
2139
2140 Value dummy;
2141 return exec->context().imp()->seenLabels()->contains(ident) ?
2142 Completion(Continue, dummy, ident) :
2143 Completion(Throw,
2144 throwError(exec, SyntaxError, "Label %s not found in containing block. Can't continue.", ident));
2145}
2146
2147// ------------------------------ BreakNode ------------------------------------
2148
2149// ECMA 12.8
2150Completion BreakNode::execute(ExecState *exec)
2151{
2152 KJS_BREAKPOINT;
2153
2154 Value dummy;
2155 return exec->context().imp()->seenLabels()->contains(ident) ?
2156 Completion(Break, dummy, ident) :
2157 Completion(Throw,
2158 throwError(exec, SyntaxError, "Label %s not found in containing block. Can't break.", ident));
2159}
2160
2161// ------------------------------ ReturnNode -----------------------------------
2162
2163void ReturnNode::ref()
2164{
2165 Node::ref();
2166 if ( value )
2167 value->ref();
2168}
2169
2170bool ReturnNode::deref()
2171{
2172 if ( value && value->deref() )
2173 delete value;
2174 return Node::deref();
2175}
2176
2177// ECMA 12.9
2178Completion ReturnNode::execute(ExecState *exec)
2179{
2180 KJS_BREAKPOINT;
2181
2182 if (!value)
2183 return Completion(ReturnValue, Undefined());
2184
2185 Value v = value->evaluate(exec);
2186 KJS_CHECKEXCEPTION
2187
2188 return Completion(ReturnValue, v);
2189}
2190
2191// ------------------------------ WithNode -------------------------------------
2192
2193void WithNode::ref()
2194{
2195 Node::ref();
2196 if ( statement )
2197 statement->ref();
2198 if ( expr )
2199 expr->ref();
2200}
2201
2202bool WithNode::deref()
2203{
2204 if ( statement && statement->deref() )
2205 delete statement;
2206 if ( expr && expr->deref() )
2207 delete expr;
2208 return Node::deref();
2209}
2210
2211// ECMA 12.10
2212Completion WithNode::execute(ExecState *exec)
2213{
2214 KJS_BREAKPOINT;
2215
2216 Value v = expr->evaluate(exec);
2217 KJS_CHECKEXCEPTION
2218 Object o = v.toObject(exec);
2219 KJS_CHECKEXCEPTION
2220 exec->context().imp()->pushScope(o);
2221 Completion res = statement->execute(exec);
2222 exec->context().imp()->popScope();
2223
2224 return res;
2225}
2226
2227void WithNode::processVarDecls(ExecState *exec)
2228{
2229 statement->processVarDecls(exec);
2230}
2231
2232// ------------------------------ CaseClauseNode -------------------------------
2233
2234void CaseClauseNode::ref()
2235{
2236 Node::ref();
2237 if ( expr )
2238 expr->ref();
2239 if ( list )
2240 list->ref();
2241}
2242
2243bool CaseClauseNode::deref()
2244{
2245 if ( expr && expr->deref() )
2246 delete expr;
2247 if ( list && list->deref() )
2248 delete list;
2249 return Node::deref();
2250}
2251
2252// ECMA 12.11
2253Value CaseClauseNode::evaluate(ExecState *exec)
2254{
2255 Value v = expr->evaluate(exec);
2256 KJS_CHECKEXCEPTIONVALUE
2257
2258 return v;
2259}
2260
2261// ECMA 12.11
2262Completion CaseClauseNode::evalStatements(ExecState *exec)
2263{
2264 if (list)
2265 return list->execute(exec);
2266 else
2267 return Completion(Normal, Undefined());
2268}
2269
2270void CaseClauseNode::processVarDecls(ExecState *exec)
2271{
2272 if (list)
2273 list->processVarDecls(exec);
2274}
2275
2276// ------------------------------ ClauseListNode -------------------------------
2277
2278void ClauseListNode::ref()
2279{
2280 for (ClauseListNode *n = this; n; n = n->nx) {
2281 n->Node::ref();
2282 if (n->cl)
2283 n->cl->ref();
2284 }
2285}
2286
2287bool ClauseListNode::deref()
2288{
2289 ClauseListNode *next;
2290 for (ClauseListNode *n = this; n; n = next) {
2291 next = n->nx;
2292 if (n->cl && n->cl->deref())
2293 delete n->cl;
2294 if (n != this && n->Node::deref())
2295 delete n;
2296 }
2297 return Node::deref();
2298}
2299
2300Value ClauseListNode::evaluate(ExecState */*exec*/)
2301{
2302 /* should never be called */
2303 assert(false);
2304 return Value();
2305}
2306
2307// ECMA 12.11
2308void ClauseListNode::processVarDecls(ExecState *exec)
2309{
2310 for (ClauseListNode *n = this; n; n = n->nx)
2311 if (n->cl)
2312 n->cl->processVarDecls(exec);
2313}
2314
2315// ------------------------------ CaseBlockNode --------------------------------
2316
2317CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2318 ClauseListNode *l2)
2319{
2320 if (l1) {
2321 list1 = l1->nx;
2322 l1->nx = 0;
2323 } else {
2324 list1 = 0;
2325 }
2326
2327 def = d;
2328
2329 if (l2) {
2330 list2 = l2->nx;
2331 l2->nx = 0;
2332 } else {
2333 list2 = 0;
2334 }
2335}
2336
2337void CaseBlockNode::ref()
2338{
2339 Node::ref();
2340 if ( def )
2341 def->ref();
2342 if ( list1 )
2343 list1->ref();
2344 if ( list2 )
2345 list2->ref();
2346}
2347
2348bool CaseBlockNode::deref()
2349{
2350 if ( def && def->deref() )
2351 delete def;
2352 if ( list1 && list1->deref() )
2353 delete list1;
2354 if ( list2 && list2->deref() )
2355 delete list2;
2356 return Node::deref();
2357}
2358
2359Value CaseBlockNode::evaluate(ExecState */*exec*/)
2360{
2361 /* should never be called */
2362 assert(false);
2363 return Value();
2364}
2365
2366// ECMA 12.11
2367Completion CaseBlockNode::evalBlock(ExecState *exec, const Value& input)
2368{
2369 Value v;
2370 Completion res;
2371 ClauseListNode *a = list1, *b = list2;
2372 CaseClauseNode *clause;
2373
2374 while (a) {
2375 clause = a->clause();
2376 a = a->next();
2377 v = clause->evaluate(exec);
2378 KJS_CHECKEXCEPTION
2379 if (strictEqual(exec, input, v)) {
2380 res = clause->evalStatements(exec);
2381 if (res.complType() != Normal)
2382 return res;
2383 while (a) {
2384 res = a->clause()->evalStatements(exec);
2385 if (res.complType() != Normal)
2386 return res;
2387 a = a->next();
2388 }
2389 break;
2390 }
2391 }
2392
2393 while (b) {
2394 clause = b->clause();
2395 b = b->next();
2396 v = clause->evaluate(exec);
2397 KJS_CHECKEXCEPTION
2398 if (strictEqual(exec, input, v)) {
2399 res = clause->evalStatements(exec);
2400 if (res.complType() != Normal)
2401 return res;
2402 goto step18;
2403 }
2404 }
2405
2406 // default clause
2407 if (def) {
2408 res = def->evalStatements(exec);
2409 if (res.complType() != Normal)
2410 return res;
2411 }
2412 b = list2;
2413 step18:
2414 while (b) {
2415 clause = b->clause();
2416 res = clause->evalStatements(exec);
2417 if (res.complType() != Normal)
2418 return res;
2419 b = b->next();
2420 }
2421
2422 // bail out on error
2423 KJS_CHECKEXCEPTION
2424
2425 return Completion(Normal);
2426}
2427
2428void CaseBlockNode::processVarDecls(ExecState *exec)
2429{
2430 if (list1)
2431 list1->processVarDecls(exec);
2432 if (def)
2433 def->processVarDecls(exec);
2434 if (list2)
2435 list2->processVarDecls(exec);
2436}
2437
2438// ------------------------------ SwitchNode -----------------------------------
2439
2440void SwitchNode::ref()
2441{
2442 Node::ref();
2443 if ( expr )
2444 expr->ref();
2445 if ( block )
2446 block->ref();
2447}
2448
2449bool SwitchNode::deref()
2450{
2451 if ( expr && expr->deref() )
2452 delete expr;
2453 if ( block && block->deref() )
2454 delete block;
2455 return Node::deref();
2456}
2457
2458// ECMA 12.11
2459Completion SwitchNode::execute(ExecState *exec)
2460{
2461 KJS_BREAKPOINT;
2462
2463 Value v = expr->evaluate(exec);
2464 KJS_CHECKEXCEPTION
2465 Completion res = block->evalBlock(exec,v);
2466
2467 if ((res.complType() == Break) && ls.contains(res.target()))
2468 return Completion(Normal, res.value());
2469 else
2470 return res;
2471}
2472
2473void SwitchNode::processVarDecls(ExecState *exec)
2474{
2475 block->processVarDecls(exec);
2476}
2477
2478// ------------------------------ LabelNode ------------------------------------
2479
2480void LabelNode::ref()
2481{
2482 Node::ref();
2483 if ( statement )
2484 statement->ref();
2485}
2486
2487bool LabelNode::deref()
2488{
2489 if ( statement && statement->deref() )
2490 delete statement;
2491 return Node::deref();
2492}
2493
2494// ECMA 12.12
2495Completion LabelNode::execute(ExecState *exec)
2496{
2497 Completion e;
2498
2499 if (!exec->context().imp()->seenLabels()->push(label)) {
2500 return Completion( Throw,
2501 throwError(exec, SyntaxError, "Duplicated label %s found.", label));
2502 };
2503 e = statement->execute(exec);
2504 exec->context().imp()->seenLabels()->pop();
2505
2506 if ((e.complType() == Break) && (e.target() == label))
2507 return Completion(Normal, e.value());
2508 else
2509 return e;
2510}
2511
2512void LabelNode::processVarDecls(ExecState *exec)
2513{
2514 statement->processVarDecls(exec);
2515}
2516
2517// ------------------------------ ThrowNode ------------------------------------
2518
2519void ThrowNode::ref()
2520{
2521 Node::ref();
2522 if ( expr )
2523 expr->ref();
2524}
2525
2526bool ThrowNode::deref()
2527{
2528 if ( expr && expr->deref() )
2529 delete expr;
2530 return Node::deref();
2531}
2532
2533// ECMA 12.13
2534Completion ThrowNode::execute(ExecState *exec)
2535{
2536 KJS_BREAKPOINT;
2537
2538 Value v = expr->evaluate(exec);
2539 KJS_CHECKEXCEPTION
2540
2541 // bail out on error
2542 KJS_CHECKEXCEPTION
2543
2544 return Completion(Throw, v);
2545}
2546
2547// ------------------------------ CatchNode ------------------------------------
2548
2549void CatchNode::ref()
2550{
2551 Node::ref();
2552 if ( block )
2553 block->ref();
2554}
2555
2556bool CatchNode::deref()
2557{
2558 if ( block && block->deref() )
2559 delete block;
2560 return Node::deref();
2561}
2562
2563Completion CatchNode::execute(ExecState */*exec*/)
2564{
2565 // should never be reached. execute(exec, arg) is used instead
2566 assert(0L);
2567 return Completion();
2568}
2569
2570// ECMA 12.14
2571Completion CatchNode::execute(ExecState *exec, const Value &arg)
2572{
2573 /* TODO: correct ? Not part of the spec */
2574
2575 exec->clearException();
2576
2577 Object obj(new ObjectImp());
2578 obj.put(exec, ident, arg, DontDelete);
2579 exec->context().imp()->pushScope(obj);
2580 Completion c = block->execute(exec);
2581 exec->context().imp()->popScope();
2582
2583 return c;
2584}
2585
2586void CatchNode::processVarDecls(ExecState *exec)
2587{
2588 block->processVarDecls(exec);
2589}
2590
2591// ------------------------------ FinallyNode ----------------------------------
2592
2593void FinallyNode::ref()
2594{
2595 Node::ref();
2596 if ( block )
2597 block->ref();
2598}
2599
2600bool FinallyNode::deref()
2601{
2602 if ( block && block->deref() )
2603 delete block;
2604 return Node::deref();
2605}
2606
2607// ECMA 12.14
2608Completion FinallyNode::execute(ExecState *exec)
2609{
2610 return block->execute(exec);
2611}
2612
2613void FinallyNode::processVarDecls(ExecState *exec)
2614{
2615 block->processVarDecls(exec);
2616}
2617
2618// ------------------------------ TryNode --------------------------------------
2619
2620void TryNode::ref()
2621{
2622 Node::ref();
2623 if ( block )
2624 block->ref();
2625 if ( _final )
2626 _final->ref();
2627 if ( _catch )
2628 _catch->ref();
2629}
2630
2631bool TryNode::deref()
2632{
2633 if ( block && block->deref() )
2634 delete block;
2635 if ( _final && _final->deref() )
2636 delete _final;
2637 if ( _catch && _catch->deref() )
2638 delete _catch;
2639 return Node::deref();
2640}
2641
2642// ECMA 12.14
2643Completion TryNode::execute(ExecState *exec)
2644{
2645 KJS_BREAKPOINT;
2646
2647 Completion c, c2;
2648
2649 c = block->execute(exec);
2650
2651 if (!_final) {
2652 if (c.complType() != Throw)
2653 return c;
2654 return _catch->execute(exec,c.value());
2655 }
2656
2657 if (!_catch) {
2658 c2 = _final->execute(exec);
2659 return (c2.complType() == Normal) ? c : c2;
2660 }
2661
2662 if (c.complType() == Throw)
2663 c = _catch->execute(exec,c.value());
2664
2665 c2 = _final->execute(exec);
2666 return (c2.complType() == Normal) ? c : c2;
2667}
2668
2669void TryNode::processVarDecls(ExecState *exec)
2670{
2671 block->processVarDecls(exec);
2672 if (_final)
2673 _final->processVarDecls(exec);
2674 if (_catch)
2675 _catch->processVarDecls(exec);
2676}
2677
2678// ------------------------------ ParameterNode --------------------------------
2679
2680void ParameterNode::ref()
2681{
2682 for (ParameterNode *n = this; n; n = n->next)
2683 n->Node::ref();
2684}
2685
2686bool ParameterNode::deref()
2687{
2688 ParameterNode *next;
2689 for (ParameterNode *n = this; n; n = next) {
2690 next = n->next;
2691 if (n != this && n->Node::deref())
2692 delete n;
2693 }
2694 return Node::deref();
2695}
2696
2697// ECMA 13
2698Value ParameterNode::evaluate(ExecState */*exec*/)
2699{
2700 return Undefined();
2701}
2702
2703// ------------------------------ FunctionBodyNode -----------------------------
2704
2705FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2706 : BlockNode(s)
2707{
2708 setLoc(-1, -1, -1);
2709 //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this);
2710}
2711
2712void FunctionBodyNode::processFuncDecl(ExecState *exec)
2713{
2714 if (source)
2715 source->processFuncDecl(exec);
2716}
2717
2718// ------------------------------ FuncDeclNode ---------------------------------
2719
2720void FuncDeclNode::ref()
2721{
2722 Node::ref();
2723 if ( param )
2724 param->ref();
2725 if ( body )
2726 body->ref();
2727}
2728
2729bool FuncDeclNode::deref()
2730{
2731 if ( param && param->deref() )
2732 delete param;
2733 if ( body && body->deref() )
2734 delete body;
2735 return Node::deref();
2736}
2737
2738// ECMA 13
2739void FuncDeclNode::processFuncDecl(ExecState *exec)
2740{
2741 // TODO: let this be an object with [[Class]] property "Function"
2742 FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
2743 Object func(fimp); // protect from GC
2744
2745 // Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty());
2746 List empty;
2747 Object proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
2748 proto.put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2749 func.put(exec, prototypePropertyName, proto, Internal|DontDelete);
2750
2751 int plen = 0;
2752 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2753 fimp->addParameter(p->ident());
2754
2755 func.put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
2756
2757 exec->context().imp()->variableObject().put(exec,ident,func);
2758
2759 if (body) {
2760 // hack the scope so that the function gets put as a property of func, and it's scope
2761 // contains the func as well as our current scope
2762 Object oldVar = exec->context().imp()->variableObject();
2763 exec->context().imp()->setVariableObject(func);
2764 exec->context().imp()->pushScope(func);
2765 body->processFuncDecl(exec);
2766 exec->context().imp()->popScope();
2767 exec->context().imp()->setVariableObject(oldVar);
2768 }
2769}
2770
2771// ------------------------------ FuncExprNode ---------------------------------
2772
2773void FuncExprNode::ref()
2774{
2775 Node::ref();
2776 if ( param )
2777 param->ref();
2778 if ( body )
2779 body->ref();
2780}
2781
2782bool FuncExprNode::deref()
2783{
2784 if ( param && param->deref() )
2785 delete param;
2786 if ( body && body->deref() )
2787 delete body;
2788 return Node::deref();
2789}
2790
2791
2792// ECMA 13
2793Value FuncExprNode::evaluate(ExecState *exec)
2794{
2795 FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), body, exec->context().imp()->scopeChain());
2796 Value ret(fimp);
2797 List empty;
2798 Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
2799 fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2800
2801 int plen = 0;
2802 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2803 fimp->addParameter(p->ident());
2804
2805 return ret;
2806}
2807
2808// ------------------------------ SourceElementsNode ---------------------------
2809
2810SourceElementsNode::SourceElementsNode(StatementNode *s1)
2811 : element(s1), elements(this)
2812{
2813 setLoc(s1->firstLine(), s1->lastLine(), s1->sourceId());
2814}
2815
2816SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
2817 : element(s2), elements(s1->elements)
2818{
2819 s1->elements = this;
2820 setLoc(s1->firstLine(), s2->lastLine(), s1->sourceId());
2821}
2822
2823void SourceElementsNode::ref()
2824{
2825 for (SourceElementsNode *n = this; n; n = n->elements) {
2826 n->Node::ref();
2827 if (n->element)
2828 n->element->ref();
2829 }
2830}
2831
2832bool SourceElementsNode::deref()
2833{
2834 SourceElementsNode *next;
2835 for (SourceElementsNode *n = this; n; n = next) {
2836 next = n->elements;
2837 if (n->element && n->element->deref())
2838 delete n->element;
2839 if (n != this && n->Node::deref())
2840 delete n;
2841 }
2842 return Node::deref();
2843}
2844
2845// ECMA 14
2846Completion SourceElementsNode::execute(ExecState *exec)
2847{
2848 KJS_CHECKEXCEPTION
2849
2850 Completion c1 = element->execute(exec);
2851 KJS_CHECKEXCEPTION;
2852 if (c1.complType() != Normal)
2853 return c1;
2854
2855 for (SourceElementsNode *n = elements; n; n = n->elements) {
2856 Completion c2 = n->element->execute(exec);
2857 if (c2.complType() != Normal)
2858 return c2;
2859 // The spec says to return c2 here, but it seems that mozilla returns c1 if
2860 // c2 doesn't have a value
2861 if (!c2.value().isNull())
2862 c1 = c2;
2863 }
2864
2865 return c1;
2866}
2867
2868// ECMA 14
2869void SourceElementsNode::processFuncDecl(ExecState *exec)
2870{
2871 for (SourceElementsNode *n = this; n; n = n->elements)
2872 n->element->processFuncDecl(exec);
2873}
2874
2875void SourceElementsNode::processVarDecls(ExecState *exec)
2876{
2877 for (SourceElementsNode *n = this; n; n = n->elements)
2878 n->element->processVarDecls(exec);
2879}
2880
2881ProgramNode::ProgramNode(SourceElementsNode *s): FunctionBodyNode(s) {
2882 //fprintf(stderr,"ProgramNode::ProgramNode %p\n",this);
2883}
Note: See TracBrowser for help on using the repository browser.