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

Last change on this file since 14502 was 14502, checked in by andersca, 19 years ago

JavaScriptCore:

2006-05-20 Anders Carlsson <[email protected]>

Reviewed by Geoff.

http://bugzilla.opendarwin.org/show_bug.cgi?id=8993
Support function declaration in case statements


  • kjs/grammar.y: Get rid of StatementList and use SourceElements instead.


  • kjs/nodes.cpp: (CaseClauseNode::evalStatements): (CaseClauseNode::processVarDecls): (CaseClauseNode::processFuncDecl): (ClauseListNode::processFuncDecl): (CaseBlockNode::processFuncDecl): (SwitchNode::processFuncDecl):
  • kjs/nodes.h: (KJS::CaseClauseNode::CaseClauseNode): (KJS::ClauseListNode::ClauseListNode): (KJS::ClauseListNode::getClause): (KJS::ClauseListNode::getNext): (KJS::ClauseListNode::releaseNext): (KJS::SwitchNode::SwitchNode): Add processFuncDecl for the relevant nodes.
  • kjs/nodes2string.cpp: (CaseClauseNode::streamTo): next got renamed to source.

LayoutTests:

2006-05-20 Anders Carlsson <[email protected]>

Reviewed by Geoff.

  • fast/js/function-declarations-in-switch-statement-expected.txt: Added.
  • fast/js/function-declarations-in-switch-statement.html: Added.
  • fast/js/resources/function-declarations-in-switch-statement.js: Added.
  • Property allow-tabs set to x
  • Property svn:eol-style set to native
