Index: src/parsing/parser.cc |
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
index 24df10cb9d7a4021d1541c90c77e09caee97ed6a..21b316e94042a3d3c2436f08e0517e29e1c9ab8c 100644 |
--- a/src/parsing/parser.cc |
+++ b/src/parsing/parser.cc |
@@ -1285,10 +1285,10 @@ Statement* Parser::ParseStatementListItem(bool* ok) { |
const Token::Value peeked = peek(); |
switch (peeked) { |
case Token::FUNCTION: |
- return ParseHoistableDeclaration(NULL, ok); |
+ return ParseHoistableDeclaration(NULL, false, ok); |
case Token::CLASS: |
Consume(Token::CLASS); |
- return ParseClassDeclaration(NULL, ok); |
+ return ParseClassDeclaration(NULL, false, ok); |
case Token::CONST: |
return ParseVariableStatement(kStatementListItem, NULL, ok); |
case Token::VAR: |
@@ -1302,7 +1302,7 @@ Statement* Parser::ParseStatementListItem(bool* ok) { |
if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && |
!scanner()->HasAnyLineTerminatorAfterNext()) { |
Consume(Token::ASYNC); |
- return ParseAsyncFunctionDeclaration(NULL, ok); |
+ return ParseAsyncFunctionDeclaration(NULL, false, ok); |
} |
/* falls through */ |
default: |
@@ -1576,66 +1576,20 @@ Statement* Parser::ParseExportDefault(bool* ok) { |
Statement* result = nullptr; |
Expression* default_export = nullptr; |
switch (peek()) { |
- case Token::FUNCTION: { |
- Consume(Token::FUNCTION); |
- int pos = position(); |
- bool is_generator = Check(Token::MUL); |
- if (peek() == Token::LPAREN) { |
- // FunctionDeclaration[+Default] :: |
- // 'function' '(' FormalParameters ')' '{' FunctionBody '}' |
- // |
- // GeneratorDeclaration[+Default] :: |
- // 'function' '*' '(' FormalParameters ')' '{' FunctionBody '}' |
- default_export = ParseFunctionLiteral( |
- default_string, Scanner::Location::invalid(), |
- kSkipFunctionNameCheck, |
- is_generator ? FunctionKind::kGeneratorFunction |
- : FunctionKind::kNormalFunction, |
- pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK); |
- result = factory()->NewEmptyStatement(kNoSourcePosition); |
- } else { |
- result = ParseHoistableDeclaration( |
- pos, is_generator ? ParseFunctionFlags::kIsGenerator |
- : ParseFunctionFlags::kIsNormal, |
- &names, CHECK_OK); |
- } |
+ case Token::FUNCTION: |
+ result = ParseHoistableDeclaration(&names, true, CHECK_OK); |
break; |
- } |
case Token::CLASS: |
Consume(Token::CLASS); |
- if (peek() == Token::EXTENDS || peek() == Token::LBRACE) { |
- // ClassDeclaration[+Default] :: |
- // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}' |
- default_export = ParseClassLiteral(nullptr, default_string, |
- Scanner::Location::invalid(), false, |
- position(), CHECK_OK); |
- result = factory()->NewEmptyStatement(kNoSourcePosition); |
- } else { |
- result = ParseClassDeclaration(&names, CHECK_OK); |
- } |
+ result = ParseClassDeclaration(&names, true, CHECK_OK); |
break; |
case Token::ASYNC: |
if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION && |
!scanner()->HasAnyLineTerminatorAfterNext()) { |
Consume(Token::ASYNC); |
- Consume(Token::FUNCTION); |
- int pos = position(); |
- if (peek() == Token::LPAREN) { |
- // AsyncFunctionDeclaration[+Default] :: |
- // async [no LineTerminator here] function ( FormalParameters ) { |
- // AsyncFunctionBody |
- // } |
- default_export = ParseFunctionLiteral( |
- default_string, Scanner::Location::invalid(), |
- kSkipFunctionNameCheck, FunctionKind::kAsyncFunction, pos, |
- FunctionLiteral::kDeclaration, language_mode(), CHECK_OK); |
- result = factory()->NewEmptyStatement(kNoSourcePosition); |
- } else { |
- result = ParseHoistableDeclaration(pos, ParseFunctionFlags::kIsAsync, |
- &names, CHECK_OK); |
- } |
+ result = ParseAsyncFunctionDeclaration(&names, true, CHECK_OK); |
break; |
} |
/* falls through */ |
@@ -1750,12 +1704,12 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
} |
case Token::FUNCTION: |
- result = ParseHoistableDeclaration(&names, CHECK_OK); |
+ result = ParseHoistableDeclaration(&names, false, CHECK_OK); |
break; |
case Token::CLASS: |
Consume(Token::CLASS); |
- result = ParseClassDeclaration(&names, CHECK_OK); |
+ result = ParseClassDeclaration(&names, false, CHECK_OK); |
break; |
case Token::VAR: |
@@ -1767,7 +1721,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
case Token::ASYNC: |
if (allow_harmony_async_await()) { |
Consume(Token::ASYNC); |
- result = ParseAsyncFunctionDeclaration(&names, CHECK_OK); |
+ result = ParseAsyncFunctionDeclaration(&names, false, CHECK_OK); |
break; |
} |
/* falls through */ |
@@ -2139,20 +2093,19 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) { |
pos); |
} |
- |
Statement* Parser::ParseHoistableDeclaration( |
- ZoneList<const AstRawString*>* names, bool* ok) { |
+ ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
Expect(Token::FUNCTION, CHECK_OK); |
int pos = position(); |
ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
if (Check(Token::MUL)) { |
flags |= ParseFunctionFlags::kIsGenerator; |
} |
- return ParseHoistableDeclaration(pos, flags, names, ok); |
+ return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
} |
Statement* Parser::ParseAsyncFunctionDeclaration( |
- ZoneList<const AstRawString*>* names, bool* ok) { |
+ ZoneList<const AstRawString*>* names, bool default_export, bool* ok) { |
DCHECK_EQ(scanner()->current_token(), Token::ASYNC); |
int pos = position(); |
if (scanner()->HasAnyLineTerminatorBeforeNext()) { |
@@ -2162,25 +2115,41 @@ Statement* Parser::ParseAsyncFunctionDeclaration( |
} |
Expect(Token::FUNCTION, CHECK_OK); |
ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync; |
- return ParseHoistableDeclaration(pos, flags, names, ok); |
+ return ParseHoistableDeclaration(pos, flags, names, default_export, ok); |
} |
Statement* Parser::ParseHoistableDeclaration( |
int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names, |
- bool* ok) { |
+ bool default_export, bool* ok) { |
// FunctionDeclaration :: |
// 'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}' |
+ // 'function' '(' FormalParameters ')' '{' FunctionBody '}' |
// GeneratorDeclaration :: |
// 'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}' |
+ // 'function' '*' '(' FormalParameters ')' '{' FunctionBody '}' |
+ // |
+ // The anonymous forms are allowed iff [default_export] is true. |
// |
// 'function' and '*' (if present) have been consumed by the caller. |
+ |
const bool is_generator = flags & ParseFunctionFlags::kIsGenerator; |
const bool is_async = flags & ParseFunctionFlags::kIsAsync; |
DCHECK(!is_generator || !is_async); |
- bool is_strict_reserved = false; |
- const AstRawString* name = ParseIdentifierOrStrictReservedWord( |
- &is_strict_reserved, CHECK_OK); |
+ const AstRawString* name; |
+ FunctionNameValidity name_validity; |
+ const AstRawString* variable_name; |
+ if (default_export && peek() == Token::LPAREN) { |
+ name = ast_value_factory()->default_string(); |
+ name_validity = kSkipFunctionNameCheck; |
+ variable_name = ast_value_factory()->star_default_star_string(); |
+ } else { |
+ bool is_strict_reserved; |
+ name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
+ name_validity = is_strict_reserved ? kFunctionNameIsStrictReserved |
+ : kFunctionNameValidityUnknown; |
+ variable_name = name; |
+ } |
if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) { |
ReportMessageAt(scanner()->location(), |
@@ -2192,9 +2161,7 @@ Statement* Parser::ParseHoistableDeclaration( |
FuncNameInferrer::State fni_state(fni_); |
if (fni_ != NULL) fni_->PushEnclosingName(name); |
FunctionLiteral* fun = ParseFunctionLiteral( |
- name, scanner()->location(), |
- is_strict_reserved ? kFunctionNameIsStrictReserved |
- : kFunctionNameValidityUnknown, |
+ name, scanner()->location(), name_validity, |
is_generator ? FunctionKind::kGeneratorFunction |
: is_async ? FunctionKind::kAsyncFunction |
: FunctionKind::kNormalFunction, |
@@ -2208,11 +2175,11 @@ Statement* Parser::ParseHoistableDeclaration( |
VariableMode mode = |
(!scope_->is_declaration_scope() || scope_->is_module_scope()) ? LET |
: VAR; |
- VariableProxy* proxy = NewUnresolved(name, mode); |
+ VariableProxy* proxy = NewUnresolved(variable_name, mode); |
Declaration* declaration = |
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); |
Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
- if (names) names->Add(name, zone()); |
+ if (names) names->Add(variable_name, zone()); |
EmptyStatement* empty = factory()->NewEmptyStatement(kNoSourcePosition); |
// Async functions don't undergo sloppy mode block scoped hoisting, and don't |
// allow duplicates in a block. Both are represented by the |
@@ -2223,18 +2190,20 @@ Statement* Parser::ParseHoistableDeclaration( |
!is_async && !(allow_harmony_restrictive_generators() && is_generator)) { |
SloppyBlockFunctionStatement* delegate = |
factory()->NewSloppyBlockFunctionStatement(empty, scope_); |
- scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name, |
- delegate); |
+ scope_->DeclarationScope()->sloppy_block_function_map()->Declare( |
+ variable_name, delegate); |
return delegate; |
} |
return empty; |
} |
- |
Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
- bool* ok) { |
+ bool default_export, bool* ok) { |
// ClassDeclaration :: |
// 'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}' |
+ // 'class' ('extends' LeftHandExpression)? '{' ClassBody '}' |
+ // |
+ // The anonymous form is allowed iff [default_export] is true. |
// |
// 'class' is expected to be consumed by the caller. |
// |
@@ -2249,13 +2218,23 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
// so rewrite it as such. |
int pos = position(); |
- bool is_strict_reserved = false; |
- const AstRawString* name = |
- ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
+ |
+ const AstRawString* name; |
+ bool is_strict_reserved; |
+ const AstRawString* variable_name; |
+ if (default_export && (peek() == Token::EXTENDS || peek() == Token::LBRACE)) { |
+ name = ast_value_factory()->default_string(); |
+ is_strict_reserved = false; |
+ variable_name = ast_value_factory()->star_default_star_string(); |
+ } else { |
+ name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK); |
+ variable_name = name; |
+ } |
+ |
ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(), |
is_strict_reserved, pos, CHECK_OK); |
- VariableProxy* proxy = NewUnresolved(name, LET); |
+ VariableProxy* proxy = NewUnresolved(variable_name, LET); |
Declaration* declaration = |
factory()->NewVariableDeclaration(proxy, LET, scope_, pos); |
Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); |
@@ -2264,7 +2243,7 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names, |
factory()->NewAssignment(Token::INIT, proxy, value, pos); |
Statement* assignment_statement = |
factory()->NewExpressionStatement(assignment, kNoSourcePosition); |
- if (names) names->Add(name, zone()); |
+ if (names) names->Add(variable_name, zone()); |
return assignment_statement; |
} |
@@ -2524,7 +2503,7 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) { |
} |
} |
- return ParseHoistableDeclaration(pos, flags, nullptr, CHECK_OK); |
+ return ParseHoistableDeclaration(pos, flags, nullptr, false, CHECK_OK); |
} |
Statement* Parser::ParseExpressionOrLabelledStatement( |