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