summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/parser.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2017-05-02 10:50:00 +0200
committerMichaël Zasso <targos@protonmail.com>2017-05-06 20:02:35 +0200
commit60d1aac8d225e844e68ae48e8f3d58802e635fbe (patch)
tree922f347dd054db18d88666fad7181e5a777f4022 /deps/v8/src/parsing/parser.cc
parent73d9c0f903ae371cd5011af64c3a6f69a1bda978 (diff)
downloadandroid-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.cc629
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;