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

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

Reviewed by Tim Hatcher.


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