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

Last change on this file since 10354 was 10354, checked in by mjs, 20 years ago

Reviewed by John.

<rdar://problem/4224911> many many leaks in kjsyyparse with malformed Javascript

Record all nodes that are created during parsing, and delete any
that are left floating with a refcount of 0.

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