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

Last change on this file since 9556 was 9556, checked in by ggaren, 20 years ago

-fixed <rdar://problem/4168161> JavaScript fails to throw an exception
for invalid function calls

Reviewed by sullivan.

Relevant mozilla test: ecma_3/Exceptions/regress-95101.js

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