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

Last change on this file since 2738 was 2735, checked in by mjs, 23 years ago

Change ArgumentListNode operations to be iterative instead of
recursive. This probably fixes 3095446 (Crash in
KJS::ArgumentListNode::ref()) but I can't reproduce it myself so
I'm not 100% sure. I think the original bug was a stack overflow
and this change would remove that possibility.

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