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

Last change on this file since 5115 was 5115, checked in by darin, 22 years ago

Reviewed by Dave.

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