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

Last change on this file since 5480 was 5480, checked in by mjs, 22 years ago

Reviewed by John.

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