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

Last change on this file since 15593 was 15593, checked in by thatcher, 19 years ago

JavaScriptCore:

Reviewed by Maciej.

Bug 9686: [Drosera] Need the ability to break into Drosera on Javascript exceptions
http://bugzilla.opendarwin.org/show_bug.cgi?id=9686

JavaScriptCore portion of the fix.

  • JavaScriptCore.exp: Update symbol for change in argument type.
  • kjs/debugger.cpp: (Debugger::detach): Clear map of recent exceptions. (Debugger::hasHandledException): Track the most recent exception thrown by an interpreter. (Debugger::exception): Change exception argument to a JSValue.
  • kjs/debugger.h:
  • kjs/nodes.cpp: (Node::debugExceptionIfNeeded): Notify the debugger of an exception if it hasn't seen it before. (ThrowNode::execute): Notify the debugger that an exception is being thrown.
  • kjs/nodes.h:

2006-07-23 Geoffrey Garen <[email protected]>

Patch by Eric Albert, reviewed by Darin and me.


  • Fixed <rdar://problem/4645931> JavaScriptCore stack-scanning code crashes (Collector::markStackObjectsConservatively)


  • bindings/jni/jni_jsobject.cpp: On 64bit systems, jint is a long, not an int. (JavaJSObject::getSlot): (JavaJSObject::setSlot):
  • kjs/collector.cpp: (KJS::Collector::markCurrentThreadConservatively): Use a pointer instead of an int as 'dummy,' because on LP64 systems, an int is not pointer-aligned, and we want to scan the stack for pointers.
  • JavaScriptCore.xcodeproj/project.pbxproj: After a tense cease-fire, the XCode war has started up again!

WebCore:

Reviewed by maciej.

Bug 9686: [Drosera] Need the ability to break into Drosera on Javascript exceptions
http://bugzilla.opendarwin.org/show_bug.cgi?id=9686

WebCore portion of the fix.

  • bridge/mac/WebCoreScriptDebugger.h: (-[WebScriptDebugger exceptionRaised:sourceId:line::]): Add delegate method.
  • bridge/mac/WebCoreScriptDebugger.mm: (WebCoreScriptDebuggerImp::exception): Call delegate method when an exception is raised.

WebKit:

Reviewed by Maciej.

Bug 9686: [Drosera] Need the ability to break into Drosera on Javascript exceptions
http://bugzilla.opendarwin.org/show_bug.cgi?id=9686

WebKit portion of the fix.

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