Parsing: Create the same scopes for non-simple params in PreParser & Parser.
Rationale: - To do scope analysis based on PreParser, and use the result again when parsing later, PreParser and Parser need to produce the same Scopes and variable declarations in them. - This is not the case for non-simple parameters: Parser creates an additional inner Scope where the declarations were, whereas PreParser does DeclareVariableName directly in the function Scope. - So this CL fixes that by moving the Scope creation for non-simple parameters into ParserBase. - As a side product (and a partial proof that this change makes sense), PreParser::ParseEagerFunctionBody is now gone. BUG=v8:5516 Review-Url: https://codereview.chromium.org/2638333002 Cr-Commit-Position: refs/heads/master@{#42537}
This commit is contained in:
parent
8b8c8df05b
commit
3534091756
@ -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).
|
||||
@ -1224,6 +1230,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:
|
||||
@ -3901,6 +3913,105 @@ ParserBase<Impl>::ParseAsyncFunctionDeclaration(
|
||||
return ParseHoistableDeclaration(pos, flags, names, default_export, ok);
|
||||
}
|
||||
|
||||
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,
|
||||
@ -4064,9 +4175,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();
|
||||
@ -5563,6 +5676,7 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
|
||||
}
|
||||
}
|
||||
|
||||
#undef CHECK_OK_VOID
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -1754,6 +1754,70 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind,
|
||||
ZoneList<Statement*>* body,
|
||||
bool* ok) {
|
||||
// We produce:
|
||||
//
|
||||
// try { InitialYield; ...body...; return {value: undefined, done: true} }
|
||||
// finally { %_GeneratorClose(generator) }
|
||||
//
|
||||
// - InitialYield yields the actual generator object.
|
||||
// - Any return statement inside the body will have its argument wrapped
|
||||
// in a "done" iterator result object.
|
||||
// - If the generator terminates for whatever reason, we must close it.
|
||||
// Hence the finally clause.
|
||||
|
||||
Block* try_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
|
||||
Expression* initial_yield = BuildInitialYield(pos, kind);
|
||||
try_block->statements()->Add(
|
||||
factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
|
||||
zone());
|
||||
ParseStatementList(try_block->statements(), Token::RBRACE, ok);
|
||||
if (!*ok) return;
|
||||
|
||||
Statement* final_return = factory()->NewReturnStatement(
|
||||
BuildIteratorResult(nullptr, true), kNoSourcePosition);
|
||||
try_block->statements()->Add(final_return, zone());
|
||||
|
||||
Block* finally_block =
|
||||
factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
|
||||
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
|
||||
VariableProxy* call_proxy =
|
||||
factory()->NewVariableProxy(function_state_->generator_object_variable());
|
||||
args->Add(call_proxy, zone());
|
||||
Expression* call = factory()->NewCallRuntime(Runtime::kInlineGeneratorClose,
|
||||
args, kNoSourcePosition);
|
||||
finally_block->statements()->Add(
|
||||
factory()->NewExpressionStatement(call, kNoSourcePosition), zone());
|
||||
|
||||
body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
|
||||
kNoSourcePosition),
|
||||
zone());
|
||||
}
|
||||
|
||||
void Parser::CreateFunctionNameAssignment(
|
||||
const AstRawString* function_name, int pos,
|
||||
FunctionLiteral::FunctionType function_type,
|
||||
DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) {
|
||||
if (function_type == FunctionLiteral::kNamedExpression) {
|
||||
StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition);
|
||||
if (function_scope->LookupLocal(function_name) == nullptr) {
|
||||
// Now that we know the language mode, we can create the const assignment
|
||||
// in the previously reserved spot.
|
||||
DCHECK_EQ(function_scope, scope());
|
||||
Variable* fvar = function_scope->DeclareFunctionVar(function_name);
|
||||
VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
|
||||
statement = factory()->NewExpressionStatement(
|
||||
factory()->NewAssignment(Token::INIT, fproxy,
|
||||
factory()->NewThisFunction(pos),
|
||||
kNoSourcePosition),
|
||||
kNoSourcePosition);
|
||||
}
|
||||
result->Set(index, statement);
|
||||
}
|
||||
}
|
||||
|
||||
// !%_IsJSReceiver(result = iterator.next()) &&
|
||||
// %ThrowIteratorResultNotAnObject(result)
|
||||
Expression* Parser::BuildIteratorNextResult(Expression* iterator,
|
||||
@ -2920,7 +2984,7 @@ Block* Parser::BuildParameterInitializationBlock(
|
||||
return init_block;
|
||||
}
|
||||
|
||||
Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) {
|
||||
Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
|
||||
// .promise = %AsyncFunctionPromiseCreate();
|
||||
// try {
|
||||
// <inner_block>
|
||||
@ -3082,8 +3146,8 @@ ZoneList<Statement*>* Parser::ParseFunction(
|
||||
CHECK_OK);
|
||||
Expect(Token::LBRACE, CHECK_OK);
|
||||
|
||||
ZoneList<Statement*>* body = ParseEagerFunctionBody(
|
||||
function_name, pos, formals, kind, function_type, ok);
|
||||
ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(8, zone());
|
||||
ParseFunctionBody(body, function_name, pos, formals, kind, function_type, ok);
|
||||
|
||||
// Validate parameter names. We can do this only after parsing the function,
|
||||
// since the function can declare itself strict.
|
||||
@ -3103,161 +3167,6 @@ ZoneList<Statement*>* Parser::ParseFunction(
|
||||
return body;
|
||||
}
|
||||
|
||||
ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
||||
const AstRawString* function_name, int pos,
|
||||
const ParserFormalParameters& parameters, FunctionKind kind,
|
||||
FunctionLiteral::FunctionType function_type, bool* ok) {
|
||||
ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());
|
||||
|
||||
static const int kFunctionNameAssignmentIndex = 0;
|
||||
if (function_type == FunctionLiteral::kNamedExpression) {
|
||||
DCHECK(function_name != NULL);
|
||||
// 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(NULL, zone());
|
||||
}
|
||||
|
||||
ZoneList<Statement*>* body = result;
|
||||
DeclarationScope* function_scope = scope()->AsDeclarationScope();
|
||||
DeclarationScope* inner_scope = function_scope;
|
||||
Block* inner_block = nullptr;
|
||||
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)) {
|
||||
// We produce:
|
||||
//
|
||||
// try { InitialYield; ...body...; return {value: undefined, done: true} }
|
||||
// finally { %_GeneratorClose(generator) }
|
||||
//
|
||||
// - InitialYield yields the actual generator object.
|
||||
// - Any return statement inside the body will have its argument wrapped
|
||||
// in a "done" iterator result object.
|
||||
// - If the generator terminates for whatever reason, we must close it.
|
||||
// Hence the finally clause.
|
||||
|
||||
Block* try_block =
|
||||
factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
|
||||
Expression* initial_yield = BuildInitialYield(pos, kind);
|
||||
try_block->statements()->Add(
|
||||
factory()->NewExpressionStatement(initial_yield, kNoSourcePosition),
|
||||
zone());
|
||||
ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);
|
||||
|
||||
Statement* final_return = factory()->NewReturnStatement(
|
||||
BuildIteratorResult(nullptr, true), kNoSourcePosition);
|
||||
try_block->statements()->Add(final_return, zone());
|
||||
|
||||
Block* finally_block =
|
||||
factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
|
||||
ZoneList<Expression*>* args =
|
||||
new (zone()) ZoneList<Expression*>(1, zone());
|
||||
VariableProxy* call_proxy = factory()->NewVariableProxy(
|
||||
function_state_->generator_object_variable());
|
||||
args->Add(call_proxy, zone());
|
||||
Expression* call = factory()->NewCallRuntime(
|
||||
Runtime::kInlineGeneratorClose, args, kNoSourcePosition);
|
||||
finally_block->statements()->Add(
|
||||
factory()->NewExpressionStatement(call, kNoSourcePosition), zone());
|
||||
|
||||
body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
|
||||
kNoSourcePosition),
|
||||
zone());
|
||||
} else if (IsAsyncFunction(kind)) {
|
||||
const bool accept_IN = true;
|
||||
ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal,
|
||||
accept_IN, pos, CHECK_OK);
|
||||
} else {
|
||||
ParseStatementList(body, Token::RBRACE, CHECK_OK);
|
||||
}
|
||||
|
||||
if (IsDerivedConstructor(kind)) {
|
||||
body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition),
|
||||
kNoSourcePosition),
|
||||
zone());
|
||||
}
|
||||
}
|
||||
|
||||
Expect(Token::RBRACE, CHECK_OK);
|
||||
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());
|
||||
DCHECK_EQ(body, inner_block->statements());
|
||||
SetLanguageMode(function_scope, inner_scope->language_mode());
|
||||
Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);
|
||||
|
||||
if (is_sloppy(inner_scope->language_mode())) {
|
||||
InsertSloppyBlockFunctionVarBindings(inner_scope);
|
||||
}
|
||||
|
||||
// TODO(littledan): Merge the two rejection blocks into one
|
||||
if (IsAsyncFunction(kind)) {
|
||||
init_block = BuildRejectPromiseOnException(init_block, CHECK_OK);
|
||||
}
|
||||
|
||||
DCHECK_NOT_NULL(init_block);
|
||||
|
||||
inner_scope->set_end_position(scanner()->location().end_pos);
|
||||
if (inner_scope->FinalizeBlockScope() != nullptr) {
|
||||
CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
|
||||
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())) {
|
||||
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());
|
||||
}
|
||||
|
||||
if (function_type == FunctionLiteral::kNamedExpression) {
|
||||
Statement* statement;
|
||||
if (function_scope->LookupLocal(function_name) == nullptr) {
|
||||
// Now that we know the language mode, we can create the const assignment
|
||||
// in the previously reserved spot.
|
||||
DCHECK_EQ(function_scope, scope());
|
||||
Variable* fvar = function_scope->DeclareFunctionVar(function_name);
|
||||
VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
|
||||
statement = factory()->NewExpressionStatement(
|
||||
factory()->NewAssignment(Token::INIT, fproxy,
|
||||
factory()->NewThisFunction(pos),
|
||||
kNoSourcePosition),
|
||||
kNoSourcePosition);
|
||||
} else {
|
||||
statement = factory()->NewEmptyStatement(kNoSourcePosition);
|
||||
}
|
||||
result->Set(kFunctionNameAssignmentIndex, statement);
|
||||
}
|
||||
|
||||
MarkCollectedTailCallExpressions();
|
||||
return result;
|
||||
}
|
||||
|
||||
void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope,
|
||||
ClassInfo* class_info, int class_token_pos,
|
||||
bool* ok) {
|
||||
@ -3880,7 +3789,7 @@ void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
|
||||
block->statements()->Add(
|
||||
factory()->NewReturnStatement(return_value, return_value->position()),
|
||||
zone());
|
||||
block = BuildRejectPromiseOnException(block, CHECK_OK_VOID);
|
||||
block = BuildRejectPromiseOnException(block);
|
||||
body->Add(block, zone());
|
||||
}
|
||||
|
||||
|
@ -340,6 +340,14 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
Block* finally_block,
|
||||
const CatchInfo& catch_info, int pos);
|
||||
|
||||
void ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind,
|
||||
ZoneList<Statement*>* body,
|
||||
bool* ok);
|
||||
void CreateFunctionNameAssignment(const AstRawString* function_name, int pos,
|
||||
FunctionLiteral::FunctionType function_type,
|
||||
DeclarationScope* function_scope,
|
||||
ZoneList<Statement*>* result, int index);
|
||||
|
||||
Statement* DeclareFunction(const AstRawString* variable_name,
|
||||
FunctionLiteral* function, VariableMode mode,
|
||||
int pos, bool is_generator, bool is_async,
|
||||
@ -533,13 +541,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
|
||||
Block* BuildParameterInitializationBlock(
|
||||
const ParserFormalParameters& parameters, bool* ok);
|
||||
Block* BuildRejectPromiseOnException(Block* block, bool* ok);
|
||||
|
||||
// Consumes the ending }.
|
||||
ZoneList<Statement*>* ParseEagerFunctionBody(
|
||||
const AstRawString* function_name, int pos,
|
||||
const ParserFormalParameters& parameters, FunctionKind kind,
|
||||
FunctionLiteral::FunctionType function_type, bool* ok);
|
||||
Block* BuildRejectPromiseOnException(Block* block);
|
||||
|
||||
ZoneList<Statement*>* ParseFunction(
|
||||
const AstRawString* function_name, int pos, FunctionKind kind,
|
||||
@ -1025,8 +1027,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
|
||||
auto* init_block = BuildParameterInitializationBlock(parameters, ok);
|
||||
if (!*ok) return;
|
||||
if (is_async) {
|
||||
init_block = BuildRejectPromiseOnException(init_block, ok);
|
||||
if (!*ok) return;
|
||||
init_block = BuildRejectPromiseOnException(init_block);
|
||||
}
|
||||
if (init_block != nullptr) body->Add(init_block, zone());
|
||||
}
|
||||
|
@ -414,10 +414,11 @@ class PreParserList {
|
||||
// These functions make list->Add(some_expression) work (and do nothing).
|
||||
PreParserList() : length_(0), variables_(nullptr) {}
|
||||
PreParserList* operator->() { return this; }
|
||||
void Add(T, Zone* zone);
|
||||
void Add(const T& element, Zone* zone);
|
||||
int length() const { return length_; }
|
||||
static PreParserList Null() { return PreParserList(-1); }
|
||||
bool IsNull() const { return length_ == -1; }
|
||||
void Set(int index, const T& element) {}
|
||||
|
||||
private:
|
||||
explicit PreParserList(int n) : length_(n), variables_(nullptr) {}
|
||||
@ -430,7 +431,7 @@ class PreParserList {
|
||||
|
||||
template <>
|
||||
inline void PreParserList<PreParserExpression>::Add(
|
||||
PreParserExpression expression, Zone* zone) {
|
||||
const PreParserExpression& expression, Zone* zone) {
|
||||
if (expression.variables_ != nullptr) {
|
||||
DCHECK(FLAG_lazy_inner_functions);
|
||||
DCHECK(zone != nullptr);
|
||||
@ -445,7 +446,7 @@ inline void PreParserList<PreParserExpression>::Add(
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PreParserList<T>::Add(T, Zone* zone) {
|
||||
void PreParserList<T>::Add(const T& element, Zone* zone) {
|
||||
++length_;
|
||||
}
|
||||
|
||||
@ -939,11 +940,6 @@ class PreParser : public ParserBase<PreParser> {
|
||||
// By making the 'exception handling' explicit, we are forced to check
|
||||
// for failure at the call sites.
|
||||
|
||||
V8_INLINE PreParserStatementList ParseEagerFunctionBody(
|
||||
PreParserIdentifier function_name, int pos,
|
||||
const PreParserFormalParameters& parameters, FunctionKind kind,
|
||||
FunctionLiteral::FunctionType function_type, bool* ok);
|
||||
|
||||
// Indicates that we won't switch from the preparser to the preparser; we'll
|
||||
// just stay where we are.
|
||||
bool AllowsLazyParsingWithoutUnresolvedVariables() const { return false; }
|
||||
@ -1075,6 +1071,16 @@ class PreParser : public ParserBase<PreParser> {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
|
||||
V8_INLINE void ParseAndRewriteGeneratorFunctionBody(
|
||||
int pos, FunctionKind kind, PreParserStatementList body, bool* ok) {
|
||||
ParseStatementList(body, Token::RBRACE, ok);
|
||||
}
|
||||
V8_INLINE void CreateFunctionNameAssignment(
|
||||
PreParserIdentifier function_name, int pos,
|
||||
FunctionLiteral::FunctionType function_type,
|
||||
DeclarationScope* function_scope, PreParserStatementList result,
|
||||
int index) {}
|
||||
|
||||
V8_INLINE PreParserExpression RewriteDoExpression(PreParserStatement body,
|
||||
int pos, bool* ok) {
|
||||
return PreParserExpression::Default();
|
||||
@ -1328,6 +1334,23 @@ class PreParser : public ParserBase<PreParser> {
|
||||
return loop;
|
||||
}
|
||||
|
||||
V8_INLINE PreParserStatement BuildParameterInitializationBlock(
|
||||
const PreParserFormalParameters& parameters, bool* ok) {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
|
||||
V8_INLINE PreParserStatement
|
||||
BuildRejectPromiseOnException(PreParserStatement init_block) {
|
||||
return PreParserStatement::Default();
|
||||
}
|
||||
|
||||
V8_INLINE void InsertSloppyBlockFunctionVarBindings(DeclarationScope* scope) {
|
||||
scope->HoistSloppyBlockFunctions(nullptr);
|
||||
}
|
||||
|
||||
V8_INLINE void InsertShadowingVarBindingInitializers(
|
||||
PreParserStatement block) {}
|
||||
|
||||
V8_INLINE PreParserExpression
|
||||
NewThrowReferenceError(MessageTemplate::Template message, int pos) {
|
||||
return PreParserExpression::Default();
|
||||
@ -1623,29 +1646,6 @@ PreParserExpression PreParser::SpreadCallNew(PreParserExpression function,
|
||||
return factory()->NewCallNew(function, args, pos);
|
||||
}
|
||||
|
||||
PreParserStatementList PreParser::ParseEagerFunctionBody(
|
||||
PreParserIdentifier function_name, int pos,
|
||||
const PreParserFormalParameters& parameters, FunctionKind kind,
|
||||
FunctionLiteral::FunctionType function_type, bool* ok) {
|
||||
PreParserStatementList result;
|
||||
|
||||
DeclarationScope* inner_scope = scope()->AsDeclarationScope();
|
||||
if (!parameters.is_simple) inner_scope = NewVarblockScope();
|
||||
|
||||
{
|
||||
BlockState block_state(&scope_state_, inner_scope);
|
||||
ParseStatementList(result, Token::RBRACE, ok);
|
||||
if (!*ok) return PreParserStatementList();
|
||||
}
|
||||
|
||||
Expect(Token::RBRACE, ok);
|
||||
|
||||
if (is_sloppy(inner_scope->language_mode())) {
|
||||
inner_scope->HoistSloppyBlockFunctions(nullptr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PreParserExpression PreParser::CloseTemplateLiteral(TemplateLiteralState* state,
|
||||
int start,
|
||||
PreParserExpression tag) {
|
||||
|
Loading…
Reference in New Issue
Block a user