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

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