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

Last change on this file since 1799 was 1799, checked in by darin, 23 years ago

top level:

  • Tests/WebFoundation-Misc/ifnsurlextensions-test.m: (TestURLCommon): Add tests for the new WebNSURLExtras methods.
  • Tests/libiftest/IFCheckLeaks.c: (IFCheckLeaksAtExit): Remove workaround for CFPreferences race condition; it's now in WebFoundation.

JavaScriptCore:

Speed improvements. 19% faster on cvs-js-performance, 1% on cvs-static-urls.

Use global string objects for length and other common property names rather
than constantly making and destroying them. Use integer versions of get() and
other related calls rather than always making a string.

Also get rid of many unneeded constructors, destructors, copy constructors, and
assignment operators. And make some functions non-virtual.

  • kjs/internal.h:
  • kjs/internal.cpp: (NumberImp::toUInt32): Implement. (ReferenceImp::ReferenceImp): Special case for numeric property names. (ReferenceImp::getPropertyName): Moved guts here from ValueImp. Handle numeric case. (ReferenceImp::getValue): Moved guts here from ValueImp. Handle numeric case. (ReferenceImp::putValue): Moved guts here from ValueImp. Handle numeric case. (ReferenceImp::deleteValue): Added. Handle numeric case.
  • kjs/array_object.h:
  • kjs/array_object.cpp: All-new array implementation that stores the elements in a C++ array rather than in a property map. (ArrayInstanceImp::ArrayInstanceImp): Allocate the C++ array. (ArrayInstanceImp::~ArrayInstanceImp): Delete the C++ array. (ArrayInstanceImp::get): Implement both the old version and the new overload that takes an unsigned index for speed. (ArrayInstanceImp::put): Implement both the old version and the new overload that takes an unsigned index for speed. (ArrayInstanceImp::hasProperty): Implement both the old version and the new overload that takes an unsigned index for speed. (ArrayInstanceImp::deleteProperty): Implement both the old version and the new overload that takes an unsigned index for speed. (ArrayInstanceImp::setLength): Added. Used by the above to resize the array. (ArrayInstanceImp::mark): Mark the elements of the array too. (ArrayPrototypeImp::ArrayPrototypeImp): Pass the length to the array instance constructor.
  • kjs/bool_object.cpp:
  • kjs/date_object.cpp:
  • kjs/error_object.cpp:
  • kjs/function.cpp:
  • kjs/function_object.cpp:
  • kjs/math_object.cpp:
  • kjs/nodes.cpp:
  • kjs/nodes.h:
  • kjs/number_object.cpp:
  • kjs/object_object.cpp:
  • kjs/regexp_object.cpp:
  • kjs/string_object.cpp:
  • kjs/nodes2string.cpp: (SourceStream::operator<<): Add a special case for char now that you can't create a UString from a char implicitly.
  • kjs/object.h:
  • kjs/object.cpp: (ObjectImp::get): Call through to the string version if the numeric version is not implemented. (ObjectImp::put): Call through to the string version if the numeric version is not implemented. (ObjectImp::hasProperty): Call through to the string version if the numeric version is not implemented. (ObjectImp::deleteProperty): Call through to the string version if the numeric version is not implemented.
  • kjs/types.h:
  • kjs/types.cpp: (Reference::Reference): Added constructors for the numeric property name case.
  • kjs/ustring.h: Made the constructor that turns a character into a string be explicit so we don't get numbers that turn themselves into strings.
  • kjs/ustring.cpp: (UString::UString): Detect the empty string case, and use a shared empty string. (UString::find): Add an overload for single character finds. (UString::rfind): Add an overload for single character finds. (KJS::operator==): Fix bug where it would call strlen(0) if the first string was not null. Also handle non-ASCII characters consistently with the rest of the code by casting to unsigned char just in case.
  • kjs/value.h: Make ValueImp and all subclasses non-copyable and non-assignable.
  • kjs/value.cpp: (ValueImp::toUInt32): New interface, mainly useful so we can detect array indices and not turn them into strings and back. (ValueImp::toInteger): Use the new toUInt32. Probably can use more improvement. (ValueImp::toInt32): Use the new toUInt32. Probably can use more improvement. (ValueImp::toUInt16): Use the new toUInt32. Probably can use more improvement. (ValueImp::getBase): Remove handling of the Reference case. That's in ReferenceImp now. (ValueImp::getPropertyName): Remove handling of the Reference case. That's in ReferenceImp now. (ValueImp::getValue): Remove handling of the Reference case. That's in ReferenceImp now. (ValueImp::putValue): Remove handling of the Reference case. That's in ReferenceImp now. (ValueImp::deleteValue): Added. Used so we can do delete the same way we do put.

WebFoundation:

  • CacheLoader.subproj/WebHTTPResourceLoader.m: (-[WebHTTPProtocolHandler createWFLoadRequest]): Fix handling of paths with queries and some other subtle path and port number handling issues by using _web_hostWithPort and _web_pathWithQuery.
  • Misc.subproj/WebNSURLExtras.h:
  • Misc.subproj/WebNSURLExtras.m: (-[NSURL _web_hostWithPort]): Added. (-[NSURL _web_pathWithQuery]): Added.
  • CacheLoader.subproj/WebResourceLoad.m: (initLoader): Get some random preference before creating threads. This makes it impossible to run into the CFPreferences race condition.

WebCore:

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