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

Last change on this file since 1837 was 1837, checked in by mjs, 23 years ago

Phase 1 of optimization to stop allocating references through the
collector. This step clearly splits evaluating to a reference and
evaluating to a value, and moves all of the reference-specific
operations from Value to Reference. A special ConstReference class
helps out for the one case where you need special reference
operations if the result is a reference, and not otherwise.

Also, Reference now inherits privately from Value, and there is a
new ReferenceList class that inherits privately from List, so the
uses of Reference and Value are now completely orthogonal. This
means that as the next step, their implementations can be
completely disentangled.

This step has no actual performance impact.

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