Move ParseHoistableDeclaration to ParserBase.
BUG= Review-Url: https://codereview.chromium.org/2311903003 Cr-Commit-Position: refs/heads/master@{#39300}
This commit is contained in:
parent
1d2574afe6
commit
751f8e99c9
@ -1141,6 +1141,11 @@ class ParserBase {
|
||||
DeclarationParsingResult* parsing_result,
|
||||
ZoneList<const AstRawString*>* names,
|
||||
bool* ok);
|
||||
StatementT ParseHoistableDeclaration(ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
StatementT ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
|
||||
ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
|
||||
// Under some circumstances, we allow preparsing to abort if the preparsed
|
||||
// function is "long and trivial", and fully parse instead. Our current
|
||||
@ -3592,6 +3597,68 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
|
||||
return init_block;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::StatementT
|
||||
ParserBase<Impl>::ParseHoistableDeclaration(
|
||||
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
|
||||
Expect(Token::FUNCTION, CHECK_OK_CUSTOM(NullStatement));
|
||||
int pos = position();
|
||||
ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
|
||||
if (Check(Token::MUL)) {
|
||||
flags |= ParseFunctionFlags::kIsGenerator;
|
||||
}
|
||||
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
typename ParserBase<Impl>::StatementT
|
||||
ParserBase<Impl>::ParseHoistableDeclaration(
|
||||
int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names,
|
||||
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);
|
||||
|
||||
IdentifierT name;
|
||||
FunctionNameValidity name_validity;
|
||||
IdentifierT variable_name;
|
||||
if (default_export && peek() == Token::LPAREN) {
|
||||
impl()->GetDefaultStrings(&name, &variable_name);
|
||||
name_validity = kSkipFunctionNameCheck;
|
||||
} else {
|
||||
bool is_strict_reserved;
|
||||
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved,
|
||||
CHECK_OK_CUSTOM(NullStatement));
|
||||
name_validity = is_strict_reserved ? kFunctionNameIsStrictReserved
|
||||
: kFunctionNameValidityUnknown;
|
||||
variable_name = name;
|
||||
}
|
||||
|
||||
FuncNameInferrer::State fni_state(fni_);
|
||||
impl()->PushEnclosingName(name);
|
||||
FunctionLiteralT function = impl()->ParseFunctionLiteral(
|
||||
name, scanner()->location(), name_validity,
|
||||
is_generator ? FunctionKind::kGeneratorFunction
|
||||
: is_async ? FunctionKind::kAsyncFunction
|
||||
: FunctionKind::kNormalFunction,
|
||||
pos, FunctionLiteral::kDeclaration, language_mode(),
|
||||
CHECK_OK_CUSTOM(NullStatement));
|
||||
|
||||
return impl()->DeclareFunction(variable_name, function, pos, is_generator,
|
||||
is_async, names, ok);
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
void ParserBase<Impl>::CheckArityRestrictions(int param_count,
|
||||
FunctionKind function_kind,
|
||||
|
@ -1504,17 +1504,6 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
||||
pos);
|
||||
}
|
||||
|
||||
Statement* Parser::ParseHoistableDeclaration(
|
||||
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, default_export, ok);
|
||||
}
|
||||
|
||||
Statement* Parser::ParseAsyncFunctionDeclaration(
|
||||
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
|
||||
DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
|
||||
@ -1529,76 +1518,6 @@ Statement* Parser::ParseAsyncFunctionDeclaration(
|
||||
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
|
||||
}
|
||||
|
||||
Statement* Parser::ParseHoistableDeclaration(
|
||||
int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names,
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FuncNameInferrer::State fni_state(fni_);
|
||||
DCHECK_NOT_NULL(fni_);
|
||||
fni_->PushEnclosingName(name);
|
||||
FunctionLiteral* fun = ParseFunctionLiteral(
|
||||
name, scanner()->location(), name_validity,
|
||||
is_generator ? FunctionKind::kGeneratorFunction
|
||||
: is_async ? FunctionKind::kAsyncFunction
|
||||
: FunctionKind::kNormalFunction,
|
||||
pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
|
||||
|
||||
// In ES6, a function behaves as a lexical binding, except in
|
||||
// a script scope, or the initial scope of eval or another function.
|
||||
VariableMode mode =
|
||||
(!scope()->is_declaration_scope() || scope()->is_module_scope()) ? LET
|
||||
: VAR;
|
||||
VariableProxy* proxy = NewUnresolved(variable_name);
|
||||
Declaration* declaration =
|
||||
factory()->NewFunctionDeclaration(proxy, fun, scope(), pos);
|
||||
Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
|
||||
CHECK_OK);
|
||||
if (names) names->Add(variable_name, zone());
|
||||
// Async functions don't undergo sloppy mode block scoped hoisting, and don't
|
||||
// allow duplicates in a block. Both are represented by the
|
||||
// sloppy_block_function_map. Don't add them to the map for async functions.
|
||||
// Generators are also supposed to be prohibited; currently doing this behind
|
||||
// a flag and UseCounting violations to assess web compatibility.
|
||||
if (is_sloppy(language_mode()) && !scope()->is_declaration_scope() &&
|
||||
!is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
|
||||
SloppyBlockFunctionStatement* delegate =
|
||||
factory()->NewSloppyBlockFunctionStatement(scope());
|
||||
DeclarationScope* target_scope = GetDeclarationScope();
|
||||
target_scope->DeclareSloppyBlockFunction(variable_name, delegate);
|
||||
return delegate;
|
||||
}
|
||||
return factory()->NewEmptyStatement(kNoSourcePosition);
|
||||
}
|
||||
|
||||
Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok) {
|
||||
// ClassDeclaration ::
|
||||
@ -1669,6 +1588,38 @@ void Parser::DeclareAndInitializeVariables(
|
||||
this, block, declaration_descriptor, declaration, names, ok);
|
||||
}
|
||||
|
||||
Statement* Parser::DeclareFunction(const AstRawString* variable_name,
|
||||
FunctionLiteral* function, int pos,
|
||||
bool is_generator, bool is_async,
|
||||
ZoneList<const AstRawString*>* names,
|
||||
bool* ok) {
|
||||
// In ES6, a function behaves as a lexical binding, except in
|
||||
// a script scope, or the initial scope of eval or another function.
|
||||
VariableMode mode =
|
||||
(!scope()->is_declaration_scope() || scope()->is_module_scope()) ? LET
|
||||
: VAR;
|
||||
VariableProxy* proxy = NewUnresolved(variable_name);
|
||||
Declaration* declaration =
|
||||
factory()->NewFunctionDeclaration(proxy, function, scope(), pos);
|
||||
Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized,
|
||||
CHECK_OK);
|
||||
if (names) names->Add(variable_name, zone());
|
||||
// Async functions don't undergo sloppy mode block scoped hoisting, and don't
|
||||
// allow duplicates in a block. Both are represented by the
|
||||
// sloppy_block_function_map. Don't add them to the map for async functions.
|
||||
// Generators are also supposed to be prohibited; currently doing this behind
|
||||
// a flag and UseCounting violations to assess web compatibility.
|
||||
if (is_sloppy(language_mode()) && !scope()->is_declaration_scope() &&
|
||||
!is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
|
||||
SloppyBlockFunctionStatement* delegate =
|
||||
factory()->NewSloppyBlockFunctionStatement(scope());
|
||||
DeclarationScope* target_scope = GetDeclarationScope();
|
||||
target_scope->DeclareSloppyBlockFunction(variable_name, delegate);
|
||||
return delegate;
|
||||
}
|
||||
return factory()->NewEmptyStatement(kNoSourcePosition);
|
||||
}
|
||||
|
||||
static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
|
||||
const AstRawString* label) {
|
||||
DCHECK(label != NULL);
|
||||
|
@ -267,11 +267,6 @@ class Parser : public ParserBase<Parser> {
|
||||
};
|
||||
ZoneList<const NamedImport*>* ParseNamedImports(int pos, bool* ok);
|
||||
Statement* ParseFunctionDeclaration(bool* ok);
|
||||
Statement* ParseHoistableDeclaration(ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
Statement* ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
|
||||
ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
Statement* ParseAsyncFunctionDeclaration(ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
Expression* ParseAsyncFunctionExpression(bool* ok);
|
||||
@ -286,6 +281,11 @@ class Parser : public ParserBase<Parser> {
|
||||
const DeclarationParsingResult::Declaration* declaration,
|
||||
ZoneList<const AstRawString*>* names, bool* ok);
|
||||
|
||||
Statement* DeclareFunction(const AstRawString* variable_name,
|
||||
FunctionLiteral* function, int pos,
|
||||
bool is_generator, bool is_async,
|
||||
ZoneList<const AstRawString*>* names, bool* ok);
|
||||
|
||||
DoExpression* ParseDoExpression(bool* ok);
|
||||
Expression* ParseYieldStarExpression(bool* ok);
|
||||
|
||||
@ -699,6 +699,13 @@ class Parser : public ParserBase<Parser> {
|
||||
return property->value();
|
||||
}
|
||||
|
||||
V8_INLINE void GetDefaultStrings(
|
||||
const AstRawString** default_string,
|
||||
const AstRawString** star_default_star_string) {
|
||||
*default_string = ast_value_factory()->default_string();
|
||||
*star_default_star_string = ast_value_factory()->star_default_star_string();
|
||||
}
|
||||
|
||||
// Functions for encapsulating the differences between parsing and preparsing;
|
||||
// operations interleaved with the recursive descent.
|
||||
V8_INLINE void PushLiteralName(const AstRawString* id) {
|
||||
@ -720,6 +727,11 @@ class Parser : public ParserBase<Parser> {
|
||||
}
|
||||
}
|
||||
|
||||
V8_INLINE void PushEnclosingName(const AstRawString* name) {
|
||||
DCHECK_NOT_NULL(fni_);
|
||||
fni_->PushEnclosingName(name);
|
||||
}
|
||||
|
||||
V8_INLINE void InferFunctionName(FunctionLiteral* func_to_infer) {
|
||||
fni_->AddFunction(func_to_infer);
|
||||
}
|
||||
|
@ -121,28 +121,6 @@ PreParser::PreParseResult PreParser::PreParseLazyFunction(
|
||||
// That means that contextual checks (like a label being declared where
|
||||
// it is used) are generally omitted.
|
||||
|
||||
PreParser::Statement PreParser::ParseHoistableDeclaration(
|
||||
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);
|
||||
|
||||
bool is_strict_reserved = false;
|
||||
Identifier name = ParseIdentifierOrStrictReservedWord(
|
||||
&is_strict_reserved, CHECK_OK);
|
||||
|
||||
ParseFunctionLiteral(name, scanner()->location(),
|
||||
is_strict_reserved ? kFunctionNameIsStrictReserved
|
||||
: kFunctionNameValidityUnknown,
|
||||
is_generator ? FunctionKind::kGeneratorFunction
|
||||
: is_async ? FunctionKind::kAsyncFunction
|
||||
: FunctionKind::kNormalFunction,
|
||||
pos, FunctionLiteral::kDeclaration, language_mode(),
|
||||
CHECK_OK);
|
||||
return Statement::FunctionDeclaration();
|
||||
}
|
||||
|
||||
PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(
|
||||
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
|
||||
// AsyncFunctionDeclaration ::
|
||||
@ -155,23 +133,6 @@ PreParser::Statement PreParser::ParseAsyncFunctionDeclaration(
|
||||
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
|
||||
}
|
||||
|
||||
PreParser::Statement PreParser::ParseHoistableDeclaration(
|
||||
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
|
||||
// FunctionDeclaration ::
|
||||
// 'function' Identifier '(' FormalParameterListopt ')' '{' FunctionBody '}'
|
||||
// GeneratorDeclaration ::
|
||||
// 'function' '*' Identifier '(' FormalParameterListopt ')'
|
||||
// '{' FunctionBody '}'
|
||||
|
||||
Expect(Token::FUNCTION, CHECK_OK);
|
||||
int pos = position();
|
||||
ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
|
||||
if (Check(Token::MUL)) {
|
||||
flags |= ParseFunctionFlags::kIsGenerator;
|
||||
}
|
||||
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
|
||||
}
|
||||
|
||||
PreParser::Statement PreParser::ParseClassDeclaration(
|
||||
ZoneList<const AstRawString*>* names, bool default_export, bool* ok) {
|
||||
int pos = position();
|
||||
@ -197,6 +158,9 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
|
||||
return Statement::Default();
|
||||
}
|
||||
}
|
||||
// PreParser is not able to parse "export default" yet (since PreParser is
|
||||
// at the moment only used for functions, and it cannot occur
|
||||
// there). TODO(marja): update this when it is.
|
||||
return ParseHoistableDeclaration(pos, flags, nullptr, false, ok);
|
||||
}
|
||||
|
||||
|
@ -393,10 +393,6 @@ class PreParserStatement {
|
||||
return PreParserStatement(kJumpStatement);
|
||||
}
|
||||
|
||||
static PreParserStatement FunctionDeclaration() {
|
||||
return PreParserStatement(kFunctionDeclaration);
|
||||
}
|
||||
|
||||
// Creates expression statement from expression.
|
||||
// Preserves being an unparenthesized string literal, possibly
|
||||
// "use strict".
|
||||
@ -425,10 +421,6 @@ class PreParserStatement {
|
||||
|
||||
bool IsUseAsmLiteral() { return code_ == kUseAsmExpressionStatement; }
|
||||
|
||||
bool IsFunctionDeclaration() {
|
||||
return code_ == kFunctionDeclaration;
|
||||
}
|
||||
|
||||
bool IsJumpStatement() {
|
||||
return code_ == kJumpStatement;
|
||||
}
|
||||
@ -447,7 +439,6 @@ class PreParserStatement {
|
||||
kStringLiteralExpressionStatement,
|
||||
kUseStrictExpressionStatement,
|
||||
kUseAsmExpressionStatement,
|
||||
kFunctionDeclaration
|
||||
};
|
||||
|
||||
explicit PreParserStatement(Type code) : code_(code) {}
|
||||
@ -764,11 +755,6 @@ class PreParser : public ParserBase<PreParser> {
|
||||
// which is set to false if parsing failed; it is unchanged otherwise.
|
||||
// By making the 'exception handling' explicit, we are forced to check
|
||||
// for failure at the call sites.
|
||||
Statement ParseHoistableDeclaration(ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
Statement ParseHoistableDeclaration(int pos, ParseFunctionFlags flags,
|
||||
ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
Statement ParseFunctionDeclaration(bool* ok);
|
||||
Statement ParseAsyncFunctionDeclaration(ZoneList<const AstRawString*>* names,
|
||||
bool default_export, bool* ok);
|
||||
@ -885,6 +871,13 @@ class PreParser : public ParserBase<PreParser> {
|
||||
const DeclarationParsingResult::Declaration* declaration,
|
||||
ZoneList<const AstRawString*>* names, bool* ok) {}
|
||||
|
||||
V8_INLINE PreParserStatement DeclareFunction(
|
||||
PreParserIdentifier variable_name, PreParserExpression function, int pos,
|
||||
bool is_generator, bool is_async, ZoneList<const AstRawString*>* names,
|
||||
bool* ok) {
|
||||
return Statement::Default();
|
||||
}
|
||||
|
||||
V8_INLINE void QueueDestructuringAssignmentForRewriting(
|
||||
PreParserExpression assignment) {}
|
||||
V8_INLINE void QueueNonPatternForRewriting(PreParserExpression expr,
|
||||
@ -968,11 +961,16 @@ class PreParser : public ParserBase<PreParser> {
|
||||
return PreParserExpression::Default();
|
||||
}
|
||||
|
||||
V8_INLINE static void GetDefaultStrings(
|
||||
PreParserIdentifier* default_string,
|
||||
PreParserIdentifier* star_default_star_string) {}
|
||||
|
||||
// Functions for encapsulating the differences between parsing and preparsing;
|
||||
// operations interleaved with the recursive descent.
|
||||
V8_INLINE static void PushLiteralName(PreParserIdentifier id) {}
|
||||
V8_INLINE static void PushVariableName(PreParserIdentifier id) {}
|
||||
V8_INLINE void PushPropertyName(PreParserExpression expression) {}
|
||||
V8_INLINE void PushEnclosingName(PreParserIdentifier name) {}
|
||||
V8_INLINE static void InferFunctionName(PreParserExpression expression) {}
|
||||
|
||||
V8_INLINE static void CheckAssigningFunctionLiteralToProperty(
|
||||
|
Loading…
Reference in New Issue
Block a user