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

Last change on this file since 6360 was 6360, checked in by mjs, 21 years ago

Reviewed by Darin.

  • fixed <rdar://problem/3600695>: String manipulation in JavaScript 24fun test is very slow (slow)
  • fixed <rdar://problem/3600691>: Table generation test is really slow
  • fixed <rdar://problem/3600661>: 24fun date test is really slow

80% speedup on the string test, lesser speedups on the other two.

Two different optimizations here:

1) Avoid large overhead of scanning strings to see if they are all
ASCII before numeric conversion.

  • kjs/nodes.cpp: (AssignNode::evaluate): Don't convert to integer until we know for sure the operation will need it. Attempting to convert strings to numbers is a waste when they are being appended with +=.

2) Avoid huge cost of appending strings.

This is done by allowing multiple strings to share a buffer but
actually use different ranges of it. The first time a string is
appended to, we start leaving at least 10% extra space in the
buffer, so doing N appends to the same string takes O(log N)
mallocs instead of O(N).

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