Commit 63b93542 authored by littledan's avatar littledan Committed by Commit bot

Disallow generator declarations in certain locations

The legacy function declaration locations from Annex B 3.2 and 3.4 do not
apply for generator declarations. This patch cracks down on those usages,
which is tested for by new incoming test262 tests.

BUG=v8:4824
LOG=Y
R=adamk

Review-Url: https://codereview.chromium.org/1900033003
Cr-Commit-Position: refs/heads/master@{#35835}
parent a1cd3cc8
......@@ -364,6 +364,8 @@ class CallSite {
"% loop variable declaration may not have an initializer.") \
T(ForInOfLoopMultiBindings, \
"Invalid left-hand side in % loop: Must have a single binding.") \
T(GeneratorInLegacyContext, \
"Generator declarations are not allowed in legacy contexts.") \
T(IllegalBreak, "Illegal break statement") \
T(IllegalContinue, "Illegal continue statement") \
T(IllegalLanguageModeDirective, \
......
......@@ -1252,7 +1252,7 @@ Statement* Parser::ParseStatementListItem(bool* ok) {
switch (peek()) {
case Token::FUNCTION:
return ParseFunctionDeclaration(NULL, ok);
return ParseHoistableDeclaration(NULL, ok);
case Token::CLASS:
Consume(Token::CLASS);
return ParseClassDeclaration(NULL, ok);
......@@ -1553,7 +1553,7 @@ Statement* Parser::ParseExportDefault(bool* ok) {
pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
} else {
result = ParseFunctionDeclaration(pos, is_generator, &names, CHECK_OK);
result = ParseHoistableDeclaration(pos, is_generator, &names, CHECK_OK);
}
break;
}
......@@ -1682,7 +1682,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
}
case Token::FUNCTION:
result = ParseFunctionDeclaration(&names, CHECK_OK);
result = ParseHoistableDeclaration(&names, CHECK_OK);
break;
case Token::CLASS:
......@@ -2051,16 +2051,16 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
}
Statement* Parser::ParseFunctionDeclaration(
Statement* Parser::ParseHoistableDeclaration(
ZoneList<const AstRawString*>* names, bool* ok) {
Expect(Token::FUNCTION, CHECK_OK);
int pos = position();
bool is_generator = Check(Token::MUL);
return ParseFunctionDeclaration(pos, is_generator, names, ok);
return ParseHoistableDeclaration(pos, is_generator, names, ok);
}
Statement* Parser::ParseFunctionDeclaration(
Statement* Parser::ParseHoistableDeclaration(
int pos, bool is_generator, ZoneList<const AstRawString*>* names,
bool* ok) {
// FunctionDeclaration ::
......@@ -2390,6 +2390,20 @@ static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
return false;
}
Statement* Parser::ParseFunctionDeclaration(bool* ok) {
Consume(Token::FUNCTION);
int pos = position();
bool is_generator = Check(Token::MUL);
if (allow_harmony_restrictive_declarations() && is_generator) {
ParserTraits::ReportMessageAt(
scanner()->location(),
MessageTemplate::kGeneratorInLegacyContext);
*ok = false;
return nullptr;
}
return ParseHoistableDeclaration(pos, is_generator, nullptr, CHECK_OK);
}
Statement* Parser::ParseExpressionOrLabelledStatement(
ZoneList<const AstRawString*>* labels,
AllowLabelledFunctionStatement allow_function, bool* ok) {
......@@ -2446,7 +2460,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(
// ES#sec-labelled-function-declarations Labelled Function Declarations
if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
if (allow_function == kAllowLabelledFunctionStatement) {
return ParseFunctionDeclaration(labels, ok);
return ParseFunctionDeclaration(ok);
} else {
return ParseScopedStatement(labels, true, ok);
}
......@@ -3430,7 +3444,7 @@ Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
body_scope->set_start_position(scanner()->location().beg_pos);
BlockState block_state(&scope_, body_scope);
Block* block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
Statement* body = ParseFunctionDeclaration(NULL, CHECK_OK);
Statement* body = ParseFunctionDeclaration(CHECK_OK);
block->statements()->Add(body, zone());
body_scope->set_end_position(scanner()->location().end_pos);
body_scope = body_scope->FinalizeBlockScope();
......
......@@ -761,9 +761,10 @@ class Parser : public ParserBase<ParserTraits> {
bool* ok);
Statement* ParseStatementAsUnlabelled(ZoneList<const AstRawString*>* labels,
bool* ok);
Statement* ParseFunctionDeclaration(ZoneList<const AstRawString*>* names,
Statement* ParseFunctionDeclaration(bool* ok);
Statement* ParseHoistableDeclaration(ZoneList<const AstRawString*>* names,
bool* ok);
Statement* ParseFunctionDeclaration(int pos, bool is_generator,
Statement* ParseHoistableDeclaration(int pos, bool is_generator,
ZoneList<const AstRawString*>* names,
bool* ok);
Statement* ParseClassDeclaration(ZoneList<const AstRawString*>* names,
......
......@@ -179,7 +179,7 @@ PreParser::Statement PreParser::ParseStatementListItem(bool* ok) {
switch (peek()) {
case Token::FUNCTION:
return ParseFunctionDeclaration(ok);
return ParseHoistableDeclaration(ok);
case Token::CLASS:
return ParseClassDeclaration(ok);
case Token::CONST:
......@@ -378,15 +378,8 @@ PreParser::Statement PreParser::ParseSubStatement(
}
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
// GeneratorDeclaration ::
// 'function' '*' Identifier '(' FormalParameterListopt ')'
// '{' FunctionBody '}'
Expect(Token::FUNCTION, CHECK_OK);
int pos = position();
bool is_generator = Check(Token::MUL);
PreParser::Statement PreParser::ParseHoistableDeclaration(
int pos, bool is_generator, bool* ok) {
bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
......@@ -401,6 +394,19 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
}
PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) {
// FunctionDeclaration ::
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
// GeneratorDeclaration ::
// 'function' '*' Identifier '(' FormalParameterListopt ')'
// '{' FunctionBody '}'
Expect(Token::FUNCTION, CHECK_OK);
int pos = position();
bool is_generator = Check(Token::MUL);
return ParseHoistableDeclaration(pos, is_generator, CHECK_OK);
}
PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) {
Expect(Token::CLASS, CHECK_OK);
......@@ -553,6 +559,20 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
return Statement::Default();
}
PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
Consume(Token::FUNCTION);
int pos = position();
bool is_generator = Check(Token::MUL);
if (allow_harmony_restrictive_declarations() && is_generator) {
PreParserTraits::ReportMessageAt(
scanner()->location(),
MessageTemplate::kGeneratorInLegacyContext);
*ok = false;
return Statement::Default();
}
return ParseHoistableDeclaration(pos, is_generator, ok);
}
PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
AllowLabelledFunctionStatement allow_function, bool* ok) {
// ExpressionStatement | LabelledStatement ::
......
......@@ -1028,6 +1028,8 @@ class PreParser : public ParserBase<PreParserTraits> {
Statement ParseSubStatement(AllowLabelledFunctionStatement allow_function,
bool* ok);
Statement ParseScopedStatement(bool legacy, bool* ok);
Statement ParseHoistableDeclaration(bool* ok);
Statement ParseHoistableDeclaration(int pos, bool is_generator, bool* ok);
Statement ParseFunctionDeclaration(bool* ok);
Statement ParseClassDeclaration(bool* ok);
Statement ParseBlock(bool* ok);
......
......@@ -7142,6 +7142,13 @@ TEST(FunctionDeclarationError) {
"with ({}) label: function f() { };",
"if (true) label: function f() {}",
"if (true) {} else label: function f() {}",
"if (true) function* f() { }",
"label: function* f() { }",
// TODO(littledan, v8:4806): Ban duplicate generator declarations in
// a block, maybe by tracking whether a Variable is a generator declaration
// "{ function* f() {} function* f() {} }",
// "{ function f() {} function* f() {} }",
// "{ function* f() {} function f() {} }",
NULL
};
// Valid only in sloppy mode, with or without
......
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