Add more generator/yield parsing tests
authorwingo@igalia.com <wingo@igalia.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 2 Jul 2014 12:27:34 +0000 (12:27 +0000)
committerwingo@igalia.com <wingo@igalia.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 2 Jul 2014 12:27:34 +0000 (12:27 +0000)
R=marja@chromium.org
BUG=

Review URL: https://codereview.chromium.org/362963002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22155 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

test/cctest/test-parsing.cc

index 8066f80..af553ed 100644 (file)
@@ -1658,6 +1658,7 @@ TEST(ErrorsFutureStrictReservedWords) {
     "var foo = interface = 1;",
     "++interface;",
     "interface++;",
+    "var yield = 13;",
     NULL
   };
 
@@ -1683,6 +1684,7 @@ TEST(NoErrorsFutureStrictReservedWords) {
     "var foo = interface = 1;",
     "++interface;",
     "interface++;",
+    "var yield = 13;",
     NULL
   };
 
@@ -1721,12 +1723,13 @@ TEST(ErrorsReservedWords) {
 }
 
 
-TEST(NoErrorsYieldSloppy) {
+TEST(NoErrorsYieldSloppyAllModes) {
   // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
   // generator (see next test).
   const char* context_data[][2] = {
     { "", "" },
-    { "function is_not_gen() {", "}" },
+    { "function not_gen() {", "}" },
+    { "(function not_gen() {", "})" },
     { NULL, NULL }
   };
 
@@ -1735,12 +1738,18 @@ TEST(NoErrorsYieldSloppy) {
     "var foo, yield;",
     "try { } catch (yield) { }",
     "function yield() { }",
+    "(function yield() { })",
     "function foo(yield) { }",
     "function foo(bar, yield) { }",
     "yield = 1;",
     "var foo = yield = 1;",
     "++yield;",
     "yield++;",
+    "yield: 34",
+    "function yield(yield) { yield: yield (yield + yield (0)); }",
+    "({ yield: 1 })",
+    "({ get yield() { 1 } })",
+    "yield (100)",
     NULL
   };
 
@@ -1748,9 +1757,15 @@ TEST(NoErrorsYieldSloppy) {
 }
 
 
-TEST(ErrorsYieldSloppyGenerator) {
+TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
+  // In sloppy mode, it's okay to use "yield" as identifier, *except* inside a
+  // generator (see next test).
   const char* context_data[][2] = {
-    { "function * is_gen() {", "}" },
+    { "", "" },
+    { "function not_gen() {", "}" },
+    { "function * gen() { function not_gen() {", "} }" },
+    { "(function not_gen() {", "})" },
+    { "(function * gen() { (function not_gen() {", "}) })" },
     { NULL, NULL }
   };
 
@@ -1759,28 +1774,40 @@ TEST(ErrorsYieldSloppyGenerator) {
     "var foo, yield;",
     "try { } catch (yield) { }",
     "function yield() { }",
-    // BUG: These should not be allowed, but they are (if kAllowGenerators is
-    // set)
-    // "function foo(yield) { }",
-    // "function foo(bar, yield) { }",
+    "(function yield() { })",
+    "function foo(yield) { }",
+    "function foo(bar, yield) { }",
+    "function * yield() { }",
+    "(function * yield() { })",
     "yield = 1;",
     "var foo = yield = 1;",
     "++yield;",
     "yield++;",
+    "yield: 34",
+    "function yield(yield) { yield: yield (yield + yield (0)); }",
+    "({ yield: 1 })",
+    "({ get yield() { 1 } })",
+    "yield (100)",
     NULL
   };
 
-  // If generators are not allowed, the error will be produced at the '*' token,
-  // so this test works both with and without the kAllowGenerators flag.
-  RunParserSyncTest(context_data, statement_data, kError);
+  // This test requires kAllowGenerators to succeed.
+  static const ParserFlag always_true_flags[] = {
+    kAllowGenerators
+  };
+  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
+                    always_true_flags, 1);
 }
 
 
 TEST(ErrorsYieldStrict) {
   const char* context_data[][2] = {
     { "\"use strict\";", "" },
-    { "\"use strict\"; function is_not_gen() {", "}" },
+    { "\"use strict\"; function not_gen() {", "}" },
     { "function test_func() {\"use strict\"; ", "}"},
+    { "\"use strict\"; function * gen() { function not_gen() {", "} }" },
+    { "\"use strict\"; (function not_gen() {", "})" },
+    { "\"use strict\"; (function * gen() { (function not_gen() {", "}) })" },
     { NULL, NULL }
   };
 
@@ -1789,12 +1816,16 @@ TEST(ErrorsYieldStrict) {
     "var foo, yield;",
     "try { } catch (yield) { }",
     "function yield() { }",
+    "(function yield() { })",
     "function foo(yield) { }",
     "function foo(bar, yield) { }",
+    "function * yield() { }",
+    "(function * yield() { })",
     "yield = 1;",
     "var foo = yield = 1;",
     "++yield;",
     "yield++;",
+    "yield: 34;",
     NULL
   };
 
@@ -1802,15 +1833,41 @@ TEST(ErrorsYieldStrict) {
 }
 
 
-TEST(NoErrorsYield) {
+TEST(NoErrorsGenerator) {
   const char* context_data[][2] = {
-    { "function * is_gen() {", "}" },
+    { "function * gen() {", "}" },
+    { "(function * gen() {", "})" },
+    { "(function * () {", "})" },
     { NULL, NULL }
   };
 
   const char* statement_data[] = {
-    "yield 2;",  // this is legal inside generator
-    "yield * 2;",  // this is legal inside generator
+    // A generator without a body is valid.
+    ""
+    // Valid yield expressions inside generators.
+    "yield 2;",
+    "yield * 2;",
+    "yield * \n 2;",
+    "yield yield 1;",
+    "yield * yield * 1;",
+    "yield 3 + (yield 4);",
+    "yield * 3 + (yield * 4);",
+    "(yield * 3) + (yield * 4);",
+    "yield 3; yield 4;",
+    "yield * 3; yield * 4;",
+    "(function (yield) { })",
+    // You can return in a generator.
+    "yield 1; return",
+    "yield * 1; return",
+    "yield 1; return 37",
+    "yield * 1; return 37",
+    "yield 1; return 37; yield 'dead';",
+    "yield * 1; return 37; yield * 'dead';",
+    // Yield is still a valid key in object literals.
+    "({ yield: 1 })",
+    "({ get yield() { } })",
+    // TODO(348893007): Invalid (no newline allowed between yield and *).
+    "yield\n*3",
     NULL
   };
 
@@ -1823,20 +1880,75 @@ TEST(NoErrorsYield) {
 }
 
 
+TEST(ErrorsYieldGenerator) {
+  const char* context_data[][2] = {
+    { "function * gen() {", "}" },
+    { "\"use strict\"; function * gen() {", "}" },
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    // Invalid yield expressions inside generators.
+    "var yield;",
+    "var foo, yield;",
+    "try { } catch (yield) { }",
+    "function yield() { }",
+    // The name of the NFE is let-bound in the generator, which does not permit
+    // yield to be an identifier.
+    "(function yield() { })",
+    "(function * yield() { })",
+    // Yield isn't valid as a formal parameter for generators.
+    "function * foo(yield) { }",
+    "(function * foo(yield) { })",
+    "yield = 1;",
+    "var foo = yield = 1;",
+    "++yield;",
+    "yield++;",
+    "yield *",
+    "(yield *)",
+    // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which
+    // is invalid.
+    "yield 3 + yield 4;",
+    "yield: 34",
+    "yield ? 1 : 2",
+    // Parses as yield (/ yield): invalid.
+    "yield / yield",
+    // TODO(348893007): The rest of these should be valid.
+    "yield;",
+    "yield",
+    "yield\n",
+    "(yield)",
+    "[yield]",
+    "{yield}",
+    "yield, yield",
+    "yield; yield",
+    "(yield) ? yield : yield",
+    "(yield) \n ? yield : yield",
+    // Parses as yield (+ yield).
+    "yield + yield",
+    NULL
+  };
+
+  RunParserSyncTest(context_data, statement_data, kError);
+}
+
+
 TEST(ErrorsNameOfStrictFunction) {
   // Tests that illegal tokens as names of a strict function produce the correct
   // errors.
   const char* context_data[][2] = {
-    { "", ""},
-    { "\"use strict\";", ""},
+    { "function ", ""},
+    { "\"use strict\"; function", ""},
+    { "function * ", ""},
+    { "\"use strict\"; function * ", ""},
     { NULL, NULL }
   };
 
   const char* statement_data[] = {
-    "function eval() {\"use strict\";}",
-    "function arguments() {\"use strict\";}",
-    "function interface() {\"use strict\";}",
-    "function yield() {\"use strict\";}",
+    "eval() {\"use strict\";}",
+    "arguments() {\"use strict\";}",
+    "interface() {\"use strict\";}",
+    "yield() {\"use strict\";}",
     // Future reserved words are always illegal
     "function super() { }",
     "function super() {\"use strict\";}",
@@ -1849,15 +1961,15 @@ TEST(ErrorsNameOfStrictFunction) {
 
 TEST(NoErrorsNameOfStrictFunction) {
   const char* context_data[][2] = {
-    { "", ""},
+    { "function ", ""},
     { NULL, NULL }
   };
 
   const char* statement_data[] = {
-    "function eval() { }",
-    "function arguments() { }",
-    "function interface() { }",
-    "function yield() { }",
+    "eval() { }",
+    "arguments() { }",
+    "interface() { }",
+    "yield() { }",
     NULL
   };
 
@@ -1865,6 +1977,28 @@ TEST(NoErrorsNameOfStrictFunction) {
 }
 
 
+TEST(NoErrorsNameOfStrictGenerator) {
+  const char* context_data[][2] = {
+    { "function * ", ""},
+    { NULL, NULL }
+  };
+
+  const char* statement_data[] = {
+    "eval() { }",
+    "arguments() { }",
+    "interface() { }",
+    "yield() { }",
+    NULL
+  };
+
+  // This test requires kAllowGenerators to succeed.
+  static const ParserFlag always_true_flags[] = {
+    kAllowGenerators
+  };
+  RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
+                    always_true_flags, 1);
+}
+
 
 TEST(ErrorsIllegalWordsAsLabelsSloppy) {
   // Using future reserved words as labels is always an error.