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

Last change on this file since 26617 was 26617, checked in by ggaren, 18 years ago

JavaScriptCore:

Reviewed by Maciej Stachowiak.


Fixed http://bugs.webkit.org/show_bug.cgi?id=15490
Iteration statements sometimes incorrectly evaluate to the empty value
(KDE r670547).


[ Broken off from http://bugs.webkit.org/show_bug.cgi?id=14868 ]


This patch is a merge of KDE r670547, with substantial modification
for performance.


It fixes do-while statements to evaluate to a value. (They used
to evaluate to the empty value in all cases.)

It also fixes SourceElementsNode to maintain the value of abnormal
completions like "break" and "continue."


It also re-works the main execution loop in SourceElementsNode so that
it (1) makes a little more sense and (2) avoids unnecessary work. This
is a .28% speedup on command-line JS iBench.

  • kjs/nodes.cpp: (DoWhileNode::execute): (SourceElementsNode::execute):

LayoutTests:

Reviewed by Maciej Stachowiak.


Layout tests for http://bugs.webkit.org/show_bug.cgi?id=15490
Iteration statements sometimes incorrectly evaluate to the empty value
(KDE r670547)

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