File size: 62.9 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// ------------------------------ AssignExprNode -------------------------------
1512
1513// ECMA 12.2
1514JSValue *AssignExprNode::evaluate(ExecState *exec)
1515{
1516 return expr->evaluate(exec);
1517}
1518
1519// ------------------------------ VarDeclNode ----------------------------------
1520
1521
1522VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t)
1523 : varType(t), ident(id), init(in)
1524{
1525}
1526
1527// ECMA 12.2
1528JSValue *VarDeclNode::evaluate(ExecState *exec)
1529{
1530 JSObject *variable = exec->context().imp()->variableObject();
1531
1532 JSValue *val;
1533 if (init) {
1534 val = init->evaluate(exec);
1535 KJS_CHECKEXCEPTIONVALUE
1536 } else {
1537 // already declared? - check with getDirect so you can override
1538 // built-in properties of the global object with var declarations.
1539 if (variable->getDirect(ident))
1540 return 0;
1541 val = jsUndefined();
1542 }
1543
1544#ifdef KJS_VERBOSE
1545 printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val);
1546#endif
1547 // We use Internal to bypass all checks in derived objects, e.g. so that
1548 // "var location" creates a dynamic property instead of activating window.location.
1549 int flags = Internal;
1550 if (exec->context().imp()->codeType() != EvalCode)
1551 flags |= DontDelete;
1552 if (varType == VarDeclNode::Constant)
1553 flags |= ReadOnly;
1554 variable->put(exec, ident, val, flags);
1555
1556 return jsString(ident.ustring());
1557}
1558
1559void VarDeclNode::processVarDecls(ExecState *exec)
1560{
1561 JSObject *variable = exec->context().imp()->variableObject();
1562
1563 // If a variable by this name already exists, don't clobber it -
1564 // it might be a function parameter
1565 if (!variable->hasProperty(exec, ident)) {
1566 int flags = Internal;
1567 if (exec->context().imp()->codeType() != EvalCode)
1568 flags |= DontDelete;
1569 if (varType == VarDeclNode::Constant)
1570 flags |= ReadOnly;
1571 variable->put(exec, ident, jsUndefined(), flags);
1572 }
1573}
1574
1575// ------------------------------ VarDeclListNode ------------------------------
1576
1577// ECMA 12.2
1578JSValue *VarDeclListNode::evaluate(ExecState *exec)
1579{
1580 for (VarDeclListNode *n = this; n; n = n->next.get()) {
1581 n->var->evaluate(exec);
1582 KJS_CHECKEXCEPTIONVALUE
1583 }
1584 return jsUndefined();
1585}
1586
1587void VarDeclListNode::processVarDecls(ExecState *exec)
1588{
1589 for (VarDeclListNode *n = this; n; n = n->next.get())
1590 n->var->processVarDecls(exec);
1591}
1592
1593void VarDeclListNode::breakCycle()
1594{
1595 next = 0;
1596}
1597
1598// ------------------------------ VarStatementNode -----------------------------
1599
1600// ECMA 12.2
1601Completion VarStatementNode::execute(ExecState *exec)
1602{
1603 KJS_BREAKPOINT;
1604
1605 (void) next->evaluate(exec);
1606 KJS_CHECKEXCEPTION
1607
1608 return Completion(Normal);
1609}
1610
1611void VarStatementNode::processVarDecls(ExecState *exec)
1612{
1613 next->processVarDecls(exec);
1614}
1615
1616// ------------------------------ BlockNode ------------------------------------
1617
1618BlockNode::BlockNode(SourceElementsNode *s)
1619{
1620 if (s) {
1621 source = s->next.release();
1622 Parser::removeNodeCycle(source.get());
1623 setLoc(s->firstLine(), s->lastLine());
1624 } else {
1625 source = 0;
1626 }
1627}
1628
1629// ECMA 12.1
1630Completion BlockNode::execute(ExecState *exec)
1631{
1632 if (!source)
1633 return Completion(Normal);
1634
1635 source->processFuncDecl(exec);
1636
1637 return source->execute(exec);
1638}
1639
1640void BlockNode::processVarDecls(ExecState *exec)
1641{
1642 if (source)
1643 source->processVarDecls(exec);
1644}
1645
1646// ------------------------------ EmptyStatementNode ---------------------------
1647
1648// ECMA 12.3
1649Completion EmptyStatementNode::execute(ExecState *)
1650{
1651 return Completion(Normal);
1652}
1653
1654// ------------------------------ ExprStatementNode ----------------------------
1655
1656// ECMA 12.4
1657Completion ExprStatementNode::execute(ExecState *exec)
1658{
1659 KJS_BREAKPOINT;
1660
1661 JSValue *v = expr->evaluate(exec);
1662 KJS_CHECKEXCEPTION
1663
1664 return Completion(Normal, v);
1665}
1666
1667// ------------------------------ IfNode ---------------------------------------
1668
1669// ECMA 12.5
1670Completion IfNode::execute(ExecState *exec)
1671{
1672 KJS_BREAKPOINT;
1673
1674 JSValue *v = expr->evaluate(exec);
1675 KJS_CHECKEXCEPTION
1676 bool b = v->toBoolean(exec);
1677
1678 // if ... then
1679 if (b)
1680 return statement1->execute(exec);
1681
1682 // no else
1683 if (!statement2)
1684 return Completion(Normal);
1685
1686 // else
1687 return statement2->execute(exec);
1688}
1689
1690void IfNode::processVarDecls(ExecState *exec)
1691{
1692 statement1->processVarDecls(exec);
1693
1694 if (statement2)
1695 statement2->processVarDecls(exec);
1696}
1697
1698// ------------------------------ DoWhileNode ----------------------------------
1699
1700// ECMA 12.6.1
1701Completion DoWhileNode::execute(ExecState *exec)
1702{
1703 KJS_BREAKPOINT;
1704
1705 JSValue *bv;
1706 Completion c;
1707
1708 do {
1709 // bail out on error
1710 KJS_CHECKEXCEPTION
1711
1712 exec->context().imp()->pushIteration();
1713 c = statement->execute(exec);
1714 exec->context().imp()->popIteration();
1715 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1716 if ((c.complType() == Break) && ls.contains(c.target()))
1717 return Completion(Normal, 0);
1718 if (c.complType() != Normal)
1719 return c;
1720 }
1721 bv = expr->evaluate(exec);
1722 KJS_CHECKEXCEPTION
1723 } while (bv->toBoolean(exec));
1724
1725 return Completion(Normal, 0);
1726}
1727
1728void DoWhileNode::processVarDecls(ExecState *exec)
1729{
1730 statement->processVarDecls(exec);
1731}
1732
1733// ------------------------------ WhileNode ------------------------------------
1734
1735// ECMA 12.6.2
1736Completion WhileNode::execute(ExecState *exec)
1737{
1738 KJS_BREAKPOINT;
1739
1740 JSValue *bv;
1741 Completion c;
1742 bool b(false);
1743 JSValue *value = 0;
1744
1745 while (1) {
1746 bv = expr->evaluate(exec);
1747 KJS_CHECKEXCEPTION
1748 b = bv->toBoolean(exec);
1749
1750 // bail out on error
1751 KJS_CHECKEXCEPTION
1752
1753 if (!b)
1754 return Completion(Normal, value);
1755
1756 exec->context().imp()->pushIteration();
1757 c = statement->execute(exec);
1758 exec->context().imp()->popIteration();
1759 if (c.isValueCompletion())
1760 value = c.value();
1761
1762 if ((c.complType() == Continue) && ls.contains(c.target()))
1763 continue;
1764 if ((c.complType() == Break) && ls.contains(c.target()))
1765 return Completion(Normal, value);
1766 if (c.complType() != Normal)
1767 return c;
1768 }
1769
1770 return Completion(); // work around gcc 4.0 bug
1771}
1772
1773void WhileNode::processVarDecls(ExecState *exec)
1774{
1775 statement->processVarDecls(exec);
1776}
1777
1778// ------------------------------ ForNode --------------------------------------
1779
1780// ECMA 12.6.3
1781Completion ForNode::execute(ExecState *exec)
1782{
1783 JSValue *v, *cval = 0;
1784
1785 if (expr1) {
1786 v = expr1->evaluate(exec);
1787 KJS_CHECKEXCEPTION
1788 }
1789 while (1) {
1790 if (expr2) {
1791 v = expr2->evaluate(exec);
1792 KJS_CHECKEXCEPTION
1793 if (!v->toBoolean(exec))
1794 return Completion(Normal, cval);
1795 }
1796 // bail out on error
1797 KJS_CHECKEXCEPTION
1798
1799 exec->context().imp()->pushIteration();
1800 Completion c = statement->execute(exec);
1801 exec->context().imp()->popIteration();
1802 if (c.isValueCompletion())
1803 cval = c.value();
1804 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1805 if ((c.complType() == Break) && ls.contains(c.target()))
1806 return Completion(Normal, cval);
1807 if (c.complType() != Normal)
1808 return c;
1809 }
1810 if (expr3) {
1811 v = expr3->evaluate(exec);
1812 KJS_CHECKEXCEPTION
1813 }
1814 }
1815
1816 return Completion(); // work around gcc 4.0 bug
1817}
1818
1819void ForNode::processVarDecls(ExecState *exec)
1820{
1821 if (expr1)
1822 expr1->processVarDecls(exec);
1823
1824 statement->processVarDecls(exec);
1825}
1826
1827// ------------------------------ ForInNode ------------------------------------
1828
1829ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
1830 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
1831{
1832}
1833
1834ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
1835 : ident(i), init(in), expr(e), statement(s)
1836{
1837 // for( var foo = bar in baz )
1838 varDecl = new VarDeclNode(ident, init.get(), VarDeclNode::Variable);
1839 lexpr = new ResolveNode(ident);
1840}
1841
1842// ECMA 12.6.4
1843Completion ForInNode::execute(ExecState *exec)
1844{
1845 JSValue *e;
1846 JSValue *retval = 0;
1847 JSObject *v;
1848 Completion c;
1849 ReferenceList propList;
1850
1851 if (varDecl) {
1852 varDecl->evaluate(exec);
1853 KJS_CHECKEXCEPTION
1854 }
1855
1856 e = expr->evaluate(exec);
1857
1858 // for Null and Undefined, we want to make sure not to go through
1859 // the loop at all, because their object wrappers will have a
1860 // property list but will throw an exception if you attempt to
1861 // access any property.
1862 if (e->isUndefinedOrNull()) {
1863 return Completion(Normal, 0);
1864 }
1865
1866 KJS_CHECKEXCEPTION
1867 v = e->toObject(exec);
1868 propList = v->propList(exec);
1869
1870 ReferenceListIterator propIt = propList.begin();
1871
1872 while (propIt != propList.end()) {
1873 Identifier name = propIt->getPropertyName(exec);
1874 if (!v->hasProperty(exec, name)) {
1875 propIt++;
1876 continue;
1877 }
1878
1879 JSValue *str = jsString(name.ustring());
1880
1881 if (lexpr->isResolveNode()) {
1882 const Identifier &ident = static_cast<ResolveNode *>(lexpr.get())->identifier();
1883
1884 const ScopeChain& chain = exec->context().imp()->scopeChain();
1885 ScopeChainIterator iter = chain.begin();
1886 ScopeChainIterator end = chain.end();
1887
1888 // we must always have something in the scope chain
1889 assert(iter != end);
1890
1891 PropertySlot slot;
1892 JSObject *o;
1893 do {
1894 o = *iter;
1895 if (o->getPropertySlot(exec, ident, slot)) {
1896 o->put(exec, ident, str);
1897 break;
1898 }
1899 ++iter;
1900 } while (iter != end);
1901
1902 if (iter == end)
1903 o->put(exec, ident, str);
1904 } else if (lexpr->isDotAccessorNode()) {
1905 const Identifier& ident = static_cast<DotAccessorNode *>(lexpr.get())->identifier();
1906 JSValue *v = static_cast<DotAccessorNode *>(lexpr.get())->base()->evaluate(exec);
1907 KJS_CHECKEXCEPTION
1908 JSObject *o = v->toObject(exec);
1909
1910 o->put(exec, ident, str);
1911 } else {
1912 assert(lexpr->isBracketAccessorNode());
1913 JSValue *v = static_cast<BracketAccessorNode *>(lexpr.get())->base()->evaluate(exec);
1914 KJS_CHECKEXCEPTION
1915 JSValue *v2 = static_cast<BracketAccessorNode *>(lexpr.get())->subscript()->evaluate(exec);
1916 KJS_CHECKEXCEPTION
1917 JSObject *o = v->toObject(exec);
1918
1919 uint32_t i;
1920 if (v2->getUInt32(i))
1921 o->put(exec, i, str);
1922 o->put(exec, Identifier(v2->toString(exec)), str);
1923 }
1924
1925 KJS_CHECKEXCEPTION
1926
1927 exec->context().imp()->pushIteration();
1928 c = statement->execute(exec);
1929 exec->context().imp()->popIteration();
1930 if (c.isValueCompletion())
1931 retval = c.value();
1932
1933 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1934 if ((c.complType() == Break) && ls.contains(c.target()))
1935 break;
1936 if (c.complType() != Normal) {
1937 return c;
1938 }
1939 }
1940
1941 propIt++;
1942 }
1943
1944 // bail out on error
1945 KJS_CHECKEXCEPTION
1946
1947 return Completion(Normal, retval);
1948}
1949
1950void ForInNode::processVarDecls(ExecState *exec)
1951{
1952 if (varDecl)
1953 varDecl->processVarDecls(exec);
1954 statement->processVarDecls(exec);
1955}
1956
1957// ------------------------------ ContinueNode ---------------------------------
1958
1959// ECMA 12.7
1960Completion ContinueNode::execute(ExecState *exec)
1961{
1962 KJS_BREAKPOINT;
1963
1964 if (ident.isEmpty() && !exec->context().imp()->inIteration())
1965 return createErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
1966 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
1967 return createErrorCompletion(exec, SyntaxError, "Label %s not found.", ident);
1968 else
1969 return Completion(Continue, 0, ident);
1970}
1971
1972// ------------------------------ BreakNode ------------------------------------
1973
1974// ECMA 12.8
1975Completion BreakNode::execute(ExecState *exec)
1976{
1977 KJS_BREAKPOINT;
1978
1979 if (ident.isEmpty() && !exec->context().imp()->inIteration() &&
1980 !exec->context().imp()->inSwitch())
1981 return createErrorCompletion(exec, SyntaxError, "Invalid break statement.");
1982 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
1983 return createErrorCompletion(exec, SyntaxError, "Label %s not found.");
1984 else
1985 return Completion(Break, 0, ident);
1986}
1987
1988// ------------------------------ ReturnNode -----------------------------------
1989
1990// ECMA 12.9
1991Completion ReturnNode::execute(ExecState *exec)
1992{
1993 KJS_BREAKPOINT;
1994
1995 CodeType codeType = exec->context().imp()->codeType();
1996 if (codeType != FunctionCode && codeType != AnonymousCode ) {
1997 return createErrorCompletion(exec, SyntaxError, "Invalid return statement.");
1998 }
1999
2000 if (!value)
2001 return Completion(ReturnValue, jsUndefined());
2002
2003 JSValue *v = value->evaluate(exec);
2004 KJS_CHECKEXCEPTION
2005
2006 return Completion(ReturnValue, v);
2007}
2008
2009// ------------------------------ WithNode -------------------------------------
2010
2011// ECMA 12.10
2012Completion WithNode::execute(ExecState *exec)
2013{
2014 KJS_BREAKPOINT;
2015
2016 JSValue *v = expr->evaluate(exec);
2017 KJS_CHECKEXCEPTION
2018 JSObject *o = v->toObject(exec);
2019 KJS_CHECKEXCEPTION
2020 exec->context().imp()->pushScope(o);
2021 Completion res = statement->execute(exec);
2022 exec->context().imp()->popScope();
2023
2024 return res;
2025}
2026
2027void WithNode::processVarDecls(ExecState *exec)
2028{
2029 statement->processVarDecls(exec);
2030}
2031
2032// ------------------------------ CaseClauseNode -------------------------------
2033
2034// ECMA 12.11
2035JSValue *CaseClauseNode::evaluate(ExecState *exec)
2036{
2037 JSValue *v = expr->evaluate(exec);
2038 KJS_CHECKEXCEPTIONVALUE
2039
2040 return v;
2041}
2042
2043// ECMA 12.11
2044Completion CaseClauseNode::evalStatements(ExecState *exec)
2045{
2046 if (source)
2047 return source->execute(exec);
2048 else
2049 return Completion(Normal, jsUndefined());
2050}
2051
2052void CaseClauseNode::processVarDecls(ExecState *exec)
2053{
2054 if (source)
2055 source->processVarDecls(exec);
2056}
2057
2058void CaseClauseNode::processFuncDecl(ExecState* exec)
2059{
2060 if (source)
2061 source->processFuncDecl(exec);
2062}
2063
2064// ------------------------------ ClauseListNode -------------------------------
2065
2066JSValue *ClauseListNode::evaluate(ExecState *)
2067{
2068 // should never be called
2069 assert(false);
2070 return 0;
2071}
2072
2073// ECMA 12.11
2074void ClauseListNode::processVarDecls(ExecState *exec)
2075{
2076 for (ClauseListNode *n = this; n; n = n->next.get())
2077 if (n->clause)
2078 n->clause->processVarDecls(exec);
2079}
2080
2081void ClauseListNode::processFuncDecl(ExecState* exec)
2082{
2083 for (ClauseListNode* n = this; n; n = n->next.get())
2084 if (n->clause)
2085 n->clause->processFuncDecl(exec);
2086}
2087
2088void ClauseListNode::breakCycle()
2089{
2090 next = 0;
2091}
2092
2093// ------------------------------ CaseBlockNode --------------------------------
2094
2095CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2096 ClauseListNode *l2)
2097{
2098 if (l1) {
2099 list1 = l1->next.release();
2100 Parser::removeNodeCycle(list1.get());
2101 } else {
2102 list1 = 0;
2103 }
2104
2105 def = d;
2106
2107 if (l2) {
2108 list2 = l2->next.release();
2109 Parser::removeNodeCycle(list2.get());
2110 } else {
2111 list2 = 0;
2112 }
2113}
2114
2115JSValue *CaseBlockNode::evaluate(ExecState *)
2116{
2117 // should never be called
2118 assert(false);
2119 return 0;
2120}
2121
2122// ECMA 12.11
2123Completion CaseBlockNode::evalBlock(ExecState *exec, JSValue *input)
2124{
2125 JSValue *v;
2126 Completion res;
2127 ClauseListNode *a = list1.get();
2128 ClauseListNode *b = list2.get();
2129 CaseClauseNode *clause;
2130
2131 while (a) {
2132 clause = a->getClause();
2133 a = a->getNext();
2134 v = clause->evaluate(exec);
2135 KJS_CHECKEXCEPTION
2136 if (strictEqual(exec, input, v)) {
2137 res = clause->evalStatements(exec);
2138 if (res.complType() != Normal)
2139 return res;
2140 while (a) {
2141 res = a->getClause()->evalStatements(exec);
2142 if (res.complType() != Normal)
2143 return res;
2144 a = a->getNext();
2145 }
2146 break;
2147 }
2148 }
2149
2150 while (b) {
2151 clause = b->getClause();
2152 b = b->getNext();
2153 v = clause->evaluate(exec);
2154 KJS_CHECKEXCEPTION
2155 if (strictEqual(exec, input, v)) {
2156 res = clause->evalStatements(exec);
2157 if (res.complType() != Normal)
2158 return res;
2159 goto step18;
2160 }
2161 }
2162
2163 // default clause
2164 if (def) {
2165 res = def->evalStatements(exec);
2166 if (res.complType() != Normal)
2167 return res;
2168 }
2169 b = list2.get();
2170 step18:
2171 while (b) {
2172 clause = b->getClause();
2173 res = clause->evalStatements(exec);
2174 if (res.complType() != Normal)
2175 return res;
2176 b = b->getNext();
2177 }
2178
2179 // bail out on error
2180 KJS_CHECKEXCEPTION
2181
2182 return Completion(Normal);
2183}
2184
2185void CaseBlockNode::processVarDecls(ExecState *exec)
2186{
2187 if (list1)
2188 list1->processVarDecls(exec);
2189 if (def)
2190 def->processVarDecls(exec);
2191 if (list2)
2192 list2->processVarDecls(exec);
2193}
2194
2195void CaseBlockNode::processFuncDecl(ExecState* exec)
2196{
2197 if (list1)
2198 list1->processFuncDecl(exec);
2199 if (def)
2200 def->processFuncDecl(exec);
2201 if (list2)
2202 list2->processFuncDecl(exec);
2203}
2204
2205// ------------------------------ SwitchNode -----------------------------------
2206
2207// ECMA 12.11
2208Completion SwitchNode::execute(ExecState *exec)
2209{
2210 KJS_BREAKPOINT;
2211
2212 JSValue *v = expr->evaluate(exec);
2213 KJS_CHECKEXCEPTION
2214
2215 exec->context().imp()->pushSwitch();
2216 Completion res = block->evalBlock(exec,v);
2217 exec->context().imp()->popSwitch();
2218
2219 if ((res.complType() == Break) && ls.contains(res.target()))
2220 return Completion(Normal, res.value());
2221 return res;
2222}
2223
2224void SwitchNode::processVarDecls(ExecState *exec)
2225{
2226 block->processVarDecls(exec);
2227}
2228
2229void SwitchNode::processFuncDecl(ExecState* exec)
2230{
2231 block->processFuncDecl(exec);
2232}
2233
2234// ------------------------------ LabelNode ------------------------------------
2235
2236// ECMA 12.12
2237Completion LabelNode::execute(ExecState *exec)
2238{
2239 if (!exec->context().imp()->seenLabels()->push(label))
2240 return createErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", label);
2241 Completion e = statement->execute(exec);
2242 exec->context().imp()->seenLabels()->pop();
2243
2244 if ((e.complType() == Break) && (e.target() == label))
2245 return Completion(Normal, e.value());
2246 return e;
2247}
2248
2249void LabelNode::processVarDecls(ExecState *exec)
2250{
2251 statement->processVarDecls(exec);
2252}
2253
2254// ------------------------------ ThrowNode ------------------------------------
2255
2256// ECMA 12.13
2257Completion ThrowNode::execute(ExecState *exec)
2258{
2259 KJS_BREAKPOINT;
2260
2261 JSValue *v = expr->evaluate(exec);
2262 KJS_CHECKEXCEPTION
2263
2264 return Completion(Throw, v);
2265}
2266
2267// ------------------------------ TryNode --------------------------------------
2268
2269// ECMA 12.14
2270Completion TryNode::execute(ExecState *exec)
2271{
2272 KJS_BREAKPOINT;
2273
2274 Completion c = tryBlock->execute(exec);
2275
2276 if (catchBlock && c.complType() == Throw) {
2277 JSObject *obj = new JSObject;
2278 obj->put(exec, exceptionIdent, c.value(), DontDelete);
2279 exec->context().imp()->pushScope(obj);
2280 c = catchBlock->execute(exec);
2281 exec->context().imp()->popScope();
2282 }
2283
2284 if (finallyBlock) {
2285 Completion c2 = finallyBlock->execute(exec);
2286 if (c2.complType() != Normal)
2287 c = c2;
2288 }
2289
2290 return c;
2291}
2292
2293void TryNode::processVarDecls(ExecState *exec)
2294{
2295 tryBlock->processVarDecls(exec);
2296 if (catchBlock)
2297 catchBlock->processVarDecls(exec);
2298 if (finallyBlock)
2299 finallyBlock->processVarDecls(exec);
2300}
2301
2302// ------------------------------ ParameterNode --------------------------------
2303
2304// ECMA 13
2305JSValue *ParameterNode::evaluate(ExecState *)
2306{
2307 return jsUndefined();
2308}
2309
2310void ParameterNode::breakCycle()
2311{
2312 next = 0;
2313}
2314
2315// ------------------------------ FunctionBodyNode -----------------------------
2316
2317FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2318 : BlockNode(s)
2319 , m_sourceURL(Lexer::curr()->sourceURL())
2320 , m_sourceId(Parser::sid)
2321{
2322
2323 setLoc(-1, -1);
2324}
2325
2326void FunctionBodyNode::processFuncDecl(ExecState *exec)
2327{
2328 if (source)
2329 source->processFuncDecl(exec);
2330}
2331
2332// ------------------------------ FuncDeclNode ---------------------------------
2333
2334// ECMA 13
2335void FuncDeclNode::processFuncDecl(ExecState *exec)
2336{
2337 ContextImp *context = exec->context().imp();
2338
2339 // TODO: let this be an object with [[Class]] property "Function"
2340 FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2341
2342 JSObject *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2343 proto->put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2344 func->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2345
2346 int plen = 0;
2347 for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
2348 func->addParameter(p->ident());
2349
2350 func->put(exec, lengthPropertyName, jsNumber(plen), ReadOnly|DontDelete|DontEnum);
2351
2352 // ECMA 10.2.2
2353 context->variableObject()->put(exec, ident, func, Internal | (context->codeType() == EvalCode ? 0 : DontDelete));
2354
2355 if (body) {
2356 // hack the scope so that the function gets put as a property of func, and it's scope
2357 // contains the func as well as our current scope
2358 JSObject *oldVar = context->variableObject();
2359 context->setVariableObject(func);
2360 context->pushScope(func);
2361 body->processFuncDecl(exec);
2362 context->popScope();
2363 context->setVariableObject(oldVar);
2364 }
2365}
2366
2367Completion FuncDeclNode::execute(ExecState *)
2368{
2369 return Completion(Normal);
2370}
2371
2372// ------------------------------ FuncExprNode ---------------------------------
2373
2374// ECMA 13
2375JSValue *FuncExprNode::evaluate(ExecState *exec)
2376{
2377 ContextImp *context = exec->context().imp();
2378 bool named = !ident.isNull();
2379 JSObject *functionScopeObject = 0;
2380
2381 if (named) {
2382 // named FunctionExpressions can recursively call themselves,
2383 // but they won't register with the current scope chain and should
2384 // be contained as single property in an anonymous object.
2385 functionScopeObject = new JSObject;
2386 context->pushScope(functionScopeObject);
2387 }
2388
2389 FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2390 JSObject *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2391 proto->put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2392 func->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2393
2394 int plen = 0;
2395 for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
2396 func->addParameter(p->ident());
2397
2398 if (named) {
2399 functionScopeObject->put(exec, ident, func, Internal | ReadOnly | (context->codeType() == EvalCode ? 0 : DontDelete));
2400 context->popScope();
2401 }
2402
2403 return func;
2404}
2405
2406// ------------------------------ SourceElementsNode ---------------------------
2407
2408int SourceElementsNode::count = 0;
2409
2410SourceElementsNode::SourceElementsNode(StatementNode *s1)
2411 : node(s1), next(this)
2412{
2413 Parser::noteNodeCycle(this);
2414 setLoc(s1->firstLine(), s1->lastLine());
2415}
2416
2417SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
2418 : node(s2), next(s1->next)
2419{
2420 s1->next = this;
2421 setLoc(s1->firstLine(), s2->lastLine());
2422}
2423
2424// ECMA 14
2425Completion SourceElementsNode::execute(ExecState *exec)
2426{
2427 KJS_CHECKEXCEPTION
2428
2429 Completion c1 = node->execute(exec);
2430 KJS_CHECKEXCEPTION;
2431 if (c1.complType() != Normal)
2432 return c1;
2433
2434 for (SourceElementsNode *n = next.get(); n; n = n->next.get()) {
2435 Completion c2 = n->node->execute(exec);
2436 if (c2.complType() != Normal)
2437 return c2;
2438 // The spec says to return c2 here, but it seems that mozilla returns c1 if
2439 // c2 doesn't have a value
2440 if (c2.value())
2441 c1 = c2;
2442 }
2443
2444 return c1;
2445}
2446
2447// ECMA 14
2448void SourceElementsNode::processFuncDecl(ExecState *exec)
2449{
2450 for (SourceElementsNode *n = this; n; n = n->next.get())
2451 n->node->processFuncDecl(exec);
2452}
2453
2454void SourceElementsNode::processVarDecls(ExecState *exec)
2455{
2456 for (SourceElementsNode *n = this; n; n = n->next.get())
2457 n->node->processVarDecls(exec);
2458}
2459
2460void SourceElementsNode::breakCycle()
2461{
2462 next = 0;
2463}
2464
2465ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
2466{
2467}
Note: See TracBrowser for help on using the repository browser.