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

Last change on this file since 15155 was 15155, checked in by darin, 19 years ago

Reviewed by Maciej.
Tweaked a bit by Darin.

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