38 #include "collector.h" 41 #include "function_object.h" 46 #include "interpreter.h" 48 #include "operations.h" 53 #define KJS_BREAKPOINT \ 54 if (!hitStatement(exec)) \ 55 return Completion(Normal); 57 #define KJS_ABORTPOINT \ 58 if (exec->dynamicInterpreter()->imp()->debugger() && \ 59 exec->dynamicInterpreter()->imp()->debugger()->imp()->aborted()) \ 60 return Completion(Normal); 62 #define KJS_CHECKEXCEPTION \ 63 if (exec->hadException()) { \ 64 setExceptionDetailsIfNeeded(exec); \ 65 return Completion(Throw, exec->exception()); \ 67 if (Collector::outOfMemory()) \ 68 return Completion(Throw, Error::create(exec,GeneralError,"Out of memory")); 70 #define KJS_CHECKEXCEPTIONVALUE \ 71 if (exec->hadException()) { \ 72 setExceptionDetailsIfNeeded(exec); \ 73 return exec->exception(); \ 75 if (Collector::outOfMemory()) \ 76 return Undefined(); // will be picked up by KJS_CHECKEXCEPTION 78 #define KJS_CHECKEXCEPTIONREFERENCE \ 79 if (exec->hadException()) { \ 80 setExceptionDetailsIfNeeded(exec); \ 81 return Reference::makeValueReference(Undefined()); \ 83 if (Collector::outOfMemory()) \ 84 return Reference::makeValueReference(Undefined()); // will be picked up by KJS_CHECKEXCEPTION 86 #define KJS_CHECKEXCEPTIONLIST \ 87 if (exec->hadException()) { \ 88 setExceptionDetailsIfNeeded(exec); \ 91 if (Collector::outOfMemory()) \ 92 return List(); // will be picked up by KJS_CHECKEXCEPTION 95 std::list<Node *> * Node::s_nodes = 0L;
102 line = Lexer::curr()->lineNo();
106 s_nodes =
new std::list<Node *>;
107 s_nodes->push_back(
this);
114 s_nodes->remove(
this );
120 Value v = evaluate(exec);
121 KJS_CHECKEXCEPTIONREFERENCE
122 return Reference::makeValueReference(v);
130 return evaluateReference(exec).getValue(exec);
133 bool Node::toBoolean(
ExecState *exec)
const 139 double Node::toNumber(
ExecState *exec)
const 142 return evaluate(exec).toNumber(exec);
147 return evaluate(exec).toString(exec);
151 void Node::finalCheck()
154 fprintf(stderr,
"Node::finalCheck(): list 0\n");
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 );
166 Value Node::throwError(
ExecState *exec, ErrorType e,
const char *msg)
const 168 Object err = Error::create(exec, e, msg, lineNo(), sourceId());
169 exec->setException(err);
173 Value Node::throwError(
ExecState *exec, ErrorType e,
const char *msg,
174 const Value &v,
const Node *expr)
const 177 char *exprStr = strdup(expr->toCode().ascii());
179 int length = strlen(msg) - 4 + strlen(vStr) + strlen(exprStr) + 1 ;
180 char *str =
new char[length];
181 sprintf(str, msg, vStr, exprStr);
185 Value result = throwError(exec, e, str);
193 const char *l = label.
ascii();
194 int length = strlen(msg) - 2 + strlen(l) + 1 ;
195 char *message =
new char[length];
196 sprintf(message, msg, l);
198 Value result = throwError(exec, e, message);
205 void Node::setExceptionDetailsIfNeeded(
ExecState *exec)
const 207 if (exec->hadException()) {
211 exception.
put(exec,
"line",
Number(line));
218 StatementNode::StatementNode() : l0(-1), l1(-1), sourceCode(0), breakPoint(false)
222 StatementNode::~StatementNode()
228 void StatementNode::setLoc(
int line0,
int line1, SourceCode *src)
233 if (sourceCode != src) {
242 bool StatementNode::hitStatement(
ExecState *exec)
245 assert(exec->
context().imp()->sourceId == sourceCode->sid);
246 exec->
context().imp()->setLines(l0,l1);
249 return dbg->atStatement(exec);
255 bool StatementNode::abortStatement(
ExecState *exec)
259 return dbg->imp()->aborted();
264 void StatementNode::processFuncDecl(
ExecState *)
275 bool NullNode::toBoolean(
ExecState *)
const 280 double NullNode::toNumber(
ExecState *)
const 297 bool BooleanNode::toBoolean(
ExecState *)
const 302 double BooleanNode::toNumber(
ExecState *)
const 304 return val ? 1.0 : 0.0;
309 return val ?
"true" :
"false";
319 bool NumberNode::toBoolean(
ExecState *)
const 321 return !((val == 0) || isNaN(val));
324 double NumberNode::toNumber(
ExecState *)
const 341 bool StringNode::toBoolean(
ExecState *)
const 343 return !val.isEmpty();
346 double StringNode::toNumber(
ExecState *)
const 348 return val.toDouble();
370 bool RegExpNode::toBoolean(
ExecState *)
const 380 return exec->
context().imp()->thisValue();
388 return evaluateReference(exec).getValue(exec);
395 while (!chain.isEmpty()) {
396 ObjectImp *o = chain.top();
400 if (o->hasProperty(exec,ident)) {
411 cerr <<
"Resolve::evaluateReference: didn't find '" << ident.ustring().ascii() <<
"'" <<
endl;
418 void GroupNode::ref()
425 bool GroupNode::deref()
427 if ( group && group->deref() )
429 return Node::deref();
435 return group->evaluate(exec);
440 return group->evaluateReference(exec);
445 void ElementNode::ref()
447 for (ElementNode *n =
this; n; n = n->list) {
454 bool ElementNode::deref()
457 for (ElementNode *n =
this; n; n = next) {
459 if (n->node && n->node->deref())
461 if (n !=
this && n->Node::deref())
464 return Node::deref();
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);
483 void ArrayNode::ref()
490 bool ArrayNode::deref()
492 if ( element && element->deref() )
494 return Node::deref();
504 array =
Object(static_cast<ObjectImp*>(element->evaluate(exec).imp()));
505 KJS_CHECKEXCEPTIONVALUE
506 length = opt ? array.
get(exec,lengthPropertyName).
toInt32(exec) : 0;
509 array =
Object(static_cast<ObjectImp*>(newArr.imp()));
514 array.
put(exec,lengthPropertyName,
Number(elision + length), DontEnum | DontDelete);
521 void ObjectLiteralNode::ref()
528 bool ObjectLiteralNode::deref()
530 if ( list && list->deref() )
532 return Node::deref();
539 return list->evaluate(exec);
546 void PropertyValueNode::ref()
548 for (PropertyValueNode *n =
this; n; n = n->list) {
557 bool PropertyValueNode::deref()
559 PropertyValueNode *next;
560 for (PropertyValueNode *n =
this; n; n = next) {
562 if ( n->name && n->name->deref() )
564 if ( n->assign && n->assign->deref() )
566 if (n !=
this && n->Node::deref() )
569 return Node::deref();
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
599 s =
String(str.ustring());
607 void AccessorNode1::ref()
616 bool AccessorNode1::deref()
618 if ( expr1 && expr1->deref() )
620 if ( expr2 && expr2->deref() )
622 return Node::deref();
628 Value v1 = expr1->evaluate(exec);
629 KJS_CHECKEXCEPTIONREFERENCE
630 Value v2 = expr2->evaluate(exec);
631 KJS_CHECKEXCEPTIONREFERENCE
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());
651 void AccessorNode2::ref()
658 bool AccessorNode2::deref()
660 if ( expr && expr->deref() )
662 return Node::deref();
668 Value v = expr->evaluate(exec);
669 KJS_CHECKEXCEPTIONREFERENCE
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());
686 void ArgumentListNode::ref()
688 for (ArgumentListNode *n =
this; n; n = n->list) {
695 bool ArgumentListNode::deref()
697 ArgumentListNode *next;
698 for (ArgumentListNode *n =
this; n; n = next) {
700 if (n->expr && n->expr->deref())
702 if (n !=
this && n->Node::deref())
705 return Node::deref();
719 for (
const ArgumentListNode *n =
this; n; n = n->list) {
720 Value v = n->expr->evaluate(exec);
721 KJS_CHECKEXCEPTIONLIST
730 void ArgumentsNode::ref()
737 bool ArgumentsNode::deref()
739 if ( list && list->deref() )
741 return Node::deref();
756 return list->evaluateList(exec);
763 void NewExprNode::ref()
772 bool NewExprNode::deref()
774 if ( expr && expr->deref() )
776 if ( args && args->deref() )
778 return Node::deref();
783 Value v = expr->evaluate(exec);
784 KJS_CHECKEXCEPTIONVALUE
788 argList = args->evaluateList(exec);
789 KJS_CHECKEXCEPTIONVALUE
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);
796 Object constr =
Object(static_cast<ObjectImp*>(v.imp()));
798 return throwError(exec, TypeError,
"Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr);
808 void FunctionCallNode::ref()
817 bool FunctionCallNode::deref()
819 if ( expr && expr->deref() )
821 if ( args && args->deref() )
823 return Node::deref();
829 Reference ref = expr->evaluateReference(exec);
830 KJS_CHECKEXCEPTIONVALUE
832 List argList = args->evaluateList(exec);
833 KJS_CHECKEXCEPTIONVALUE
836 KJS_CHECKEXCEPTIONVALUE
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);
845 return throwError(exec, TypeError,
"Object %s (result of expression %s) does not allow calls.", v, expr);
854 if (thisVal.
type() == ObjectType &&
858 if (thisVal.
type() != ObjectType) {
870 Value result = func.
call(exec,thisObj, argList);
877 void PostfixNode::ref()
884 bool PostfixNode::deref()
886 if ( expr && expr->deref() )
888 return Node::deref();
894 Reference ref = expr->evaluateReference(exec);
895 KJS_CHECKEXCEPTIONVALUE
899 double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
908 void DeleteNode::ref()
915 bool DeleteNode::deref()
917 if ( expr && expr->deref() )
919 return Node::deref();
925 Reference ref = expr->evaluateReference(exec);
926 KJS_CHECKEXCEPTIONVALUE
927 return Boolean(ref.deleteValue(exec));
939 bool VoidNode::deref()
941 if ( expr && expr->deref() )
943 return Node::deref();
949 Value dummy1 = expr->evaluate(exec);
950 KJS_CHECKEXCEPTIONVALUE
957 void TypeOfNode::ref()
964 bool TypeOfNode::deref()
966 if ( expr && expr->deref() )
968 return Node::deref();
975 Reference ref = expr->evaluateReference(exec);
976 KJS_CHECKEXCEPTIONVALUE
977 if (ref.isMutable()) {
979 if (b.
type() == NullType)
980 return String(
"undefined");
1001 if (v.
type() == ObjectType &&
static_cast<ObjectImp*
>(v.imp())->implementsCall())
1013 void PrefixNode::ref()
1020 bool PrefixNode::deref()
1022 if ( expr && expr->deref() )
1024 return Node::deref();
1030 Reference ref = expr->evaluateReference(exec);
1031 KJS_CHECKEXCEPTIONVALUE
1035 double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
1045 void UnaryPlusNode::ref()
1052 bool UnaryPlusNode::deref()
1054 if ( expr && expr->deref() )
1056 return Node::deref();
1060 double UnaryPlusNode::toNumber(
ExecState *exec)
const 1062 return expr->toNumber(exec);
1068 Value v = expr->evaluate(exec);
1069 KJS_CHECKEXCEPTIONVALUE
1076 void NegateNode::ref()
1083 bool NegateNode::deref()
1085 if ( expr && expr->deref() )
1087 return Node::deref();
1091 double NegateNode::toNumber(
ExecState *exec)
const 1093 return -expr->toNumber(exec);
1098 Value v = expr->evaluate(exec);
1099 KJS_CHECKEXCEPTIONVALUE
1107 void BitwiseNotNode::ref()
1114 bool BitwiseNotNode::deref()
1116 if ( expr && expr->deref() )
1118 return Node::deref();
1124 Value v = expr->evaluate(exec);
1125 KJS_CHECKEXCEPTIONVALUE
1133 void LogicalNotNode::ref()
1140 bool LogicalNotNode::deref()
1142 if ( expr && expr->deref() )
1144 return Node::deref();
1148 bool LogicalNotNode::toBoolean(
ExecState *exec)
const 1150 return !expr->toBoolean(exec);
1157 KJS_CHECKEXCEPTIONVALUE
1164 void MultNode::ref()
1173 bool MultNode::deref()
1175 if ( term1 && term1->deref() )
1177 if ( term2 && term2->deref() )
1179 return Node::deref();
1185 Value v1 = term1->evaluate(exec);
1186 KJS_CHECKEXCEPTIONVALUE
1188 Value v2 = term2->evaluate(exec);
1189 KJS_CHECKEXCEPTIONVALUE
1191 return mult(exec,v1, v2, oper);
1197 Node* AddNode::create(Node *t1, Node *t2,
char op)
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));
1210 if (op ==
'+' && t2->type() == StringType)
1211 return new AppendStringNode(t1, t2->toString(0));
1214 return new AddNode(t1, t2, op);
1226 bool AddNode::deref()
1228 if ( term1 && term1->deref() )
1230 if ( term2 && term2->deref() )
1232 return Node::deref();
1238 Value v1 = term1->evaluate(exec);
1239 KJS_CHECKEXCEPTIONVALUE
1241 Value v2 = term2->evaluate(exec);
1242 KJS_CHECKEXCEPTIONVALUE
1244 return add(exec,v1, v2, oper);
1249 void AppendStringNode::ref()
1255 bool AppendStringNode::deref()
1259 return Node::deref();
1265 UString s = term->toString(exec);
1266 KJS_CHECKEXCEPTIONVALUE
1273 void ShiftNode::ref()
1282 bool ShiftNode::deref()
1284 if ( term1 && term1->deref() )
1286 if ( term2 && term2->deref() )
1288 return Node::deref();
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);
1309 assert(!
"ShiftNode: unhandled switch case");
1316 void RelationalNode::ref()
1325 bool RelationalNode::deref()
1327 if ( expr1 && expr1->deref() )
1329 if ( expr2 && expr2->deref() )
1331 return Node::deref();
1337 Value v1 = expr1->evaluate(exec);
1338 KJS_CHECKEXCEPTIONVALUE
1339 Value v2 = expr2->evaluate(exec);
1340 KJS_CHECKEXCEPTIONVALUE
1343 if (oper == OpLess || oper == OpGreaterEq) {
1344 int r = relation(exec, v1, v2);
1348 b = (oper == OpLess) ? (r == 1) : (r == 0);
1349 }
else if (oper == OpGreater || oper == OpLessEq) {
1350 int r = relation(exec, v2, v1);
1354 b = (oper == OpGreater) ? (r == 1) : (r == 0);
1355 }
else if (oper == OpIn) {
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()));
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);
1367 Object o2(static_cast<ObjectImp*>(v2.imp()));
1368 if (!o2.implementsHasInstance()) {
1377 return o2.hasInstance(exec, v1);
1385 void EqualNode::ref()
1394 bool EqualNode::deref()
1396 if ( expr1 && expr1->deref() )
1398 if ( expr2 && expr2->deref() )
1400 return Node::deref();
1406 Value v1 = expr1->evaluate(exec);
1407 KJS_CHECKEXCEPTIONVALUE
1408 Value v2 = expr2->evaluate(exec);
1409 KJS_CHECKEXCEPTIONVALUE
1412 if (oper == OpEqEq || oper == OpNotEq) {
1414 bool eq = equal(exec,v1, v2);
1415 result = oper == OpEqEq ? eq : !eq;
1418 bool eq = strictEqual(exec,v1, v2);
1419 result = oper == OpStrEq ? eq : !eq;
1426 void BitOperNode::ref()
1435 bool BitOperNode::deref()
1437 if ( expr1 && expr1->deref() )
1439 if ( expr2 && expr2->deref() )
1441 return Node::deref();
1447 Value v1 = expr1->evaluate(exec);
1448 KJS_CHECKEXCEPTIONVALUE
1449 Value v2 = expr2->evaluate(exec);
1450 KJS_CHECKEXCEPTIONVALUE
1452 int i2 = v2.toInt32(exec);
1454 if (oper == OpBitAnd)
1456 else if (oper == OpBitXOr)
1466 void BinaryLogicalNode::ref()
1475 bool BinaryLogicalNode::deref()
1477 if ( expr1 && expr1->deref() )
1479 if ( expr2 && expr2->deref() )
1481 return Node::deref();
1487 Value v1 = expr1->evaluate(exec);
1488 KJS_CHECKEXCEPTIONVALUE
1490 if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
1493 Value v2 = expr2->evaluate(exec);
1494 KJS_CHECKEXCEPTIONVALUE
1501 void ConditionalNode::ref()
1512 bool ConditionalNode::deref()
1514 if ( expr1 && expr1->deref() )
1516 if ( expr2 && expr2->deref() )
1518 if ( logical && logical->deref() )
1520 return Node::deref();
1527 KJS_CHECKEXCEPTIONVALUE
1529 Value v = b ? expr1->evaluate(exec) : expr2->evaluate(exec);
1530 KJS_CHECKEXCEPTIONVALUE
1537 void AssignNode::ref()
1546 bool AssignNode::deref()
1548 if ( left && left->deref() )
1550 if ( expr && expr->deref() )
1552 return Node::deref();
1558 Reference l = left->evaluateReference(exec);
1559 KJS_CHECKEXCEPTIONVALUE
1561 if (oper == OpEqual) {
1562 v = expr->evaluate(exec);
1563 KJS_CHECKEXCEPTIONVALUE
1566 Value v2 = expr->evaluate(exec);
1567 KJS_CHECKEXCEPTIONVALUE
1573 v = mult(exec, v1, v2,
'*');
1576 v = mult(exec, v1, v2,
'/');
1579 v = add(exec, v1, v2,
'+');
1582 v = add(exec, v1, v2,
'-');
1626 KJS_CHECKEXCEPTIONVALUE
1633 void CommaNode::ref()
1642 bool CommaNode::deref()
1644 if ( expr1 && expr1->deref() )
1646 if ( expr2 && expr2->deref() )
1648 return Node::deref();
1654 (void) expr1->evaluate(exec);
1655 KJS_CHECKEXCEPTIONVALUE
1656 Value v = expr2->evaluate(exec);
1657 KJS_CHECKEXCEPTIONVALUE
1664 StatListNode::StatListNode(StatementNode *s)
1665 : statement(s), list(this)
1667 setLoc(s->firstLine(), s->lastLine(), s->code());
1670 StatListNode::StatListNode(StatListNode *l, StatementNode *s)
1671 : statement(s), list(l->list)
1674 setLoc(l->firstLine(),s->lastLine(),l->code());
1677 void StatListNode::ref()
1679 for (StatListNode *n =
this; n; n = n->list) {
1682 n->statement->ref();
1686 bool StatListNode::deref()
1689 for (StatListNode *n =
this; n; n = next) {
1691 if (n->statement && n->statement->deref())
1692 delete n->statement;
1693 if (n !=
this && n->Node::deref())
1696 return StatementNode::deref();
1704 if (exec->hadException()) {
1705 Value ex = exec->exception();
1706 exec->clearException();
1710 if (c.complType() != Normal)
1713 Value v = c.value();
1715 for (StatListNode *n = list; n; n = n->list) {
1718 if (c2.complType() != Normal)
1721 if (exec->hadException()) {
1722 Value ex = exec->exception();
1723 exec->clearException();
1727 if (c2.isValueCompletion())
1732 return Completion(c.complType(), v, c.target());
1735 void StatListNode::processVarDecls(
ExecState *exec)
1737 for (StatListNode *n =
this; n; n = n->list)
1738 n->statement->processVarDecls(exec);
1743 void AssignExprNode::ref()
1750 bool AssignExprNode::deref()
1752 if ( expr && expr->deref() )
1754 return Node::deref();
1760 return expr->evaluate(exec);
1765 VarDeclNode::VarDeclNode(
const Identifier &
id, AssignExprNode *in, Type t)
1766 : varType(t), ident(id), init(in)
1770 void VarDeclNode::ref()
1777 bool VarDeclNode::deref()
1779 if ( init && init->deref() )
1781 return Node::deref();
1791 val = init->evaluate(exec);
1792 KJS_CHECKEXCEPTIONVALUE
1795 if (variable.imp()->getDirect(ident))
1801 printInfo(exec,(
UString(
"new variable ")+ident.ustring()).cstring().c_str(),val);
1805 int flags = Internal;
1806 if (exec->
context().imp()->codeType() != EvalCode)
1807 flags |= DontDelete;
1808 if (varType == VarDeclNode::Constant)
1810 variable.
put(exec, ident, val, flags);
1818 void VarDeclNode::processVarDecls(
ExecState *exec)
1825 if (exec->_context->codeType() != EvalCode)
1826 flags |= DontDelete;
1827 if (varType == VarDeclNode::Constant)
1836 void VarDeclListNode::ref()
1838 for (VarDeclListNode *n =
this; n; n = n->list) {
1845 bool VarDeclListNode::deref()
1847 VarDeclListNode *next;
1848 for (VarDeclListNode *n =
this; n; n = next) {
1850 if (n->var && n->var->deref())
1852 if (n !=
this && n->Node::deref())
1855 return Node::deref();
1862 for (
const VarDeclListNode *n =
this; n; n = n->list) {
1863 (void)n->var->evaluate(exec);
1864 KJS_CHECKEXCEPTIONVALUE
1869 void VarDeclListNode::processVarDecls(
ExecState *exec)
1871 for (VarDeclListNode *n =
this; n; n = n->list)
1872 n->var->processVarDecls(exec);
1877 void VarStatementNode::ref()
1879 StatementNode::ref();
1884 bool VarStatementNode::deref()
1886 if ( list && list->deref() )
1888 return StatementNode::deref();
1896 (void) list->evaluate(exec);
1902 void VarStatementNode::processVarDecls(
ExecState *exec)
1904 list->processVarDecls(exec);
1909 BlockNode::BlockNode(SourceElementsNode *s)
1912 source = s->elements;
1914 setLoc(s->firstLine(), s->lastLine(), s->code());
1920 void BlockNode::ref()
1922 StatementNode::ref();
1927 bool BlockNode::deref()
1929 if ( source && source->deref() )
1931 return StatementNode::deref();
1940 source->processFuncDecl(exec);
1942 return source->execute(exec);
1945 void BlockNode::processVarDecls(
ExecState *exec)
1948 source->processVarDecls(exec);
1961 void ExprStatementNode::ref()
1963 StatementNode::ref();
1968 bool ExprStatementNode::deref()
1970 if ( expr && expr->deref() )
1972 return StatementNode::deref();
1980 Value v = expr->evaluate(exec);
1990 StatementNode::ref();
1999 bool IfNode::deref()
2001 if ( statement1 && statement1->deref() )
2003 if ( statement2 && statement2->deref() )
2005 if ( expr && expr->deref() )
2007 return StatementNode::deref();
2016 bool b = expr->toBoolean(exec);
2021 return statement1->execute(exec);
2028 return statement2->execute(exec);
2031 void IfNode::processVarDecls(
ExecState *exec)
2033 statement1->processVarDecls(exec);
2036 statement2->processVarDecls(exec);
2041 void DoWhileNode::ref()
2043 StatementNode::ref();
2050 bool DoWhileNode::deref()
2052 if ( statement && statement->deref() )
2054 if ( expr && expr->deref() )
2056 return StatementNode::deref();
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()))
2078 if (c.complType() != Normal)
2088 void DoWhileNode::processVarDecls(
ExecState *exec)
2090 statement->processVarDecls(exec);
2095 void WhileNode::ref()
2097 StatementNode::ref();
2104 bool WhileNode::deref()
2106 if ( statement && statement->deref() )
2108 if ( expr && expr->deref() )
2110 return StatementNode::deref();
2131 exec->
context().imp()->seenLabels()->pushIteration();
2132 c = statement->execute(exec);
2133 exec->
context().imp()->seenLabels()->popIteration();
2134 if (c.isValueCompletion())
2137 if ((c.complType() == Continue) && ls.contains(c.target()))
2139 if ((c.complType() == Break) && ls.contains(c.target()))
2141 if (c.complType() != Normal)
2146 void WhileNode::processVarDecls(
ExecState *exec)
2148 statement->processVarDecls(exec);
2155 StatementNode::ref();
2166 bool ForNode::deref()
2168 if ( statement && statement->deref() )
2170 if ( expr1 && expr1->deref() )
2172 if ( expr2 && expr2->deref() )
2174 if ( expr3 && expr3->deref() )
2176 return StatementNode::deref();
2185 v = expr1->evaluate(exec);
2190 bool b = expr2->toBoolean(exec);
2198 exec->
context().imp()->seenLabels()->pushIteration();
2200 exec->
context().imp()->seenLabels()->popIteration();
2201 if (c.isValueCompletion())
2203 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2204 if ((c.complType() == Break) && ls.contains(c.target()))
2206 if (c.complType() != Normal)
2210 v = expr3->evaluate(exec);
2216 void ForNode::processVarDecls(
ExecState *exec)
2219 expr1->processVarDecls(exec);
2221 statement->processVarDecls(exec);
2226 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
2227 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
2231 ForInNode::ForInNode(
const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
2232 : ident(i), init(in), expr(e), statement(s)
2235 varDecl =
new VarDeclNode(ident, init, VarDeclNode::Variable);
2236 lexpr =
new ResolveNode(ident);
2239 void ForInNode::ref()
2241 StatementNode::ref();
2254 bool ForInNode::deref()
2256 if ( statement && statement->deref() )
2258 if ( expr && expr->deref() )
2260 if ( lexpr && lexpr->deref() )
2262 if ( init && init->deref() )
2264 if ( varDecl && varDecl->deref() )
2266 return StatementNode::deref();
2276 (void)varDecl->evaluate(exec);
2280 Value v = expr->evaluate(exec);
2285 if (v.isA(NullType) || v.isA(UndefinedType))
2294 while (propIt != propList.end()) {
2301 Reference ref = lexpr->evaluateReference(exec);
2305 exec->
context().imp()->seenLabels()->pushIteration();
2306 c = statement->execute(exec);
2307 exec->
context().imp()->seenLabels()->popIteration();
2308 if (c.isValueCompletion())
2311 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2312 if ((c.complType() == Break) && ls.contains(c.target()))
2314 if (c.complType() != Normal) {
2328 void ForInNode::processVarDecls(
ExecState *exec)
2330 statement->processVarDecls(exec);
2342 if (ident.isEmpty() && !exec->
context().imp()->seenLabels()->inIteration())
2344 throwError(exec, SyntaxError,
"continue used outside of iteration statement"));
2345 else if (!ident.isEmpty() && !exec->
context().imp()->seenLabels()->
contains(ident))
2347 throwError(exec, SyntaxError,
"Label %s not found in containing block. Can't continue.", ident));
2361 if (ident.isEmpty() && !exec->
context().imp()->seenLabels()->inIteration() &&
2362 !exec->
context().imp()->seenLabels()->inSwitch())
2364 throwError(exec, SyntaxError,
"break used outside of iteration or switch statement"));
2365 else if (!ident.isEmpty() && !exec->
context().imp()->seenLabels()->
contains(ident))
2367 throwError(exec, SyntaxError,
"Label %s not found in containing block. Can't break.", ident));
2374 void ReturnNode::ref()
2376 StatementNode::ref();
2381 bool ReturnNode::deref()
2383 if ( value && value->deref() )
2385 return StatementNode::deref();
2393 CodeType codeType = exec->
context().imp()->codeType();
2394 if (codeType != FunctionCode) {
2395 return Completion(Throw, throwError(exec, SyntaxError,
"Invalid return statement."));
2401 Value v = value->evaluate(exec);
2409 void WithNode::ref()
2411 StatementNode::ref();
2418 bool WithNode::deref()
2420 if ( statement && statement->deref() )
2422 if ( expr && expr->deref() )
2424 return StatementNode::deref();
2432 Value v = expr->evaluate(exec);
2436 exec->
context().imp()->pushScope(o);
2438 exec->
context().imp()->popScope();
2443 void WithNode::processVarDecls(
ExecState *exec)
2445 statement->processVarDecls(exec);
2450 void CaseClauseNode::ref()
2459 bool CaseClauseNode::deref()
2461 if ( expr && expr->deref() )
2463 if ( list && list->deref() )
2465 return Node::deref();
2471 Value v = expr->evaluate(exec);
2472 KJS_CHECKEXCEPTIONVALUE
2481 return list->execute(exec);
2486 void CaseClauseNode::processVarDecls(
ExecState *exec)
2489 list->processVarDecls(exec);
2494 void ClauseListNode::ref()
2496 for (ClauseListNode *n =
this; n; n = n->nx) {
2503 bool ClauseListNode::deref()
2505 ClauseListNode *next;
2506 for (ClauseListNode *n =
this; n; n = next) {
2508 if (n->cl && n->cl->deref())
2510 if (n !=
this && n->Node::deref())
2513 return Node::deref();
2524 void ClauseListNode::processVarDecls(
ExecState *exec)
2526 for (ClauseListNode *n =
this; n; n = n->nx)
2528 n->cl->processVarDecls(exec);
2533 CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2551 void CaseBlockNode::ref()
2562 bool CaseBlockNode::deref()
2564 if ( def && def->deref() )
2566 if ( list1 && list1->deref() )
2568 if ( list2 && list2->deref() )
2570 return Node::deref();
2585 ClauseListNode *a = list1, *b = list2;
2586 CaseClauseNode *clause;
2589 clause = a->clause();
2591 v = clause->evaluate(exec);
2593 if (strictEqual(exec, input, v)) {
2594 res = clause->evalStatements(exec);
2595 if (res.complType() != Normal)
2598 res = a->clause()->evalStatements(exec);
2599 if (res.complType() != Normal)
2608 clause = b->clause();
2610 v = clause->evaluate(exec);
2612 if (strictEqual(exec, input, v)) {
2613 res = clause->evalStatements(exec);
2614 if (res.complType() != Normal)
2622 res = def->evalStatements(exec);
2623 if (res.complType() != Normal)
2629 clause = b->clause();
2630 res = clause->evalStatements(exec);
2631 if (res.complType() != Normal)
2642 void CaseBlockNode::processVarDecls(
ExecState *exec)
2645 list1->processVarDecls(exec);
2647 def->processVarDecls(exec);
2649 list2->processVarDecls(exec);
2654 void SwitchNode::ref()
2656 StatementNode::ref();
2663 bool SwitchNode::deref()
2665 if ( expr && expr->deref() )
2667 if ( block && block->deref() )
2669 return StatementNode::deref();
2677 Value v = expr->evaluate(exec);
2679 exec->
context().imp()->seenLabels()->pushSwitch();
2681 exec->
context().imp()->seenLabels()->popSwitch();
2683 if ((res.complType() == Break) && ls.contains(res.target()))
2689 void SwitchNode::processVarDecls(
ExecState *exec)
2691 block->processVarDecls(exec);
2696 void LabelNode::ref()
2698 StatementNode::ref();
2703 bool LabelNode::deref()
2705 if ( statement && statement->deref() )
2707 return StatementNode::deref();
2715 if (!exec->
context().imp()->seenLabels()->
push(label)) {
2717 throwError(exec, SyntaxError,
"Duplicated label %s found.", label));
2719 e = statement->execute(exec);
2722 if ((e.complType() == Break) && (e.target() == label))
2728 void LabelNode::processVarDecls(
ExecState *exec)
2730 statement->processVarDecls(exec);
2735 void ThrowNode::ref()
2737 StatementNode::ref();
2742 bool ThrowNode::deref()
2744 if ( expr && expr->deref() )
2746 return StatementNode::deref();
2754 Value v = expr->evaluate(exec);
2760 Debugger *dbg = exec->interpreter()->imp()->debugger();
2762 dbg->exception(exec,v,exec->
context().imp()->inTryCatch());
2769 void CatchNode::ref()
2771 StatementNode::ref();
2776 bool CatchNode::deref()
2778 if ( block && block->deref() )
2780 return StatementNode::deref();
2795 exec->clearException();
2797 Object obj(
new ObjectImp());
2798 obj.
put(exec, ident, arg, DontDelete);
2799 exec->
context().imp()->pushScope(obj);
2801 exec->
context().imp()->popScope();
2806 void CatchNode::processVarDecls(
ExecState *exec)
2808 block->processVarDecls(exec);
2813 void FinallyNode::ref()
2815 StatementNode::ref();
2820 bool FinallyNode::deref()
2822 if ( block && block->deref() )
2824 return StatementNode::deref();
2830 return block->execute(exec);
2833 void FinallyNode::processVarDecls(
ExecState *exec)
2835 block->processVarDecls(exec);
2842 StatementNode::ref();
2851 bool TryNode::deref()
2853 if ( block && block->deref() )
2855 if ( _final && _final->deref() )
2857 if ( _catch && _catch->deref() )
2859 return StatementNode::deref();
2870 exec->
context().imp()->pushTryCatch();
2871 c = block->execute(exec);
2873 exec->
context().imp()->popTryCatch();
2876 if (c.complType() != Throw)
2878 return _catch->execute(exec,c.value());
2882 Value exception = exec->_exception;
2883 exec->_exception =
Value();
2885 c2 = _final->execute(exec);
2887 if (!exec->hadException() && c2.complType() != Throw)
2888 exec->_exception = exception;
2890 return (c2.complType() == Normal) ? c : c2;
2893 if (c.complType() == Throw)
2894 c = _catch->execute(exec,c.value());
2896 c2 = _final->execute(exec);
2897 return (c2.complType() == Normal) ? c : c2;
2900 void TryNode::processVarDecls(
ExecState *exec)
2902 block->processVarDecls(exec);
2904 _final->processVarDecls(exec);
2906 _catch->processVarDecls(exec);
2911 void ParameterNode::ref()
2913 for (ParameterNode *n =
this; n; n = n->next)
2917 bool ParameterNode::deref()
2919 ParameterNode *next;
2920 for (ParameterNode *n =
this; n; n = next) {
2922 if (n !=
this && n->Node::deref())
2925 return Node::deref();
2937 FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2943 void FunctionBodyNode::processFuncDecl(
ExecState *exec)
2946 source->processFuncDecl(exec);
2951 void FuncDeclNode::ref()
2953 StatementNode::ref();
2960 bool FuncDeclNode::deref()
2962 if ( param && param->deref() )
2964 if ( body && body->deref() )
2966 return StatementNode::deref();
2970 void FuncDeclNode::processFuncDecl(
ExecState *exec)
2974 FunctionImp *fimp =
new DeclaredFunctionImp(exec, ident, body, exec->
context().imp()->scopeChain());
2980 proto.
put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2981 func.
put(exec, prototypePropertyName, proto, Internal|DontDelete);
2984 for(
const ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2985 fimp->addParameter(p->ident());
2987 func.
put(exec, lengthPropertyName,
Number(plen), ReadOnly|DontDelete|DontEnum);
2990 fprintf(stderr,
"KJS: new function %s in %p\n", ident.ustring().cstring().c_str(), ctx->variableObject().imp());
2992 if (exec->_context->codeType() == EvalCode) {
2994 ctx->variableObject().
put(exec, ident, func, Internal);
2996 ctx->variableObject().
put(exec, ident, func, DontDelete | Internal);
3002 Object oldVar = ctx->variableObject();
3003 ctx->setVariableObject(func);
3004 ctx->pushScope(func);
3005 body->processFuncDecl(exec);
3007 ctx->setVariableObject(oldVar);
3013 void FuncExprNode::ref()
3022 bool FuncExprNode::deref()
3024 if ( param && param->deref() )
3026 if ( body && body->deref() )
3028 return Node::deref();
3036 bool named = !ident.isNull();
3037 Object functionScopeObject;
3043 functionScopeObject =
Object(
new ObjectImp());
3044 context->pushScope(functionScopeObject);
3051 fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
3053 for(
const ParameterNode *p = param; p != 0L; p = p->nextParam())
3054 fimp->addParameter(p->ident());
3057 functionScopeObject.
put(exec, ident,
Value(fimp), ReadOnly|DontDelete);
3058 context->popScope();
3066 SourceElementsNode::SourceElementsNode(StatementNode *s1)
3070 setLoc(s1->firstLine(), s1->lastLine(), s1->code());
3073 SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
3075 elements = s1->elements;
3076 s1->elements =
this;
3078 setLoc(s1->firstLine(), s2->lastLine(), s1->code());
3081 void SourceElementsNode::ref()
3083 for (SourceElementsNode *n =
this; n; n = n->elements) {
3090 bool SourceElementsNode::deref()
3092 SourceElementsNode *next;
3093 for (SourceElementsNode *n =
this; n; n = next) {
3095 if (n->element && n->element->deref())
3097 if (n !=
this && n->Node::deref())
3100 return StatementNode::deref();
3110 if (c1.complType() != Normal)
3113 for (SourceElementsNode *n = elements; n; n = n->elements) {
3115 if (c2.complType() != Normal)
3127 void SourceElementsNode::processFuncDecl(
ExecState *exec)
3129 for (SourceElementsNode *n =
this; n; n = n->elements)
3130 n->element->processFuncDecl(exec);
3133 void SourceElementsNode::processVarDecls(
ExecState *exec)
3135 for (SourceElementsNode *n =
this; n; n = n->elements)
3136 n->element->processVarDecls(exec);
Value objects are act as wrappers ("smart pointers") around ValueImp objects and their descendents...
Type type() const
Returns the type of value.
Object builtinObject() const
Returns the builtin "Object" object.
const TDEShortcut & next()
static UString from(int i)
Constructs a string from an int.
Interpreter * dynamicInterpreter() const
Returns the interpreter associated with this execution state.
Value get(ExecState *exec, const Identifier &propertyName) const
Retrieves the specified property from the object.
Object construct(ExecState *exec, const List &args)
Creates a new object based on this object.
Represents an primitive Number value.
An iterator for a ReferenceList.
void append(const Value &val)
Append an object to the end of the list.
bool implementsConstruct() const
Whether or not the object implements the construct() method.
Object & globalObject() const
Returns the object that is used as the global object during all script execution performed by this in...
bool toBoolean(ExecState *exec) const
Performs the ToBoolean type conversion operation on this value (ECMA 9.2)
Represents an primitive Null value.
Interpreter * lexicalInterpreter() const
Returns the interpreter associated with the current scope's global object.
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...
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...
int toInt32(ExecState *exec) const
Performs the ToInt32 type conversion operation on this value (ECMA 9.5)
Identifier getPropertyName(ExecState *exec) const
Performs the GetPropertyName type conversion operation on this value (ECMA 8.7)
double toNumber(ExecState *exec) const
Performs the ToNumber type conversion operation on this value (ECMA 9.3)
unsigned int toUInt32(ExecState *exec) const
Performs the ToUInt32 type conversion operation on this value (ECMA 9.6)
Represents an primitive Undefined value.
Value getValue(ExecState *exec) const
Performs the GetValue type conversion operation on this value (ECMA 8.7.1)
Object toObject(ExecState *exec) const
Performs the ToObject type conversion operation on this value (ECMA 9.9)
Implementation class for functions implemented in JS.
const char * ascii() const
Char * of the identifier's string.
bool implementsCall() const
Whether or not the object implements the call() method.
bool isA(Type t) const
Checks whether or not the value is of a particular tpye.
Represents an primitive String value.
Defines a Javascript reference.
static Object dynamicCast(const Value &v)
Converts a Value into an Object.
bool contains(const Identifier &id) const
Is the id in the stack?
const UString & ustring() const
returns a UString of the identifier
Context context() const
Returns the execution context associated with this execution state.
void pop()
Removes from the stack the last pushed id (what else?)
static const List & empty()
Returns a pointer to a static instance of an empty list.
Completion objects are used to convey the return status and value from functions. ...
ReferenceList propList(ExecState *exec, bool recursive=true)
Returns a List of References to all the properties of the object.
A list of Reference objects.
Value getBase(ExecState *exec) const
Performs the GetBase type conversion operation on this value (ECMA 8.7)
void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr=None)
Sets the specified property.
Represents an primitive Boolean value.
UString toString(ExecState *exec) const
Performs the ToString type conversion operation on this value (ECMA 9.8)
kndbgstream & endl(kndbgstream &s)
Object builtinArray() const
Returns the builtin "Array" object.
Value call(ExecState *exec, Object &thisObj, const List &args)
Calls this object as if it is a function.
TQString name(StdAccel id)
void putValue(ExecState *exec, const Value &w)
Performs the PutValue type conversion operation on this value (ECMA 8.7.1)
bool isValid() const
Returns whether or not this is a valid value.
Object variableObject() const
Returns the variable object for the execution context.
char * ascii() const
Convert the Unicode string to plain ASCII chars chopping of any higher bytes.
static const Identifier & null()
Creates an empty Identifier.
Represents the current state of script execution.
Represents an Identifier for a Javascript object.