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

Last change on this file since 26914 was 26914, checked in by darin, 18 years ago

Reviewed by Eric.

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