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

Last change on this file since 10636 was 10636, checked in by eseidel, 20 years ago

Bug #: 3537
Submitted by: eseidel
Reviewed by: mjs

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