Commit f9a50479 authored by ggaren's avatar ggaren

Reviewed by mjs.

        - Fixed <rdar://problem/4364705> run-javascriptcore-tests crashes in
        KJS::BlockNode::deref
        AKA
        http://bugzilla.opendarwin.org/show_bug.cgi?id=6233
        Reproducible stack-overflow crash in ~RefPtr<T> due to RefPtr<T> use in
        linked lists

        This patch does four things:
        (1) Standardizes all our linked list nodes to use "next" as their next
        pointers.
        (2) Creates the ListRefPtr<T> class, a subclass of RefPtr<T> specialized
        to iteratively deref "next" pointers.
        (3) Standardizes our linked list nodes to use ListRefPtr<T> and
        implement the releaseNext() function used by ~ListRefPtr<T>().
        (4) Adds to RefPtr<T> the release() method used by releaseNext().

        - Modified existing mozilla test to ensure it would make deployment
        builds crash as well.

        * JavaScriptCore.xcodeproj/project.pbxproj:
        * kjs/nodes.cpp:
        (ElementNode::evaluate):
        (PropertyListNode::evaluate):
        (ArgumentListNode::evaluateList):
        (StatListNode::StatListNode):
        (StatListNode::execute):
        (StatListNode::processVarDecls):
        (VarDeclListNode::evaluate):
        (VarDeclListNode::processVarDecls):
        (VarStatementNode::execute):
        (VarStatementNode::processVarDecls):
        (BlockNode::BlockNode):
        (CaseClauseNode::evalStatements):
        (CaseClauseNode::processVarDecls):
        (ClauseListNode::processVarDecls):
        (CaseBlockNode::CaseBlockNode):
        (CaseBlockNode::evalBlock):
        (SourceElementsNode::SourceElementsNode):
        (SourceElementsNode::execute):
        (SourceElementsNode::processFuncDecl):
        (SourceElementsNode::processVarDecls):
        * kjs/nodes.h:
        (KJS::ElementNode::ElementNode):
        (KJS::ElementNode::releaseNext):
        (KJS::ArrayNode::ArrayNode):
        (KJS::PropertyListNode::PropertyListNode):
        (KJS::PropertyListNode::releaseNext):
        (KJS::ObjectLiteralNode::ObjectLiteralNode):
        (KJS::ArgumentListNode::ArgumentListNode):
        (KJS::ArgumentListNode::releaseNext):
        (KJS::ArgumentsNode::ArgumentsNode):
        (KJS::StatListNode::releaseNext):
        (KJS::VarDeclListNode::VarDeclListNode):
        (KJS::VarDeclListNode::releaseNext):
        (KJS::VarStatementNode::VarStatementNode):
        (KJS::ForNode::ForNode):
        (KJS::CaseClauseNode::CaseClauseNode):
        (KJS::ClauseListNode::ClauseListNode):
        (KJS::ClauseListNode::getClause):
        (KJS::ClauseListNode::getNext):
        (KJS::ClauseListNode::releaseNext):
        (KJS::ParameterNode::ParameterNode):
        (KJS::ParameterNode::releaseNext):
        (KJS::SourceElementsNode::releaseNext):
        * kjs/nodes2string.cpp:
        (ElementNode::streamTo):
        (PropertyListNode::streamTo):
        (ArgumentListNode::streamTo):
        (StatListNode::streamTo):
        (VarDeclListNode::streamTo):
        (VarStatementNode::streamTo):
        (CaseClauseNode::streamTo):
        (ClauseListNode::streamTo):
        (CaseBlockNode::streamTo):
        (SourceElementsNode::streamTo):
        * kxmlcore/ListRefPtr.h: Added.
        (KXMLCore::ListRefPtr::ListRefPtr):
        (KXMLCore::ListRefPtr::~ListRefPtr):
        (KXMLCore::ListRefPtr::operator=):
        * kxmlcore/RefPtr.h:
        (KXMLCore::RefPtr::release):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@11802 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2443c09d
2005-12-26 Geoffrey Garen <ggaren@apple.com>
Reviewed by mjs.
- Fixed <rdar://problem/4364705> run-javascriptcore-tests crashes in
KJS::BlockNode::deref
AKA
http://bugzilla.opendarwin.org/show_bug.cgi?id=6233
Reproducible stack-overflow crash in ~RefPtr<T> due to RefPtr<T> use in
linked lists
This patch does four things:
(1) Standardizes all our linked list nodes to use "next" as their next
pointers.
(2) Creates the ListRefPtr<T> class, a subclass of RefPtr<T> specialized
to iteratively deref "next" pointers.
(3) Standardizes our linked list nodes to use ListRefPtr<T> and
implement the releaseNext() function used by ~ListRefPtr<T>().
(4) Adds to RefPtr<T> the release() method used by releaseNext().
- Modified existing mozilla test to ensure it would make deployment
builds crash as well.
* JavaScriptCore.xcodeproj/project.pbxproj:
* kjs/nodes.cpp:
(ElementNode::evaluate):
(PropertyListNode::evaluate):
(ArgumentListNode::evaluateList):
(StatListNode::StatListNode):
(StatListNode::execute):
(StatListNode::processVarDecls):
(VarDeclListNode::evaluate):
(VarDeclListNode::processVarDecls):
(VarStatementNode::execute):
(VarStatementNode::processVarDecls):
(BlockNode::BlockNode):
(CaseClauseNode::evalStatements):
(CaseClauseNode::processVarDecls):
(ClauseListNode::processVarDecls):
(CaseBlockNode::CaseBlockNode):
(CaseBlockNode::evalBlock):
(SourceElementsNode::SourceElementsNode):
(SourceElementsNode::execute):
(SourceElementsNode::processFuncDecl):
(SourceElementsNode::processVarDecls):
* kjs/nodes.h:
(KJS::ElementNode::ElementNode):
(KJS::ElementNode::releaseNext):
(KJS::ArrayNode::ArrayNode):
(KJS::PropertyListNode::PropertyListNode):
(KJS::PropertyListNode::releaseNext):
(KJS::ObjectLiteralNode::ObjectLiteralNode):
(KJS::ArgumentListNode::ArgumentListNode):
(KJS::ArgumentListNode::releaseNext):
(KJS::ArgumentsNode::ArgumentsNode):
(KJS::StatListNode::releaseNext):
(KJS::VarDeclListNode::VarDeclListNode):
(KJS::VarDeclListNode::releaseNext):
(KJS::VarStatementNode::VarStatementNode):
(KJS::ForNode::ForNode):
(KJS::CaseClauseNode::CaseClauseNode):
(KJS::ClauseListNode::ClauseListNode):
(KJS::ClauseListNode::getClause):
(KJS::ClauseListNode::getNext):
(KJS::ClauseListNode::releaseNext):
(KJS::ParameterNode::ParameterNode):
(KJS::ParameterNode::releaseNext):
(KJS::SourceElementsNode::releaseNext):
* kjs/nodes2string.cpp:
(ElementNode::streamTo):
(PropertyListNode::streamTo):
(ArgumentListNode::streamTo):
(StatListNode::streamTo):
(VarDeclListNode::streamTo):
(VarStatementNode::streamTo):
(CaseClauseNode::streamTo):
(ClauseListNode::streamTo):
(CaseBlockNode::streamTo):
(SourceElementsNode::streamTo):
* kxmlcore/ListRefPtr.h: Added.
(KXMLCore::ListRefPtr::ListRefPtr):
(KXMLCore::ListRefPtr::~ListRefPtr):
(KXMLCore::ListRefPtr::operator=):
* kxmlcore/RefPtr.h:
(KXMLCore::RefPtr::release):
2005-12-29 Geoffrey Garen <ggaren@apple.com>
Reviewed by mjs.
......
......@@ -25,6 +25,7 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
148A1627095D16BB00666D0D /* ListRefPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 148A1626095D16BB00666D0D /* ListRefPtr.h */; };
652C107F08DA7B1E0020887D /* protected_reference.h in Headers */ = {isa = PBXBuildFile; fileRef = 652C107E08DA7B1E0020887D /* protected_reference.h */; };
6541BD7208E80A17002CBEE7 /* TCPageMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */; };
6541BD7308E80A17002CBEE7 /* TCSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */; };
......@@ -277,6 +278,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
148A1626095D16BB00666D0D /* ListRefPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ListRefPtr.h; sourceTree = "<group>"; };
45E12D8806A49B0F00E9DF84 /* testkjs.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = testkjs.cpp; sourceTree = "<group>"; tabWidth = 8; };
5114F47B05E4426200D1BBBD /* runtime_root.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; name = runtime_root.cpp; path = bindings/runtime_root.cpp; sourceTree = "<group>"; tabWidth = 8; };
5114F47C05E4426200D1BBBD /* runtime_root.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = runtime_root.h; path = bindings/runtime_root.h; sourceTree = "<group>"; tabWidth = 8; };
......@@ -665,6 +667,7 @@
657EEBBF094E445E008C9C7B /* HashCountedSet.h */,
65C647B3093EF8D60022C380 /* RefPtr.h */,
6580F795094070560082C219 /* PassRefPtr.h */,
148A1626095D16BB00666D0D /* ListRefPtr.h */,
65D7D19B08F10B5B0015ABD8 /* FastMallocInternal.h */,
6557E8F708EA5D4D0049CDFC /* HashMapPtrSpec.h */,
65DFC92A08EA173A00F7300B /* HashFunctions.h */,
......@@ -852,6 +855,7 @@
6580F796094070560082C219 /* PassRefPtr.h in Headers */,
657EEBC0094E445E008C9C7B /* HashCountedSet.h in Headers */,
93AA4F780957251F0084B3A7 /* AlwaysInline.h in Headers */,
148A1627095D16BB00666D0D /* ListRefPtr.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......
......@@ -309,7 +309,7 @@ JSValue *ElementNode::evaluate(ExecState *exec)
{
JSObject *array = exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty());
int length = 0;
for (ElementNode *n = this; n; n = n->list.get()) {
for (ElementNode *n = this; n; n = n->next.get()) {
JSValue *val = n->node->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
length += n->elision;
......@@ -360,7 +360,7 @@ JSValue *PropertyListNode::evaluate(ExecState *exec)
{
JSObject *obj = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
for (PropertyListNode *p = this; p; p = p->list.get()) {
for (PropertyListNode *p = this; p; p = p->next.get()) {
JSValue *n = p->node->name->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
JSValue *v = p->node->assign->evaluate(exec);
......@@ -449,7 +449,7 @@ List ArgumentListNode::evaluateList(ExecState *exec)
{
List l;
for (ArgumentListNode *n = this; n; n = n->list.get()) {
for (ArgumentListNode *n = this; n; n = n->next.get()) {
JSValue *v = n->expr->evaluate(exec);
KJS_CHECKEXCEPTIONLIST
l.append(v);
......@@ -1415,15 +1415,15 @@ JSValue *CommaNode::evaluate(ExecState *exec)
// ------------------------------ StatListNode ---------------------------------
StatListNode::StatListNode(StatementNode *s)
: statement(s), list(this)
: statement(s), next(this)
{
setLoc(s->firstLine(), s->lastLine(), s->sourceId());
}
StatListNode::StatListNode(StatListNode *l, StatementNode *s)
: statement(s), list(l->list)
: statement(s), next(l->next)
{
l->list = this;
l->next = this;
setLoc(l->firstLine(), s->lastLine(), l->sourceId());
}
......@@ -1437,7 +1437,7 @@ Completion StatListNode::execute(ExecState *exec)
JSValue *v = c.value();
for (StatListNode *n = list.get(); n; n = n->list.get()) {
for (StatListNode *n = next.get(); n; n = n->next.get()) {
Completion c2 = n->statement->execute(exec);
KJS_ABORTPOINT
if (c2.complType() != Normal)
......@@ -1453,7 +1453,7 @@ Completion StatListNode::execute(ExecState *exec)
void StatListNode::processVarDecls(ExecState *exec)
{
for (StatListNode *n = this; n; n = n->list.get())
for (StatListNode *n = this; n; n = n->next.get())
n->statement->processVarDecls(exec);
}
......@@ -1526,7 +1526,7 @@ void VarDeclNode::processVarDecls(ExecState *exec)
// ECMA 12.2
JSValue *VarDeclListNode::evaluate(ExecState *exec)
{
for (VarDeclListNode *n = this; n; n = n->list.get()) {
for (VarDeclListNode *n = this; n; n = n->next.get()) {
n->var->evaluate(exec);
KJS_CHECKEXCEPTIONVALUE
}
......@@ -1535,7 +1535,7 @@ JSValue *VarDeclListNode::evaluate(ExecState *exec)
void VarDeclListNode::processVarDecls(ExecState *exec)
{
for (VarDeclListNode *n = this; n; n = n->list.get())
for (VarDeclListNode *n = this; n; n = n->next.get())
n->var->processVarDecls(exec);
}
......@@ -1546,7 +1546,7 @@ Completion VarStatementNode::execute(ExecState *exec)
{
KJS_BREAKPOINT;
(void) list->evaluate(exec);
(void) next->evaluate(exec);
KJS_CHECKEXCEPTION
return Completion(Normal);
......@@ -1554,7 +1554,7 @@ Completion VarStatementNode::execute(ExecState *exec)
void VarStatementNode::processVarDecls(ExecState *exec)
{
list->processVarDecls(exec);
next->processVarDecls(exec);
}
// ------------------------------ BlockNode ------------------------------------
......@@ -1562,8 +1562,8 @@ void VarStatementNode::processVarDecls(ExecState *exec)
BlockNode::BlockNode(SourceElementsNode *s)
{
if (s) {
source = s->elements;
s->elements = 0;
source = s->next;
s->next = 0;
setLoc(s->firstLine(), s->lastLine(), s->sourceId());
} else {
source = 0;
......@@ -1984,16 +1984,16 @@ JSValue *CaseClauseNode::evaluate(ExecState *exec)
// ECMA 12.11
Completion CaseClauseNode::evalStatements(ExecState *exec)
{
if (list)
return list->execute(exec);
if (next)
return next->execute(exec);
else
return Completion(Normal, jsUndefined());
}
void CaseClauseNode::processVarDecls(ExecState *exec)
{
if (list)
list->processVarDecls(exec);
if (next)
next->processVarDecls(exec);
}
// ------------------------------ ClauseListNode -------------------------------
......@@ -2008,9 +2008,9 @@ JSValue *ClauseListNode::evaluate(ExecState *)
// ECMA 12.11
void ClauseListNode::processVarDecls(ExecState *exec)
{
for (ClauseListNode *n = this; n; n = n->nx.get())
if (n->cl)
n->cl->processVarDecls(exec);
for (ClauseListNode *n = this; n; n = n->next.get())
if (n->clause)
n->clause->processVarDecls(exec);
}
// ------------------------------ CaseBlockNode --------------------------------
......@@ -2019,8 +2019,8 @@ CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
ClauseListNode *l2)
{
if (l1) {
list1 = l1->nx;
l1->nx = 0;
list1 = l1->next;
l1->next = 0;
} else {
list1 = 0;
}
......@@ -2028,8 +2028,8 @@ CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
def = d;
if (l2) {
list2 = l2->nx;
l2->nx = 0;
list2 = l2->next;
l2->next = 0;
} else {
list2 = 0;
}
......@@ -2052,8 +2052,8 @@ Completion CaseBlockNode::evalBlock(ExecState *exec, JSValue *input)
CaseClauseNode *clause;
while (a) {
clause = a->clause();
a = a->next();
clause = a->getClause();
a = a->getNext();
v = clause->evaluate(exec);
KJS_CHECKEXCEPTION
if (strictEqual(exec, input, v)) {
......@@ -2061,18 +2061,18 @@ Completion CaseBlockNode::evalBlock(ExecState *exec, JSValue *input)
if (res.complType() != Normal)
return res;
while (a) {
res = a->clause()->evalStatements(exec);
res = a->getClause()->evalStatements(exec);
if (res.complType() != Normal)
return res;
a = a->next();
a = a->getNext();
}
break;
}
}
while (b) {
clause = b->clause();
b = b->next();
clause = b->getClause();
b = b->getNext();
v = clause->evaluate(exec);
KJS_CHECKEXCEPTION
if (strictEqual(exec, input, v)) {
......@@ -2092,11 +2092,11 @@ Completion CaseBlockNode::evalBlock(ExecState *exec, JSValue *input)
b = list2.get();
step18:
while (b) {
clause = b->clause();
clause = b->getClause();
res = clause->evalStatements(exec);
if (res.complType() != Normal)
return res;
b = b->next();
b = b->getNext();
}
// bail out on error
......@@ -2305,16 +2305,18 @@ JSValue *FuncExprNode::evaluate(ExecState *exec)
// ------------------------------ SourceElementsNode ---------------------------
int SourceElementsNode::count = 0;
SourceElementsNode::SourceElementsNode(StatementNode *s1)
: element(s1), elements(this)
: node(s1), next(this)
{
setLoc(s1->firstLine(), s1->lastLine(), s1->sourceId());
}
SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
: element(s2), elements(s1->elements)
: node(s2), next(s1->next)
{
s1->elements = this;
s1->next = this;
setLoc(s1->firstLine(), s2->lastLine(), s1->sourceId());
}
......@@ -2323,13 +2325,13 @@ Completion SourceElementsNode::execute(ExecState *exec)
{
KJS_CHECKEXCEPTION
Completion c1 = element->execute(exec);
Completion c1 = node->execute(exec);
KJS_CHECKEXCEPTION;
if (c1.complType() != Normal)
return c1;
for (SourceElementsNode *n = elements.get(); n; n = n->elements.get()) {
Completion c2 = n->element->execute(exec);
for (SourceElementsNode *n = next.get(); n; n = n->next.get()) {
Completion c2 = n->node->execute(exec);
if (c2.complType() != Normal)
return c2;
// The spec says to return c2 here, but it seems that mozilla returns c1 if
......@@ -2344,14 +2346,14 @@ Completion SourceElementsNode::execute(ExecState *exec)
// ECMA 14
void SourceElementsNode::processFuncDecl(ExecState *exec)
{
for (SourceElementsNode *n = this; n; n = n->elements.get())
n->element->processFuncDecl(exec);
for (SourceElementsNode *n = this; n; n = n->next.get())
n->node->processFuncDecl(exec);
}
void SourceElementsNode::processVarDecls(ExecState *exec)
{
for (SourceElementsNode *n = this; n; n = n->elements.get())
n->element->processVarDecls(exec);
for (SourceElementsNode *n = this; n; n = n->next.get())
n->node->processVarDecls(exec);
}
ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
......
......@@ -26,6 +26,7 @@
#define _NODES_H_
#include <kxmlcore/RefPtr.h>
#include <kxmlcore/ListRefPtr.h>
#include "internal.h"
......@@ -219,14 +220,15 @@ namespace KJS {
class ElementNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ArrayNode ctor
ElementNode(int e, Node *n) : list(this), elision(e), node(n) { }
ElementNode(int e, Node *n) : next(this), elision(e), node(n) { }
ElementNode(ElementNode *l, int e, Node *n)
: list(l->list), elision(e), node(n) { l->list = this; }
: next(l->next), elision(e), node(n) { l->next = this; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
PassRefPtr<ElementNode> releaseNext() { return next.release(); }
private:
friend class ArrayNode;
RefPtr<ElementNode> list;
ListRefPtr<ElementNode> next;
int elision;
RefPtr<Node> node;
};
......@@ -235,9 +237,9 @@ namespace KJS {
public:
ArrayNode(int e) : element(0), elision(e), opt(true) { }
ArrayNode(ElementNode *ele)
: element(ele->list), elision(0), opt(false) { ele->list = 0; }
: element(ele->next), elision(0), opt(false) { ele->next = 0; }
ArrayNode(int eli, ElementNode *ele)
: element(ele->list), elision(eli), opt(true) { ele->list = 0; }
: element(ele->next), elision(eli), opt(true) { ele->next = 0; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
......@@ -274,22 +276,23 @@ namespace KJS {
class PropertyListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ObjectLiteralNode ctor
PropertyListNode(PropertyNode *n)
: node(n), list(this) { }
PropertyListNode(PropertyNode *n)
: node(n), next(this) { }
PropertyListNode(PropertyNode *n, PropertyListNode *l)
: node(n), list(l->list) { l->list = this; }
: node(n), next(l->next) { l->next = this; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
PassRefPtr<PropertyListNode> releaseNext() { return next.release(); }
private:
friend class ObjectLiteralNode;
RefPtr<PropertyNode> node;
RefPtr<PropertyListNode> list;
ListRefPtr<PropertyListNode> next;
};
class ObjectLiteralNode : public Node {
public:
ObjectLiteralNode() : list(0) { }
ObjectLiteralNode(PropertyListNode *l) : list(l->list) { l->list = 0; }
ObjectLiteralNode(PropertyListNode *l) : list(l->next) { l->next = 0; }
JSValue *evaluate(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
......@@ -331,15 +334,16 @@ namespace KJS {
class ArgumentListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ArgumentsNode ctor
ArgumentListNode(Node *e) : list(this), expr(e) { }
ArgumentListNode(Node *e) : next(this), expr(e) { }
ArgumentListNode(ArgumentListNode *l, Node *e)
: list(l->list), expr(e) { l->list = this; }
: next(l->next), expr(e) { l->next = this; }
JSValue *evaluate(ExecState *exec);
List evaluateList(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
PassRefPtr<ArgumentListNode> releaseNext() { return next.release(); }
private:
friend class ArgumentsNode;
RefPtr<ArgumentListNode> list;
ListRefPtr<ArgumentListNode> next;
RefPtr<Node> expr;
};
......@@ -347,7 +351,7 @@ namespace KJS {
public:
ArgumentsNode() : list(0) { }
ArgumentsNode(ArgumentListNode *l)
: list(l->list) { l->list = 0; }
: list(l->next) { l->next = 0; }
JSValue *evaluate(ExecState *exec);
List evaluateList(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
......@@ -741,10 +745,11 @@ namespace KJS {
virtual Completion execute(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
PassRefPtr<StatListNode> releaseNext() { return next.release(); }
private:
friend class CaseClauseNode;
RefPtr<StatementNode> statement;
RefPtr<StatListNode> list;
ListRefPtr<StatListNode> next;
};
class AssignExprNode : public Node {
......@@ -772,27 +777,28 @@ namespace KJS {
class VarDeclListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the ForNode/VarStatementNode ctor
VarDeclListNode(VarDeclNode *v) : list(this), var(v) {}
VarDeclListNode(VarDeclNode *v) : next(this), var(v) {}
VarDeclListNode(VarDeclListNode *l, VarDeclNode *v)
: list(l->list), var(v) { l->list = this; }
: next(l->next), var(v) { l->next = this; }
JSValue *evaluate(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
PassRefPtr<VarDeclListNode> releaseNext() { return next.release(); }
private:
friend class ForNode;
friend class VarStatementNode;
RefPtr<VarDeclListNode> list;
ListRefPtr<VarDeclListNode> next;
RefPtr<VarDeclNode> var;
};
class VarStatementNode : public StatementNode {
public:
VarStatementNode(VarDeclListNode *l) : list(l->list) { l->list = 0; }
VarStatementNode(VarDeclListNode *l) : next(l->next) { l->next = 0; }
virtual Completion execute(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
RefPtr<VarDeclListNode> list;
RefPtr<VarDeclListNode> next;
};
class BlockNode : public StatementNode {
......@@ -861,7 +867,7 @@ namespace KJS {
ForNode(Node *e1, Node *e2, Node *e3, StatementNode *s) :
expr1(e1), expr2(e2), expr3(e3), statement(s) {}
ForNode(VarDeclListNode *e1, Node *e2, Node *e3, StatementNode *s) :
expr1(e1->list), expr2(e2), expr3(e3), statement(s) { e1->list = 0; }
expr1(e1->next), expr2(e2), expr3(e3), statement(s) { e1->next = 0; }
virtual Completion execute(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
......@@ -930,33 +936,34 @@ namespace KJS {
class CaseClauseNode : public Node {
public:
CaseClauseNode(Node *e) : expr(e), list(0) { }
CaseClauseNode(Node *e) : expr(e), next(0) { }
CaseClauseNode(Node *e, StatListNode *l)
: expr(e), list(l->list) { l->list = 0; }
: expr(e), next(l->next) { l->next = 0; }
JSValue *evaluate(ExecState *exec);
Completion evalStatements(ExecState *exec);
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
private:
RefPtr<Node> expr;
RefPtr<StatListNode> list;
RefPtr<StatListNode> next;
};
class ClauseListNode : public Node {
public:
// list pointer is tail of a circular list, cracked in the CaseBlockNode ctor
ClauseListNode(CaseClauseNode *c) : cl(c), nx(this) { }
ClauseListNode(CaseClauseNode *c) : clause(c), next(this) { }
ClauseListNode(ClauseListNode *n, CaseClauseNode *c)
: cl(c), nx(n->nx) { n->nx = this; }
: clause(c), next(n->next) { n->next = this; }
JSValue *evaluate(ExecState *exec);
CaseClauseNode *clause() const { return cl.get(); }
ClauseListNode *next() const { return nx.get(); }
CaseClauseNode *getClause() const { return clause.get(); }
ClauseListNode *getNext() const { return next.get(); }
virtual void processVarDecls(ExecState *exec);
virtual void streamTo(SourceStream &s) const;
PassRefPtr<ClauseListNode> releaseNext() { return next.release(); }
private:
friend class CaseBlockNode;
RefPtr<CaseClauseNode> cl;
RefPtr<ClauseListNode> nx;
RefPtr<CaseClauseNode> clause;
ListRefPtr<ClauseListNode> next;
};
class CaseBlockNode : public Node {
......@@ -1021,17 +1028,18 @@ namespace KJS {
public:
// list pointer is tail of a circular list, cracked in the FuncDeclNode/FuncExprNode ctor
ParameterNode(const Identifier &i) : id(i), next(this) { }
ParameterNode(ParameterNode *list, const Identifier &i)
: id(i), next(list->next) { list->next = this; }
ParameterNode(ParameterNode *next, const Identifier &i)
: id(i), next(next->next) { next->next = this; }
JSValue *evaluate(ExecState *exec);
Identifier ident() { return id; }
ParameterNode *nextParam() { return next.get(); }
virtual void streamTo(SourceStream &s) const;
PassRefPtr<ParameterNode> releaseNext() { return next.release(); }
private:
friend class FuncDeclNode;
friend class FuncExprNode;
Identifier id;
RefPtr<ParameterNode> next;
ListRefPtr<ParameterNode> next;
};
// inherited by ProgramNode
......@@ -1073,18 +1081,20 @@ namespace KJS {
// A linked list of source element nodes
class SourceElementsNode : public StatementNode {
public:
static int count;
// list pointer is tail of a circular list, cracked in the BlockNode (or subclass) ctor
SourceElementsNode(StatementNode *s1);
SourceElementsNode(SourceElementsNode *s1, StatementNode *s2);
Completion execute(ExecState *exec);
void processFuncDecl(ExecState *exec);
virtual void processVarDecls(ExecState *exec);