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

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

Reviewed by Darin Adler.


Removed the concept of AnonymousCode. It was unused, and it doesn't
exist in the ECMA spec.


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

  • kjs/Context.cpp: (KJS::Context::Context):
  • kjs/function.h: (KJS::):
  • kjs/nodes.cpp: (ReturnNode::execute):
  • 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)
2111 return createErrorCompletion(exec, SyntaxError, "Invalid return statement.");
2112
2113 if (!value)
2114 return Completion(ReturnValue, jsUndefined());
2115
2116 JSValue *v = value->evaluate(exec);
2117 KJS_CHECKEXCEPTION
2118
2119 return Completion(ReturnValue, v);
2120}
2121
2122// ------------------------------ WithNode -------------------------------------
2123
2124// ECMA 12.10
2125Completion WithNode::execute(ExecState *exec)
2126{
2127 KJS_BREAKPOINT;
2128
2129 JSValue *v = expr->evaluate(exec);
2130 KJS_CHECKEXCEPTION
2131 JSObject *o = v->toObject(exec);
2132 KJS_CHECKEXCEPTION
2133 exec->context()->pushScope(o);
2134 Completion res = statement->execute(exec);
2135 exec->context()->popScope();
2136
2137 return res;
2138}
2139
2140void WithNode::processVarDecls(ExecState *exec)
2141{
2142 statement->processVarDecls(exec);
2143}
2144
2145// ------------------------------ CaseClauseNode -------------------------------
2146
2147// ECMA 12.11
2148JSValue *CaseClauseNode::evaluate(ExecState *exec)
2149{
2150 JSValue *v = expr->evaluate(exec);
2151 KJS_CHECKEXCEPTIONVALUE
2152
2153 return v;
2154}
2155
2156// ECMA 12.11
2157Completion CaseClauseNode::evalStatements(ExecState *exec)
2158{
2159 if (source)
2160 return source->execute(exec);
2161 else
2162 return Completion(Normal, jsUndefined());
2163}
2164
2165void CaseClauseNode::processVarDecls(ExecState *exec)
2166{
2167 if (source)
2168 source->processVarDecls(exec);
2169}
2170
2171void CaseClauseNode::processFuncDecl(ExecState* exec)
2172{
2173 if (source)
2174 source->processFuncDecl(exec);
2175}
2176
2177// ------------------------------ ClauseListNode -------------------------------
2178
2179JSValue *ClauseListNode::evaluate(ExecState *)
2180{
2181 // should never be called
2182 assert(false);
2183 return 0;
2184}
2185
2186// ECMA 12.11
2187void ClauseListNode::processVarDecls(ExecState *exec)
2188{
2189 for (ClauseListNode *n = this; n; n = n->next.get())
2190 if (n->clause)
2191 n->clause->processVarDecls(exec);
2192}
2193
2194void ClauseListNode::processFuncDecl(ExecState* exec)
2195{
2196 for (ClauseListNode* n = this; n; n = n->next.get())
2197 if (n->clause)
2198 n->clause->processFuncDecl(exec);
2199}
2200
2201void ClauseListNode::breakCycle()
2202{
2203 next = 0;
2204}
2205
2206// ------------------------------ CaseBlockNode --------------------------------
2207
2208CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2209 ClauseListNode *l2)
2210{
2211 if (l1) {
2212 list1 = l1->next.release();
2213 Parser::removeNodeCycle(list1.get());
2214 } else {
2215 list1 = 0;
2216 }
2217
2218 def = d;
2219
2220 if (l2) {
2221 list2 = l2->next.release();
2222 Parser::removeNodeCycle(list2.get());
2223 } else {
2224 list2 = 0;
2225 }
2226}
2227
2228JSValue *CaseBlockNode::evaluate(ExecState *)
2229{
2230 // should never be called
2231 assert(false);
2232 return 0;
2233}
2234
2235// ECMA 12.11
2236Completion CaseBlockNode::evalBlock(ExecState *exec, JSValue *input)
2237{
2238 JSValue *v;
2239 Completion res;
2240 ClauseListNode *a = list1.get();
2241 ClauseListNode *b = list2.get();
2242 CaseClauseNode *clause;
2243
2244 while (a) {
2245 clause = a->getClause();
2246 a = a->getNext();
2247 v = clause->evaluate(exec);
2248 KJS_CHECKEXCEPTION
2249 if (strictEqual(exec, input, v)) {
2250 res = clause->evalStatements(exec);
2251 if (res.complType() != Normal)
2252 return res;
2253 while (a) {
2254 res = a->getClause()->evalStatements(exec);
2255 if (res.complType() != Normal)
2256 return res;
2257 a = a->getNext();
2258 }
2259 break;
2260 }
2261 }
2262
2263 while (b) {
2264 clause = b->getClause();
2265 b = b->getNext();
2266 v = clause->evaluate(exec);
2267 KJS_CHECKEXCEPTION
2268 if (strictEqual(exec, input, v)) {
2269 res = clause->evalStatements(exec);
2270 if (res.complType() != Normal)
2271 return res;
2272 goto step18;
2273 }
2274 }
2275
2276 // default clause
2277 if (def) {
2278 res = def->evalStatements(exec);
2279 if (res.complType() != Normal)
2280 return res;
2281 }
2282 b = list2.get();
2283 step18:
2284 while (b) {
2285 clause = b->getClause();
2286 res = clause->evalStatements(exec);
2287 if (res.complType() != Normal)
2288 return res;
2289 b = b->getNext();
2290 }
2291
2292 // bail out on error
2293 KJS_CHECKEXCEPTION
2294
2295 return Completion(Normal);
2296}
2297
2298void CaseBlockNode::processVarDecls(ExecState *exec)
2299{
2300 if (list1)
2301 list1->processVarDecls(exec);
2302 if (def)
2303 def->processVarDecls(exec);
2304 if (list2)
2305 list2->processVarDecls(exec);
2306}
2307
2308void CaseBlockNode::processFuncDecl(ExecState* exec)
2309{
2310 if (list1)
2311 list1->processFuncDecl(exec);
2312 if (def)
2313 def->processFuncDecl(exec);
2314 if (list2)
2315 list2->processFuncDecl(exec);
2316}
2317
2318// ------------------------------ SwitchNode -----------------------------------
2319
2320// ECMA 12.11
2321Completion SwitchNode::execute(ExecState *exec)
2322{
2323 KJS_BREAKPOINT;
2324
2325 JSValue *v = expr->evaluate(exec);
2326 KJS_CHECKEXCEPTION
2327
2328 exec->context()->pushSwitch();
2329 Completion res = block->evalBlock(exec,v);
2330 exec->context()->popSwitch();
2331
2332 if ((res.complType() == Break) && ls.contains(res.target()))
2333 return Completion(Normal, res.value());
2334 return res;
2335}
2336
2337void SwitchNode::processVarDecls(ExecState *exec)
2338{
2339 block->processVarDecls(exec);
2340}
2341
2342void SwitchNode::processFuncDecl(ExecState* exec)
2343{
2344 block->processFuncDecl(exec);
2345}
2346
2347// ------------------------------ LabelNode ------------------------------------
2348
2349// ECMA 12.12
2350Completion LabelNode::execute(ExecState *exec)
2351{
2352 if (!exec->context()->seenLabels()->push(label))
2353 return createErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", label);
2354 Completion e = statement->execute(exec);
2355 exec->context()->seenLabels()->pop();
2356
2357 if ((e.complType() == Break) && (e.target() == label))
2358 return Completion(Normal, e.value());
2359 return e;
2360}
2361
2362void LabelNode::processVarDecls(ExecState *exec)
2363{
2364 statement->processVarDecls(exec);
2365}
2366
2367// ------------------------------ ThrowNode ------------------------------------
2368
2369// ECMA 12.13
2370Completion ThrowNode::execute(ExecState *exec)
2371{
2372 KJS_BREAKPOINT;
2373
2374 JSValue *v = expr->evaluate(exec);
2375 KJS_CHECKEXCEPTION
2376
2377 handleException(exec, v);
2378 return Completion(Throw, v);
2379}
2380
2381// ------------------------------ TryNode --------------------------------------
2382
2383// ECMA 12.14
2384Completion TryNode::execute(ExecState *exec)
2385{
2386 KJS_BREAKPOINT;
2387
2388 Completion c = tryBlock->execute(exec);
2389
2390 if (catchBlock && c.complType() == Throw) {
2391 JSObject *obj = new JSObject;
2392 obj->put(exec, exceptionIdent, c.value(), DontDelete);
2393 exec->context()->pushScope(obj);
2394 c = catchBlock->execute(exec);
2395 exec->context()->popScope();
2396 }
2397
2398 if (finallyBlock) {
2399 Completion c2 = finallyBlock->execute(exec);
2400 if (c2.complType() != Normal)
2401 c = c2;
2402 }
2403
2404 return c;
2405}
2406
2407void TryNode::processVarDecls(ExecState *exec)
2408{
2409 tryBlock->processVarDecls(exec);
2410 if (catchBlock)
2411 catchBlock->processVarDecls(exec);
2412 if (finallyBlock)
2413 finallyBlock->processVarDecls(exec);
2414}
2415
2416// ------------------------------ ParameterNode --------------------------------
2417
2418// ECMA 13
2419JSValue *ParameterNode::evaluate(ExecState *)
2420{
2421 return jsUndefined();
2422}
2423
2424void ParameterNode::breakCycle()
2425{
2426 next = 0;
2427}
2428
2429// ------------------------------ FunctionBodyNode -----------------------------
2430
2431FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2432 : BlockNode(s)
2433 , m_sourceURL(Lexer::curr()->sourceURL())
2434 , m_sourceId(Parser::sid)
2435{
2436
2437 setLoc(-1, -1);
2438}
2439
2440void FunctionBodyNode::processFuncDecl(ExecState *exec)
2441{
2442 if (source)
2443 source->processFuncDecl(exec);
2444}
2445
2446void FunctionBodyNode::addParam(const Identifier& ident)
2447{
2448 m_parameters.append(Parameter(ident));
2449}
2450
2451UString FunctionBodyNode::paramString() const
2452{
2453 UString s("");
2454 size_t count = numParams();
2455 for (size_t pos = 0; pos < count; ++pos) {
2456 if (!s.isEmpty())
2457 s += ", ";
2458 s += paramName(pos).ustring();
2459 }
2460
2461 return s;
2462}
2463
2464
2465// ------------------------------ FuncDeclNode ---------------------------------
2466
2467void FuncDeclNode::addParams()
2468{
2469 for (ParameterNode *p = param.get(); p != 0L; p = p->nextParam())
2470 body->addParam(p->ident());
2471}
2472
2473// ECMA 13
2474void FuncDeclNode::processFuncDecl(ExecState *exec)
2475{
2476 Context *context = exec->context();
2477
2478 // TODO: let this be an object with [[Class]] property "Function"
2479 FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2480
2481 JSObject *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2482 proto->put(exec, exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
2483 func->put(exec, exec->propertyNames().prototype, proto, Internal|DontDelete);
2484
2485 func->put(exec, exec->propertyNames().length, jsNumber(body->numParams()), ReadOnly|DontDelete|DontEnum);
2486
2487 // ECMA 10.2.2
2488 context->variableObject()->put(exec, ident, func, Internal | (context->codeType() == EvalCode ? 0 : DontDelete));
2489
2490 if (body) {
2491 // hack the scope so that the function gets put as a property of func, and it's scope
2492 // contains the func as well as our current scope
2493 JSObject *oldVar = context->variableObject();
2494 context->setVariableObject(func);
2495 context->pushScope(func);
2496 body->processFuncDecl(exec);
2497 context->popScope();
2498 context->setVariableObject(oldVar);
2499 }
2500}
2501
2502Completion FuncDeclNode::execute(ExecState *)
2503{
2504 return Completion(Normal);
2505}
2506
2507// ------------------------------ FuncExprNode ---------------------------------
2508
2509// ECMA 13
2510void FuncExprNode::addParams()
2511{
2512 for (ParameterNode *p = param.get(); p != 0L; p = p->nextParam())
2513 body->addParam(p->ident());
2514}
2515
2516JSValue *FuncExprNode::evaluate(ExecState *exec)
2517{
2518 Context *context = exec->context();
2519 bool named = !ident.isNull();
2520 JSObject *functionScopeObject = 0;
2521
2522 if (named) {
2523 // named FunctionExpressions can recursively call themselves,
2524 // but they won't register with the current scope chain and should
2525 // be contained as single property in an anonymous object.
2526 functionScopeObject = new JSObject;
2527 context->pushScope(functionScopeObject);
2528 }
2529
2530 FunctionImp* func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2531 JSObject* proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2532 proto->put(exec, exec->propertyNames().constructor, func, ReadOnly | DontDelete | DontEnum);
2533 func->put(exec, exec->propertyNames().prototype, proto, Internal | DontDelete);
2534
2535 if (named) {
2536 functionScopeObject->put(exec, ident, func, Internal | ReadOnly | (context->codeType() == EvalCode ? 0 : DontDelete));
2537 context->popScope();
2538 }
2539
2540 return func;
2541}
2542
2543// ------------------------------ SourceElementsNode ---------------------------
2544
2545int SourceElementsNode::count = 0;
2546
2547SourceElementsNode::SourceElementsNode(StatementNode *s1)
2548 : node(s1), next(this)
2549{
2550 Parser::noteNodeCycle(this);
2551 setLoc(s1->firstLine(), s1->lastLine());
2552}
2553
2554SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
2555 : node(s2), next(s1->next)
2556{
2557 s1->next = this;
2558 setLoc(s1->firstLine(), s2->lastLine());
2559}
2560
2561// ECMA 14
2562Completion SourceElementsNode::execute(ExecState *exec)
2563{
2564 KJS_CHECKEXCEPTION
2565 JSValue* v = 0;
2566 SourceElementsNode* n = this;
2567 while (1) {
2568 Completion c = n->node->execute(exec);
2569
2570 if (JSValue* v2 = c.value())
2571 v = v2;
2572 c.setValue(v);
2573
2574 if (c.complType() != Normal)
2575 return c;
2576
2577 n = n->next.get();
2578 if (!n)
2579 return c;
2580 }
2581}
2582
2583// ECMA 14
2584void SourceElementsNode::processFuncDecl(ExecState *exec)
2585{
2586 for (SourceElementsNode *n = this; n; n = n->next.get())
2587 n->node->processFuncDecl(exec);
2588}
2589
2590void SourceElementsNode::processVarDecls(ExecState *exec)
2591{
2592 for (SourceElementsNode *n = this; n; n = n->next.get())
2593 n->node->processVarDecls(exec);
2594}
2595
2596void SourceElementsNode::breakCycle()
2597{
2598 next = 0;
2599}
2600
2601ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
2602{
2603}
Note: See TracBrowser for help on using the repository browser.