Commit 2ea7f3c8 authored by adamk's avatar adamk Committed by Commit bot

[es6] Fix parsing of 'yield' in function and generator expressions

In a function expression, 'yield' is allowed, even if the expression
occurs inside a generator. Similarly, even in a non-generator,
a generator expression's name must not be 'yield'.

BUG=v8:3983
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#32188}
parent 21a7a106
......@@ -664,9 +664,20 @@ class ParserBase : public Traits {
IdentifierT ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
bool* ok);
// Parses an identifier or a strict mode future reserved word, and indicate
// whether it is strict mode future reserved.
IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
// whether it is strict mode future reserved. Allows passing in is_generator
// for the case of parsing the identifier in a function expression, where the
// relevant "is_generator" bit is of the function being parsed, not the
// containing
// function.
IdentifierT ParseIdentifierOrStrictReservedWord(bool is_generator,
bool* is_strict_reserved,
bool* ok);
IdentifierT ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
bool* ok) {
return ParseIdentifierOrStrictReservedWord(this->is_generator(),
is_strict_reserved, ok);
}
IdentifierT ParseIdentifierName(bool* ok);
// Parses an identifier and determines whether or not it is 'get' or 'set'.
IdentifierT ParseIdentifierNameOrGetOrSet(bool* is_get, bool* is_set,
......@@ -2146,15 +2157,14 @@ ParserBase<Traits>::ParseAndClassifyIdentifier(ExpressionClassifier* classifier,
template <class Traits>
typename ParserBase<Traits>::IdentifierT ParserBase<
Traits>::ParseIdentifierOrStrictReservedWord(bool* is_strict_reserved,
bool* ok) {
typename ParserBase<Traits>::IdentifierT
ParserBase<Traits>::ParseIdentifierOrStrictReservedWord(
bool is_generator, bool* is_strict_reserved, bool* ok) {
Token::Value next = Next();
if (next == Token::IDENTIFIER) {
*is_strict_reserved = false;
} else if (next == Token::FUTURE_STRICT_RESERVED_WORD || next == Token::LET ||
next == Token::STATIC ||
(next == Token::YIELD && !this->is_generator())) {
next == Token::STATIC || (next == Token::YIELD && !is_generator)) {
*is_strict_reserved = true;
} else {
ReportUnexpectedToken(next);
......@@ -3496,8 +3506,8 @@ ParserBase<Traits>::ParseMemberExpression(ExpressionClassifier* classifier,
FunctionLiteral::FunctionType function_type =
FunctionLiteral::ANONYMOUS_EXPRESSION;
if (peek_any_identifier()) {
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
CHECK_OK);
name = ParseIdentifierOrStrictReservedWord(
is_generator, &is_strict_reserved_name, CHECK_OK);
function_name_location = scanner()->location();
function_type = FunctionLiteral::NAMED_EXPRESSION;
}
......
......@@ -2221,7 +2221,6 @@ TEST(NoErrorsYieldSloppyGeneratorsEnabled) {
"function foo(yield) { }",
"function foo(bar, yield) { }",
"function * yield() { }",
"(function * yield() { })",
"yield = 1;",
"var foo = yield = 1;",
"yield * 2;",
......@@ -2282,6 +2281,23 @@ TEST(ErrorsYieldStrict) {
}
TEST(ErrorsYieldSloppy) {
const char* context_data[][2] = {
{ "", "" },
{ "function not_gen() {", "}" },
{ "(function not_gen() {", "})" },
{ NULL, NULL }
};
const char* statement_data[] = {
"(function * yield() { })",
NULL
};
RunParserSyncTest(context_data, statement_data, kError);
}
TEST(NoErrorsGenerator) {
const char* context_data[][2] = {
{ "function * gen() {", "}" },
......@@ -2305,6 +2321,7 @@ TEST(NoErrorsGenerator) {
"yield 3; yield 4;",
"yield * 3; yield * 4;",
"(function (yield) { })",
"(function yield() { })",
"yield { yield: 12 }",
"yield /* comment */ { yield: 12 }",
"yield * \n { yield: 12 }",
......@@ -2354,9 +2371,8 @@ TEST(ErrorsYieldGenerator) {
"var foo, yield;",
"try { } catch (yield) { }",
"function yield() { }",
// The name of the NFE is let-bound in the generator, which does not permit
// The name of the NFE is 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) { }",
......
......@@ -124,8 +124,8 @@ assertThrows("function* g() { yield 3 + yield 4; }", SyntaxError);
// Yield is still a future-reserved-word in strict mode
assertThrows("function f() { \"use strict\"; var yield = 13; }", SyntaxError);
// The name of the NFE is let-bound in G, so is invalid.
assertThrows("function* g() { yield (function yield() {}); }", SyntaxError);
// The name of the NFE is bound in the generator expression, so is invalid.
assertThrows("function f() { (function* yield() {}); }", SyntaxError);
// In generators, yield is invalid as a formal argument name.
assertThrows("function* g(yield) { yield (10); }", SyntaxError);
......@@ -179,13 +179,6 @@
'built-ins/Array/prototype/values/iteration-mutable': [FAIL],
'built-ins/Array/prototype/Symbol.unscopables/value': [FAIL],
#https://code.google.com/p/v8/issues/detail?id=3983
'language/expressions/generators/yield-as-function-expression-binding-identifier': [FAIL],
'language/expressions/generators/yield-as-generator-expression-binding-identifier': [FAIL],
'language/expressions/object/method-definition/generator-argSuperProperty': [FAIL],
'language/expressions/object/method-definition/yield-as-function-expression-binding-identifier': [FAIL],
'language/statements/generators/yield-as-function-expression-binding-identifier': [FAIL],
# https://code.google.com/p/v8/issues/detail?id=3566
'built-ins/GeneratorPrototype/return/from-state-completed': [FAIL],
'built-ins/GeneratorPrototype/return/from-state-suspended-start': [FAIL],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment