diff options
author | Michaël Zasso <targos@protonmail.com> | 2017-05-02 10:50:00 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2017-05-06 20:02:35 +0200 |
commit | 60d1aac8d225e844e68ae48e8f3d58802e635fbe (patch) | |
tree | 922f347dd054db18d88666fad7181e5a777f4022 /deps/v8/src/parsing/parser.cc | |
parent | 73d9c0f903ae371cd5011af64c3a6f69a1bda978 (diff) | |
download | android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.gz android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.tar.bz2 android-node-v8-60d1aac8d225e844e68ae48e8f3d58802e635fbe.zip |
deps: update V8 to 5.8.283.38
PR-URL: https://github.com/nodejs/node/pull/12784
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com>
Diffstat (limited to 'deps/v8/src/parsing/parser.cc')
-rw-r--r-- | deps/v8/src/parsing/parser.cc | 629 |
1 files changed, 296 insertions, 333 deletions
diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 685fe1d6ea..cc6b6a260b 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -9,7 +9,6 @@ #include "src/api.h" #include "src/ast/ast-expression-rewriter.h" #include "src/ast/ast-function-literal-id-reindexer.h" -#include "src/ast/ast-literal-reindexer.h" #include "src/ast/ast-traversal-visitor.h" #include "src/ast/ast.h" #include "src/bailout-reason.h" @@ -168,7 +167,6 @@ void Parser::SetCachedData(ParseInfo* info) { FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, bool call_super, int pos, int end_pos) { - int materialized_literal_count = -1; int expected_property_count = -1; const int parameter_count = 0; if (name == nullptr) name = ast_value_factory()->empty_string(); @@ -183,8 +181,7 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, ZoneList<Statement*>* body = NULL; { - FunctionState function_state(&function_state_, &scope_state_, - function_scope); + FunctionState function_state(&function_state_, &scope_, function_scope); body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone()); if (call_super) { @@ -208,14 +205,12 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name, body->Add(factory()->NewReturnStatement(call, pos), zone()); } - materialized_literal_count = function_state.materialized_literal_count(); expected_property_count = function_state.expected_property_count(); } FunctionLiteral* function_literal = factory()->NewFunctionLiteral( - name, function_scope, body, materialized_literal_count, - expected_property_count, parameter_count, parameter_count, - FunctionLiteral::kNoDuplicateParameters, + name, function_scope, body, expected_property_count, parameter_count, + parameter_count, FunctionLiteral::kNoDuplicateParameters, FunctionLiteral::kAnonymousExpression, default_eager_compile_hint(), pos, true, GetNextFunctionLiteralId()); @@ -389,8 +384,8 @@ Expression* Parser::NewSuperPropertyReference(int pos) { // this_function[home_object_symbol] VariableProxy* this_function_proxy = NewUnresolved(ast_value_factory()->this_function_string(), pos); - Expression* home_object_symbol_literal = - factory()->NewSymbolLiteral("home_object_symbol", kNoSourcePosition); + Expression* home_object_symbol_literal = factory()->NewSymbolLiteral( + AstSymbol::kHomeObjectSymbol, kNoSourcePosition); Expression* home_object = factory()->NewProperty( this_function_proxy, home_object_symbol_literal, pos); return factory()->NewSuperPropertyReference( @@ -519,7 +514,9 @@ Parser::Parser(ParseInfo* info) cached_parse_data_(nullptr), total_preparse_skipped_(0), temp_zoned_(false), - log_(nullptr) { + log_(nullptr), + preparsed_scope_data_(info->preparsed_scope_data()), + parameters_end_pos_(info->parameters_end_pos()) { // Even though we were passed ParseInfo, we should not store it in // Parser - this makes sure that Isolate is not accidentally accessed via // ParseInfo during background parsing. @@ -552,7 +549,10 @@ Parser::Parser(ParseInfo* info) set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators); set_allow_harmony_trailing_commas(FLAG_harmony_trailing_commas); set_allow_harmony_class_fields(FLAG_harmony_class_fields); - set_allow_harmony_object_spread(FLAG_harmony_object_spread); + set_allow_harmony_object_rest_spread(FLAG_harmony_object_rest_spread); + set_allow_harmony_dynamic_import(FLAG_harmony_dynamic_import); + set_allow_harmony_async_iteration(FLAG_harmony_async_iteration); + set_allow_harmony_template_escapes(FLAG_harmony_template_escapes); for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; ++feature) { use_counts_[feature] = 0; @@ -657,7 +657,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { // Note that this function can be called from the main thread or from a // background thread. We should not access anything Isolate / heap dependent // via ParseInfo, and also not pass it forward. - DCHECK_NULL(scope_state_); + DCHECK_NULL(scope_); DCHECK_NULL(target_stack_); ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); @@ -681,7 +681,7 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { scope->set_start_position(0); - FunctionState function_state(&function_state_, &scope_state_, scope); + FunctionState function_state(&function_state_, &scope_, scope); ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone()); bool ok = true; @@ -747,8 +747,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) { RewriteDestructuringAssignments(); int parameter_count = parsing_module_ ? 1 : 0; result = factory()->NewScriptOrEvalFunctionLiteral( - scope, body, function_state.materialized_literal_count(), - function_state.expected_property_count(), parameter_count); + scope, body, function_state.expected_property_count(), + parameter_count); } } @@ -823,7 +823,7 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, const AstRawString* raw_name, Utf16CharacterStream* source) { scanner_.Initialize(source); - DCHECK_NULL(scope_state_); + DCHECK_NULL(scope_); DCHECK_NULL(target_stack_); DCHECK(ast_value_factory()); @@ -844,9 +844,8 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, Scope* outer = original_scope_; DeclarationScope* outer_function = outer->GetClosureScope(); DCHECK(outer); - FunctionState function_state(&function_state_, &scope_state_, - outer_function); - BlockState block_state(&scope_state_, outer); + FunctionState function_state(&function_state_, &scope_, outer_function); + BlockState block_state(&scope_, outer); DCHECK(is_sloppy(outer->language_mode()) || is_strict(info->language_mode())); FunctionLiteral::FunctionType function_type = ComputeFunctionType(info); @@ -881,12 +880,14 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, scope->set_start_position(info->start_position()); ExpressionClassifier formals_classifier(this); 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 // scope for formal parameter parsing. - BlockState block_state(&scope_state_, scope); + BlockState block_state(&scope_, scope); if (Check(Token::LPAREN)) { // '(' StrictFormalParameters ')' ParseFormalParameterList(&formals, &ok); @@ -917,7 +918,8 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should // not be observable, or else the preparser would have failed. - Expression* expression = ParseArrowFunctionLiteral(true, formals, &ok); + Expression* expression = + ParseArrowFunctionLiteral(true, formals, rewritable_length, &ok); if (ok) { // Scanning must end at the same position that was recorded // previously. If not, parsing has been interrupted due to a stack @@ -930,6 +932,10 @@ FunctionLiteral* Parser::DoParseFunction(ParseInfo* info, // must produce a FunctionLiteral. DCHECK(expression->IsFunctionLiteral()); result = expression->AsFunctionLiteral(); + // Rewrite destructuring assignments in the parameters. (The ones + // inside the function body are rewritten by + // ParseArrowFunctionLiteral.) + RewriteDestructuringAssignments(); } else { ok = false; } @@ -962,15 +968,21 @@ Statement* Parser::ParseModuleItem(bool* ok) { // ExportDeclaration // StatementListItem - switch (peek()) { - case Token::IMPORT: - ParseImportDeclaration(CHECK_OK); - return factory()->NewEmptyStatement(kNoSourcePosition); - case Token::EXPORT: - return ParseExportDeclaration(ok); - default: - return ParseStatementListItem(ok); + Token::Value next = peek(); + + if (next == Token::EXPORT) { + return ParseExportDeclaration(ok); + } + + // We must be careful not to parse a dynamic import expression as an import + // declaration. + if (next == Token::IMPORT && + (!allow_harmony_dynamic_import() || PeekAhead() != Token::LPAREN)) { + ParseImportDeclaration(CHECK_OK); + return factory()->NewEmptyStatement(kNoSourcePosition); } + + return ParseStatementListItem(ok); } @@ -1474,12 +1486,12 @@ void Parser::DeclareAndInitializeVariables( Statement* Parser::DeclareFunction(const AstRawString* variable_name, FunctionLiteral* function, VariableMode mode, - int pos, bool is_generator, bool is_async, - bool is_sloppy_block_function, + int pos, bool is_sloppy_block_function, ZoneList<const AstRawString*>* names, bool* ok) { VariableProxy* proxy = factory()->NewVariableProxy(variable_name, NORMAL_VARIABLE); + Declaration* declaration = factory()->NewFunctionDeclaration(proxy, function, scope(), pos); Declare(declaration, DeclarationDescriptor::NORMAL, mode, kCreatedInitialized, @@ -1488,8 +1500,8 @@ Statement* Parser::DeclareFunction(const AstRawString* variable_name, if (is_sloppy_block_function) { SloppyBlockFunctionStatement* statement = factory()->NewSloppyBlockFunctionStatement(); - DeclarationScope* target_scope = GetDeclarationScope(); - target_scope->DeclareSloppyBlockFunction(variable_name, scope(), statement); + GetDeclarationScope()->DeclareSloppyBlockFunction(variable_name, scope(), + statement); return statement; } return factory()->NewEmptyStatement(kNoSourcePosition); @@ -1676,7 +1688,6 @@ void Parser::RewriteCatchPattern(CatchInfo* catch_info, bool* ok) { DeclarationDescriptor descriptor; descriptor.declaration_kind = DeclarationDescriptor::NORMAL; descriptor.scope = scope(); - descriptor.hoist_scope = nullptr; descriptor.mode = LET; descriptor.declaration_pos = catch_info->pattern->position(); descriptor.initialization_pos = catch_info->pattern->position(); @@ -1756,10 +1767,80 @@ Statement* Parser::RewriteTryStatement(Block* try_block, Block* catch_block, } } -// !%_IsJSReceiver(result = iterator.next()) && -// %ThrowIteratorResultNotAnObject(result) +void Parser::ParseAndRewriteGeneratorFunctionBody(int pos, FunctionKind kind, + ZoneList<Statement*>* body, + bool* ok) { + // We produce: + // + // try { InitialYield; ...body...; return {value: undefined, done: true} } + // finally { %_GeneratorClose(generator) } + // + // - InitialYield yields the actual generator object. + // - Any return statement inside the body will have its argument wrapped + // in a "done" iterator result object. + // - If the generator terminates for whatever reason, we must close it. + // Hence the finally clause. + + Block* try_block = factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); + Expression* initial_yield = BuildInitialYield(pos, kind); + try_block->statements()->Add( + factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), + zone()); + ParseStatementList(try_block->statements(), Token::RBRACE, ok); + if (!*ok) return; + + Statement* final_return = factory()->NewReturnStatement( + BuildIteratorResult(nullptr, true), kNoSourcePosition); + try_block->statements()->Add(final_return, zone()); + + Block* finally_block = + factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); + ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); + VariableProxy* call_proxy = + factory()->NewVariableProxy(function_state_->generator_object_variable()); + args->Add(call_proxy, zone()); + Expression* call = factory()->NewCallRuntime(Runtime::kInlineGeneratorClose, + args, kNoSourcePosition); + finally_block->statements()->Add( + factory()->NewExpressionStatement(call, kNoSourcePosition), zone()); + + body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, + kNoSourcePosition), + zone()); +} + +void Parser::CreateFunctionNameAssignment( + const AstRawString* function_name, int pos, + FunctionLiteral::FunctionType function_type, + DeclarationScope* function_scope, ZoneList<Statement*>* result, int index) { + if (function_type == FunctionLiteral::kNamedExpression) { + StatementT statement = factory()->NewEmptyStatement(kNoSourcePosition); + if (function_scope->LookupLocal(function_name) == nullptr) { + // Now that we know the language mode, we can create the const assignment + // in the previously reserved spot. + DCHECK_EQ(function_scope, scope()); + Variable* fvar = function_scope->DeclareFunctionVar(function_name); + VariableProxy* fproxy = factory()->NewVariableProxy(fvar); + statement = factory()->NewExpressionStatement( + factory()->NewAssignment(Token::INIT, fproxy, + factory()->NewThisFunction(pos), + kNoSourcePosition), + kNoSourcePosition); + } + result->Set(index, statement); + } +} + +// [if (IteratorType == kNormal)] +// !%_IsJSReceiver(result = iterator.next()) && +// %ThrowIteratorResultNotAnObject(result) +// [else if (IteratorType == kAsync)] +// !%_IsJSReceiver(result = Await(iterator.next())) && +// %ThrowIteratorResultNotAnObject(result) +// [endif] Expression* Parser::BuildIteratorNextResult(Expression* iterator, - Variable* result, int pos) { + Variable* result, IteratorType type, + int pos) { Expression* next_literal = factory()->NewStringLiteral( ast_value_factory()->next_string(), kNoSourcePosition); Expression* next_property = @@ -1768,6 +1849,9 @@ Expression* Parser::BuildIteratorNextResult(Expression* iterator, new (zone()) ZoneList<Expression*>(0, zone()); Expression* next_call = factory()->NewCall(next_property, next_arguments, pos); + if (type == IteratorType::kAsync) { + next_call = RewriteAwaitExpression(next_call, pos); + } Expression* result_proxy = factory()->NewVariableProxy(result); Expression* left = factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos); @@ -1802,7 +1886,7 @@ Statement* Parser::InitializeForEachStatement(ForEachStatement* stmt, if (for_of != NULL) { const bool finalize = true; return InitializeForOfStatement(for_of, each, subject, body, finalize, - each_keyword_pos); + IteratorType::kNormal, each_keyword_pos); } else { if (each->IsArrayLiteral() || each->IsObjectLiteral()) { Variable* temp = NewTemporary(ast_value_factory()->empty_string()); @@ -1896,14 +1980,13 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info, bool is_for_var_of = for_info->mode == ForEachStatement::ITERATE && for_info->parsing_result.descriptor.mode == VariableMode::VAR; + bool collect_names = + IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) || + is_for_var_of; PatternRewriter::DeclareAndInitializeVariables( this, each_initialization_block, &descriptor, &decl, - (IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) || - is_for_var_of) - ? &for_info->bound_names - : nullptr, - CHECK_OK_VOID); + collect_names ? &for_info->bound_names : nullptr, CHECK_OK_VOID); // Annex B.3.5 prohibits the form // `try {} catch(e) { for (var e of {}); }` @@ -1956,17 +2039,14 @@ Block* Parser::CreateForEachStatementTDZ(Block* init_block, return init_block; } -Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of, - Expression* each, - Expression* iterable, - Statement* body, bool finalize, - int next_result_pos) { +Statement* Parser::InitializeForOfStatement( + ForOfStatement* for_of, Expression* each, Expression* iterable, + Statement* body, bool finalize, IteratorType type, int next_result_pos) { // Create the auxiliary expressions needed for iterating over the iterable, // and initialize the given ForOfStatement with them. // If finalize is true, also instrument the loop with code that performs the // proper ES6 iterator finalization. In that case, the result is not // immediately a ForOfStatement. - const int nopos = kNoSourcePosition; auto avfactory = ast_value_factory(); @@ -1974,22 +2054,27 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of, Variable* result = NewTemporary(avfactory->dot_result_string()); Variable* completion = NewTemporary(avfactory->empty_string()); - // iterator = GetIterator(iterable) + // iterator = GetIterator(iterable, type) Expression* assign_iterator; { assign_iterator = factory()->NewAssignment( Token::ASSIGN, factory()->NewVariableProxy(iterator), - factory()->NewGetIterator(iterable, iterable->position()), + factory()->NewGetIterator(iterable, type, iterable->position()), iterable->position()); } - // !%_IsJSReceiver(result = iterator.next()) && - // %ThrowIteratorResultNotAnObject(result) + // [if (IteratorType == kNormal)] + // !%_IsJSReceiver(result = iterator.next()) && + // %ThrowIteratorResultNotAnObject(result) + // [else if (IteratorType == kAsync)] + // !%_IsJSReceiver(result = Await(iterator.next())) && + // %ThrowIteratorResultNotAnObject(result) + // [endif] Expression* next_result; { Expression* iterator_proxy = factory()->NewVariableProxy(iterator); next_result = - BuildIteratorNextResult(iterator_proxy, result, next_result_pos); + BuildIteratorNextResult(iterator_proxy, result, type, next_result_pos); } // result.done @@ -2077,7 +2162,8 @@ Statement* Parser::InitializeForOfStatement(ForOfStatement* for_of, for_of->Initialize(body, iterator, assign_iterator, next_result, result_done, assign_each); - return finalize ? FinalizeForOfStatement(for_of, completion, nopos) : for_of; + return finalize ? FinalizeForOfStatement(for_of, completion, type, nopos) + : for_of; } Statement* Parser::DesugarLexicalBindingsInForStatement( @@ -2176,7 +2262,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( Block* inner_block = factory()->NewBlock(NULL, 3, false, kNoSourcePosition); { - BlockState block_state(&scope_state_, inner_scope); + BlockState block_state(&scope_, inner_scope); Block* ignore_completion_block = factory()->NewBlock( nullptr, for_info.bound_names.length() + 3, true, kNoSourcePosition); @@ -2312,7 +2398,6 @@ Statement* Parser::DesugarLexicalBindingsInForStatement( inner_block->statements()->Add(ignore_completion_block, zone()); } - inner_scope->set_end_position(scanner()->location().end_pos); inner_block->set_scope(inner_scope); } @@ -2370,7 +2455,8 @@ void Parser::AddArrowFunctionFormalParameters( expr = assignment->target(); } - AddFormalParameter(parameters, expr, initializer, end_pos, is_rest); + AddFormalParameter(parameters, expr, initializer, + end_pos, is_rest); } void Parser::DeclareArrowFunctionFormalParameters( @@ -2401,19 +2487,6 @@ void Parser::DeclareArrowFunctionFormalParameters( DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters()); } -void Parser::ReindexLiterals(const ParserFormalParameters& parameters) { - if (function_state_->materialized_literal_count() > 0) { - AstLiteralReindexer reindexer; - - for (auto p : parameters.params) { - if (p->pattern != nullptr) reindexer.Reindex(p->pattern); - if (p->initializer != nullptr) reindexer.Reindex(p->initializer); - } - - DCHECK(reindexer.count() <= function_state_->materialized_literal_count()); - } -} - void Parser::PrepareGeneratorVariables() { // For generators, allocating variables in contexts is currently a win because // it minimizes the work needed to suspend and resume an activation. The @@ -2542,7 +2615,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral( use_temp_zone && FLAG_lazy_inner_functions && !is_lazy_top_level_function; ZoneList<Statement*>* body = nullptr; - int materialized_literal_count = -1; int expected_property_count = -1; bool should_be_used_once_hint = false; int num_parameters = -1; @@ -2587,11 +2659,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral( if (is_lazy_top_level_function || is_lazy_inner_function) { Scanner::BookmarkScope bookmark(scanner()); bookmark.Set(); - LazyParsingResult result = - SkipFunction(kind, scope, &num_parameters, &function_length, - &has_duplicate_parameters, &materialized_literal_count, - &expected_property_count, is_lazy_inner_function, - is_lazy_top_level_function, CHECK_OK); + 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) { DCHECK(is_lazy_top_level_function); @@ -2611,10 +2682,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral( } if (!is_lazy_top_level_function && !is_lazy_inner_function) { - body = ParseFunction( - function_name, pos, kind, function_type, scope, &num_parameters, - &function_length, &has_duplicate_parameters, - &materialized_literal_count, &expected_property_count, CHECK_OK); + body = ParseFunction(function_name, pos, kind, function_type, scope, + &num_parameters, &function_length, + &has_duplicate_parameters, &expected_property_count, + CHECK_OK); } DCHECK(use_temp_zone || !is_lazy_top_level_function); @@ -2622,7 +2693,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // If the preconditions are correct the function body should never be // accessed, but do this anyway for better behaviour if they're wrong. body = nullptr; - scope->AnalyzePartially(&previous_zone_ast_node_factory); + scope->AnalyzePartially(&previous_zone_ast_node_factory, + preparsed_scope_data_); } DCHECK_IMPLIES(use_temp_zone, temp_zoned_); @@ -2669,10 +2741,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral( // Note that the FunctionLiteral needs to be created in the main Zone again. FunctionLiteral* function_literal = factory()->NewFunctionLiteral( - function_name, scope, body, materialized_literal_count, - expected_property_count, num_parameters, function_length, - duplicate_parameters, function_type, eager_compile_hint, pos, true, - function_literal_id); + function_name, scope, body, expected_property_count, num_parameters, + function_length, duplicate_parameters, function_type, eager_compile_hint, + pos, true, function_literal_id); function_literal->set_function_token_position(function_token_pos); if (should_be_used_once_hint) function_literal->set_should_be_used_once_hint(); @@ -2687,9 +2758,10 @@ FunctionLiteral* Parser::ParseFunctionLiteral( Parser::LazyParsingResult Parser::SkipFunction( FunctionKind kind, DeclarationScope* function_scope, int* num_parameters, int* function_length, bool* has_duplicate_parameters, - int* materialized_literal_count, int* expected_property_count, - bool is_inner_function, bool may_abort, bool* ok) { + int* expected_property_count, 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_); DCHECK_IMPLIES(IsArrowFunction(kind), @@ -2714,7 +2786,6 @@ Parser::LazyParsingResult Parser::SkipFunction( *num_parameters = entry.num_parameters(); *function_length = entry.function_length(); *has_duplicate_parameters = entry.has_duplicate_parameters(); - *materialized_literal_count = entry.literal_count(); *expected_property_count = entry.property_count(); SetLanguageMode(function_scope, entry.language_mode()); if (entry.uses_super_property()) @@ -2740,7 +2811,9 @@ Parser::LazyParsingResult Parser::SkipFunction( SET_ALLOW(harmony_function_sent); SET_ALLOW(harmony_trailing_commas); SET_ALLOW(harmony_class_fields); - SET_ALLOW(harmony_object_spread); + 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 @@ -2771,7 +2844,6 @@ Parser::LazyParsingResult Parser::SkipFunction( *num_parameters = logger->num_parameters(); *function_length = logger->function_length(); *has_duplicate_parameters = logger->has_duplicate_parameters(); - *materialized_literal_count = logger->literals(); *expected_property_count = logger->properties(); SkipFunctionLiterals(logger->num_inner_functions()); if (!is_inner_function && produce_cached_parse_data()) { @@ -2779,7 +2851,7 @@ Parser::LazyParsingResult Parser::SkipFunction( log_->LogFunction( function_scope->start_position(), function_scope->end_position(), *num_parameters, *function_length, *has_duplicate_parameters, - *materialized_literal_count, *expected_property_count, language_mode(), + *expected_property_count, language_mode(), function_scope->uses_super_property(), function_scope->calls_eval(), logger->num_inner_functions()); } @@ -2855,11 +2927,10 @@ Block* Parser::BuildParameterInitializationBlock( Block* init_block = factory()->NewBlock(NULL, 1, true, kNoSourcePosition); int index = 0; for (auto parameter : parameters.params) { - if (parameter->is_rest && parameter->pattern->IsVariableProxy()) break; + if (parameter->is_nondestructuring_rest()) break; DeclarationDescriptor descriptor; descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; descriptor.scope = scope(); - descriptor.hoist_scope = nullptr; descriptor.mode = LET; descriptor.declaration_pos = parameter->pattern->position(); // The position that will be used by the AssignmentExpression @@ -2894,7 +2965,6 @@ Block* Parser::BuildParameterInitializationBlock( param_scope->RecordEvalCall(); param_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); param_block->set_scope(param_scope); - descriptor.hoist_scope = scope(); // Pass the appropriate scope in so that PatternRewriter can appropriately // rewrite inner initializers of the pattern to param_scope descriptor.scope = param_scope; @@ -2903,14 +2973,14 @@ Block* Parser::BuildParameterInitializationBlock( param_scope); } - BlockState block_state(&scope_state_, param_scope); + BlockState block_state(&scope_, param_scope); DeclarationParsingResult::Declaration decl( parameter->pattern, parameter->initializer_end_position, initial_value); PatternRewriter::DeclareAndInitializeVariables( this, param_block, &descriptor, &decl, nullptr, CHECK_OK); if (param_block != init_block) { - param_scope = block_state.FinalizedBlockScope(); + param_scope = param_scope->FinalizeBlockScope(); if (param_scope != nullptr) { CheckConflictingVarDeclarations(param_scope, CHECK_OK); } @@ -2921,7 +2991,7 @@ Block* Parser::BuildParameterInitializationBlock( return init_block; } -Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) { +Block* Parser::BuildRejectPromiseOnException(Block* inner_block) { // .promise = %AsyncFunctionPromiseCreate(); // try { // <inner_block> @@ -2940,7 +3010,7 @@ Block* Parser::BuildRejectPromiseOnException(Block* inner_block, bool* ok) { Context::ASYNC_FUNCTION_PROMISE_CREATE_INDEX, new (zone()) ZoneList<Expression*>(0, zone()), kNoSourcePosition); Assignment* assign_promise = factory()->NewAssignment( - Token::INIT, factory()->NewVariableProxy(PromiseVariable()), + Token::ASSIGN, factory()->NewVariableProxy(PromiseVariable()), create_promise, kNoSourcePosition); set_promise = factory()->NewExpressionStatement(assign_promise, kNoSourcePosition); @@ -3019,15 +3089,15 @@ Expression* Parser::BuildResolvePromise(Expression* value, int pos) { } Expression* Parser::BuildRejectPromise(Expression* value, int pos) { - // %RejectPromiseNoDebugEvent(.promise, value, true), .promise - // The NoDebugEvent variant disables the additional debug event for the - // rejection since a debug event already happened for the exception that got - // us here. - ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone()); + // %promise_internal_reject(.promise, value, false), .promise + // Disables the additional debug event for the rejection since a debug event + // already happened for the exception that got us here. + ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(3, zone()); args->Add(factory()->NewVariableProxy(PromiseVariable()), zone()); args->Add(value, zone()); + args->Add(factory()->NewBooleanLiteral(false, pos), zone()); Expression* call_runtime = factory()->NewCallRuntime( - Context::REJECT_PROMISE_NO_DEBUG_EVENT_INDEX, args, pos); + Context::PROMISE_INTERNAL_REJECT_INDEX, args, pos); return factory()->NewBinaryOperation( Token::COMMA, call_runtime, factory()->NewVariableProxy(PromiseVariable()), pos); @@ -3060,19 +3130,44 @@ ZoneList<Statement*>* Parser::ParseFunction( const AstRawString* function_name, int pos, FunctionKind kind, FunctionLiteral::FunctionType function_type, DeclarationScope* function_scope, int* num_parameters, int* function_length, - bool* has_duplicate_parameters, int* materialized_literal_count, - int* expected_property_count, bool* ok) { + bool* has_duplicate_parameters, int* expected_property_count, bool* ok) { ParsingModeScope mode(this, allow_lazy_ ? PARSE_LAZILY : PARSE_EAGERLY); - FunctionState function_state(&function_state_, &scope_state_, function_scope); + FunctionState function_state(&function_state_, &scope_, function_scope); DuplicateFinder duplicate_finder; ExpressionClassifier formals_classifier(this, &duplicate_finder); if (IsResumableFunction(kind)) PrepareGeneratorVariables(); + int expected_parameters_end_pos = parameters_end_pos_; + if (expected_parameters_end_pos != kNoSourcePosition) { + // This is the first function encountered in a CreateDynamicFunction eval. + parameters_end_pos_ = kNoSourcePosition; + // The function name should have been ignored, giving us the empty string + // here. + DCHECK_EQ(function_name, ast_value_factory()->empty_string()); + } + ParserFormalParameters formals(function_scope); ParseFormalParameterList(&formals, CHECK_OK); + if (expected_parameters_end_pos != kNoSourcePosition) { + // Check for '(' or ')' shenanigans in the parameter string for dynamic + // functions. + int position = peek_position(); + if (position < expected_parameters_end_pos) { + ReportMessageAt(Scanner::Location(position, position + 1), + MessageTemplate::kArgStringTerminatesParametersEarly); + *ok = false; + return nullptr; + } else if (position > expected_parameters_end_pos) { + ReportMessageAt(Scanner::Location(expected_parameters_end_pos - 2, + expected_parameters_end_pos), + MessageTemplate::kUnexpectedEndOfArgString); + *ok = false; + return nullptr; + } + } Expect(Token::RPAREN, CHECK_OK); int formals_end_position = scanner()->location().end_pos; *num_parameters = formals.num_parameters(); @@ -3083,8 +3178,8 @@ ZoneList<Statement*>* Parser::ParseFunction( CHECK_OK); Expect(Token::LBRACE, CHECK_OK); - ZoneList<Statement*>* body = ParseEagerFunctionBody( - function_name, pos, formals, kind, function_type, ok); + ZoneList<Statement*>* body = new (zone()) ZoneList<Statement*>(8, zone()); + ParseFunctionBody(body, function_name, pos, formals, kind, function_type, ok); // Validate parameter names. We can do this only after parsing the function, // since the function can declare itself strict. @@ -3099,167 +3194,11 @@ ZoneList<Statement*>* Parser::ParseFunction( *has_duplicate_parameters = !classifier()->is_valid_formal_parameter_list_without_duplicates(); - *materialized_literal_count = function_state.materialized_literal_count(); *expected_property_count = function_state.expected_property_count(); return body; } -ZoneList<Statement*>* Parser::ParseEagerFunctionBody( - const AstRawString* function_name, int pos, - const ParserFormalParameters& parameters, FunctionKind kind, - FunctionLiteral::FunctionType function_type, bool* ok) { - ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone()); - - static const int kFunctionNameAssignmentIndex = 0; - if (function_type == FunctionLiteral::kNamedExpression) { - DCHECK(function_name != NULL); - // If we have a named function expression, we add a local variable - // declaration to the body of the function with the name of the - // function and let it refer to the function itself (closure). - // Not having parsed the function body, the language mode may still change, - // so we reserve a spot and create the actual const assignment later. - DCHECK_EQ(kFunctionNameAssignmentIndex, result->length()); - result->Add(NULL, zone()); - } - - ZoneList<Statement*>* body = result; - DeclarationScope* function_scope = scope()->AsDeclarationScope(); - DeclarationScope* inner_scope = function_scope; - Block* inner_block = nullptr; - if (!parameters.is_simple) { - inner_scope = NewVarblockScope(); - inner_scope->set_start_position(scanner()->location().beg_pos); - inner_block = factory()->NewBlock(NULL, 8, true, kNoSourcePosition); - inner_block->set_scope(inner_scope); - body = inner_block->statements(); - } - - { - BlockState block_state(&scope_state_, inner_scope); - - if (IsGeneratorFunction(kind)) { - // We produce: - // - // try { InitialYield; ...body...; return {value: undefined, done: true} } - // finally { %_GeneratorClose(generator) } - // - // - InitialYield yields the actual generator object. - // - Any return statement inside the body will have its argument wrapped - // in a "done" iterator result object. - // - If the generator terminates for whatever reason, we must close it. - // Hence the finally clause. - - Block* try_block = - factory()->NewBlock(nullptr, 3, false, kNoSourcePosition); - Expression* initial_yield = BuildInitialYield(pos, kind); - try_block->statements()->Add( - factory()->NewExpressionStatement(initial_yield, kNoSourcePosition), - zone()); - ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK); - - Statement* final_return = factory()->NewReturnStatement( - BuildIteratorResult(nullptr, true), kNoSourcePosition); - try_block->statements()->Add(final_return, zone()); - - Block* finally_block = - factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); - ZoneList<Expression*>* args = - new (zone()) ZoneList<Expression*>(1, zone()); - VariableProxy* call_proxy = factory()->NewVariableProxy( - function_state_->generator_object_variable()); - args->Add(call_proxy, zone()); - Expression* call = factory()->NewCallRuntime( - Runtime::kInlineGeneratorClose, args, kNoSourcePosition); - finally_block->statements()->Add( - factory()->NewExpressionStatement(call, kNoSourcePosition), zone()); - - body->Add(factory()->NewTryFinallyStatement(try_block, finally_block, - kNoSourcePosition), - zone()); - } else if (IsAsyncFunction(kind)) { - const bool accept_IN = true; - ParseAsyncFunctionBody(inner_scope, body, kind, FunctionBodyType::kNormal, - accept_IN, pos, CHECK_OK); - } else { - ParseStatementList(body, Token::RBRACE, CHECK_OK); - } - - if (IsDerivedConstructor(kind)) { - body->Add(factory()->NewReturnStatement(ThisExpression(kNoSourcePosition), - kNoSourcePosition), - zone()); - } - } - - Expect(Token::RBRACE, CHECK_OK); - scope()->set_end_position(scanner()->location().end_pos); - - if (!parameters.is_simple) { - DCHECK_NOT_NULL(inner_scope); - DCHECK_EQ(function_scope, scope()); - DCHECK_EQ(function_scope, inner_scope->outer_scope()); - DCHECK_EQ(body, inner_block->statements()); - SetLanguageMode(function_scope, inner_scope->language_mode()); - Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK); - - if (is_sloppy(inner_scope->language_mode())) { - InsertSloppyBlockFunctionVarBindings(inner_scope); - } - - // TODO(littledan): Merge the two rejection blocks into one - if (IsAsyncFunction(kind)) { - init_block = BuildRejectPromiseOnException(init_block, CHECK_OK); - } - - DCHECK_NOT_NULL(init_block); - - inner_scope->set_end_position(scanner()->location().end_pos); - if (inner_scope->FinalizeBlockScope() != nullptr) { - CheckConflictingVarDeclarations(inner_scope, CHECK_OK); - InsertShadowingVarBindingInitializers(inner_block); - } - inner_scope = nullptr; - - result->Add(init_block, zone()); - result->Add(inner_block, zone()); - } else { - DCHECK_EQ(inner_scope, function_scope); - if (is_sloppy(function_scope->language_mode())) { - InsertSloppyBlockFunctionVarBindings(function_scope); - } - } - - if (!IsArrowFunction(kind)) { - // Declare arguments after parsing the function since lexical 'arguments' - // masks the arguments object. Declare arguments before declaring the - // function var since the arguments object masks 'function arguments'. - function_scope->DeclareArguments(ast_value_factory()); - } - - if (function_type == FunctionLiteral::kNamedExpression) { - Statement* statement; - if (function_scope->LookupLocal(function_name) == nullptr) { - // Now that we know the language mode, we can create the const assignment - // in the previously reserved spot. - DCHECK_EQ(function_scope, scope()); - Variable* fvar = function_scope->DeclareFunctionVar(function_name); - VariableProxy* fproxy = factory()->NewVariableProxy(fvar); - statement = factory()->NewExpressionStatement( - factory()->NewAssignment(Token::INIT, fproxy, - factory()->NewThisFunction(pos), - kNoSourcePosition), - kNoSourcePosition); - } else { - statement = factory()->NewEmptyStatement(kNoSourcePosition); - } - result->Set(kFunctionNameAssignmentIndex, statement); - } - - MarkCollectedTailCallExpressions(); - return result; -} - -void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, +void Parser::DeclareClassVariable(const AstRawString* name, ClassInfo* class_info, int class_token_pos, bool* ok) { #ifdef DEBUG @@ -3269,7 +3208,7 @@ void Parser::DeclareClassVariable(const AstRawString* name, Scope* block_scope, if (name != nullptr) { class_info->proxy = factory()->NewVariableProxy(name, NORMAL_VARIABLE); Declaration* declaration = factory()->NewVariableDeclaration( - class_info->proxy, block_scope, class_token_pos); + class_info->proxy, scope(), class_token_pos); Declare(declaration, DeclarationDescriptor::NORMAL, CONST, Variable::DefaultInitializationFlag(CONST), ok); } @@ -3379,7 +3318,7 @@ void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) { DCHECK(inner_scope->is_declaration_scope()); Scope* function_scope = inner_scope->outer_scope(); DCHECK(function_scope->is_function_scope()); - BlockState block_state(&scope_state_, inner_scope); + BlockState block_state(&scope_, inner_scope); for (Declaration* decl : *inner_scope->declarations()) { if (decl->proxy()->var()->mode() != VAR || !decl->IsVariableDeclaration()) { continue; @@ -3460,21 +3399,18 @@ void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) { } } - -void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) { - // Internalize strings and values. - ast_value_factory()->Internalize(isolate); - - // Error processing. - if (error) { - if (stack_overflow()) { - isolate->StackOverflow(); - } else { - DCHECK(pending_error_handler_.has_pending_error()); - pending_error_handler_.ThrowPendingError(isolate, script); - } +void Parser::ReportErrors(Isolate* isolate, Handle<Script> script) { + if (stack_overflow()) { + isolate->StackOverflow(); + } else { + DCHECK(pending_error_handler_.has_pending_error()); + // Internalize ast values for throwing the pending error. + ast_value_factory()->Internalize(isolate); + pending_error_handler_.ThrowPendingError(isolate, script); } +} +void Parser::UpdateStatistics(Isolate* isolate, Handle<Script> script) { // Move statistics to Isolate. for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; ++feature) { @@ -3571,15 +3507,20 @@ Parser::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) { return new (zone()) TemplateLiteral(zone(), pos); } - -void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) { +void Parser::AddTemplateSpan(TemplateLiteralState* state, bool should_cook, + bool tail) { + DCHECK(should_cook || allow_harmony_template_escapes()); int pos = scanner()->location().beg_pos; int end = scanner()->location().end_pos - (tail ? 1 : 2); - const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory()); const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory()); - Literal* cooked = factory()->NewStringLiteral(tv, pos); Literal* raw = factory()->NewStringLiteral(trv, pos); - (*state)->AddTemplateSpan(cooked, raw, end, zone()); + if (should_cook) { + const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory()); + Literal* cooked = factory()->NewStringLiteral(tv, pos); + (*state)->AddTemplateSpan(cooked, raw, end, zone()); + } else { + (*state)->AddTemplateSpan(GetLiteralUndefined(pos), raw, end, zone()); + } } @@ -3623,19 +3564,14 @@ Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start, } else { uint32_t hash = ComputeTemplateLiteralHash(lit); - int cooked_idx = function_state_->NextMaterializedLiteralIndex(); - int raw_idx = function_state_->NextMaterializedLiteralIndex(); - // $getTemplateCallSite ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone()); args->Add(factory()->NewArrayLiteral( - const_cast<ZoneList<Expression*>*>(cooked_strings), - cooked_idx, pos), + const_cast<ZoneList<Expression*>*>(cooked_strings), pos), + zone()); + args->Add(factory()->NewArrayLiteral( + const_cast<ZoneList<Expression*>*>(raw_strings), pos), zone()); - args->Add( - factory()->NewArrayLiteral( - const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos), - zone()); // Truncate hash to Smi-range. Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash))); @@ -3683,6 +3619,19 @@ uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) { return running_hash; } +namespace { + +bool OnlyLastArgIsSpread(ZoneList<Expression*>* args) { + for (int i = 0; i < args->length() - 1; i++) { + if (args->at(i)->IsSpread()) { + return false; + } + } + return args->at(args->length() - 1)->IsSpread(); +} + +} // namespace + ZoneList<Expression*>* Parser::PrepareSpreadArguments( ZoneList<Expression*>* list) { ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone()); @@ -3719,9 +3668,7 @@ ZoneList<Expression*>* Parser::PrepareSpreadArguments( while (i < n && !list->at(i)->IsSpread()) { unspread->Add(list->at(i++), zone()); } - int literal_index = function_state_->NextMaterializedLiteralIndex(); - args->Add(factory()->NewArrayLiteral(unspread, literal_index, - kNoSourcePosition), + args->Add(factory()->NewArrayLiteral(unspread, kNoSourcePosition), zone()); if (i == n) break; @@ -3746,27 +3693,20 @@ ZoneList<Expression*>* Parser::PrepareSpreadArguments( } Expression* Parser::SpreadCall(Expression* function, - ZoneList<Expression*>* args, int pos) { + ZoneList<Expression*>* args, int pos, + Call::PossiblyEval is_possibly_eval) { + // Handle these cases in BytecodeGenerator. + // [Call,New]WithSpread bytecodes aren't used with tailcalls - see + // https://crbug.com/v8/5867 + if (!allow_tailcalls() && OnlyLastArgIsSpread(args)) { + return factory()->NewCall(function, args, pos); + } + if (function->IsSuperCallReference()) { // Super calls // $super_constructor = %_GetSuperConstructor(<this-function>) // %reflect_construct($super_constructor, args, new.target) - bool only_last_arg_is_spread = false; - for (int i = 0; i < args->length(); i++) { - if (args->at(i)->IsSpread()) { - if (i == args->length() - 1) { - only_last_arg_is_spread = true; - } - break; - } - } - - if (only_last_arg_is_spread) { - // Handle in BytecodeGenerator. - Expression* super_call_ref = NewSuperCallReference(pos); - return factory()->NewCall(super_call_ref, args, pos); - } args = PrepareSpreadArguments(args); ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone()); tmp->Add(function->AsSuperCallReference()->this_function_var(), zone()); @@ -3808,6 +3748,10 @@ Expression* Parser::SpreadCall(Expression* function, Expression* Parser::SpreadCallNew(Expression* function, ZoneList<Expression*>* args, int pos) { + if (OnlyLastArgIsSpread(args)) { + // Handle in BytecodeGenerator. + return factory()->NewCallNew(function, args, pos); + } args = PrepareSpreadArguments(args); args->InsertAt(0, function, zone()); @@ -3881,7 +3825,7 @@ void Parser::RewriteAsyncFunctionBody(ZoneList<Statement*>* body, Block* block, block->statements()->Add( factory()->NewReturnStatement(return_value, return_value->position()), zone()); - block = BuildRejectPromiseOnException(block, CHECK_OK_VOID); + block = BuildRejectPromiseOnException(block); body->Add(block, zone()); } @@ -4149,12 +4093,11 @@ Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { kNoSourcePosition); } // for (each of spread) %AppendElement($R, each) - ForEachStatement* loop = factory()->NewForEachStatement( - ForEachStatement::ITERATE, nullptr, kNoSourcePosition); + ForOfStatement* loop = + factory()->NewForOfStatement(nullptr, kNoSourcePosition); const bool finalize = false; - InitializeForOfStatement(loop->AsForOfStatement(), - factory()->NewVariableProxy(each), subject, - append_body, finalize); + InitializeForOfStatement(loop, factory()->NewVariableProxy(each), subject, + append_body, finalize, IteratorType::kNormal); do_block->statements()->Add(loop, zone()); } } @@ -4235,7 +4178,7 @@ void Parser::SetFunctionName(Expression* value, const AstRawString* name) { // const kReturn = 1; // const kThrow = 2; // -// let input = function.sent; +// let input = undefined; // let mode = kNext; // let output = undefined; // @@ -4346,7 +4289,8 @@ Expression* Parser::RewriteYieldStar(Expression* generator, Variable* var_iterator = NewTemporary(ast_value_factory()->empty_string()); Statement* get_iterator; { - Expression* iterator = factory()->NewGetIterator(iterable, nopos); + Expression* iterator = + factory()->NewGetIterator(iterable, IteratorType::kNormal, nopos); Expression* iterator_proxy = factory()->NewVariableProxy(var_iterator); Expression* assignment = factory()->NewAssignment( Token::ASSIGN, iterator_proxy, iterator, nopos); @@ -4428,7 +4372,8 @@ 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)); + factory()->NewSmiLiteral(Parser::kNormalCompletion, nopos), + IteratorType::kNormal); then->statements()->Add(throw_call, zone()); check_throw = factory()->NewIfStatement( condition, then, factory()->NewEmptyStatement(nopos), nopos); @@ -4795,7 +4740,8 @@ void Parser::BuildIteratorClose(ZoneList<Statement*>* statements, void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, Expression* condition, Variable* iter, - Block* iterator_use, Block* target) { + Block* iterator_use, Block* target, + IteratorType type) { // // This function adds two statements to [target], corresponding to the // following code: @@ -4851,8 +4797,8 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, { Block* block = factory()->NewBlock(nullptr, 2, true, nopos); Expression* proxy = factory()->NewVariableProxy(completion); - BuildIteratorCloseForCompletion(use_scope, block->statements(), iter, - proxy); + BuildIteratorCloseForCompletion(use_scope, block->statements(), iter, proxy, + type); DCHECK(block->statements()->length() == 2); maybe_close = factory()->NewBlock(nullptr, 1, true, nopos); @@ -4911,7 +4857,8 @@ void Parser::FinalizeIteratorUse(Scope* use_scope, Variable* completion, void Parser::BuildIteratorCloseForCompletion(Scope* scope, ZoneList<Statement*>* statements, Variable* iterator, - Expression* completion) { + Expression* completion, + IteratorType type) { // // This function adds two statements to [statements], corresponding to the // following code: @@ -4922,9 +4869,17 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope, // if (!IS_CALLABLE(iteratorReturn)) { // throw MakeTypeError(kReturnMethodNotCallable); // } - // try { %_Call(iteratorReturn, iterator) } catch (_) { } + // [if (IteratorType == kAsync)] + // try { Await(%_Call(iteratorReturn, iterator) } catch (_) { } + // [else] + // try { %_Call(iteratorReturn, iterator) } catch (_) { } + // [endif] // } else { - // let output = %_Call(iteratorReturn, iterator); + // [if (IteratorType == kAsync)] + // let output = Await(%_Call(iteratorReturn, iterator)); + // [else] + // let output = %_Call(iteratorReturn, iterator); + // [endif] // if (!IS_RECEIVER(output)) { // %ThrowIterResultNotAnObject(output); // } @@ -4969,6 +4924,10 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope, Expression* call = factory()->NewCallRuntime(Runtime::kInlineCall, args, nopos); + if (type == IteratorType::kAsync) { + call = RewriteAwaitExpression(call, nopos); + } + Block* try_block = factory()->NewBlock(nullptr, 1, false, nopos); try_block->statements()->Add(factory()->NewExpressionStatement(call, nopos), zone()); @@ -4998,6 +4957,9 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope, args->Add(factory()->NewVariableProxy(iterator), zone()); 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 = @@ -5068,7 +5030,8 @@ void Parser::BuildIteratorCloseForCompletion(Scope* scope, } Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop, - Variable* var_completion, int pos) { + Variable* var_completion, + IteratorType type, int pos) { // // This function replaces the loop with the following wrapping: // @@ -5112,7 +5075,7 @@ Statement* Parser::FinalizeForOfStatement(ForOfStatement* loop, DCHECK_EQ(scope()->scope_type(), BLOCK_SCOPE); FinalizeIteratorUse(loop_scope, var_completion, closing_condition, - loop->iterator(), try_block, final_loop); + loop->iterator(), try_block, final_loop, type); } return final_loop; |