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

Last change on this file since 21080 was 21080, checked in by mjs, 18 years ago

Reviewed by Oliver.


  • use custom calling convention for everything in nodes.cpp on intel gcc for 1.5% speed boost

Nearly all functions in nodes.cpp were marked up to use the
regparm(3) calling convention under GCC for x86, since this is
faster and they are all guaranteed to be called only internally to
kjs.


The only exception is destructors, since delete doesn't know how to use a custom calling convention.


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