Chromium Code Reviews| 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); |
|
marja
2016/09/05 08:14:33
Maybe something for a follow-up CL: I find it some
nickie
2016/09/05 11:29:31
Yes, you're right. It starts from the fact that i
|
| } |
| 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 '}'. |