Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(919)

Unified Diff: src/parsing/parser.cc

Issue 1757543003: Restrict FunctionDeclarations in Statement position (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: git cl format Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/parser.cc
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index 36c966110b2f432202993592a552d3c46bc3e0fb..0511569ffd184dd4f2ab45d233130bba5ef06b1b 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -774,6 +774,8 @@ Parser::Parser(ParseInfo* info)
set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
set_allow_harmony_function_name(FLAG_harmony_function_name);
set_allow_harmony_function_sent(FLAG_harmony_function_sent);
+ set_allow_harmony_restrictive_declarations(
+ FLAG_harmony_restrictive_declarations);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
@@ -1839,26 +1841,18 @@ Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels,
case Token::SWITCH:
return ParseSwitchStatement(labels, ok);
- case Token::FUNCTION: {
- // FunctionDeclaration is only allowed in the context of SourceElements
- // (Ecma 262 5th Edition, clause 14):
- // SourceElement:
- // Statement
- // FunctionDeclaration
- // Common language extension is to allow function declaration in place
- // of any statement. This language extension is disabled in strict mode.
- //
- // In Harmony mode, this case also handles the extension:
- // Statement:
- // GeneratorDeclaration
- if (is_strict(language_mode())) {
- ReportMessageAt(scanner()->peek_location(),
- MessageTemplate::kStrictFunction);
- *ok = false;
- return NULL;
- }
- return ParseFunctionDeclaration(NULL, ok);
- }
+ case Token::FUNCTION:
+ // FunctionDeclaration only allowed as a StatementListItem, not in
+ // an arbitrary Statement position. Exceptions such as
+ // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
+ // are handled by calling ParseScopedStatement rather than
+ // ParseSubStatement directly.
+ ReportMessageAt(scanner()->peek_location(),
+ is_strict(language_mode())
+ ? MessageTemplate::kStrictFunction
+ : MessageTemplate::kSloppyFunction);
+ *ok = false;
+ return nullptr;
case Token::DEBUGGER:
return ParseDebuggerStatement(ok);
@@ -2581,6 +2575,10 @@ Statement* Parser::ParseExpressionOrLabelledStatement(
// during the scope processing.
scope_->RemoveUnresolved(var);
Expect(Token::COLON, CHECK_OK);
+ // ES#sec-labelled-function-declarations Labelled Function Declarations
+ if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
+ return ParseFunctionDeclaration(labels, ok);
+ }
return ParseStatement(labels, ok);
}
@@ -2621,11 +2619,11 @@ IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
Expect(Token::LPAREN, CHECK_OK);
Expression* condition = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- Statement* then_statement = ParseSubStatement(labels, CHECK_OK);
+ Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK);
Statement* else_statement = NULL;
if (peek() == Token::ELSE) {
Next();
- else_statement = ParseSubStatement(labels, CHECK_OK);
+ else_statement = ParseScopedStatement(labels, false, CHECK_OK);
} else {
else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
}
@@ -2824,25 +2822,10 @@ Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
scope_->DeclarationScope()->RecordWithStatement();
Scope* with_scope = NewScope(scope_, WITH_SCOPE);
- Block* body;
+ Statement* body;
{ BlockState block_state(&scope_, with_scope);
with_scope->set_start_position(scanner()->peek_location().beg_pos);
-
- // The body of the with statement must be enclosed in an additional
- // lexical scope in case the body is a FunctionDeclaration.
- body = factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
- Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
- block_scope->set_start_position(scanner()->location().beg_pos);
- {
- BlockState block_state(&scope_, block_scope);
- Target target(&this->target_stack_, body);
- Statement* stmt = ParseSubStatement(labels, CHECK_OK);
- body->statements()->Add(stmt, zone());
- block_scope->set_end_position(scanner()->location().end_pos);
- block_scope = block_scope->FinalizeBlockScope();
- body->set_scope(block_scope);
- }
-
+ body = ParseScopedStatement(labels, true, CHECK_OK);
with_scope->set_end_position(scanner()->location().end_pos);
}
return factory()->NewWithStatement(with_scope, expr, body, pos);
@@ -3183,7 +3166,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(
Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
Expect(Token::WHILE, CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
@@ -3213,7 +3196,7 @@ WhileStatement* Parser::ParseWhileStatement(
Expect(Token::LPAREN, CHECK_OK);
Expression* cond = ParseExpression(true, CHECK_OK);
Expect(Token::RPAREN, CHECK_OK);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
if (loop != NULL) loop->Initialize(cond, body);
return loop;
@@ -3595,6 +3578,28 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
return outer_block;
}
+Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
+ bool legacy, bool* ok) {
+ if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
+ (legacy && allow_harmony_restrictive_declarations())) {
+ return ParseSubStatement(labels, ok);
+ } else {
+ if (legacy) {
+ ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
+ }
+ // Make a block around the statement for a lexical binding
+ // is introduced by a FunctionDeclaration.
+ Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
+ BlockState block_state(&scope_, body_scope);
+ Block* block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
+ Statement* body = ParseFunctionDeclaration(NULL, CHECK_OK);
+ block->statements()->Add(body, zone());
+ body_scope->set_end_position(scanner()->location().end_pos);
+ body_scope = body_scope->FinalizeBlockScope();
+ block->set_scope(body_scope);
+ return block;
+ }
+}
Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
bool* ok) {
@@ -3708,7 +3713,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
{
BlockState block_state(&scope_, body_scope);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
auto each_initialization_block =
factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
@@ -3825,25 +3830,11 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
Expect(Token::RPAREN, CHECK_OK);
- // Make a block around the statement in case a lexical binding
- // is introduced, e.g. by a FunctionDeclaration.
- // This block must not use for_scope as its scope because if a
- // lexical binding is introduced which overlaps with the for-in/of,
- // expressions in head of the loop should actually have variables
- // resolved in the outer scope.
- Scope* body_scope = NewScope(for_scope, BLOCK_SCOPE);
- {
- BlockState block_state(&scope_, body_scope);
- Block* block =
- factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
- Statement* body = ParseSubStatement(NULL, CHECK_OK);
- block->statements()->Add(body, zone());
- InitializeForEachStatement(loop, expression, enumerable, block,
- is_destructuring);
- body_scope->set_end_position(scanner()->location().end_pos);
- body_scope = body_scope->FinalizeBlockScope();
- block->set_scope(body_scope);
- }
+ // For legacy compat reasons, give for loops similar treatment to
+ // if statements in allowing a function declaration for a body
+ Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
+ InitializeForEachStatement(loop, expression, enumerable, body,
+ is_destructuring);
Statement* final_loop = loop->IsForOfStatement()
? FinalizeForOfStatement(
@@ -3900,7 +3891,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
}
Expect(Token::RPAREN, CHECK_OK);
- body = ParseSubStatement(NULL, CHECK_OK);
+ body = ParseScopedStatement(NULL, true, CHECK_OK);
}
Statement* result = NULL;
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698