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

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

JavaScriptCore:

Reviewed by Darin.

  • Add a explicit check for arguments. Previously check was done with getDirect, but since the arguments is created on-demand in ActivationImp, it doesn't show up in the test. 'arguments' should always be in the VarDeclNode's evaluation scope.
  • kjs/nodes.cpp: (VarDeclNode::evaluate): Additional check if the var decl identifier is 'arguments'

LayoutTests:

Reviewed by Darin.

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