Index: src/parsing/parser-base.h |
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h |
index 5ce82407ca79bd54b3e7219c97b3062e2c017117..7fec44b2e6e2f9976fc7ba5d26509107358e0277 100644 |
--- a/src/parsing/parser-base.h |
+++ b/src/parsing/parser-base.h |
@@ -101,6 +101,12 @@ struct FormalParametersBase { |
// Used in functions where the return type is ExpressionT. |
#define CHECK_OK CHECK_OK_CUSTOM(EmptyExpression) |
+#define CHECK_OK_VOID ok); \ |
+ if (!*ok) return; \ |
+ ((void)0 |
+#define DUMMY ) // to make indentation work |
+#undef DUMMY |
+ |
// Common base class template shared between parser and pre-parser. |
// The Impl parameter is the actual class of the parser/pre-parser, |
// following the Curiously Recurring Template Pattern (CRTP). |
@@ -1223,6 +1229,12 @@ class ParserBase { |
bool default_export, bool* ok); |
StatementT ParseNativeDeclaration(bool* ok); |
+ // Consumes the ending }. |
+ void ParseFunctionBody(StatementListT result, IdentifierT function_name, |
+ int pos, const FormalParametersT& parameters, |
+ FunctionKind kind, |
+ FunctionLiteral::FunctionType function_type, bool* ok); |
+ |
// Under some circumstances, we allow preparsing to abort if the preparsed |
// function is "long and trivial", and fully parse instead. Our current |
// definition of "long and trivial" is: |
@@ -3885,6 +3897,105 @@ ParserBase<Impl>::ParseAsyncFunctionDeclaration( |
} |
template <typename Impl> |
+void ParserBase<Impl>::ParseFunctionBody( |
+ typename ParserBase<Impl>::StatementListT result, IdentifierT function_name, |
+ int pos, const FormalParametersT& parameters, FunctionKind kind, |
+ FunctionLiteral::FunctionType function_type, bool* ok) { |
+ static const int kFunctionNameAssignmentIndex = 0; |
+ if (function_type == FunctionLiteral::kNamedExpression) { |
+ DCHECK(!impl()->IsEmptyIdentifier(function_name)); |
+ // If we have a named function expression, we add a local variable |
+ // declaration to the body of the function with the name of the |
+ // function and let it refer to the function itself (closure). |
+ // Not having parsed the function body, the language mode may still change, |
+ // so we reserve a spot and create the actual const assignment later. |
+ DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); |
+ result->Add(impl()->NullStatement(), zone()); |
+ } |
+ |
+ DeclarationScope* function_scope = scope()->AsDeclarationScope(); |
+ DeclarationScope* inner_scope = function_scope; |
+ BlockT inner_block = impl()->NullBlock(); |
+ |
+ StatementListT body = result; |
+ if (!parameters.is_simple) { |
+ inner_scope = NewVarblockScope(); |
+ inner_scope->set_start_position(scanner()->location().beg_pos); |
+ inner_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); |
+ inner_block->set_scope(inner_scope); |
+ body = inner_block->statements(); |
+ } |
+ |
+ { |
+ BlockState block_state(&scope_state_, inner_scope); |
+ |
+ if (IsGeneratorFunction(kind)) { |
+ impl()->ParseAndRewriteGeneratorFunctionBody(pos, kind, body, ok); |
+ } else if (IsAsyncFunction(kind)) { |
+ const bool accept_IN = true; |
+ ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal, |
+ accept_IN, pos, CHECK_OK_VOID); |
+ } else { |
+ ParseStatementList(body, Token::RBRACE, CHECK_OK_VOID); |
+ } |
+ |
+ if (IsDerivedConstructor(kind)) { |
+ body->Add(factory()->NewReturnStatement(impl()->ThisExpression(), |
+ kNoSourcePosition), |
+ zone()); |
+ } |
+ } |
+ |
+ Expect(Token::RBRACE, CHECK_OK_VOID); |
+ scope()->set_end_position(scanner()->location().end_pos); |
+ |
+ if (!parameters.is_simple) { |
+ DCHECK_NOT_NULL(inner_scope); |
+ DCHECK_EQ(function_scope, scope()); |
+ DCHECK_EQ(function_scope, inner_scope->outer_scope()); |
+ impl()->SetLanguageMode(function_scope, inner_scope->language_mode()); |
+ BlockT init_block = |
+ impl()->BuildParameterInitializationBlock(parameters, CHECK_OK_VOID); |
+ |
+ if (is_sloppy(inner_scope->language_mode())) { |
+ impl()->InsertSloppyBlockFunctionVarBindings(inner_scope); |
+ } |
+ |
+ // TODO(littledan): Merge the two rejection blocks into one |
+ if (IsAsyncFunction(kind)) { |
+ init_block = impl()->BuildRejectPromiseOnException(init_block); |
+ } |
+ |
+ inner_scope->set_end_position(scanner()->location().end_pos); |
+ if (inner_scope->FinalizeBlockScope() != nullptr) { |
+ impl()->CheckConflictingVarDeclarations(inner_scope, CHECK_OK_VOID); |
+ impl()->InsertShadowingVarBindingInitializers(inner_block); |
+ } |
+ inner_scope = nullptr; |
+ |
+ result->Add(init_block, zone()); |
+ result->Add(inner_block, zone()); |
+ } else { |
+ DCHECK_EQ(inner_scope, function_scope); |
+ if (is_sloppy(function_scope->language_mode())) { |
+ impl()->InsertSloppyBlockFunctionVarBindings(function_scope); |
+ } |
+ } |
+ |
+ if (!IsArrowFunction(kind)) { |
+ // Declare arguments after parsing the function since lexical 'arguments' |
+ // masks the arguments object. Declare arguments before declaring the |
+ // function var since the arguments object masks 'function arguments'. |
+ function_scope->DeclareArguments(ast_value_factory()); |
+ } |
+ |
+ impl()->CreateFunctionNameAssignment(function_name, pos, function_type, |
+ function_scope, result, |
+ kFunctionNameAssignmentIndex); |
+ impl()->MarkCollectedTailCallExpressions(); |
+} |
+ |
+template <typename Impl> |
void ParserBase<Impl>::CheckArityRestrictions(int param_count, |
FunctionKind function_kind, |
bool has_rest, |
@@ -4047,9 +4158,11 @@ ParserBase<Impl>::ParseArrowFunctionLiteral( |
} |
if (!is_lazy_top_level_function) { |
Consume(Token::LBRACE); |
- body = impl()->ParseEagerFunctionBody( |
- impl()->EmptyIdentifier(), kNoSourcePosition, formal_parameters, |
- kind, FunctionLiteral::kAnonymousExpression, CHECK_OK); |
+ body = impl()->NewStatementList(8); |
+ impl()->ParseFunctionBody(body, impl()->EmptyIdentifier(), |
+ kNoSourcePosition, formal_parameters, kind, |
+ FunctionLiteral::kAnonymousExpression, |
+ CHECK_OK); |
materialized_literal_count = |
function_state.materialized_literal_count(); |
expected_property_count = function_state.expected_property_count(); |
@@ -5546,6 +5659,7 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName( |
} |
} |
+#undef CHECK_OK_VOID |
} // namespace internal |
} // namespace v8 |