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

Last change on this file since 12512 was 12512, checked in by mjs, 19 years ago

Reviewed by Darin.


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