Index: src/parsing/preparser.cc |
diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc |
index 369ff2415efb8dbe3351b73dfb3c818147460c64..4a3f680f035d1384bb8d445bf5b40ec5b4ee2910 100644 |
--- a/src/parsing/preparser.cc |
+++ b/src/parsing/preparser.cc |
@@ -122,223 +122,19 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction( |
// it is used) are generally omitted. |
-PreParser::Statement PreParser::ParseStatementListItem(bool* ok) { |
- // ECMA 262 6th Edition |
- // StatementListItem[Yield, Return] : |
- // Statement[?Yield, ?Return] |
- // Declaration[?Yield] |
- // |
- // Declaration[Yield] : |
- // HoistableDeclaration[?Yield] |
- // ClassDeclaration[?Yield] |
- // LexicalDeclaration[In, ?Yield] |
- // |
- // HoistableDeclaration[Yield, Default] : |
- // FunctionDeclaration[?Yield, ?Default] |
- // GeneratorDeclaration[?Yield, ?Default] |
- // |
- // LexicalDeclaration[In, Yield] : |
- // LetOrConst BindingList[?In, ?Yield] ; |
- |
- switch (peek()) { |
- case Token::FUNCTION: |
- return ParseHoistableDeclaration(ok); |
- case Token::CLASS: |
- return ParseClassDeclaration(ok); |
- case Token::CONST: |
- return ParseVariableStatement(kStatementListItem, ok); |
- case Token::LET: |
- if (IsNextLetKeyword()) { |
- return ParseVariableStatement(kStatementListItem, ok); |
- } |
- break; |
- case Token::ASYNC: |
- if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && |
- !scanner()->HasAnyLineTerminatorAfterNext()) { |
- Consume(Token::ASYNC); |
- return ParseAsyncFunctionDeclaration(ok); |
- } |
- /* falls through */ |
- default: |
- break; |
- } |
- return ParseStatement(kAllowLabelledFunctionStatement, ok); |
-} |
- |
-PreParser::LazyParsingResult PreParser::ParseStatementList(int end_token, |
- bool may_abort, |
- bool* ok) { |
- // SourceElements :: |
- // (Statement)* <end_token> |
- |
- int count_statements = 0; |
- |
- bool directive_prologue = true; |
- while (peek() != end_token) { |
- if (directive_prologue && peek() != Token::STRING) { |
- directive_prologue = false; |
- } |
- bool starts_with_identifier = peek() == Token::IDENTIFIER; |
- Scanner::Location token_loc = scanner()->peek_location(); |
- Statement statement = |
- ParseStatementListItem(CHECK_OK_VALUE(kLazyParsingComplete)); |
- |
- if (directive_prologue) { |
- bool use_strict_found = statement.IsUseStrictLiteral(); |
- |
- if (use_strict_found) { |
- scope()->SetLanguageMode( |
- static_cast<LanguageMode>(scope()->language_mode() | STRICT)); |
- } else if (!statement.IsStringLiteral()) { |
- directive_prologue = false; |
- } |
- |
- if (use_strict_found && !scope()->HasSimpleParameters()) { |
- // TC39 deemed "use strict" directives to be an error when occurring |
- // in the body of a function with non-simple parameter list, on |
- // 29/7/2015. https://goo.gl/ueA7Ln |
- ReportMessageAt(token_loc, |
- MessageTemplate::kIllegalLanguageModeDirective, |
- "use strict"); |
- *ok = false; |
- return kLazyParsingComplete; |
- } |
- } |
- |
- // If we're allowed to reset to a bookmark, we will do so when we see a long |
- // and trivial function. |
- // Our current definition of 'long and trivial' is: |
- // - over 200 statements |
- // - all starting with an identifier (i.e., no if, for, while, etc.) |
- if (may_abort) { |
- if (!starts_with_identifier) { |
- may_abort = false; |
- } else if (++count_statements > kLazyParseTrialLimit) { |
- return kLazyParsingAborted; |
- } |
- } |
- } |
- return kLazyParsingComplete; |
-} |
- |
- |
-PreParser::Statement PreParser::ParseStatement( |
- AllowLabelledFunctionStatement allow_function, bool* ok) { |
- // Statement :: |
- // EmptyStatement |
- // ... |
- |
- if (peek() == Token::SEMICOLON) { |
- Next(); |
- return Statement::Default(); |
- } |
- return ParseSubStatement(allow_function, ok); |
-} |
- |
PreParser::Statement PreParser::ParseScopedStatement(bool legacy, bool* ok) { |
if (is_strict(language_mode()) || peek() != Token::FUNCTION || |
(legacy && allow_harmony_restrictive_declarations())) { |
- return ParseSubStatement(kDisallowLabelledFunctionStatement, ok); |
+ return ParseStatement(nullptr, kDisallowLabelledFunctionStatement, ok); |
} else { |
BlockState block_state(&scope_state_); |
return ParseFunctionDeclaration(ok); |
} |
} |
-PreParser::Statement PreParser::ParseSubStatement( |
- AllowLabelledFunctionStatement allow_function, bool* ok) { |
- // Statement :: |
- // Block |
- // VariableStatement |
- // EmptyStatement |
- // ExpressionStatement |
- // IfStatement |
- // IterationStatement |
- // ContinueStatement |
- // BreakStatement |
- // ReturnStatement |
- // WithStatement |
- // LabelledStatement |
- // SwitchStatement |
- // ThrowStatement |
- // TryStatement |
- // DebuggerStatement |
- |
- // Note: Since labels can only be used by 'break' and 'continue' |
- // statements, which themselves are only valid within blocks, |
- // iterations or 'switch' statements (i.e., BreakableStatements), |
- // labels can be simply ignored in all other cases; except for |
- // trivial labeled break statements 'label: break label' which is |
- // parsed into an empty statement. |
- |
- // Keep the source position of the statement |
- switch (peek()) { |
- case Token::LBRACE: |
- return ParseBlock(ok); |
- |
- case Token::SEMICOLON: |
- Next(); |
- return Statement::Default(); |
- |
- case Token::IF: |
- return ParseIfStatement(ok); |
- |
- case Token::DO: |
- return ParseDoWhileStatement(ok); |
- |
- case Token::WHILE: |
- return ParseWhileStatement(ok); |
- |
- case Token::FOR: |
- return ParseForStatement(ok); |
- |
- case Token::CONTINUE: |
- return ParseContinueStatement(ok); |
- |
- case Token::BREAK: |
- return ParseBreakStatement(ok); |
- |
- case Token::RETURN: |
- return ParseReturnStatement(ok); |
- |
- case Token::WITH: |
- return ParseWithStatement(ok); |
- |
- case Token::SWITCH: |
- return ParseSwitchStatement(ok); |
- |
- case Token::THROW: |
- return ParseThrowStatement(ok); |
- |
- case Token::TRY: |
- return ParseTryStatement(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 Statement::Default(); |
- |
- case Token::DEBUGGER: |
- return ParseDebuggerStatement(ok); |
- |
- case Token::VAR: |
- return ParseVariableStatement(kStatement, ok); |
- |
- default: |
- return ParseExpressionOrLabelledStatement(allow_function, ok); |
- } |
-} |
- |
PreParser::Statement PreParser::ParseHoistableDeclaration( |
- int pos, ParseFunctionFlags flags, bool* ok) { |
+ int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names, |
+ bool default_export, bool* ok) { |
const bool is_generator = flags & ParseFunctionFlags::kIsGenerator; |
const bool is_async = flags & ParseFunctionFlags::kIsAsync; |
DCHECK(!is_generator || !is_async); |
@@ -358,7 +154,8 @@ PreParser::Statement PreParser::ParseHoistableDeclaration( |
return Statement::FunctionDeclaration(); |
} |
-PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(bool* ok) { |
+PreParser::Statement PreParser::ParseAsyncFunctionDeclaration( |
+ ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
// AsyncFunctionDeclaration :: |
// async [no LineTerminator here] function BindingIdentifier[Await] |
// ( FormalParameters[Await] ) { AsyncFunctionBody } |
@@ -366,10 +163,11 @@ PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(bool* ok) { |
int pos = position(); |
Expect(Token::FUNCTION, CHECK_OK); |
ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; |
- return ParseHoistableDeclaration(pos, flags, ok); |
+ return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
} |
-PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { |
+PreParser::Statement PreParser::ParseHoistableDeclaration( |
+ ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
// FunctionDeclaration :: |
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}' |
// GeneratorDeclaration :: |
@@ -382,13 +180,11 @@ PreParser::Statement PreParser::ParseHoistableDeclaration(bool* ok) { |
if (Check(Token::MUL)) { |
flags |= ParseFunctionFlags::kIsGenerator; |
} |
- return ParseHoistableDeclaration(pos, flags, ok); |
+ return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
} |
- |
-PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { |
- Expect(Token::CLASS, CHECK_OK); |
- |
+PreParser::Statement PreParser::ParseClassDeclaration( |
+ ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
int pos = position(); |
bool is_strict_reserved = false; |
Identifier name = |
@@ -399,8 +195,8 @@ PreParser::Statement PreParser::ParseClassDeclaration(bool* ok) { |
return Statement::Default(); |
} |
- |
-PreParser::Statement PreParser::ParseBlock(bool* ok) { |
+PreParser::Statement PreParser::ParseBlock( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// Block :: |
// '{' StatementList '}' |
@@ -416,15 +212,14 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) { |
return final; |
} |
- |
PreParser::Statement PreParser::ParseVariableStatement( |
VariableDeclarationContext var_context, |
- bool* ok) { |
+ ZoneList<const AstRawString*>* names, bool* ok) { |
// VariableStatement :: |
// VariableDeclarations ';' |
Statement result = |
- ParseVariableDeclarations(var_context, nullptr, nullptr, CHECK_OK); |
+ ParseVariableDeclarations(var_context, nullptr, names, CHECK_OK); |
ExpectSemicolon(CHECK_OK); |
return result; |
} |
@@ -442,10 +237,11 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
return Statement::Default(); |
} |
} |
- return ParseHoistableDeclaration(pos, flags, ok); |
+ return ParseHoistableDeclaration(pos, flags, nullptr, false, ok); |
} |
PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( |
+ ZoneList<const AstRawString*>* names, |
AllowLabelledFunctionStatement allow_function, bool* ok) { |
// ExpressionStatement | LabelledStatement :: |
// Expression ';' |
@@ -489,7 +285,7 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( |
} |
} |
Statement statement = |
- ParseStatement(kDisallowLabelledFunctionStatement, ok); |
+ ParseStatement(nullptr, kDisallowLabelledFunctionStatement, ok); |
return statement.IsJumpStatement() ? Statement::Default() : statement; |
// Preparsing is disabled for extensions (because the extension details |
// aren't passed to lazily compiled functions), so we don't |
@@ -500,8 +296,8 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement( |
return Statement::ExpressionStatement(expr); |
} |
- |
-PreParser::Statement PreParser::ParseIfStatement(bool* ok) { |
+PreParser::Statement PreParser::ParseIfStatement( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// IfStatement :: |
// 'if' '(' Expression ')' Statement ('else' Statement)? |
@@ -539,8 +335,8 @@ PreParser::Statement PreParser::ParseContinueStatement(bool* ok) { |
return Statement::Jump(); |
} |
- |
-PreParser::Statement PreParser::ParseBreakStatement(bool* ok) { |
+PreParser::Statement PreParser::ParseBreakStatement( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// BreakStatement :: |
// 'break' [no line terminator] Identifier? ';' |
@@ -593,8 +389,8 @@ PreParser::Statement PreParser::ParseReturnStatement(bool* ok) { |
return Statement::Jump(); |
} |
- |
-PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
+PreParser::Statement PreParser::ParseWithStatement( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// WithStatement :: |
// 'with' '(' Expression ')' Statement |
Expect(Token::WITH, CHECK_OK); |
@@ -613,8 +409,8 @@ PreParser::Statement PreParser::ParseWithStatement(bool* ok) { |
return Statement::Default(); |
} |
- |
-PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { |
+PreParser::Statement PreParser::ParseSwitchStatement( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// SwitchStatement :: |
// 'switch' '(' Expression ')' '{' CaseClause* '}' |
@@ -649,8 +445,8 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { |
return Statement::Default(); |
} |
- |
-PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { |
+PreParser::Statement PreParser::ParseDoWhileStatement( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// DoStatement :: |
// 'do' Statement 'while' '(' Expression ')' ';' |
@@ -664,8 +460,8 @@ PreParser::Statement PreParser::ParseDoWhileStatement(bool* ok) { |
return Statement::Default(); |
} |
- |
-PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { |
+PreParser::Statement PreParser::ParseWhileStatement( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// WhileStatement :: |
// 'while' '(' Expression ')' Statement |
@@ -677,8 +473,8 @@ PreParser::Statement PreParser::ParseWhileStatement(bool* ok) { |
return Statement::Default(); |
} |
- |
-PreParser::Statement PreParser::ParseForStatement(bool* ok) { |
+PreParser::Statement PreParser::ParseForStatement( |
+ ZoneList<const AstRawString*>* labels, bool* ok) { |
// ForStatement :: |
// 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
@@ -844,7 +640,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
{ |
ReturnExprScope no_tail_calls(function_state_, |
ReturnExprContext::kInsideTryBlock); |
- ParseBlock(CHECK_OK); |
+ ParseBlock(nullptr, CHECK_OK); |
} |
Token::Value tok = peek(); |
@@ -870,7 +666,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
BlockState block_state(&scope_state_, catch_scope); |
{ |
BlockState block_state(&scope_state_); |
- ParseBlock(CHECK_OK); |
+ ParseBlock(nullptr, CHECK_OK); |
} |
} |
catch_block_exists = true; |
@@ -878,7 +674,7 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) { |
} |
if (tok == Token::FINALLY) { |
Consume(Token::FINALLY); |
- ParseBlock(CHECK_OK); |
+ ParseBlock(nullptr, CHECK_OK); |
if (FLAG_harmony_explicit_tailcalls && catch_block_exists && |
tail_call_expressions_in_catch_block.has_explicit_tail_calls()) { |
// TODO(ishell): update chapter number. |
@@ -919,6 +715,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( |
// '(' FormalParameterList? ')' '{' FunctionBody '}' |
// Parse function body. |
+ PreParserStatementList body; |
bool outer_is_script_scope = scope()->is_script_scope(); |
DeclarationScope* function_scope = NewFunctionScope(kind); |
function_scope->SetLanguageMode(language_mode); |
@@ -947,7 +744,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral( |
if (is_lazily_parsed) { |
ParseLazyFunctionLiteralBody(false, CHECK_OK); |
} else { |
- ParseStatementList(Token::RBRACE, CHECK_OK); |
+ ParseStatementList(body, Token::RBRACE, CHECK_OK); |
} |
Expect(Token::RBRACE, CHECK_OK); |
@@ -1002,8 +799,9 @@ PreParser::Expression PreParser::ParseAsyncFunctionExpression(bool* ok) { |
PreParser::LazyParsingResult PreParser::ParseLazyFunctionLiteralBody( |
bool may_abort, bool* ok) { |
int body_start = position(); |
+ PreParserStatementList body; |
LazyParsingResult result = ParseStatementList( |
- Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete)); |
+ body, Token::RBRACE, may_abort, CHECK_OK_VALUE(kLazyParsingComplete)); |
if (result == kLazyParsingAborted) return result; |
// Position right after terminal '}'. |