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

Last change on this file since 14429 was 14429, checked in by staikos, 19 years ago

Reviewed by Maciej.

Fix some warnings and strict compilation errors.

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