diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-06-06 10:28:14 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-06-07 10:33:31 +0200 |
commit | 3dc8c3bed4cf3a77607edbb0b015e33f8b60fc09 (patch) | |
tree | 9dee56e142638b34f1eccbd0ad88c3bce5377c29 /deps/v8/src/parsing/parser.cc | |
parent | 91a1bbe3055a660194ca4d403795aa0c03e9d056 (diff) | |
download | android-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.cc | 508 |
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); |