summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-06-06 10:28:14 +0200
committerMichaël Zasso <targos@protonmail.com>2017-06-07 10:33:31 +0200
commit3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09 (patch)
tree9dee56e142638b34f1eccbd0ad88c3bce5377c29 /deps/v8/src/parsing/parser.cc
parent91a1bbe3055a660194ca4d403795aa0c03e9d056 (diff)
downloadandroid-node-v8-3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09.tar.gz
android-node-v8-3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09.tar.bz2
android-node-v8-3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09.zip
deps: update V8 to 5.9.211.32
PR-URL: https://github.com/nodejs/node/pull/13263 Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing/parser.cc')
-rw-r--r--deps/v8/src/parsing/parser.cc508
1 files changed, 309 insertions, 199 deletions
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc
index cc6b6a260b..6a2c2db0d1 100644
--- a/deps/v8/src/parsing/parser.cc
+++ b/deps/v8/src/parsing/parser.cc
@@ -192,7 +192,7 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
bool is_optional = false;
Variable* constructor_args = function_scope->DeclareParameter(
constructor_args_name, TEMPORARY, is_optional, is_rest, &is_duplicate,
- ast_value_factory());
+ ast_value_factory(), pos);
ZoneList<Expression*>* args =
new (zone()) ZoneList<Expression*>(1, zone());
@@ -503,11 +503,9 @@ Expression* Parser::NewV8Intrinsic(const AstRawString* name,
Parser::Parser(ParseInfo* info)
: ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
info->extension(), info->ast_value_factory(),
- info->isolate()->counters()->runtime_call_stats(),
- true),
+ info->runtime_call_stats(), true),
scanner_(info->unicode_cache()),
reusable_preparser_(nullptr),
- original_scope_(nullptr),
mode_(PARSE_EAGERLY), // Lazy mode must be set explicitly.
target_stack_(nullptr),
compile_options_(info->compile_options()),
@@ -543,7 +541,7 @@ Parser::Parser(ParseInfo* info)
info->extension() == nullptr && can_compile_lazily;
set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
- info->isolate()->is_tail_call_elimination_enabled());
+ info->is_tail_call_elimination_enabled());
set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
set_allow_harmony_function_sent(FLAG_harmony_function_sent);
set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
@@ -560,7 +558,7 @@ Parser::Parser(ParseInfo* info)
if (info->ast_value_factory() == NULL) {
// info takes ownership of AstValueFactory.
info->set_ast_value_factory(new AstValueFactory(
- zone(), info->isolate()->ast_string_constants(), info->hash_seed()));
+ zone(), info->ast_string_constants(), info->hash_seed()));
info->set_ast_value_factory_owned();
ast_value_factory_ = info->ast_value_factory();
ast_node_factory_.set_ast_value_factory(ast_value_factory_);
@@ -569,7 +567,6 @@ Parser::Parser(ParseInfo* info)
void Parser::DeserializeScopeChain(
ParseInfo* info, MaybeHandle<ScopeInfo> maybe_outer_scope_info) {
- DCHECK(ThreadId::Current().Equals(info->isolate()->thread_id()));
// TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
// context, which will have the "this" binding for script scopes.
DeclarationScope* script_scope = NewScriptScope();
@@ -577,9 +574,11 @@ void Parser::DeserializeScopeChain(
Scope* scope = script_scope;
Handle<ScopeInfo> outer_scope_info;
if (maybe_outer_scope_info.ToHandle(&outer_scope_info)) {
+ DCHECK(ThreadId::Current().Equals(
+ outer_scope_info->GetIsolate()->thread_id()));
scope = Scope::DeserializeScopeChain(
- info->isolate(), zone(), *outer_scope_info, script_scope,
- ast_value_factory(), Scope::DeserializationMode::kScopesOnly);
+ zone(), *outer_scope_info, script_scope, ast_value_factory(),
+ Scope::DeserializationMode::kScopesOnly);
DCHECK(!info->is_module() || scope->is_module_scope());
}
original_scope_ = scope;
@@ -624,6 +623,22 @@ FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
{
std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(source));
+ if (FLAG_use_parse_tasks) {
+ // FIXME(wiktorg) make it useful for something
+ // TODO(wiktorg) make preparser work also with modules
+ if (!info->is_module()) {
+ scanner_.Initialize(stream.get());
+ // NOTE: Some features will be double counted - once here and one more
+ // time while being fully parsed by a parse task.
+ PreParser::PreParseResult result =
+ reusable_preparser()->PreParseProgram(false, use_counts_);
+ if (result == PreParser::kPreParseStackOverflow) {
+ set_stack_overflow();
+ return nullptr;
+ }
+ stream->Seek(0);
+ }
+ }
scanner_.Initialize(stream.get());
result = DoParseProgram(info);
}
@@ -692,8 +707,9 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
bool is_duplicate;
bool is_rest = false;
bool is_optional = false;
- auto var = scope->DeclareParameter(name, VAR, is_optional, is_rest,
- &is_duplicate, ast_value_factory());
+ auto var =
+ scope->DeclareParameter(name, VAR, is_optional, is_rest,
+ &is_duplicate, ast_value_factory(), beg_pos);
DCHECK(!is_duplicate);
var->AllocateTo(VariableLocation::PARAMETER, 0);
@@ -789,8 +805,8 @@ FunctionLiteral* Parser::ParseFunction(Isolate* isolate, ParseInfo* info) {
std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
source, shared_info->start_position(), shared_info->end_position()));
Handle<String> name(String::cast(shared_info->name()));
- result = DoParseFunction(info, ast_value_factory()->GetString(name),
- stream.get());
+ scanner_.Initialize(stream.get());
+ result = DoParseFunction(info, ast_value_factory()->GetString(name));
if (result != nullptr) {
Handle<String> inferred_name(shared_info->inferred_name());
result->set_inferred_name(inferred_name);
@@ -820,9 +836,8 @@ static FunctionLiteral::FunctionType ComputeFunctionType(ParseInfo* info) {
}
FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
- const AstRawString* raw_name,
- Utf16CharacterStream* source) {
- scanner_.Initialize(source);
+ const AstRawString* raw_name) {
+ DCHECK_NOT_NULL(raw_name);
DCHECK_NULL(scope_);
DCHECK_NULL(target_stack_);
@@ -868,13 +883,8 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
// TODO(adamk): We should construct this scope from the ScopeInfo.
DeclarationScope* scope = NewFunctionScope(kind);
- // These two bits only need to be explicitly set because we're
+ // This bit only needs to be explicitly set because we're
// not passing the ScopeInfo to the Scope constructor.
- // TODO(adamk): Remove these calls once the above NewScope call
- // passes the ScopeInfo.
- if (info->calls_eval()) {
- scope->RecordEvalCall();
- }
SetLanguageMode(scope, info->language_mode());
scope->set_start_position(info->start_position());
@@ -882,10 +892,9 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
ParserFormalParameters formals(scope);
int rewritable_length =
function_state.destructuring_assignments_to_rewrite().length();
- Checkpoint checkpoint(this);
{
// Parsing patterns as variable reference expression creates
- // NewUnresolved references in current scope. Entrer arrow function
+ // NewUnresolved references in current scope. Enter arrow function
// scope for formal parameter parsing.
BlockState block_state(&scope_, scope);
if (Check(Token::LPAREN)) {
@@ -900,7 +909,6 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
}
if (ok) {
- checkpoint.Restore(&formals.materialized_literals_count);
if (GetLastFunctionLiteralId() != info->function_literal_id() - 1) {
// If there were FunctionLiterals in the parameters, we need to
// renumber them to shift down so the next function literal id for
@@ -958,6 +966,8 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info,
DCHECK_NULL(target_stack_);
DCHECK_IMPLIES(result,
info->function_literal_id() == result->function_literal_id());
+ DCHECK_IMPLIES(!info->scope_info_is_empty() && result,
+ info->calls_eval() == result->scope()->calls_eval());
return result;
}
@@ -1044,7 +1054,7 @@ void Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
const AstRawString* local_name = ParseIdentifierName(CHECK_OK_VOID);
const AstRawString* export_name = NULL;
Scanner::Location location = scanner()->location();
- if (CheckContextualKeyword(CStrVector("as"))) {
+ if (CheckContextualKeyword(Token::AS)) {
export_name = ParseIdentifierName(CHECK_OK_VOID);
// Set the location to the whole "a as b" string, so that it makes sense
// both for errors due to "a" and for errors due to "b".
@@ -1089,7 +1099,7 @@ ZoneList<const Parser::NamedImport*>* Parser::ParseNamedImports(
// In the presence of 'as', the left-side of the 'as' can
// be any IdentifierName. But without 'as', it must be a valid
// BindingIdentifier.
- if (CheckContextualKeyword(CStrVector("as"))) {
+ if (CheckContextualKeyword(Token::AS)) {
local_name = ParseIdentifierName(CHECK_OK);
}
if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false,
@@ -1166,7 +1176,7 @@ void Parser::ParseImportDeclaration(bool* ok) {
switch (peek()) {
case Token::MUL: {
Consume(Token::MUL);
- ExpectContextualKeyword(CStrVector("as"), CHECK_OK_VOID);
+ ExpectContextualKeyword(Token::AS, CHECK_OK_VOID);
module_namespace_binding =
ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK_VOID);
module_namespace_binding_loc = scanner()->location();
@@ -1186,7 +1196,7 @@ void Parser::ParseImportDeclaration(bool* ok) {
}
}
- ExpectContextualKeyword(CStrVector("from"), CHECK_OK_VOID);
+ ExpectContextualKeyword(Token::FROM, CHECK_OK_VOID);
const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK_VOID);
ExpectSemicolon(CHECK_OK_VOID);
@@ -1271,7 +1281,8 @@ Statement* Parser::ParseExportDefault(bool* ok) {
Assignment* assignment = factory()->NewAssignment(
Token::INIT, decl->proxy(), value, kNoSourcePosition);
- result = factory()->NewExpressionStatement(assignment, kNoSourcePosition);
+ result = IgnoreCompletion(
+ factory()->NewExpressionStatement(assignment, kNoSourcePosition));
ExpectSemicolon(CHECK_OK);
break;
@@ -1308,7 +1319,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
case Token::MUL: {
Consume(Token::MUL);
loc = scanner()->location();
- ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
+ ExpectContextualKeyword(Token::FROM, CHECK_OK);
const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
ExpectSemicolon(CHECK_OK);
module()->AddStarExport(module_specifier, loc, zone());
@@ -1334,7 +1345,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
ParseExportClause(&export_names, &export_locations, &original_names,
&reserved_loc, CHECK_OK);
const AstRawString* module_specifier = nullptr;
- if (CheckContextualKeyword(CStrVector("from"))) {
+ if (CheckContextualKeyword(Token::FROM)) {
module_specifier = ParseModuleSpecifier(CHECK_OK);
} else if (reserved_loc.IsValid()) {
// No FromClause, so reserved words are invalid in ExportClause.
@@ -1514,12 +1525,12 @@ Statement* Parser::DeclareClass(const AstRawString* variable_name,
Declaration* decl =
DeclareVariable(variable_name, LET, class_token_pos, CHECK_OK);
decl->proxy()->var()->set_initializer_position(end_pos);
+ if (names) names->Add(variable_name, zone());
+
Assignment* assignment = factory()->NewAssignment(Token::INIT, decl->proxy(),
value, class_token_pos);
- Statement* assignment_statement =
- factory()->NewExpressionStatement(assignment, kNoSourcePosition);
- if (names) names->Add(variable_name, zone());
- return assignment_statement;
+ return IgnoreCompletion(
+ factory()->NewExpressionStatement(assignment, kNoSourcePosition));
}
Statement* Parser::DeclareNative(const AstRawString* name, int pos, bool* ok) {
@@ -1577,47 +1588,37 @@ bool Parser::ContainsLabel(ZoneList<const AstRawString*>* labels,
return false;
}
+Block* Parser::IgnoreCompletion(Statement* statement) {
+ Block* block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
+ block->statements()->Add(statement, zone());
+ return block;
+}
+
Expression* Parser::RewriteReturn(Expression* return_value, int pos) {
if (IsDerivedConstructor(function_state_->kind())) {
- // For subclass constructors we need to return this in case of undefined
- // return a Smi (transformed into an exception in the ConstructStub)
- // for a non object.
+ // For subclass constructors we need to return this in case of undefined;
+ // other primitive values trigger an exception in the ConstructStub.
//
// return expr;
//
// Is rewritten as:
//
- // return (temp = expr) === undefined ? this :
- // %_IsJSReceiver(temp) ? temp : 1;
+ // return (temp = expr) === undefined ? this : temp;
// temp = expr
Variable* temp = NewTemporary(ast_value_factory()->empty_string());
Assignment* assign = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);
- // %_IsJSReceiver(temp)
- ZoneList<Expression*>* is_spec_object_args =
- new (zone()) ZoneList<Expression*>(1, zone());
- is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
- Expression* is_spec_object_call = factory()->NewCallRuntime(
- Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);
-
- // %_IsJSReceiver(temp) ? temp : 1;
- Expression* is_object_conditional = factory()->NewConditional(
- is_spec_object_call, factory()->NewVariableProxy(temp),
- factory()->NewSmiLiteral(1, pos), pos);
-
// temp === undefined
Expression* is_undefined = factory()->NewCompareOperation(
Token::EQ_STRICT, assign,
factory()->NewUndefinedLiteral(kNoSourcePosition), pos);
- // is_undefined ? this : is_object_conditional
- return_value = factory()->NewConditional(is_undefined, ThisExpression(pos),
- is_object_conditional, pos);
- }
- if (is_generator()) {
- return_value = BuildIteratorResult(return_value, true);
+ // is_undefined ? this : temp
+ return_value =
+ factory()->NewConditional(is_undefined, ThisExpression(pos),
+ factory()->NewVariableProxy(temp), pos);
}
return return_value;
}
@@ -1683,7 +1684,8 @@ void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {
DCHECK_NOT_NULL(catch_info->pattern);
catch_info->name = ast_value_factory()->dot_catch_string();
}
- catch_info->variable = catch_info->scope->DeclareLocal(catch_info->name, VAR);
+ Variable* catch_variable =
+ catch_info->scope->DeclareLocal(catch_info->name, VAR);
if (catch_info->pattern != nullptr) {
DeclarationDescriptor descriptor;
descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
@@ -1697,7 +1699,7 @@ void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) {
DeclarationParsingResult::Declaration decl(
catch_info->pattern, initializer_position,
- factory()->NewVariableProxy(catch_info->variable));
+ factory()->NewVariableProxy(catch_variable));
catch_info->init_block =
factory()->NewBlock(nullptr, 8, true, kNoSourcePosition);
@@ -1739,10 +1741,8 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
if (catch_block != nullptr && finally_block != nullptr) {
// If we have both, create an inner try/catch.
DCHECK_NOT_NULL(catch_info.scope);
- DCHECK_NOT_NULL(catch_info.variable);
TryCatchStatement* statement;
statement = factory()->NewTryCatchStatement(try_block, catch_info.scope,
- catch_info.variable,
catch_block, kNoSourcePosition);
try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
@@ -1758,9 +1758,8 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
DCHECK_NULL(finally_block);
DCHECK_NOT_NULL(catch_info.scope);
- DCHECK_NOT_NULL(catch_info.variable);
- return factory()->NewTryCatchStatement(
- try_block, catch_info.scope, catch_info.variable, catch_block, pos);
+ return factory()->NewTryCatchStatement(try_block, catch_info.scope,
+ catch_block, pos);
} else {
DCHECK_NOT_NULL(finally_block);
return factory()->NewTryFinallyStatement(try_block, finally_block, pos);
@@ -1770,16 +1769,31 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block,
void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind,
ZoneList<Statement*>* body,
bool* ok) {
- // We produce:
+ // For ES6 Generators, we produce:
//
// try { InitialYield; ...body...; return {value: undefined, done: true} }
// finally { %_GeneratorClose(generator) }
//
+ // For ES2017 Async Generators, we produce:
+ //
+ // try {
+ // InitialYield;
+ // ...body...;
+ // return undefined; // See comment below
+ // } catch (.catch) {
+ // %AsyncGeneratorReject(generator, .catch);
+ // } 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.
+ // in an iterator result object with a "done" property set to `true`.
// - If the generator terminates for whatever reason, we must close it.
// Hence the finally clause.
+ // - BytecodeGenerator performs special handling for ReturnStatements in
+ // async generator functions, resolving the appropriate Promise with an
+ // "done" iterator result object containing a Promise-unwrapped value.
Block* try_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition);
Expression* initial_yield = BuildInitialYield(pos, kind);
@@ -1789,9 +1803,38 @@ void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind,
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());
+ if (IsAsyncGeneratorFunction(kind)) {
+ // Don't create iterator result for async generators, as the resume methods
+ // will create it.
+ Statement* final_return = BuildReturnStatement(
+ factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
+ try_block->statements()->Add(final_return, zone());
+
+ // For AsyncGenerators, a top-level catch block will reject the Promise.
+ Scope* catch_scope = NewHiddenCatchScopeWithParent(scope());
+
+ ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
+ args->Add(factory()->NewVariableProxy(
+ function_state_->generator_object_variable()),
+ zone());
+ args->Add(factory()->NewVariableProxy(catch_scope->catch_variable()),
+ zone());
+
+ Expression* call = factory()->NewCallRuntime(
+ Runtime::kInlineAsyncGeneratorReject, args, kNoSourcePosition);
+ Block* catch_block = IgnoreCompletion(
+ factory()->NewReturnStatement(call, kNoSourcePosition));
+
+ TryStatement* try_catch = factory()->NewTryCatchStatementForAsyncAwait(
+ try_block, catch_scope, catch_block, kNoSourcePosition);
+
+ try_block = factory()->NewBlock(nullptr, 1, false, kNoSourcePosition);
+ try_block->statements()->Add(try_catch, zone());
+ } else {
+ 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);
@@ -1999,7 +2042,7 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
Scope* catch_scope = scope();
while (catch_scope != nullptr && !catch_scope->is_declaration_scope()) {
if (catch_scope->is_catch_scope()) {
- auto name = catch_scope->catch_variable_name();
+ auto name = catch_scope->catch_variable()->raw_name();
// If it's a simple binding and the name is declared in the for loop.
if (name != ast_value_factory()->dot_catch_string() &&
for_info->bound_names.Contains(name)) {
@@ -2104,10 +2147,8 @@ Statement* Parser::InitializeForOfStatement(
Token::ASSIGN, proxy,
factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
- Block* block = factory()->NewBlock(nullptr, 1, true, nopos);
- block->statements()->Add(
- factory()->NewExpressionStatement(assignment, nopos), zone());
- set_completion_abrupt = block;
+ set_completion_abrupt =
+ IgnoreCompletion(factory()->NewExpressionStatement(assignment, nopos));
}
// do { let tmp = #result_value; #set_completion_abrupt; tmp }
@@ -2145,10 +2186,8 @@ Statement* Parser::InitializeForOfStatement(
Token::ASSIGN, proxy,
factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
- Block* block = factory()->NewBlock(nullptr, 1, true, nopos);
- block->statements()->Add(
- factory()->NewExpressionStatement(assignment, nopos), zone());
- set_completion_normal = block;
+ set_completion_normal =
+ IgnoreCompletion(factory()->NewExpressionStatement(assignment, nopos));
}
// { #loop-body; #set_completion_normal }
@@ -2392,10 +2431,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
Statement* empty = factory()->NewEmptyStatement(kNoSourcePosition);
Statement* if_flag_break =
factory()->NewIfStatement(compare, stop, empty, kNoSourcePosition);
- Block* ignore_completion_block =
- factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
- ignore_completion_block->statements()->Add(if_flag_break, zone());
- inner_block->statements()->Add(ignore_completion_block, zone());
+ inner_block->statements()->Add(IgnoreCompletion(if_flag_break), zone());
}
inner_block->set_scope(inner_scope);
@@ -2661,7 +2697,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
bookmark.Set();
LazyParsingResult result = SkipFunction(
kind, scope, &num_parameters, &function_length,
- &has_duplicate_parameters, &expected_property_count,
is_lazy_inner_function, is_lazy_top_level_function, CHECK_OK);
if (result == kLazyParsingAborted) {
@@ -2757,9 +2792,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Parser::LazyParsingResult Parser::SkipFunction(
FunctionKind kind, DeclarationScope* function_scope, int* num_parameters,
- int* function_length, bool* has_duplicate_parameters,
- int* expected_property_count, bool is_inner_function, bool may_abort,
- bool* ok) {
+ int* function_length, bool is_inner_function, bool may_abort, bool* ok) {
DCHECK_NE(kNoSourcePosition, function_scope->start_position());
DCHECK_EQ(kNoSourcePosition, parameters_end_pos_);
if (produce_cached_parse_data()) CHECK(log_);
@@ -2785,8 +2818,6 @@ Parser::LazyParsingResult Parser::SkipFunction(
Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
*num_parameters = entry.num_parameters();
*function_length = entry.function_length();
- *has_duplicate_parameters = entry.has_duplicate_parameters();
- *expected_property_count = entry.property_count();
SetLanguageMode(function_scope, entry.language_mode());
if (entry.uses_super_property())
function_scope->RecordSuperPropertyUsage();
@@ -2797,30 +2828,71 @@ Parser::LazyParsingResult Parser::SkipFunction(
cached_parse_data_->Reject();
}
+ if (FLAG_use_parse_tasks && !is_inner_function &&
+ reusable_preparser()->preparse_data()) {
+ // All top-level functions are already preparsed and parser tasks for eager
+ // functions are already created. Use data gathered during the preparse step
+ // to skip the function.
+ PreParseData::FunctionData data =
+ reusable_preparser()->preparse_data()->GetFunctionData(
+ function_scope->start_position());
+ if (data.is_valid()) {
+ if (FLAG_trace_parse_tasks) {
+ PrintF("Skipping top level func @ %d : %d using preparse data\n",
+ function_scope->start_position(), data.end);
+ }
+ function_scope->set_end_position(data.end);
+ scanner()->SeekForward(data.end - 1);
+ Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
+ *num_parameters = data.num_parameters;
+ *function_length = data.function_length;
+ SetLanguageMode(function_scope, data.language_mode);
+ if (data.uses_super_property) {
+ function_scope->RecordSuperPropertyUsage();
+ }
+ if (data.calls_eval) {
+ function_scope->RecordEvalCall();
+ }
+ SkipFunctionLiterals(data.num_inner_functions);
+ return kLazyParsingComplete;
+ }
+ }
+
+ // FIXME(marja): There are 3 ways to skip functions now. Unify them.
+ if (preparsed_scope_data_->Consuming()) {
+ DCHECK(FLAG_preparser_scope_analysis);
+ const PreParseData::FunctionData& data =
+ preparsed_scope_data_->FindFunction(function_scope->start_position());
+ if (data.is_valid()) {
+ function_scope->set_is_skipped_function(true);
+ function_scope->outer_scope()->SetMustUsePreParsedScopeData();
+
+ function_scope->set_end_position(data.end);
+ scanner()->SeekForward(data.end - 1);
+ Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
+ *num_parameters = data.num_parameters;
+ *function_length = data.function_length;
+ SetLanguageMode(function_scope, data.language_mode);
+ if (data.uses_super_property) {
+ function_scope->RecordSuperPropertyUsage();
+ }
+ if (data.calls_eval) {
+ function_scope->RecordEvalCall();
+ }
+ SkipFunctionLiterals(data.num_inner_functions);
+ return kLazyParsingComplete;
+ }
+ }
+
// With no cached data, we partially parse the function, without building an
// AST. This gathers the data needed to build a lazy function.
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.PreParse");
- if (reusable_preparser_ == NULL) {
- reusable_preparser_ = new PreParser(
- zone(), &scanner_, stack_limit_, ast_value_factory(),
- &pending_error_handler_, runtime_call_stats_, parsing_on_main_thread_);
-#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
- SET_ALLOW(natives);
- SET_ALLOW(harmony_do_expressions);
- SET_ALLOW(harmony_function_sent);
- SET_ALLOW(harmony_trailing_commas);
- SET_ALLOW(harmony_class_fields);
- SET_ALLOW(harmony_object_rest_spread);
- SET_ALLOW(harmony_dynamic_import);
- SET_ALLOW(harmony_async_iteration);
-#undef SET_ALLOW
- }
// Aborting inner function preparsing would leave scopes in an inconsistent
// state; we don't parse inner functions in the abortable mode anyway.
DCHECK(!is_inner_function || !may_abort);
- PreParser::PreParseResult result = reusable_preparser_->PreParseFunction(
+ PreParser::PreParseResult result = reusable_preparser()->PreParseFunction(
kind, function_scope, parsing_module_, is_inner_function, may_abort,
use_counts_);
@@ -2836,22 +2908,19 @@ Parser::LazyParsingResult Parser::SkipFunction(
*ok = false;
return kLazyParsingComplete;
}
- PreParserLogger* logger = reusable_preparser_->logger();
+ PreParserLogger* logger = reusable_preparser()->logger();
function_scope->set_end_position(logger->end());
Expect(Token::RBRACE, CHECK_OK_VALUE(kLazyParsingComplete));
total_preparse_skipped_ +=
function_scope->end_position() - function_scope->start_position();
*num_parameters = logger->num_parameters();
*function_length = logger->function_length();
- *has_duplicate_parameters = logger->has_duplicate_parameters();
- *expected_property_count = logger->properties();
SkipFunctionLiterals(logger->num_inner_functions());
if (!is_inner_function && produce_cached_parse_data()) {
DCHECK(log_);
log_->LogFunction(
function_scope->start_position(), function_scope->end_position(),
- *num_parameters, *function_length, *has_duplicate_parameters,
- *expected_property_count, language_mode(),
+ *num_parameters, *function_length, language_mode(),
function_scope->uses_super_property(), function_scope->calls_eval(),
logger->num_inner_functions());
}
@@ -2924,10 +2993,10 @@ Block* Parser::BuildParameterInitializationBlock(
const ParserFormalParameters& parameters, bool* ok) {
DCHECK(!parameters.is_simple);
DCHECK(scope()->is_function_scope());
+ DCHECK_EQ(scope(), parameters.scope);
Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition);
int index = 0;
for (auto parameter : parameters.params) {
- if (parameter->is_nondestructuring_rest()) break;
DeclarationDescriptor descriptor;
descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
descriptor.scope = scope();
@@ -2991,6 +3060,13 @@ Block* Parser::BuildParameterInitializationBlock(
return init_block;
}
+Scope* Parser::NewHiddenCatchScopeWithParent(Scope* parent) {
+ Scope* catch_scope = NewScopeWithParent(parent, CATCH_SCOPE);
+ catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
+ catch_scope->set_is_hidden();
+ return catch_scope;
+}
+
Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
// .promise = %AsyncFunctionPromiseCreate();
// try {
@@ -3018,31 +3094,23 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
result->statements()->Add(set_promise, zone());
// catch (.catch) { return %RejectPromise(.promise, .catch), .promise }
- Scope* catch_scope = NewScope(CATCH_SCOPE);
- catch_scope->set_is_hidden();
- Variable* catch_variable =
- catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
- Block* catch_block = factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
+ Scope* catch_scope = NewHiddenCatchScopeWithParent(scope());
Expression* promise_reject = BuildRejectPromise(
- factory()->NewVariableProxy(catch_variable), kNoSourcePosition);
- ReturnStatement* return_promise_reject =
- factory()->NewReturnStatement(promise_reject, kNoSourcePosition);
- catch_block->statements()->Add(return_promise_reject, zone());
+ factory()->NewVariableProxy(catch_scope->catch_variable()),
+ kNoSourcePosition);
+ Block* catch_block = IgnoreCompletion(
+ factory()->NewReturnStatement(promise_reject, kNoSourcePosition));
TryStatement* try_catch_statement =
- factory()->NewTryCatchStatementForAsyncAwait(inner_block, catch_scope,
- catch_variable, catch_block,
- kNoSourcePosition);
+ factory()->NewTryCatchStatementForAsyncAwait(
+ inner_block, catch_scope, catch_block, kNoSourcePosition);
// There is no TryCatchFinally node, so wrap it in an outer try/finally
- Block* outer_try_block =
- factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
- outer_try_block->statements()->Add(try_catch_statement, zone());
+ Block* outer_try_block = IgnoreCompletion(try_catch_statement);
// finally { %AsyncFunctionPromiseRelease(.promise) }
- Block* finally_block =
- factory()->NewBlock(nullptr, 1, true, kNoSourcePosition);
+ Block* finally_block;
{
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
@@ -3050,7 +3118,7 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block) {
Context::ASYNC_FUNCTION_PROMISE_RELEASE_INDEX, args, kNoSourcePosition);
Statement* promise_release = factory()->NewExpressionStatement(
call_promise_release, kNoSourcePosition);
- finally_block->statements()->Add(promise_release, zone());
+ finally_block = IgnoreCompletion(promise_release);
}
Statement* try_finally_statement = factory()->NewTryFinallyStatement(
@@ -3115,6 +3183,15 @@ Variable* Parser::PromiseVariable() {
return promise;
}
+Variable* Parser::AsyncGeneratorAwaitVariable() {
+ Variable* result = function_state_->scope()->async_generator_await_var();
+ if (result == nullptr) {
+ result = function_state_->scope()->DeclareAsyncGeneratorAwaitVar(
+ ast_value_factory()->empty_string());
+ }
+ return result;
+}
+
Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
Assignment* assignment = BuildCreateJSGeneratorObject(pos, kind);
VariableProxy* generator =
@@ -3122,8 +3199,8 @@ Expression* Parser::BuildInitialYield(int pos, FunctionKind kind) {
// The position of the yield is important for reporting the exception
// caused by calling the .throw method on a generator suspended at the
// initial yield (i.e. right after generator instantiation).
- return factory()->NewYield(generator, assignment, scope()->start_position(),
- Yield::kOnExceptionThrow);
+ return BuildSuspend(generator, assignment, scope()->start_position(),
+ Suspend::kOnExceptionThrow, SuspendFlags::kYield);
}
ZoneList<Statement*>* Parser::ParseFunction(
@@ -3228,8 +3305,8 @@ void Parser::DeclareClassProperty(const AstRawString* class_name,
class_info->constructor = GetPropertyValue(property)->AsFunctionLiteral();
DCHECK_NOT_NULL(class_info->constructor);
class_info->constructor->set_raw_name(
- class_name != nullptr ? class_name
- : ast_value_factory()->empty_string());
+ class_name != nullptr ? ast_value_factory()->NewConsString(class_name)
+ : ast_value_factory()->empty_cons_string());
return;
}
@@ -3466,6 +3543,7 @@ void Parser::ParseOnBackground(ParseInfo* info) {
runtime_call_stats_));
stream_ptr = stream.get();
}
+ scanner_.Initialize(stream_ptr);
DCHECK(info->maybe_outer_scope_info().is_null());
DCHECK(original_scope_);
@@ -3478,10 +3556,14 @@ void Parser::ParseOnBackground(ParseInfo* info) {
// scopes) and set their end position after we know the script length.
if (info->is_toplevel()) {
fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
- scanner_.Initialize(stream_ptr);
result = DoParseProgram(info);
} else {
- result = DoParseFunction(info, info->function_name(), stream_ptr);
+ const AstRawString* function_name = info->function_name();
+ if (!function_name) {
+ // FIXME(wiktorg) solve fni in parse tasks
+ function_name = ast_value_factory()->empty_string();
+ }
+ result = DoParseFunction(info, function_name);
}
info->set_literal(result);
@@ -3830,11 +3912,20 @@ void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block,
}
Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
- // yield do {
- // tmp = <operand>;
- // %AsyncFunctionAwait(.generator_object, tmp, .promise);
- // .promise
- // }
+ // In an Async Function:
+ // yield do {
+ // tmp = <operand>;
+ // %AsyncFunctionAwait(.generator_object, tmp, .promise);
+ // .promise
+ // }
+ //
+ // In an Async Generator:
+ // yield do {
+ // tmp = <operand>;
+ // %AsyncGeneratorAwait(.generator_object, tmp)
+ // .await_result_var
+ // }
+ //
// The value of the expression is returned to the caller of the async
// function for the first yield statement; for this, .promise is the
// appropriate return value, being a Promise that will be fulfilled or
@@ -3849,6 +3940,10 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
// a break location, and the .promise needs to be read earlier so that it
// doesn't insert a false location.
// TODO(littledan): investigate why this ordering is needed in more detail.
+ //
+ // In the case of Async Generators, `.await_result_var` is not actually used
+ // for anything, but exists because of the current requirement that
+ // Do Expressions have a result variable.
Variable* generator_object_variable =
function_state_->generator_object_variable();
DCHECK_NOT_NULL(generator_object_variable);
@@ -3857,8 +3952,6 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
Block* do_block = factory()->NewBlock(nullptr, 2, false, nopos);
- Variable* promise = PromiseVariable();
-
// Wrap value evaluation to provide a break location.
Variable* temp_var = NewTemporary(ast_value_factory()->empty_string());
Expression* value_assignment = factory()->NewAssignment(
@@ -3867,30 +3960,51 @@ Expression* Parser::RewriteAwaitExpression(Expression* value, int await_pos) {
factory()->NewExpressionStatement(value_assignment, value->position()),
zone());
- ZoneList<Expression*>* async_function_await_args =
- new (zone()) ZoneList<Expression*>(3, zone());
Expression* generator_object =
factory()->NewVariableProxy(generator_object_variable);
- async_function_await_args->Add(generator_object, zone());
- async_function_await_args->Add(factory()->NewVariableProxy(temp_var), zone());
- async_function_await_args->Add(factory()->NewVariableProxy(promise), zone());
-
- // The parser emits calls to AsyncFunctionAwaitCaught, but the
- // AstNumberingVisitor will rewrite this to AsyncFunctionAwaitUncaught
- // if there is no local enclosing try/catch block.
- Expression* async_function_await =
- factory()->NewCallRuntime(Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX,
- async_function_await_args, nopos);
+
+ if (is_async_generator()) {
+ // AsyncGeneratorAwaitCaught will be rewritten to
+ // AsyncGeneratorAwaitUncaught by AstNumberingVisitor if there is no local
+ // enclosing try/catch block (not counting the one implicitly added in
+ // ParseAndRewriteGeneratorFunctionBody)
+ ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
+ args->Add(generator_object, zone());
+ args->Add(factory()->NewVariableProxy(temp_var), zone());
+
+ Expression* await = factory()->NewCallRuntime(
+ Context::ASYNC_GENERATOR_AWAIT_CAUGHT, args, nopos);
+ do_block->statements()->Add(
+ factory()->NewExpressionStatement(await, await_pos), zone());
+
+ // Wrap await to provide a break location between value evaluation and
+ // yield.
+ Expression* do_expr = factory()->NewDoExpression(
+ do_block, AsyncGeneratorAwaitVariable(), nopos);
+ return BuildSuspend(generator_object, do_expr, nopos,
+ Suspend::kOnExceptionRethrow, SuspendFlags::kAwait);
+ }
+
+ // The parser emits calls to AsyncFunctionAwaitCaught or but the
+ // AstNumberingVisitor will rewrite this to AsyncFunctionAwaitUncaught or if
+ // there is no local enclosing try/catch block.
+ ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(3, zone());
+ args->Add(generator_object, zone());
+ args->Add(factory()->NewVariableProxy(temp_var), zone());
+ args->Add(factory()->NewVariableProxy(PromiseVariable()), zone());
+
+ Expression* await = factory()->NewCallRuntime(
+ Context::ASYNC_FUNCTION_AWAIT_CAUGHT_INDEX, args, nopos);
do_block->statements()->Add(
- factory()->NewExpressionStatement(async_function_await, await_pos),
- zone());
+ factory()->NewExpressionStatement(await, await_pos), zone());
// Wrap await to provide a break location between value evaluation and yield.
- Expression* do_expr = factory()->NewDoExpression(do_block, promise, nopos);
+ Expression* do_expr =
+ factory()->NewDoExpression(do_block, PromiseVariable(), nopos);
- generator_object = factory()->NewVariableProxy(generator_object_variable);
- return factory()->NewYield(generator_object, do_expr, nopos,
- Yield::kOnExceptionRethrow);
+ return factory()->NewSuspend(generator_object, do_expr, nopos,
+ Suspend::kOnExceptionRethrow,
+ SuspendFlags::kAwait);
}
class NonPatternRewriter : public AstExpressionRewriter {
@@ -4157,10 +4271,11 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name) {
if (!value->IsAnonymousFunctionDefinition()) return;
auto function = value->AsFunctionLiteral();
if (function != nullptr) {
- function->set_raw_name(name);
+ function->set_raw_name(ast_value_factory()->NewConsString(name));
} else {
DCHECK(value->IsDoExpression());
- value->AsDoExpression()->represented_function()->set_raw_name(name);
+ value->AsDoExpression()->represented_function()->set_raw_name(
+ ast_value_factory()->NewConsString(name));
}
}
@@ -4247,6 +4362,8 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name) {
Expression* Parser::RewriteYieldStar(Expression* generator,
Expression* iterable, int pos) {
const int nopos = kNoSourcePosition;
+ IteratorType type =
+ is_async_generator() ? IteratorType::kAsync : IteratorType::kNormal;
// Forward definition for break/continue statements.
WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
@@ -4289,8 +4406,7 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
Variable* var_iterator = NewTemporary(ast_value_factory()->empty_string());
Statement* get_iterator;
{
- Expression* iterator =
- factory()->NewGetIterator(iterable, IteratorType::kNormal, nopos);
+ Expression* iterator = factory()->NewGetIterator(iterable, type, nopos);
Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator);
Expression* assignment = factory()->NewAssignment(
Token::ASSIGN, iterator_proxy, iterator, nopos);
@@ -4309,6 +4425,9 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
auto args = new (zone()) ZoneList<Expression*>(1, zone());
args->Add(input_proxy, zone());
Expression* call = factory()->NewCall(next_property, args, nopos);
+ if (type == IteratorType::kAsync) {
+ call = RewriteAwaitExpression(call, nopos);
+ }
Expression* output_proxy = factory()->NewVariableProxy(var_output);
Expression* assignment =
factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
@@ -4372,8 +4491,7 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
Block* then = factory()->NewBlock(nullptr, 4 + 1, false, nopos);
BuildIteratorCloseForCompletion(
scope(), then->statements(), var_iterator,
- factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos),
- IteratorType::kNormal);
+ factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), type);
then->statements()->Add(throw_call, zone());
check_throw = factory()->NewIfStatement(
condition, then, factory()->NewEmptyStatement(nopos), nopos);
@@ -4388,6 +4506,9 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
args->Add(factory()->NewVariableProxy(var_input), zone());
Expression* call =
factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
+ if (type == IteratorType::kAsync) {
+ call = RewriteAwaitExpression(call, nopos);
+ }
Expression* assignment = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(var_output), call, nopos);
call_throw = factory()->NewExpressionStatement(assignment, nopos);
@@ -4446,8 +4567,9 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
Statement* yield_output;
{
Expression* output_proxy = factory()->NewVariableProxy(var_output);
- Yield* yield = factory()->NewYield(generator, output_proxy, nopos,
- Yield::kOnExceptionThrow);
+ Suspend* yield =
+ BuildSuspend(generator, output_proxy, nopos, Suspend::kOnExceptionThrow,
+ SuspendFlags::kYieldStar);
yield_output = factory()->NewExpressionStatement(yield, nopos);
}
@@ -4498,8 +4620,7 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
Expression* literal =
factory()->NewStringLiteral(ast_value_factory()->value_string(), nopos);
Expression* property = factory()->NewProperty(output_proxy, literal, nopos);
- Statement* return_value = factory()->NewReturnStatement(
- BuildIteratorResult(property, true), nopos);
+ Statement* return_value = BuildReturnStatement(property, nopos);
maybe_return_value = factory()->NewIfStatement(
condition, return_value, factory()->NewEmptyStatement(nopos), nopos);
@@ -4527,13 +4648,10 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
Block* catch_block = factory()->NewBlock(nullptr, 1, false, nopos);
catch_block->statements()->Add(set_mode_throw, zone());
- Scope* catch_scope = NewScope(CATCH_SCOPE);
- catch_scope->set_is_hidden();
- const AstRawString* name = ast_value_factory()->dot_catch_string();
- Variable* catch_variable = catch_scope->DeclareLocal(name, VAR);
+ Scope* catch_scope = NewHiddenCatchScopeWithParent(scope());
try_catch = factory()->NewTryCatchStatementForDesugaring(
- try_block, catch_scope, catch_variable, catch_block, nopos);
+ try_block, catch_scope, catch_block, nopos);
}
// try { ... } finally { ... }
@@ -4559,7 +4677,7 @@ Expression* Parser::RewriteYieldStar(Expression* generator,
case_next->Add(factory()->NewBreakStatement(switch_mode, nopos), zone());
auto case_return = new (zone()) ZoneList<Statement*>(5, zone());
- BuildIteratorClose(case_return, var_iterator, var_input, var_output);
+ BuildIteratorClose(case_return, var_iterator, var_input, var_output, type);
case_return->Add(factory()->NewBreakStatement(switch_mode, nopos), zone());
auto case_throw = new (zone()) ZoneList<Statement*>(5, zone());
@@ -4643,7 +4761,7 @@ Statement* Parser::CheckCallable(Variable* var, Expression* error, int pos) {
void Parser::BuildIteratorClose(ZoneList<Statement*>* statements,
Variable* iterator, Variable* input,
- Variable* var_output) {
+ Variable* var_output, IteratorType type) {
//
// This function adds four statements to [statements], corresponding to the
// following code:
@@ -4684,8 +4802,7 @@ void Parser::BuildIteratorClose(ZoneList<Statement*>* statements,
Expression* value = factory()->NewVariableProxy(input);
- Statement* return_input =
- factory()->NewReturnStatement(BuildIteratorResult(value, true), nopos);
+ Statement* return_input = BuildReturnStatement(value, nopos);
check_return = factory()->NewIfStatement(
condition, return_input, factory()->NewEmptyStatement(nopos), nopos);
@@ -4701,6 +4818,9 @@ void Parser::BuildIteratorClose(ZoneList<Statement*>* statements,
Expression* call =
factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos);
+ if (type == IteratorType::kAsync) {
+ call = RewriteAwaitExpression(call, nopos);
+ }
Expression* output_proxy = factory()->NewVariableProxy(var_output);
Expression* assignment =
factory()->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
@@ -4801,11 +4921,8 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
type);
DCHECK(block->statements()->length() == 2);
- maybe_close = factory()->NewBlock(nullptr, 1, true, nopos);
- maybe_close->statements()->Add(
- factory()->NewIfStatement(condition, block,
- factory()->NewEmptyStatement(nopos), nopos),
- zone());
+ maybe_close = IgnoreCompletion(factory()->NewIfStatement(
+ condition, block, factory()->NewEmptyStatement(nopos), nopos));
}
// try { #try_block }
@@ -4815,10 +4932,7 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
// }
Statement* try_catch;
{
- Scope* catch_scope = NewScopeWithParent(use_scope, CATCH_SCOPE);
- Variable* catch_variable =
- catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
- catch_scope->set_is_hidden();
+ Scope* catch_scope = NewHiddenCatchScopeWithParent(use_scope);
Statement* rethrow;
// We use %ReThrow rather than the ordinary throw because we want to
@@ -4827,7 +4941,8 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
// message), rather than a TryCatchStatement.
{
auto args = new (zone()) ZoneList<Expression*>(1, zone());
- args->Add(factory()->NewVariableProxy(catch_variable), zone());
+ args->Add(factory()->NewVariableProxy(catch_scope->catch_variable()),
+ zone());
rethrow = factory()->NewExpressionStatement(
factory()->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos);
}
@@ -4837,7 +4952,7 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion,
catch_block->statements()->Add(rethrow, zone());
try_catch = factory()->NewTryCatchStatementForReThrow(
- iterator_use, catch_scope, catch_variable, catch_block, nopos);
+ iterator_use, catch_scope, catch_block, nopos);
}
// try { #try_catch } finally { #maybe_close }
@@ -4933,14 +5048,9 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope,
zone());
Block* catch_block = factory()->NewBlock(nullptr, 0, false, nopos);
-
- Scope* catch_scope = NewScopeWithParent(scope, CATCH_SCOPE);
- Variable* catch_variable =
- catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR);
- catch_scope->set_is_hidden();
-
- try_call_return = factory()->NewTryCatchStatement(
- try_block, catch_scope, catch_variable, catch_block, nopos);
+ Scope* catch_scope = NewHiddenCatchScopeWithParent(scope);
+ try_call_return = factory()->NewTryCatchStatement(try_block, catch_scope,
+ catch_block, nopos);
}
// let output = %_Call(iteratorReturn, iterator);