Index: test/cctest/test-parsing.cc |
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc |
index 8066f8052a83dd02586575cf694a268d9aeef17e..552038d8b9d554f962643a680d1f52d06489d1df 100644 |
--- a/test/cctest/test-parsing.cc |
+++ b/test/cctest/test-parsing.cc |
@@ -292,6 +292,7 @@ TEST(StandAlonePreParser) { |
"function foo(x, y) { return x + y; }", |
"%ArgleBargle(glop);", |
"var x = new new Function('this.x = 42');", |
+ "var f = (x, y) => x + y;", |
NULL |
}; |
@@ -308,6 +309,7 @@ TEST(StandAlonePreParser) { |
i::PreParser preparser(&scanner, &log, stack_limit); |
preparser.set_allow_lazy(true); |
preparser.set_allow_natives_syntax(true); |
+ preparser.set_allow_arrow_functions(true); |
i::PreParser::PreParseResult result = preparser.PreParseProgram(); |
CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
i::ScriptData data(log.ExtractData()); |
@@ -914,7 +916,7 @@ static int Utf8LengthHelper(const char* s) { |
TEST(ScopePositions) { |
- v8::internal::FLAG_harmony_scoping = true; |
+ i::FLAG_harmony_scoping = true; |
// Test the parser for correctly setting the start and end positions |
// of a scope. We check the scope positions of exactly one scope |
@@ -970,7 +972,8 @@ TEST(ScopePositions) { |
" infunction;\n" |
" }", "\n" |
" more;", i::FUNCTION_SCOPE, i::SLOPPY }, |
- { " (function fun", "(a,b) { infunction; }", ")();", |
+ { " start;\n" |
marja
2014/07/01 07:23:40
Why this change?
|
+ " (function fun", "(a,b) { infunction; }", ")();", |
i::FUNCTION_SCOPE, i::SLOPPY }, |
{ " for ", "(let x = 1 ; x < 10; ++ x) { block; }", " more;", |
i::BLOCK_SCOPE, i::STRICT }, |
@@ -1181,7 +1184,8 @@ enum ParserFlag { |
kAllowModules, |
kAllowGenerators, |
kAllowForOf, |
- kAllowHarmonyNumericLiterals |
+ kAllowHarmonyNumericLiterals, |
+ kAllowArrowFunctions |
}; |
@@ -1202,6 +1206,7 @@ void SetParserFlags(i::ParserBase<Traits>* parser, |
parser->set_allow_for_of(flags.Contains(kAllowForOf)); |
parser->set_allow_harmony_numeric_literals( |
flags.Contains(kAllowHarmonyNumericLiterals)); |
+ parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions)); |
} |
@@ -1406,7 +1411,7 @@ TEST(ParserSync) { |
static const ParserFlag flags1[] = { |
kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators, |
- kAllowForOf |
+ kAllowForOf, kAllowArrowFunctions |
}; |
for (int i = 0; context_data[i][0] != NULL; ++i) { |
for (int j = 0; statement_data[j] != NULL; ++j) { |
@@ -1427,7 +1432,8 @@ TEST(ParserSync) { |
termination_data[k], |
context_data[i][1]); |
CHECK(length == kProgramSize); |
- TestParserSync(program.start(), flags1, ARRAY_SIZE(flags1)); |
+ TestParserSync(program.start(), flags1, ARRAY_SIZE(flags1), |
+ kSuccessOrError); |
} |
} |
} |
@@ -1436,11 +1442,11 @@ TEST(ParserSync) { |
// interaction with the flags above, so test these separately to reduce |
// the combinatorial explosion. |
static const ParserFlag flags2[] = { kAllowHarmonyNumericLiterals }; |
- TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2)); |
- TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2)); |
+ TestParserSync("0o1234", flags2, ARRAY_SIZE(flags2), kSuccessOrError); |
+ TestParserSync("0b1011", flags2, ARRAY_SIZE(flags2), kSuccessOrError); |
static const ParserFlag flags3[] = { kAllowNativesSyntax }; |
- TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3)); |
+ TestParserSync("%DebugPrint(123)", flags3, ARRAY_SIZE(flags3), kSuccessOrError); |
} |
@@ -1448,6 +1454,7 @@ TEST(StrictOctal) { |
// Test that syntax error caused by octal literal is reported correctly as |
// such (issue 2220). |
v8::V8::Initialize(); |
+ |
marja
2014/07/01 07:23:40
This file seems to contain some unintentional chan
|
v8::HandleScope scope(CcTest::isolate()); |
v8::Context::Scope context_scope( |
v8::Context::New(CcTest::isolate())); |
@@ -1484,7 +1491,7 @@ void RunParserSyncTest(const char* context_data[][2], |
static const ParserFlag default_flags[] = { |
kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators, |
- kAllowForOf, kAllowNativesSyntax |
+ kAllowForOf, kAllowNativesSyntax, kAllowArrowFunctions |
}; |
ParserFlag* generated_flags = NULL; |
if (flags == NULL) { |
@@ -1561,6 +1568,10 @@ TEST(ErrorsEvalAndArguments) { |
"function foo(arguments) { }", |
"function foo(bar, eval) { }", |
"function foo(bar, arguments) { }", |
+ "(eval) => { }", |
+ "(arguments) => { }", |
+ "(foo, eval) => { }", |
+ "(foo, arguments) => { }", |
"eval = 1;", |
"arguments = 1;", |
"var foo = eval = 1;", |
@@ -1617,6 +1628,7 @@ TEST(NoErrorsEvalAndArgumentsStrict) { |
const char* context_data[][2] = { |
{ "\"use strict\";", "" }, |
{ "function test_func() { \"use strict\";", "}" }, |
+ { "() => { \"use strict\"; ", "}" }, |
{ NULL, NULL } |
}; |
@@ -1632,7 +1644,9 @@ TEST(NoErrorsEvalAndArgumentsStrict) { |
NULL |
}; |
- RunParserSyncTest(context_data, statement_data, kSuccess); |
+ static const ParserFlag always_flags[] = { kAllowArrowFunctions }; |
+ RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, |
+ always_flags, ARRAY_SIZE(always_flags)); |
} |
@@ -1644,6 +1658,7 @@ TEST(ErrorsFutureStrictReservedWords) { |
const char* context_data[][2] = { |
{ "\"use strict\";", "" }, |
{ "function test_func() {\"use strict\"; ", "}"}, |
+ { "() => { \"use strict\"; ", "}" }, |
{ NULL, NULL } |
}; |
@@ -1654,6 +1669,8 @@ TEST(ErrorsFutureStrictReservedWords) { |
"function interface() { }", |
"function foo(interface) { }", |
"function foo(bar, interface) { }", |
+ "(interface) => { }", |
+ "(bar, interface) => { }", |
"interface = 1;", |
"var foo = interface = 1;", |
"++interface;", |
@@ -1661,7 +1678,9 @@ TEST(ErrorsFutureStrictReservedWords) { |
NULL |
}; |
- RunParserSyncTest(context_data, statement_data, kError); |
+ static const ParserFlag always_flags[] = { kAllowArrowFunctions }; |
+ RunParserSyncTest(context_data, statement_data, kError, NULL, 0, |
+ always_flags, ARRAY_SIZE(always_flags)); |
} |
@@ -1669,6 +1688,7 @@ TEST(NoErrorsFutureStrictReservedWords) { |
const char* context_data[][2] = { |
{ "", "" }, |
{ "function test_func() {", "}"}, |
+ { "() => {", "}" }, |
{ NULL, NULL } |
}; |
@@ -1686,7 +1706,10 @@ TEST(NoErrorsFutureStrictReservedWords) { |
NULL |
}; |
- RunParserSyncTest(context_data, statement_data, kSuccess); |
+ static const ParserFlag always_flags[] = { kAllowArrowFunctions }; |
+ RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, |
+ always_flags, ARRAY_SIZE(always_flags)); |
+ |
} |
@@ -1699,6 +1722,8 @@ TEST(ErrorsReservedWords) { |
{ "\"use strict\";", "" }, |
{ "var eval; function test_func() {", "}"}, |
{ "var eval; function test_func() {\"use strict\"; ", "}"}, |
+ { "var eval; () => {", "}" }, |
+ { "var eval; () => {\"use strict\"; ", "}" }, |
{ NULL, NULL } |
}; |
@@ -1709,6 +1734,8 @@ TEST(ErrorsReservedWords) { |
"function super() { }", |
"function foo(super) { }", |
"function foo(bar, super) { }", |
+ "(super) => { }", |
+ "(bar, super) => { }", |
"super = 1;", |
"var foo = super = 1;", |
"++super;", |
@@ -1727,6 +1754,7 @@ TEST(NoErrorsYieldSloppy) { |
const char* context_data[][2] = { |
{ "", "" }, |
{ "function is_not_gen() {", "}" }, |
+ { "() => {", "}" }, |
{ NULL, NULL } |
}; |
@@ -1744,7 +1772,9 @@ TEST(NoErrorsYieldSloppy) { |
NULL |
}; |
- RunParserSyncTest(context_data, statement_data, kSuccess); |
+ static const ParserFlag always_flags[] = { kAllowArrowFunctions }; |
+ RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, |
+ always_flags, ARRAY_SIZE(always_flags)); |
} |
@@ -1781,6 +1811,7 @@ TEST(ErrorsYieldStrict) { |
{ "\"use strict\";", "" }, |
{ "\"use strict\"; function is_not_gen() {", "}" }, |
{ "function test_func() {\"use strict\"; ", "}"}, |
+ { "() => {\"use strict\"; ", "}" }, |
{ NULL, NULL } |
}; |
@@ -1791,6 +1822,8 @@ TEST(ErrorsYieldStrict) { |
"function yield() { }", |
"function foo(yield) { }", |
"function foo(bar, yield) { }", |
+ "(yield) => { }", |
+ "(bar, yield) => { }", |
"yield = 1;", |
"var foo = yield = 1;", |
"++yield;", |
@@ -1816,7 +1849,7 @@ TEST(NoErrorsYield) { |
// This test requires kAllowGenerators to succeed. |
static const ParserFlag always_true_flags[] = { |
- kAllowGenerators |
+ kAllowGenerators, |
}; |
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, |
always_true_flags, 1); |
@@ -1871,6 +1904,7 @@ TEST(ErrorsIllegalWordsAsLabelsSloppy) { |
const char* context_data[][2] = { |
{ "", ""}, |
{ "function test_func() {", "}" }, |
+ { "() => {", "}" }, |
{ NULL, NULL } |
}; |
@@ -1888,6 +1922,7 @@ TEST(ErrorsIllegalWordsAsLabelsStrict) { |
const char* context_data[][2] = { |
{ "\"use strict\";", "" }, |
{ "function test_func() {\"use strict\"; ", "}"}, |
+ { "() => {\"use strict\"; ", "}" }, |
{ NULL, NULL } |
}; |
@@ -1907,8 +1942,10 @@ TEST(NoErrorsIllegalWordsAsLabels) { |
const char* context_data[][2] = { |
{ "", ""}, |
{ "function test_func() {", "}" }, |
+ { "() => {", "}" }, |
{ "\"use strict\";", "" }, |
{ "\"use strict\"; function test_func() {", "}" }, |
+ { "\"use strict\"; () => {", "}" }, |
{ NULL, NULL } |
}; |
@@ -1919,7 +1956,9 @@ TEST(NoErrorsIllegalWordsAsLabels) { |
NULL |
}; |
- RunParserSyncTest(context_data, statement_data, kSuccess); |
+ static const ParserFlag always_flags[] = { kAllowArrowFunctions }; |
+ RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, |
+ always_flags, ARRAY_SIZE(always_flags)); |
} |
@@ -1928,6 +1967,7 @@ TEST(ErrorsParenthesizedLabels) { |
const char* context_data[][2] = { |
{ "", ""}, |
{ "function test_func() {", "}" }, |
+ { "() => {", "}" }, |
{ NULL, NULL } |
}; |
@@ -2177,6 +2217,7 @@ TEST(Intrinsics) { |
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, |
always_true_flags, 1); |
+ RunParserSyncTest(context_data, statement_data, kSuccessOrError); |
} |
@@ -2771,3 +2812,168 @@ TEST(UseAsmUseCount) { |
"function bar() { \"use asm\"; var baz = 1; }"); |
CHECK_EQ(2, use_counts[v8::Isolate::kUseAsm]); |
} |
+ |
+ |
+TEST(ErrorsArrowFunctions) { |
marja
2014/07/01 07:23:40
I like this test! :)
|
+ // Tests that parser and preparser generate the same kind of errors |
+ // on invalid arrow function syntax. |
+ const char* context_data[][2] = { |
+ {"", ";"}, |
+ {"v = ", ";"}, |
+ {"bar ? (", ") : baz;"}, |
+ {"bar ? baz : (", ");"}, |
+ {"bar[", "];"}, |
+ {"bar, ", ";"}, |
+ {"", ", bar;"}, |
+ { NULL, NULL } |
+ }; |
+ |
+ const char* statement_data[] = { |
+ "=> 0", |
+ "=>", |
+ "() =>", |
+ "=> {}", |
+ ") => {}", |
+ ", => {}", |
+ "(,) => {}", |
+ "return => {}", |
+ "() => {'value': 42}", |
+ |
+ // Check that the early return introduced in ParsePrimaryExpression |
+ // does not accept stray closing parentheses. |
+ ")", |
+ ") => 0", |
+ "foo[()]", |
+ "()", |
+ |
+ // Parameter lists with extra parens should be recognized as errors. |
+ "(()) => 0", |
+ "((x)) => 0", |
+ "((x, y)) => 0", |
+ "(x, (y)) => 0", |
+ "((x, y, z)) => 0", |
+ "(x, (y, z)) => 0", |
+ "((x, y), z) => 0", |
+ |
+ // Parameter lists are always validated as strict, so those are errors. |
+ "eval => {}", |
+ "arguments => {}", |
+ "yield => {}", |
+ "interface => {}", |
+ "(eval) => {}", |
+ "(arguments) => {}", |
+ "(yield) => {}", |
+ "(interface) => {}", |
+ "(eval, bar) => {}", |
+ "(bar, eval) => {}", |
+ "(bar, arguments) => {}", |
+ "(bar, yield) => {}", |
+ "(bar, interface) => {}", |
+ // TODO(aperez): Detecting duplicates does not work in PreParser. |
+ //"(bar, bar) => {}", |
+ |
+ // The parameter list is parsed as an expression, but only |
+ // a comma-separated list of identifier is valid. |
+ "32 => {}", |
+ "(32) => {}", |
+ "(a, 32) => {}", |
+ "if => {}", |
+ "(if) => {}", |
+ "(a, if) => {}", |
+ "a + b => {}", |
+ "(a + b) => {}", |
+ "(a + b, c) => {}", |
+ "(a, b - c) => {}", |
+ "\"a\" => {}", |
+ "(\"a\") => {}", |
+ "(\"a\", b) => {}", |
+ "(a, \"b\") => {}", |
+ "-a => {}", |
+ "(-a) => {}", |
+ "(-a, b) => {}", |
+ "(a, -b) => {}", |
+ "{} => {}", |
+ "({}) => {}", |
+ "(a, {}) => {}", |
+ "({}, a) => {}", |
+ "a++ => {}", |
+ "(a++) => {}", |
+ "(a++, b) => {}", |
+ "(a, b++) => {}", |
+ "[] => {}", |
+ "([]) => {}", |
+ "(a, []) => {}", |
+ "([], a) => {}", |
+ "(a = b) => {}", |
+ "(a = b, c) => {}", |
+ "(a, b = c) => {}", |
+ "(foo ? bar : baz) => {}", |
+ "(a, foo ? bar : baz) => {}", |
+ "(foo ? bar : baz, a) => {}", |
+ |
+ NULL |
+ }; |
+ |
+ RunParserSyncTest(context_data, statement_data, kError); |
+} |
+ |
+ |
+TEST(NoErrorsArrowFunctions) { |
+ // Tests that parser and preparser accept valid arrow functions syntax. |
+ const char* context_data[][2] = { |
+ {"", ";"}, |
+ // TODO(aperez): Uncomment this when ParseArrowFunctionLiteral() |
+ // generates code and returns a non-NULL expression. Currently it |
+ // crashes when expression->set_is_parenthesized(true) is called. |
+ //{"bar ? (", ") : baz;"}, |
+ //{"bar ? baz : (", ");"}, |
+ {"bar, ", ";"}, |
+ {"", ", bar;"}, |
+ { NULL, NULL } |
+ }; |
+ |
+ const char* statement_data[] = { |
+ "() => {}", |
+ "() => { return 42 }", |
+ "x => { return x; }", |
+ "(x) => { return x; }", |
+ "(x, y) => { return x + y; }", |
+ "(x, y, z) => { return x + y + z; }", |
+ "(x, y) => { x.a = y; }", |
+ "() => 42", |
+ "x => x", |
+ "x => x * x", |
+ "(x) => x", |
+ "(x) => x * x", |
+ "(x, y) => x + y", |
+ "(x, y, z) => x, y, z", |
+ "(x, y) => x.a = y", |
+ "() => ({'value': 42})", |
+ "x => y => x + y", |
+ "(x, y) => (u, v) => x*u + y*v", |
+ "(x, y) => z => z * (x + y)", |
+ "x => (y, z) => z * (x + y)", |
+ |
+ // Those are comma-separated expressions, with arrow functions as items. |
+ // They stress the code for validating arrow function parameter lists. |
+ "a, b => 0", |
+ "a, b, (c, d) => 0", |
+ "(a, b, (c, d) => 0)", |
+ "(a, b) => 0, (c, d) => 1", |
+ "(a, b => {}, a => a + 1)", |
+ // TODO(aperez): Uncomment this when ParseArrowFunctionLiteral() |
+ // generates code and returns a non-NULL expression. Currently it |
+ // crashes when expression->set_is_parenthesized(true) is called. |
+ //"((a, b) => {}, (a => a + 1))", |
+ //"(a, (a, (b, c) => 0))", |
+ |
+ // Arrow has more precedence, this is the same as: foo ? bar : (baz = {}) |
+ "foo ? bar : baz => {}", |
+ |
+ NULL |
+ }; |
+ |
+ static const ParserFlag always_flags[] = { kAllowArrowFunctions }; |
+ RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0, |
+ always_flags, ARRAY_SIZE(always_flags)); |
+} |