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

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