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

Last change on this file since 7222 was 7222, checked in by darin, 21 years ago

Reviewed by Maciej.

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