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

Last change on this file since 2881 was 2881, checked in by rjw, 23 years ago

JavaScriptCore

Remove debugging code. Could be cause of performance regresssion.

  • kjs/nodes.cpp: (FunctionCallNode::evaluate):

Restire attributes correctly.

  • kjs/property_map.cpp:

WebKit Only cache page if the load has completed.

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