• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kjs
 

kjs

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

kjs

Skip menu "kjs"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kjs

Skip menu "kjs"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kjs by doxygen 1.9.1
This website is maintained by Timothy Pearson.