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

Last change on this file since 9352 was 9352, checked in by darin, 20 years ago

Change by Mark Rowe <[email protected]>.
Reviewed by me.

  • further improvements to exception file/line number fix
  • kjs/nodes.h: Added setExceptionDetailsIfNeeded function.
  • kjs/nodes.cpp: Updated macros to call the new setExceptionDetailsIfNeeded function. (Node::setExceptionDetailsIfNeeded): Added.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 60.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// 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
724 KJS_CHECKEXCEPTIONVALUE
725
726 Value v = ref.getValue(exec);
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
1590VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in)
1591 : ident(id), init(in)
1592{
1593}
1594
1595void VarDeclNode::ref()
1596{
1597 Node::ref();
1598 if ( init )
1599 init->ref();
1600}
1601
1602bool VarDeclNode::deref()
1603{
1604 if ( init && init->deref() )
1605 delete init;
1606 return Node::deref();
1607}
1608
1609// ECMA 12.2
1610Value VarDeclNode::evaluate(ExecState *exec)
1611{
1612 Object variable = exec->context().imp()->variableObject();
1613
1614 Value val;
1615 if (init) {
1616 val = init->evaluate(exec);
1617 KJS_CHECKEXCEPTIONVALUE
1618 } else {
1619 // already declared? - check with getDirect so you can override
1620 // built-in properties of the global object with var declarations.
1621 if ( variable.imp()->getDirect(ident) )
1622 return Value();
1623 val = Undefined();
1624 }
1625
1626#ifdef KJS_VERBOSE
1627 printInfo(exec,(UString("new variable ")+ident).cstring().c_str(),val);
1628#endif
1629 // We use Internal to bypass all checks in derived objects, e.g. so that
1630 // "var location" creates a dynamic property instead of activating window.location.
1631 variable.put(exec, ident, val, DontDelete | Internal);
1632
1633 return ident.ustring();
1634}
1635
1636void VarDeclNode::processVarDecls(ExecState *exec)
1637{
1638 Object variable = exec->context().imp()->variableObject();
1639
1640 // If a variable by this name already exists, don't clobber it -
1641 // it might be a function parameter
1642 if (!variable.hasProperty(exec, ident)) {
1643 variable.put(exec,ident, Undefined(), DontDelete);
1644 }
1645}
1646
1647// ------------------------------ VarDeclListNode ------------------------------
1648
1649void VarDeclListNode::ref()
1650{
1651 for (VarDeclListNode *n = this; n; n = n->list) {
1652 n->Node::ref();
1653 if (n->var)
1654 n->var->ref();
1655 }
1656}
1657
1658bool VarDeclListNode::deref()
1659{
1660 VarDeclListNode *next;
1661 for (VarDeclListNode *n = this; n; n = next) {
1662 next = n->list;
1663 if (n->var && n->var->deref())
1664 delete n->var;
1665 if (n != this && n->Node::deref())
1666 delete n;
1667 }
1668 return Node::deref();
1669}
1670
1671
1672// ECMA 12.2
1673Value VarDeclListNode::evaluate(ExecState *exec)
1674{
1675 for (VarDeclListNode *n = this; n; n = n->list) {
1676 n->var->evaluate(exec);
1677 KJS_CHECKEXCEPTIONVALUE
1678 }
1679 return Undefined();
1680}
1681
1682void VarDeclListNode::processVarDecls(ExecState *exec)
1683{
1684 for (VarDeclListNode *n = this; n; n = n->list)
1685 n->var->processVarDecls(exec);
1686}
1687
1688// ------------------------------ VarStatementNode -----------------------------
1689
1690void VarStatementNode::ref()
1691{
1692 Node::ref();
1693 if ( list )
1694 list->ref();
1695}
1696
1697bool VarStatementNode::deref()
1698{
1699 if ( list && list->deref() )
1700 delete list;
1701 return Node::deref();
1702}
1703
1704// ECMA 12.2
1705Completion VarStatementNode::execute(ExecState *exec)
1706{
1707 KJS_BREAKPOINT;
1708
1709 (void) list->evaluate(exec); // returns 0L
1710 KJS_CHECKEXCEPTION
1711
1712 return Completion(Normal);
1713}
1714
1715void VarStatementNode::processVarDecls(ExecState *exec)
1716{
1717 list->processVarDecls(exec);
1718}
1719
1720// ------------------------------ BlockNode ------------------------------------
1721
1722BlockNode::BlockNode(SourceElementsNode *s)
1723{
1724 if (s) {
1725 source = s->elements;
1726 s->elements = 0;
1727 setLoc(s->firstLine(), s->lastLine(), s->sourceId());
1728 } else {
1729 source = 0;
1730 }
1731}
1732
1733void BlockNode::ref()
1734{
1735 Node::ref();
1736 if ( source )
1737 source->ref();
1738}
1739
1740bool BlockNode::deref()
1741{
1742 if ( source && source->deref() )
1743 delete source;
1744 return Node::deref();
1745}
1746
1747// ECMA 12.1
1748Completion BlockNode::execute(ExecState *exec)
1749{
1750 if (!source)
1751 return Completion(Normal);
1752
1753 source->processFuncDecl(exec);
1754
1755 return source->execute(exec);
1756}
1757
1758void BlockNode::processVarDecls(ExecState *exec)
1759{
1760 if (source)
1761 source->processVarDecls(exec);
1762}
1763
1764// ------------------------------ EmptyStatementNode ---------------------------
1765
1766// ECMA 12.3
1767Completion EmptyStatementNode::execute(ExecState */*exec*/)
1768{
1769 return Completion(Normal);
1770}
1771
1772// ------------------------------ ExprStatementNode ----------------------------
1773
1774void ExprStatementNode::ref()
1775{
1776 Node::ref();
1777 if ( expr )
1778 expr->ref();
1779}
1780
1781bool ExprStatementNode::deref()
1782{
1783 if ( expr && expr->deref() )
1784 delete expr;
1785 return Node::deref();
1786}
1787
1788// ECMA 12.4
1789Completion ExprStatementNode::execute(ExecState *exec)
1790{
1791 KJS_BREAKPOINT;
1792
1793 Value v = expr->evaluate(exec);
1794 KJS_CHECKEXCEPTION
1795
1796 return Completion(Normal, v);
1797}
1798
1799// ------------------------------ IfNode ---------------------------------------
1800
1801void IfNode::ref()
1802{
1803 Node::ref();
1804 if ( statement1 )
1805 statement1->ref();
1806 if ( statement2 )
1807 statement2->ref();
1808 if ( expr )
1809 expr->ref();
1810}
1811
1812bool IfNode::deref()
1813{
1814 if ( statement1 && statement1->deref() )
1815 delete statement1;
1816 if ( statement2 && statement2->deref() )
1817 delete statement2;
1818 if ( expr && expr->deref() )
1819 delete expr;
1820 return Node::deref();
1821}
1822
1823// ECMA 12.5
1824Completion IfNode::execute(ExecState *exec)
1825{
1826 KJS_BREAKPOINT;
1827
1828 Value v = expr->evaluate(exec);
1829 KJS_CHECKEXCEPTION
1830 bool b = v.toBoolean(exec);
1831
1832 // if ... then
1833 if (b)
1834 return statement1->execute(exec);
1835
1836 // no else
1837 if (!statement2)
1838 return Completion(Normal);
1839
1840 // else
1841 return statement2->execute(exec);
1842}
1843
1844void IfNode::processVarDecls(ExecState *exec)
1845{
1846 statement1->processVarDecls(exec);
1847
1848 if (statement2)
1849 statement2->processVarDecls(exec);
1850}
1851
1852// ------------------------------ DoWhileNode ----------------------------------
1853
1854void DoWhileNode::ref()
1855{
1856 Node::ref();
1857 if ( statement )
1858 statement->ref();
1859 if ( expr )
1860 expr->ref();
1861}
1862
1863bool DoWhileNode::deref()
1864{
1865 if ( statement && statement->deref() )
1866 delete statement;
1867 if ( expr && expr->deref() )
1868 delete expr;
1869 return Node::deref();
1870}
1871
1872// ECMA 12.6.1
1873Completion DoWhileNode::execute(ExecState *exec)
1874{
1875 KJS_BREAKPOINT;
1876
1877 Value be, bv;
1878 Completion c;
1879 Value value;
1880
1881 do {
1882 // bail out on error
1883 KJS_CHECKEXCEPTION
1884
1885 c = statement->execute(exec);
1886 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1887 if ((c.complType() == Break) && ls.contains(c.target()))
1888 return Completion(Normal, value);
1889 if (c.complType() != Normal)
1890 return c;
1891 }
1892 bv = expr->evaluate(exec);
1893 KJS_CHECKEXCEPTION
1894 } while (bv.toBoolean(exec));
1895
1896 return Completion(Normal, value);
1897}
1898
1899void DoWhileNode::processVarDecls(ExecState *exec)
1900{
1901 statement->processVarDecls(exec);
1902}
1903
1904// ------------------------------ WhileNode ------------------------------------
1905
1906void WhileNode::ref()
1907{
1908 Node::ref();
1909 if ( statement )
1910 statement->ref();
1911 if ( expr )
1912 expr->ref();
1913}
1914
1915bool WhileNode::deref()
1916{
1917 if ( statement && statement->deref() )
1918 delete statement;
1919 if ( expr && expr->deref() )
1920 delete expr;
1921 return Node::deref();
1922}
1923
1924// ECMA 12.6.2
1925Completion WhileNode::execute(ExecState *exec)
1926{
1927 KJS_BREAKPOINT;
1928
1929 Value be, bv;
1930 Completion c;
1931 bool b(false);
1932 Value value;
1933
1934 while (1) {
1935 bv = expr->evaluate(exec);
1936 KJS_CHECKEXCEPTION
1937 b = bv.toBoolean(exec);
1938
1939 // bail out on error
1940 KJS_CHECKEXCEPTION
1941
1942 if (!b)
1943 return Completion(Normal, value);
1944
1945 c = statement->execute(exec);
1946 if (c.isValueCompletion())
1947 value = c.value();
1948
1949 if ((c.complType() == Continue) && ls.contains(c.target()))
1950 continue;
1951 if ((c.complType() == Break) && ls.contains(c.target()))
1952 return Completion(Normal, value);
1953 if (c.complType() != Normal)
1954 return c;
1955 }
1956
1957 return Completion(); // work around gcc 4.0 bug
1958}
1959
1960void WhileNode::processVarDecls(ExecState *exec)
1961{
1962 statement->processVarDecls(exec);
1963}
1964
1965// ------------------------------ ForNode --------------------------------------
1966
1967void ForNode::ref()
1968{
1969 Node::ref();
1970 if ( statement )
1971 statement->ref();
1972 if ( expr1 )
1973 expr1->ref();
1974 if ( expr2 )
1975 expr2->ref();
1976 if ( expr3 )
1977 expr3->ref();
1978}
1979
1980bool ForNode::deref()
1981{
1982 if ( statement && statement->deref() )
1983 delete statement;
1984 if ( expr1 && expr1->deref() )
1985 delete expr1;
1986 if ( expr2 && expr2->deref() )
1987 delete expr2;
1988 if ( expr3 && expr3->deref() )
1989 delete expr3;
1990 return Node::deref();
1991}
1992
1993// ECMA 12.6.3
1994Completion ForNode::execute(ExecState *exec)
1995{
1996 Value v, cval;
1997
1998 if (expr1) {
1999 v = expr1->evaluate(exec);
2000 KJS_CHECKEXCEPTION
2001 }
2002 while (1) {
2003 if (expr2) {
2004 v = expr2->evaluate(exec);
2005 KJS_CHECKEXCEPTION
2006 if (!v.toBoolean(exec))
2007 return Completion(Normal, cval);
2008 }
2009 // bail out on error
2010 KJS_CHECKEXCEPTION
2011
2012 Completion c = statement->execute(exec);
2013 if (c.isValueCompletion())
2014 cval = c.value();
2015 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2016 if ((c.complType() == Break) && ls.contains(c.target()))
2017 return Completion(Normal, cval);
2018 if (c.complType() != Normal)
2019 return c;
2020 }
2021 if (expr3) {
2022 v = expr3->evaluate(exec);
2023 KJS_CHECKEXCEPTION
2024 }
2025 }
2026
2027 return Completion(); // work around gcc 4.0 bug
2028}
2029
2030void ForNode::processVarDecls(ExecState *exec)
2031{
2032 if (expr1)
2033 expr1->processVarDecls(exec);
2034
2035 statement->processVarDecls(exec);
2036}
2037
2038// ------------------------------ ForInNode ------------------------------------
2039
2040ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
2041 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
2042{
2043}
2044
2045ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
2046 : ident(i), init(in), expr(e), statement(s)
2047{
2048 // for( var foo = bar in baz )
2049 varDecl = new VarDeclNode(ident, init);
2050 lexpr = new ResolveNode(ident);
2051}
2052
2053void ForInNode::ref()
2054{
2055 Node::ref();
2056 if ( statement )
2057 statement->ref();
2058 if ( expr )
2059 expr->ref();
2060 if ( lexpr )
2061 lexpr->ref();
2062 if ( init )
2063 init->ref();
2064 if ( varDecl )
2065 varDecl->ref();
2066}
2067
2068bool ForInNode::deref()
2069{
2070 if ( statement && statement->deref() )
2071 delete statement;
2072 if ( expr && expr->deref() )
2073 delete expr;
2074 if ( lexpr && lexpr->deref() )
2075 delete lexpr;
2076 if ( init && init->deref() )
2077 delete init;
2078 if ( varDecl && varDecl->deref() )
2079 delete varDecl;
2080 return Node::deref();
2081}
2082
2083// ECMA 12.6.4
2084Completion ForInNode::execute(ExecState *exec)
2085{
2086 Value e, retval;
2087 Object v;
2088 Completion c;
2089 ReferenceList propList;
2090
2091 if ( varDecl ) {
2092 varDecl->evaluate(exec);
2093 KJS_CHECKEXCEPTION
2094 }
2095
2096 e = expr->evaluate(exec);
2097
2098 // for Null and Undefined, we want to make sure not to go through
2099 // the loop at all, because their object wrappers will have a
2100 // property list but will throw an exception if you attempt to
2101 // access any property.
2102 if (e.type() == UndefinedType || e.type() == NullType) {
2103 return Completion(Normal, retval);
2104 }
2105
2106 KJS_CHECKEXCEPTION
2107 v = e.toObject(exec);
2108 propList = v.propList(exec);
2109
2110 ReferenceListIterator propIt = propList.begin();
2111
2112 while (propIt != propList.end()) {
2113 Identifier name = propIt->getPropertyName(exec);
2114 if (!v.hasProperty(exec,name)) {
2115 propIt++;
2116 continue;
2117 }
2118
2119 Reference ref = lexpr->evaluateReference(exec);
2120 KJS_CHECKEXCEPTION
2121 ref.putValue(exec, String(name.ustring()));
2122
2123 c = statement->execute(exec);
2124 if (c.isValueCompletion())
2125 retval = c.value();
2126
2127 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2128 if ((c.complType() == Break) && ls.contains(c.target()))
2129 break;
2130 if (c.complType() != Normal) {
2131 return c;
2132 }
2133 }
2134
2135 propIt++;
2136 }
2137
2138 // bail out on error
2139 KJS_CHECKEXCEPTION
2140
2141 return Completion(Normal, retval);
2142}
2143
2144void ForInNode::processVarDecls(ExecState *exec)
2145{
2146 statement->processVarDecls(exec);
2147}
2148
2149// ------------------------------ ContinueNode ---------------------------------
2150
2151// ECMA 12.7
2152Completion ContinueNode::execute(ExecState *exec)
2153{
2154 KJS_BREAKPOINT;
2155
2156 Value dummy;
2157 return exec->context().imp()->seenLabels()->contains(ident) ?
2158 Completion(Continue, dummy, ident) :
2159 Completion(Throw,
2160 throwError(exec, SyntaxError, "Label %s not found in containing block. Can't continue.", ident));
2161}
2162
2163// ------------------------------ BreakNode ------------------------------------
2164
2165// ECMA 12.8
2166Completion BreakNode::execute(ExecState *exec)
2167{
2168 KJS_BREAKPOINT;
2169
2170 Value dummy;
2171 return exec->context().imp()->seenLabels()->contains(ident) ?
2172 Completion(Break, dummy, ident) :
2173 Completion(Throw,
2174 throwError(exec, SyntaxError, "Label %s not found in containing block. Can't break.", ident));
2175}
2176
2177// ------------------------------ ReturnNode -----------------------------------
2178
2179void ReturnNode::ref()
2180{
2181 Node::ref();
2182 if ( value )
2183 value->ref();
2184}
2185
2186bool ReturnNode::deref()
2187{
2188 if ( value && value->deref() )
2189 delete value;
2190 return Node::deref();
2191}
2192
2193// ECMA 12.9
2194Completion ReturnNode::execute(ExecState *exec)
2195{
2196 KJS_BREAKPOINT;
2197
2198 if (!value)
2199 return Completion(ReturnValue, Undefined());
2200
2201 Value v = value->evaluate(exec);
2202 KJS_CHECKEXCEPTION
2203
2204 return Completion(ReturnValue, v);
2205}
2206
2207// ------------------------------ WithNode -------------------------------------
2208
2209void WithNode::ref()
2210{
2211 Node::ref();
2212 if ( statement )
2213 statement->ref();
2214 if ( expr )
2215 expr->ref();
2216}
2217
2218bool WithNode::deref()
2219{
2220 if ( statement && statement->deref() )
2221 delete statement;
2222 if ( expr && expr->deref() )
2223 delete expr;
2224 return Node::deref();
2225}
2226
2227// ECMA 12.10
2228Completion WithNode::execute(ExecState *exec)
2229{
2230 KJS_BREAKPOINT;
2231
2232 Value v = expr->evaluate(exec);
2233 KJS_CHECKEXCEPTION
2234 Object o = v.toObject(exec);
2235 KJS_CHECKEXCEPTION
2236 exec->context().imp()->pushScope(o);
2237 Completion res = statement->execute(exec);
2238 exec->context().imp()->popScope();
2239
2240 return res;
2241}
2242
2243void WithNode::processVarDecls(ExecState *exec)
2244{
2245 statement->processVarDecls(exec);
2246}
2247
2248// ------------------------------ CaseClauseNode -------------------------------
2249
2250void CaseClauseNode::ref()
2251{
2252 Node::ref();
2253 if ( expr )
2254 expr->ref();
2255 if ( list )
2256 list->ref();
2257}
2258
2259bool CaseClauseNode::deref()
2260{
2261 if ( expr && expr->deref() )
2262 delete expr;
2263 if ( list && list->deref() )
2264 delete list;
2265 return Node::deref();
2266}
2267
2268// ECMA 12.11
2269Value CaseClauseNode::evaluate(ExecState *exec)
2270{
2271 Value v = expr->evaluate(exec);
2272 KJS_CHECKEXCEPTIONVALUE
2273
2274 return v;
2275}
2276
2277// ECMA 12.11
2278Completion CaseClauseNode::evalStatements(ExecState *exec)
2279{
2280 if (list)
2281 return list->execute(exec);
2282 else
2283 return Completion(Normal, Undefined());
2284}
2285
2286void CaseClauseNode::processVarDecls(ExecState *exec)
2287{
2288 if (list)
2289 list->processVarDecls(exec);
2290}
2291
2292// ------------------------------ ClauseListNode -------------------------------
2293
2294void ClauseListNode::ref()
2295{
2296 for (ClauseListNode *n = this; n; n = n->nx) {
2297 n->Node::ref();
2298 if (n->cl)
2299 n->cl->ref();
2300 }
2301}
2302
2303bool ClauseListNode::deref()
2304{
2305 ClauseListNode *next;
2306 for (ClauseListNode *n = this; n; n = next) {
2307 next = n->nx;
2308 if (n->cl && n->cl->deref())
2309 delete n->cl;
2310 if (n != this && n->Node::deref())
2311 delete n;
2312 }
2313 return Node::deref();
2314}
2315
2316Value ClauseListNode::evaluate(ExecState */*exec*/)
2317{
2318 /* should never be called */
2319 assert(false);
2320 return Value();
2321}
2322
2323// ECMA 12.11
2324void ClauseListNode::processVarDecls(ExecState *exec)
2325{
2326 for (ClauseListNode *n = this; n; n = n->nx)
2327 if (n->cl)
2328 n->cl->processVarDecls(exec);
2329}
2330
2331// ------------------------------ CaseBlockNode --------------------------------
2332
2333CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2334 ClauseListNode *l2)
2335{
2336 if (l1) {
2337 list1 = l1->nx;
2338 l1->nx = 0;
2339 } else {
2340 list1 = 0;
2341 }
2342
2343 def = d;
2344
2345 if (l2) {
2346 list2 = l2->nx;
2347 l2->nx = 0;
2348 } else {
2349 list2 = 0;
2350 }
2351}
2352
2353void CaseBlockNode::ref()
2354{
2355 Node::ref();
2356 if ( def )
2357 def->ref();
2358 if ( list1 )
2359 list1->ref();
2360 if ( list2 )
2361 list2->ref();
2362}
2363
2364bool CaseBlockNode::deref()
2365{
2366 if ( def && def->deref() )
2367 delete def;
2368 if ( list1 && list1->deref() )
2369 delete list1;
2370 if ( list2 && list2->deref() )
2371 delete list2;
2372 return Node::deref();
2373}
2374
2375Value CaseBlockNode::evaluate(ExecState */*exec*/)
2376{
2377 /* should never be called */
2378 assert(false);
2379 return Value();
2380}
2381
2382// ECMA 12.11
2383Completion CaseBlockNode::evalBlock(ExecState *exec, const Value& input)
2384{
2385 Value v;
2386 Completion res;
2387 ClauseListNode *a = list1, *b = list2;
2388 CaseClauseNode *clause;
2389
2390 while (a) {
2391 clause = a->clause();
2392 a = a->next();
2393 v = clause->evaluate(exec);
2394 KJS_CHECKEXCEPTION
2395 if (strictEqual(exec, input, v)) {
2396 res = clause->evalStatements(exec);
2397 if (res.complType() != Normal)
2398 return res;
2399 while (a) {
2400 res = a->clause()->evalStatements(exec);
2401 if (res.complType() != Normal)
2402 return res;
2403 a = a->next();
2404 }
2405 break;
2406 }
2407 }
2408
2409 while (b) {
2410 clause = b->clause();
2411 b = b->next();
2412 v = clause->evaluate(exec);
2413 KJS_CHECKEXCEPTION
2414 if (strictEqual(exec, input, v)) {
2415 res = clause->evalStatements(exec);
2416 if (res.complType() != Normal)
2417 return res;
2418 goto step18;
2419 }
2420 }
2421
2422 // default clause
2423 if (def) {
2424 res = def->evalStatements(exec);
2425 if (res.complType() != Normal)
2426 return res;
2427 }
2428 b = list2;
2429 step18:
2430 while (b) {
2431 clause = b->clause();
2432 res = clause->evalStatements(exec);
2433 if (res.complType() != Normal)
2434 return res;
2435 b = b->next();
2436 }
2437
2438 // bail out on error
2439 KJS_CHECKEXCEPTION
2440
2441 return Completion(Normal);
2442}
2443
2444void CaseBlockNode::processVarDecls(ExecState *exec)
2445{
2446 if (list1)
2447 list1->processVarDecls(exec);
2448 if (def)
2449 def->processVarDecls(exec);
2450 if (list2)
2451 list2->processVarDecls(exec);
2452}
2453
2454// ------------------------------ SwitchNode -----------------------------------
2455
2456void SwitchNode::ref()
2457{
2458 Node::ref();
2459 if ( expr )
2460 expr->ref();
2461 if ( block )
2462 block->ref();
2463}
2464
2465bool SwitchNode::deref()
2466{
2467 if ( expr && expr->deref() )
2468 delete expr;
2469 if ( block && block->deref() )
2470 delete block;
2471 return Node::deref();
2472}
2473
2474// ECMA 12.11
2475Completion SwitchNode::execute(ExecState *exec)
2476{
2477 KJS_BREAKPOINT;
2478
2479 Value v = expr->evaluate(exec);
2480 KJS_CHECKEXCEPTION
2481 Completion res = block->evalBlock(exec,v);
2482
2483 if ((res.complType() == Break) && ls.contains(res.target()))
2484 return Completion(Normal, res.value());
2485 return res;
2486}
2487
2488void SwitchNode::processVarDecls(ExecState *exec)
2489{
2490 block->processVarDecls(exec);
2491}
2492
2493// ------------------------------ LabelNode ------------------------------------
2494
2495void LabelNode::ref()
2496{
2497 Node::ref();
2498 if ( statement )
2499 statement->ref();
2500}
2501
2502bool LabelNode::deref()
2503{
2504 if ( statement && statement->deref() )
2505 delete statement;
2506 return Node::deref();
2507}
2508
2509// ECMA 12.12
2510Completion LabelNode::execute(ExecState *exec)
2511{
2512 Completion e;
2513
2514 if (!exec->context().imp()->seenLabels()->push(label)) {
2515 return Completion( Throw,
2516 throwError(exec, SyntaxError, "Duplicated label %s found.", label));
2517 };
2518 e = statement->execute(exec);
2519 exec->context().imp()->seenLabels()->pop();
2520
2521 if ((e.complType() == Break) && (e.target() == label))
2522 return Completion(Normal, e.value());
2523 return e;
2524}
2525
2526void LabelNode::processVarDecls(ExecState *exec)
2527{
2528 statement->processVarDecls(exec);
2529}
2530
2531// ------------------------------ ThrowNode ------------------------------------
2532
2533void ThrowNode::ref()
2534{
2535 Node::ref();
2536 if ( expr )
2537 expr->ref();
2538}
2539
2540bool ThrowNode::deref()
2541{
2542 if ( expr && expr->deref() )
2543 delete expr;
2544 return Node::deref();
2545}
2546
2547// ECMA 12.13
2548Completion ThrowNode::execute(ExecState *exec)
2549{
2550 KJS_BREAKPOINT;
2551
2552 Value v = expr->evaluate(exec);
2553 KJS_CHECKEXCEPTION
2554
2555 // bail out on error
2556 KJS_CHECKEXCEPTION
2557
2558 return Completion(Throw, v);
2559}
2560
2561// ------------------------------ CatchNode ------------------------------------
2562
2563void CatchNode::ref()
2564{
2565 Node::ref();
2566 if ( block )
2567 block->ref();
2568}
2569
2570bool CatchNode::deref()
2571{
2572 if ( block && block->deref() )
2573 delete block;
2574 return Node::deref();
2575}
2576
2577Completion CatchNode::execute(ExecState */*exec*/)
2578{
2579 // should never be reached. execute(exec, arg) is used instead
2580 assert(0L);
2581 return Completion();
2582}
2583
2584// ECMA 12.14
2585Completion CatchNode::execute(ExecState *exec, const Value &arg)
2586{
2587 /* TODO: correct ? Not part of the spec */
2588
2589 exec->clearException();
2590
2591 Object obj(new ObjectImp());
2592 obj.put(exec, ident, arg, DontDelete);
2593 exec->context().imp()->pushScope(obj);
2594 Completion c = block->execute(exec);
2595 exec->context().imp()->popScope();
2596
2597 return c;
2598}
2599
2600void CatchNode::processVarDecls(ExecState *exec)
2601{
2602 block->processVarDecls(exec);
2603}
2604
2605// ------------------------------ FinallyNode ----------------------------------
2606
2607void FinallyNode::ref()
2608{
2609 Node::ref();
2610 if ( block )
2611 block->ref();
2612}
2613
2614bool FinallyNode::deref()
2615{
2616 if ( block && block->deref() )
2617 delete block;
2618 return Node::deref();
2619}
2620
2621// ECMA 12.14
2622Completion FinallyNode::execute(ExecState *exec)
2623{
2624 return block->execute(exec);
2625}
2626
2627void FinallyNode::processVarDecls(ExecState *exec)
2628{
2629 block->processVarDecls(exec);
2630}
2631
2632// ------------------------------ TryNode --------------------------------------
2633
2634void TryNode::ref()
2635{
2636 Node::ref();
2637 if ( block )
2638 block->ref();
2639 if ( _final )
2640 _final->ref();
2641 if ( _catch )
2642 _catch->ref();
2643}
2644
2645bool TryNode::deref()
2646{
2647 if ( block && block->deref() )
2648 delete block;
2649 if ( _final && _final->deref() )
2650 delete _final;
2651 if ( _catch && _catch->deref() )
2652 delete _catch;
2653 return Node::deref();
2654}
2655
2656// ECMA 12.14
2657Completion TryNode::execute(ExecState *exec)
2658{
2659 KJS_BREAKPOINT;
2660
2661 Completion c, c2;
2662
2663 c = block->execute(exec);
2664
2665 if (!_final) {
2666 if (c.complType() != Throw)
2667 return c;
2668 return _catch->execute(exec,c.value());
2669 }
2670
2671 if (!_catch) {
2672 c2 = _final->execute(exec);
2673 return (c2.complType() == Normal) ? c : c2;
2674 }
2675
2676 if (c.complType() == Throw)
2677 c = _catch->execute(exec,c.value());
2678
2679 c2 = _final->execute(exec);
2680 return (c2.complType() == Normal) ? c : c2;
2681}
2682
2683void TryNode::processVarDecls(ExecState *exec)
2684{
2685 block->processVarDecls(exec);
2686 if (_final)
2687 _final->processVarDecls(exec);
2688 if (_catch)
2689 _catch->processVarDecls(exec);
2690}
2691
2692// ------------------------------ ParameterNode --------------------------------
2693
2694void ParameterNode::ref()
2695{
2696 for (ParameterNode *n = this; n; n = n->next)
2697 n->Node::ref();
2698}
2699
2700bool ParameterNode::deref()
2701{
2702 ParameterNode *next;
2703 for (ParameterNode *n = this; n; n = next) {
2704 next = n->next;
2705 if (n != this && n->Node::deref())
2706 delete n;
2707 }
2708 return Node::deref();
2709}
2710
2711// ECMA 13
2712Value ParameterNode::evaluate(ExecState */*exec*/)
2713{
2714 return Undefined();
2715}
2716
2717// ------------------------------ FunctionBodyNode -----------------------------
2718
2719FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2720 : BlockNode(s)
2721{
2722 setLoc(-1, -1, -1);
2723 //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this);
2724}
2725
2726void FunctionBodyNode::processFuncDecl(ExecState *exec)
2727{
2728 if (source)
2729 source->processFuncDecl(exec);
2730}
2731
2732// ------------------------------ FuncDeclNode ---------------------------------
2733
2734void FuncDeclNode::ref()
2735{
2736 Node::ref();
2737 if ( param )
2738 param->ref();
2739 if ( body )
2740 body->ref();
2741}
2742
2743bool FuncDeclNode::deref()
2744{
2745 if ( param && param->deref() )
2746 delete param;
2747 if ( body && body->deref() )
2748 delete body;
2749 return Node::deref();
2750}
2751
2752// ECMA 13
2753void FuncDeclNode::processFuncDecl(ExecState *exec)
2754{
2755 // TODO: let this be an object with [[Class]] property "Function"
2756 FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
2757 Object func(fimp); // protect from GC
2758
2759 // Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty());
2760 List empty;
2761 Object proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
2762 proto.put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2763 func.put(exec, prototypePropertyName, proto, Internal|DontDelete);
2764
2765 int plen = 0;
2766 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2767 fimp->addParameter(p->ident());
2768
2769 func.put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
2770
2771 exec->context().imp()->variableObject().put(exec,ident,func);
2772
2773 if (body) {
2774 // hack the scope so that the function gets put as a property of func, and it's scope
2775 // contains the func as well as our current scope
2776 Object oldVar = exec->context().imp()->variableObject();
2777 exec->context().imp()->setVariableObject(func);
2778 exec->context().imp()->pushScope(func);
2779 body->processFuncDecl(exec);
2780 exec->context().imp()->popScope();
2781 exec->context().imp()->setVariableObject(oldVar);
2782 }
2783}
2784
2785// ------------------------------ FuncExprNode ---------------------------------
2786
2787void FuncExprNode::ref()
2788{
2789 Node::ref();
2790 if ( param )
2791 param->ref();
2792 if ( body )
2793 body->ref();
2794}
2795
2796bool FuncExprNode::deref()
2797{
2798 if ( param && param->deref() )
2799 delete param;
2800 if ( body && body->deref() )
2801 delete body;
2802 return Node::deref();
2803}
2804
2805
2806// ECMA 13
2807Value FuncExprNode::evaluate(ExecState *exec)
2808{
2809 FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), body, exec->context().imp()->scopeChain());
2810 Value ret(fimp);
2811 List empty;
2812 Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
2813 fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2814
2815 int plen = 0;
2816 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2817 fimp->addParameter(p->ident());
2818
2819 return ret;
2820}
2821
2822// ------------------------------ SourceElementsNode ---------------------------
2823
2824SourceElementsNode::SourceElementsNode(StatementNode *s1)
2825 : element(s1), elements(this)
2826{
2827 setLoc(s1->firstLine(), s1->lastLine(), s1->sourceId());
2828}
2829
2830SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
2831 : element(s2), elements(s1->elements)
2832{
2833 s1->elements = this;
2834 setLoc(s1->firstLine(), s2->lastLine(), s1->sourceId());
2835}
2836
2837void SourceElementsNode::ref()
2838{
2839 for (SourceElementsNode *n = this; n; n = n->elements) {
2840 n->Node::ref();
2841 if (n->element)
2842 n->element->ref();
2843 }
2844}
2845
2846bool SourceElementsNode::deref()
2847{
2848 SourceElementsNode *next;
2849 for (SourceElementsNode *n = this; n; n = next) {
2850 next = n->elements;
2851 if (n->element && n->element->deref())
2852 delete n->element;
2853 if (n != this && n->Node::deref())
2854 delete n;
2855 }
2856 return Node::deref();
2857}
2858
2859// ECMA 14
2860Completion SourceElementsNode::execute(ExecState *exec)
2861{
2862 KJS_CHECKEXCEPTION
2863
2864 Completion c1 = element->execute(exec);
2865 KJS_CHECKEXCEPTION;
2866 if (c1.complType() != Normal)
2867 return c1;
2868
2869 for (SourceElementsNode *n = elements; n; n = n->elements) {
2870 Completion c2 = n->element->execute(exec);
2871 if (c2.complType() != Normal)
2872 return c2;
2873 // The spec says to return c2 here, but it seems that mozilla returns c1 if
2874 // c2 doesn't have a value
2875 if (!c2.value().isNull())
2876 c1 = c2;
2877 }
2878
2879 return c1;
2880}
2881
2882// ECMA 14
2883void SourceElementsNode::processFuncDecl(ExecState *exec)
2884{
2885 for (SourceElementsNode *n = this; n; n = n->elements)
2886 n->element->processFuncDecl(exec);
2887}
2888
2889void SourceElementsNode::processVarDecls(ExecState *exec)
2890{
2891 for (SourceElementsNode *n = this; n; n = n->elements)
2892 n->element->processVarDecls(exec);
2893}
2894
2895ProgramNode::ProgramNode(SourceElementsNode *s): FunctionBodyNode(s) {
2896 //fprintf(stderr,"ProgramNode::ProgramNode %p\n",this);
2897}
Note: See TracBrowser for help on using the repository browser.