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

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

JavaScriptCore:

Rubber stamped by Maciej.

  • did long-promised KJS renaming:

ValueImp -> JSValue
ObjectImp -> JSObject
AllocatedValueImp -> JSCell

A renaming to get a class out of the way

KJS::Bindings::JSObject -> JavaJSObject

and some other "imp-reduction" renaming

*InstanceImp -> *Instance
*ProtoFuncImp -> *ProtoFunc
*PrototypeImp -> *Prototype
ArgumentsImp -> Arguments
RuntimeArrayImp -> RuntimeArray
RuntimeMethodImp -> RuntimeMethod

  • most files and functions

WebCore:

Rubber stamped by Maciej.

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