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

Last change on this file since 6768 was 6768, checked in by kdecker, 21 years ago

JavaScriptCore:

Reviewed by Dave.

  • ObjC bindings do not (yet) pass along sourceurl or line numbers
  • we don't have a way as of yet to accomidate line numbers and urls for dynamic javascript
  • changed the wording of an error message
  • the lexer, parser, and interpreter have been made "sourceURL aware"
  • stored the url into Error
  • bindings/NP_jsobject.cpp: (NPN_Evaluate):
  • bindings/jni/jni_jsobject.cpp: (JSObject::eval):
  • bindings/objc/WebScriptObject.mm: (-[WebScriptObject evaluateWebScript:]):
  • kjs/function.cpp: (GlobalFuncImp::call):
  • kjs/function_object.cpp: (FunctionObjectImp::construct):
  • kjs/internal.cpp: (Parser::parse): (InterpreterImp::checkSyntax): (InterpreterImp::evaluate):
  • kjs/internal.h:
  • kjs/interpreter.cpp: (Interpreter::evaluate):
  • kjs/interpreter.h:
  • kjs/lexer.cpp: (Lexer::setCode):
  • kjs/lexer.h: (KJS::Lexer::sourceURL):
  • kjs/nodes.cpp: (Node::Node): (Node::throwError): (FunctionCallNode::evaluate):
  • kjs/nodes.h:
  • kjs/object.cpp: (KJS::Error::create):
  • kjs/object.h:

WebCore:

Reviewed by Dave.

  • kwq/KWQKHTMLPart.mm: addMessagetoConsole places sourceURL in the dictionary
  • khtml/xml/dom_docimpl.cpp: right now, we don't have a way to get a url, so we leave this blank
  • khtml/ecma/kjs_window.cpp: still need to get the real line number and sourceURL
  • khtml/ecma/kjs_proxy.cpp: now passing the sourceURL to addMessageToConsole
  • khtml/ecma/kjs_events.cpp: still need to grab an accurate line number and sourceURL
  • khtml/ecma/kjs_events.cpp: (JSEventListener::handleEvent): (JSLazyEventListener::handleEvent):
  • khtml/ecma/kjs_proxy.cpp: (KJSProxyImpl::evaluate):
  • khtml/ecma/kjs_window.cpp: (Window::isSafeScript): (ScheduledAction::execute):
  • khtml/xml/dom_docimpl.cpp: (DocumentImpl::open):
  • kwq/KWQKHTMLPart.h:
  • kwq/KWQKHTMLPart.mm: (KWQKHTMLPart::addMessageToConsole):

WebBrowser:

Reviewed by Dave.

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