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

kjs

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

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
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kjs by doxygen 1.8.13
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |