JavaScriptCore:
authorandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 May 2006 20:19:22 +0000 (20:19 +0000)
committerandersca <andersca@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 20 May 2006 20:19:22 +0000 (20:19 +0000)
2006-05-20  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Geoff.

        http://bugzilla.opendarwin.org/show_bug.cgi?id=8993
        Support function declaration in case statements

        * kjs/grammar.y: Get rid of StatementList and use SourceElements instead.

        * kjs/nodes.cpp:
        (CaseClauseNode::evalStatements):
        (CaseClauseNode::processVarDecls):
        (CaseClauseNode::processFuncDecl):
        (ClauseListNode::processFuncDecl):
        (CaseBlockNode::processFuncDecl):
        (SwitchNode::processFuncDecl):
        * kjs/nodes.h:
        (KJS::CaseClauseNode::CaseClauseNode):
        (KJS::ClauseListNode::ClauseListNode):
        (KJS::ClauseListNode::getClause):
        (KJS::ClauseListNode::getNext):
        (KJS::ClauseListNode::releaseNext):
        (KJS::SwitchNode::SwitchNode):
        Add processFuncDecl for the relevant nodes.

        * kjs/nodes2string.cpp:
        (CaseClauseNode::streamTo):
        next got renamed to source.

LayoutTests:

2006-05-20  Anders Carlsson  <acarlsson@apple.com>

        Reviewed by Geoff.

        * fast/js/function-declarations-in-switch-statement-expected.txt: Added.
        * fast/js/function-declarations-in-switch-statement.html: Added.
        * fast/js/resources/function-declarations-in-switch-statement.js: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14502 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/kjs/grammar.y
JavaScriptCore/kjs/nodes.cpp
JavaScriptCore/kjs/nodes.h
JavaScriptCore/kjs/nodes2string.cpp
LayoutTests/ChangeLog
LayoutTests/fast/js/function-declarations-in-switch-statement-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/function-declarations-in-switch-statement.html [new file with mode: 0644]
LayoutTests/fast/js/resources/function-declarations-in-switch-statement.js [new file with mode: 0644]

index 0a811e5152d6a8e52fed960c325c493530753b67..4ab80327709301469e83ebf7aa4a2d32eef5293f 100644 (file)
@@ -1,3 +1,32 @@
+2006-05-19  Anders Carlsson  <acarlsson@apple.com>
+
+        Reviewed by Geoff.
+
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=8993
+        Support function declaration in case statements
+        
+        * kjs/grammar.y: Get rid of StatementList and use SourceElements instead.
+        
+        * kjs/nodes.cpp:
+        (CaseClauseNode::evalStatements):
+        (CaseClauseNode::processVarDecls):
+        (CaseClauseNode::processFuncDecl):
+        (ClauseListNode::processFuncDecl):
+        (CaseBlockNode::processFuncDecl):
+        (SwitchNode::processFuncDecl):
+        * kjs/nodes.h:
+        (KJS::CaseClauseNode::CaseClauseNode):
+        (KJS::ClauseListNode::ClauseListNode):
+        (KJS::ClauseListNode::getClause):
+        (KJS::ClauseListNode::getNext):
+        (KJS::ClauseListNode::releaseNext):
+        (KJS::SwitchNode::SwitchNode):
+        Add processFuncDecl for the relevant nodes.        
+
+        * kjs/nodes2string.cpp:
+        (CaseClauseNode::streamTo):
+        next got renamed to source.
+
 2006-05-17  George Staikos <staikos@kde.org>
 
         Reviewed by Maciej, Alexey, and Eric.
index 138dbd65c242b68910b99b171409deca71cdb145..b0aa05feacc20ef0ce3fab25976ee411527feeef 100644 (file)
@@ -76,7 +76,6 @@ static Node *makeDeleteNode(Node *expr);
   ProgramNode         *prog;
   AssignExprNode      *init;
   SourceElementsNode  *srcs;
-  StatListNode        *slist;
   ArgumentsNode       *args;
   ArgumentListNode    *alist;
   VarDeclNode         *decl;
@@ -167,7 +166,6 @@ static Node *makeDeleteNode(Node *expr);
 %type <stat>  DebuggerStatement
 %type <stat>  SourceElement
 
-%type <slist> StatementList
 %type <init>  Initializer InitializerNoIn
 %type <func>  FunctionDeclaration
 %type <funcExpr>  FunctionExpr
@@ -637,11 +635,6 @@ Block:
   | '{' SourceElements '}'              { $$ = new BlockNode($2); DBG($$, @3, @3); }
 ;
 
-StatementList:
-    Statement                           { $$ = new StatListNode($1); }
-  | StatementList Statement             { $$ = new StatListNode($1, $2); }
-;
-
 VariableStatement:
     VAR VariableDeclarationList ';'     { $$ = new VarStatementNode($2); DBG($$, @1, @3); }
   | VAR VariableDeclarationList error   { $$ = new VarStatementNode($2); DBG($$, @1, @2); AUTO_SEMICOLON; }
@@ -787,12 +780,12 @@ CaseClauses:
 
 CaseClause:
     CASE Expr ':'                       { $$ = new CaseClauseNode($2); }
-  | CASE Expr ':' StatementList         { $$ = new CaseClauseNode($2, $4); }
+  | CASE Expr ':' SourceElements        { $$ = new CaseClauseNode($2, $4); }
 ;
 
 DefaultClause:
     DEFAULT ':'                         { $$ = new CaseClauseNode(0); }
-  | DEFAULT ':' StatementList           { $$ = new CaseClauseNode(0, $3); }
+  | DEFAULT ':' SourceElements          { $$ = new CaseClauseNode(0, $3); }
 ;
 
 LabelledStatement:
index d9110fa0cb0946f47396f8b7b4dbd847cd24cb3d..721c113a403f8182abd8fa9694cc8c19181c8c0a 100644 (file)
@@ -1508,57 +1508,6 @@ JSValue *CommaNode::evaluate(ExecState *exec)
   return v;
 }
 
-// ------------------------------ StatListNode ---------------------------------
-
-StatListNode::StatListNode(StatementNode *s)
-  : statement(s), next(this)
-{
-    Parser::noteNodeCycle(this);
-    setLoc(s->firstLine(), s->lastLine());
-}
-StatListNode::StatListNode(StatListNode *l, StatementNode *s)
-  : statement(s), next(l->next)
-{
-  l->next = this;
-  setLoc(l->firstLine(), s->lastLine());
-}
-
-// ECMA 12.1
-Completion StatListNode::execute(ExecState *exec)
-{
-  Completion c = statement->execute(exec);
-  KJS_ABORTPOINT
-  if (c.complType() != Normal)
-    return c;
-  
-  JSValue *v = c.value();
-  
-  for (StatListNode *n = next.get(); n; n = n->next.get()) {
-    Completion c2 = n->statement->execute(exec);
-    KJS_ABORTPOINT
-    if (c2.complType() != Normal)
-      return c2;
-
-    if (c2.isValueCompletion())
-      v = c2.value();
-    c = c2;
-  }
-
-  return Completion(c.complType(), v, c.target());
-}
-
-void StatListNode::processVarDecls(ExecState *exec)
-{
-  for (StatListNode *n = this; n; n = n->next.get())
-    n->statement->processVarDecls(exec);
-}
-
-void StatListNode::breakCycle() 
-{ 
-    next = 0;
-}
-
 // ------------------------------ AssignExprNode -------------------------------
 
 // ECMA 12.2
@@ -2094,16 +2043,22 @@ JSValue *CaseClauseNode::evaluate(ExecState *exec)
 // ECMA 12.11
 Completion CaseClauseNode::evalStatements(ExecState *exec)
 {
-  if (next)
-    return next->execute(exec);
+  if (source)
+    return source->execute(exec);
   else
     return Completion(Normal, jsUndefined());
 }
 
 void CaseClauseNode::processVarDecls(ExecState *exec)
 {
-  if (next)
-    next->processVarDecls(exec);
+  if (source)
+    source->processVarDecls(exec);
+}
+
+void CaseClauseNode::processFuncDecl(ExecState* exec)
+{
+  if (source)
+      source->processFuncDecl(exec);
 }
 
 // ------------------------------ ClauseListNode -------------------------------
@@ -2123,6 +2078,13 @@ void ClauseListNode::processVarDecls(ExecState *exec)
       n->clause->processVarDecls(exec);
 }
 
+void ClauseListNode::processFuncDecl(ExecState* exec)
+{
+  for (ClauseListNode* n = this; n; n = n->next.get())
+    if (n->clause)
+      n->clause->processFuncDecl(exec);
+}
+
 void ClauseListNode::breakCycle() 
 { 
     next = 0;
@@ -2230,6 +2192,16 @@ void CaseBlockNode::processVarDecls(ExecState *exec)
     list2->processVarDecls(exec);
 }
 
+void CaseBlockNode::processFuncDecl(ExecState* exec)
+{
+  if (list1)
+   list1->processFuncDecl(exec);
+  if (def)
+    def->processFuncDecl(exec);
+  if (list2)
+    list2->processFuncDecl(exec);
+}
+
 // ------------------------------ SwitchNode -----------------------------------
 
 // ECMA 12.11
@@ -2254,6 +2226,11 @@ void SwitchNode::processVarDecls(ExecState *exec)
   block->processVarDecls(exec);
 }
 
+void SwitchNode::processFuncDecl(ExecState* exec)
+{
+  block->processFuncDecl(exec);
+}
+
 // ------------------------------ LabelNode ------------------------------------
 
 // ECMA 12.12
index c909298080ba5f59ebf33ade80eab927812318de..c3ecf7fa7e9a8489d13ea82f9d9e276d46dc00e3 100644 (file)
@@ -734,22 +734,6 @@ namespace KJS {
     RefPtr<Node> expr2;
   };
 
-  class StatListNode : public StatementNode {
-  public:
-    // list pointer is tail of a circular list, cracked in the CaseClauseNode ctor
-    StatListNode(StatementNode *s);
-    StatListNode(StatListNode *l, StatementNode *s);
-    virtual Completion execute(ExecState*);
-    virtual void processVarDecls(ExecState*);
-    virtual void streamTo(SourceStream&) const;
-    PassRefPtr<StatListNode> releaseNext() { return next.release(); }
-    virtual void breakCycle();
-  private:
-    friend class CaseClauseNode;
-    RefPtr<StatementNode> statement;
-    ListRefPtr<StatListNode> next;
-  };
-
   class AssignExprNode : public Node {
   public:
     AssignExprNode(Node *e) : expr(e) {}
@@ -933,63 +917,6 @@ namespace KJS {
     RefPtr<StatementNode> statement;
   };
 
-  class CaseClauseNode : public Node {
-  public:
-    CaseClauseNode(Node *e) : expr(e) { }
-    CaseClauseNode(Node *e, StatListNode *l)
-      : expr(e), next(l->next.release()) { Parser::removeNodeCycle(next.get()); }
-    JSValue* evaluate(ExecState*);
-    Completion evalStatements(ExecState*);
-    virtual void processVarDecls(ExecState*);
-    virtual void streamTo(SourceStream&) const;
-  private:
-    RefPtr<Node> expr;
-    RefPtr<StatListNode> next;
-  };
-
-  class ClauseListNode : public Node {
-  public:
-    // list pointer is tail of a circular list, cracked in the CaseBlockNode ctor
-    ClauseListNode(CaseClauseNode *c) : clause(c), next(this) { Parser::noteNodeCycle(this); }
-    ClauseListNode(ClauseListNode *n, CaseClauseNode *c)
-      : clause(c), next(n->next) { n->next = this; }
-    JSValue* evaluate(ExecState*);
-    CaseClauseNode *getClause() const { return clause.get(); }
-    ClauseListNode *getNext() const { return next.get(); }
-    virtual void processVarDecls(ExecState*);
-    virtual void streamTo(SourceStream&) const;
-    PassRefPtr<ClauseListNode> releaseNext() { return next.release(); }
-    virtual void breakCycle();
-  private:
-    friend class CaseBlockNode;
-    RefPtr<CaseClauseNode> clause;
-    ListRefPtr<ClauseListNode> next;
-  };
-
-  class CaseBlockNode : public Node {
-  public:
-    CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, ClauseListNode *l2);
-    JSValue* evaluate(ExecState*);
-    Completion evalBlock(ExecState *exec, JSValue *input);
-    virtual void processVarDecls(ExecState*);
-    virtual void streamTo(SourceStream&) const;
-  private:
-    RefPtr<ClauseListNode> list1;
-    RefPtr<CaseClauseNode> def;
-    RefPtr<ClauseListNode> list2;
-  };
-
-  class SwitchNode : public StatementNode {
-  public:
-    SwitchNode(Node *e, CaseBlockNode *b) : expr(e), block(b) { }
-    virtual Completion execute(ExecState*);
-    virtual void processVarDecls(ExecState*);
-    virtual void streamTo(SourceStream&) const;
-  private:
-    RefPtr<Node> expr;
-    RefPtr<CaseBlockNode> block;
-  };
-
   class LabelNode : public StatementNode {
   public:
     LabelNode(const Identifier &l, StatementNode *s) : label(l), statement(s) { }
@@ -1087,7 +1014,7 @@ namespace KJS {
   // A linked list of source element nodes
   class SourceElementsNode : public StatementNode {
   public:
-      static int count;
+    static int count;
     // list pointer is tail of a circular list, cracked in the BlockNode (or subclass) ctor
     SourceElementsNode(StatementNode*);
     SourceElementsNode(SourceElementsNode *s1, StatementNode *s2);
@@ -1100,10 +1027,72 @@ namespace KJS {
     virtual void breakCycle();
   private:
     friend class BlockNode;
+    friend class CaseClauseNode;
     RefPtr<StatementNode> node;
     ListRefPtr<SourceElementsNode> next;
   };
 
+  class CaseClauseNode : public Node {
+  public:
+      CaseClauseNode(Node *e) : expr(e) { }
+      CaseClauseNode(Node *e, SourceElementsNode *s)
+      : expr(e), source(s->next.release()) { Parser::removeNodeCycle(source.get()); }
+      JSValue* evaluate(ExecState*);
+      Completion evalStatements(ExecState*);
+      void processFuncDecl(ExecState*);
+      virtual void processVarDecls(ExecState*);
+      virtual void streamTo(SourceStream&) const;
+  private:
+      RefPtr<Node> expr;
+      RefPtr<SourceElementsNode> source;
+  };
+  
+  class ClauseListNode : public Node {
+  public:
+      // list pointer is tail of a circular list, cracked in the CaseBlockNode ctor
+      ClauseListNode(CaseClauseNode *c) : clause(c), next(this) { Parser::noteNodeCycle(this); }
+      ClauseListNode(ClauseListNode *n, CaseClauseNode *c)
+      : clause(c), next(n->next) { n->next = this; }
+      JSValue* evaluate(ExecState*);
+      CaseClauseNode *getClause() const { return clause.get(); }
+      ClauseListNode *getNext() const { return next.get(); }
+      virtual void processVarDecls(ExecState*);
+      void processFuncDecl(ExecState*);
+      virtual void streamTo(SourceStream&) const;
+      PassRefPtr<ClauseListNode> releaseNext() { return next.release(); }
+      virtual void breakCycle();
+  private:
+      friend class CaseBlockNode;
+      RefPtr<CaseClauseNode> clause;
+      ListRefPtr<ClauseListNode> next;
+  };
+  
+  class CaseBlockNode : public Node {
+  public:
+      CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d, ClauseListNode *l2);
+      JSValue* evaluate(ExecState*);
+      Completion evalBlock(ExecState *exec, JSValue *input);
+      virtual void processVarDecls(ExecState*);
+      void processFuncDecl(ExecState*);
+      virtual void streamTo(SourceStream&) const;
+  private:
+      RefPtr<ClauseListNode> list1;
+      RefPtr<CaseClauseNode> def;
+      RefPtr<ClauseListNode> list2;
+  };
+  
+  class SwitchNode : public StatementNode {
+  public:
+      SwitchNode(Node *e, CaseBlockNode *b) : expr(e), block(b) { }
+      virtual Completion execute(ExecState*);
+      virtual void processVarDecls(ExecState*);
+      virtual void processFuncDecl(ExecState*);
+      virtual void streamTo(SourceStream&) const;
+  private:
+      RefPtr<Node> expr;
+      RefPtr<CaseBlockNode> block;
+  };
+  
   class ProgramNode : public FunctionBodyNode {
   public:
     ProgramNode(SourceElementsNode *s);
index cfc7ed047c8b7be56c619f26020c86ff1e4a0b29..caff9f19aa8ebc75dde1679d0261b111a8893a65 100644 (file)
@@ -523,12 +523,6 @@ void CommaNode::streamTo(SourceStream &s) const
   s << expr1 << ", " << expr2;
 }
 
-void StatListNode::streamTo(SourceStream &s) const
-{
-  for (const StatListNode *n = this; n; n = n->next.get())
-    s << n->statement;
-}
-
 void AssignExprNode::streamTo(SourceStream &s) const
 {
   s << " = " << expr;
@@ -650,8 +644,8 @@ void CaseClauseNode::streamTo(SourceStream &s) const
   else
     s << "default";
   s << ":" << SourceStream::Indent;
-  if (next)
-    s << next;
+  if (source)
+    s << source;
   s << SourceStream::Unindent;
 }
 
index a125b0f83b2cb4702f60512a267fa911f9398158..246a81ce87fb5fb3326f0304add62764413c86f3 100644 (file)
@@ -1,3 +1,11 @@
+2006-05-20  Anders Carlsson  <acarlsson@apple.com>
+
+        Reviewed by Geoff.
+
+        * fast/js/function-declarations-in-switch-statement-expected.txt: Added.
+        * fast/js/function-declarations-in-switch-statement.html: Added.
+        * fast/js/resources/function-declarations-in-switch-statement.js: Added.
+
 2006-05-20  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Reviewed and landed by ap.
diff --git a/LayoutTests/fast/js/function-declarations-in-switch-statement-expected.txt b/LayoutTests/fast/js/function-declarations-in-switch-statement-expected.txt
new file mode 100644 (file)
index 0000000..83bb0f1
--- /dev/null
@@ -0,0 +1,10 @@
+WARN: shouldBe() expects string arguments
+PASS 20 is 20
+WARN: shouldBe() expects string arguments
+PASS 20 is 20
+WARN: shouldBe() expects string arguments
+PASS 20 is 20
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/function-declarations-in-switch-statement.html b/LayoutTests/fast/js/function-declarations-in-switch-statement.html
new file mode 100644 (file)
index 0000000..a9464e8
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="resources/function-declarations-in-switch-statement.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/js/resources/function-declarations-in-switch-statement.js b/LayoutTests/fast/js/resources/function-declarations-in-switch-statement.js
new file mode 100644 (file)
index 0000000..aecdbcf
--- /dev/null
@@ -0,0 +1,26 @@
+function t(n) {
+    switch (n) {
+        case 1:
+            function f() {
+                return 10;
+            }
+            break;
+        case 2:
+            function f() {
+                return 20;
+            }
+            break;
+    }
+
+    try {
+      return f();
+    } catch (e) {
+      return -1;
+    }
+}
+
+shouldBe(t(1), '20');
+shouldBe(t(2), '20');
+shouldBe(t(3), '20');
+
+var successfullyParsed = true;