Merge V8 5.2.361.47 DO NOT MERGE
https://chromium.googlesource.com/v8/v8/+/5.2.361.47
FPIIM-449
Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/parsing/pattern-rewriter.cc b/src/parsing/pattern-rewriter.cc
index e699255..3dcff98 100644
--- a/src/parsing/pattern-rewriter.cc
+++ b/src/parsing/pattern-rewriter.cc
@@ -272,15 +272,9 @@
factory()->NewExpressionStatement(initialize, initialize->position()),
zone());
}
- } else if (value != nullptr && (descriptor_->mode == CONST_LEGACY ||
- IsLexicalVariableMode(descriptor_->mode))) {
- // Constant initializations always assign to the declared constant which
- // is always at the function scope level. This is only relevant for
- // dynamically looked-up variables and constants (the
- // start context for constant lookups is always the function context,
- // while it is the top context for var declared variables). Sigh...
- // For 'let' and 'const' declared variables in harmony mode the
- // initialization also always assigns to the declared variable.
+ } else if (value != nullptr && IsLexicalVariableMode(descriptor_->mode)) {
+ // For 'let' and 'const' declared variables the initialization always
+ // assigns to the declared variable.
DCHECK_NOT_NULL(proxy);
DCHECK_NOT_NULL(proxy->var());
DCHECK_NOT_NULL(value);
@@ -387,6 +381,37 @@
return set_context(old_context);
}
+// Two cases for scope rewriting the scope of default parameters:
+// - Eagerly parsed arrow functions are initially parsed as having
+// expressions in the enclosing scope, but when the arrow is encountered,
+// need to be in the scope of the function.
+// - When an extra declaration scope needs to be inserted to account for
+// a sloppy eval in a default parameter or function body, the expressions
+// needs to be in that new inner scope which was added after initial
+// parsing.
+// Each of these cases can be handled by rewriting the contents of the
+// expression to the current scope. The source scope is typically the outer
+// scope when one case occurs; when both cases occur, both scopes need to
+// be included as the outer scope. (Both rewritings still need to be done
+// to account for lazily parsed arrow functions which hit the second case.)
+// TODO(littledan): Remove the outer_scope parameter of
+// RewriteParameterInitializerScope
+void Parser::PatternRewriter::RewriteParameterScopes(Expression* expr) {
+ if (!IsBindingContext()) return;
+ if (descriptor_->declaration_kind != DeclarationDescriptor::PARAMETER) return;
+ if (!scope()->is_arrow_scope() && !scope()->is_block_scope()) return;
+
+ // Either this scope is an arrow scope or a declaration block scope.
+ DCHECK(scope()->is_declaration_scope());
+
+ if (scope()->outer_scope()->is_arrow_scope() && scope()->is_block_scope()) {
+ RewriteParameterInitializerScope(parser_->stack_limit(), expr,
+ scope()->outer_scope()->outer_scope(),
+ scope());
+ }
+ RewriteParameterInitializerScope(parser_->stack_limit(), expr,
+ scope()->outer_scope(), scope());
+}
void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
Variable** temp_var) {
@@ -396,6 +421,11 @@
for (ObjectLiteralProperty* property : *pattern->properties()) {
PatternContext context = SetInitializerContextIfNeeded(property->value());
+
+ // Computed property names contain expressions which might require
+ // scope rewriting.
+ if (!property->key()->IsLiteral()) RewriteParameterScopes(property->key());
+
RecurseIntoSubpattern(
property->value(),
factory()->NewProperty(factory()->NewVariableProxy(temp),
@@ -552,11 +582,11 @@
// let array = [];
// while (!done) {
+ // done = true; // If .next, .done or .value throws, don't close.
// result = IteratorNext(iterator);
- // if (result.done) {
- // done = true;
- // } else {
+ // if (!result.done) {
// %AppendElement(array, result.value);
+ // done = false;
// }
// }
@@ -571,12 +601,6 @@
node->literal_index(), RelocInfo::kNoPosition));
}
- // result = IteratorNext(iterator);
- Statement* get_next = factory()->NewExpressionStatement(
- parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
- result, nopos),
- nopos);
-
// done = true;
Statement* set_done = factory()->NewExpressionStatement(
factory()->NewAssignment(
@@ -584,6 +608,12 @@
factory()->NewBooleanLiteral(true, nopos), nopos),
nopos);
+ // result = IteratorNext(iterator);
+ Statement* get_next = factory()->NewExpressionStatement(
+ parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
+ result, nopos),
+ nopos);
+
// %AppendElement(array, result.value);
Statement* append_element;
{
@@ -600,29 +630,44 @@
nopos);
}
- // if (result.done) { #set_done } else { #append_element }
- Statement* set_done_or_append;
+ // done = false;
+ Statement* unset_done = factory()->NewExpressionStatement(
+ factory()->NewAssignment(
+ Token::ASSIGN, factory()->NewVariableProxy(done),
+ factory()->NewBooleanLiteral(false, nopos), nopos),
+ nopos);
+
+ // if (!result.done) { #append_element; #unset_done }
+ Statement* maybe_append_and_unset_done;
{
Expression* result_done =
factory()->NewProperty(factory()->NewVariableProxy(result),
factory()->NewStringLiteral(
ast_value_factory()->done_string(), nopos),
nopos);
- set_done_or_append = factory()->NewIfStatement(result_done, set_done,
- append_element, nopos);
+
+ Block* then = factory()->NewBlock(nullptr, 2, true, nopos);
+ then->statements()->Add(append_element, zone());
+ then->statements()->Add(unset_done, zone());
+
+ maybe_append_and_unset_done = factory()->NewIfStatement(
+ factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
+ factory()->NewEmptyStatement(nopos), nopos);
}
// while (!done) {
+ // #set_done;
// #get_next;
- // #set_done_or_append;
+ // #maybe_append_and_unset_done;
// }
WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
{
Expression* condition = factory()->NewUnaryOperation(
Token::NOT, factory()->NewVariableProxy(done), nopos);
- Block* body = factory()->NewBlock(nullptr, 2, true, nopos);
+ Block* body = factory()->NewBlock(nullptr, 3, true, nopos);
+ body->statements()->Add(set_done, zone());
body->statements()->Add(get_next, zone());
- body->statements()->Add(set_done_or_append, zone());
+ body->statements()->Add(maybe_append_and_unset_done, zone());
loop->Initialize(condition, body);
}
@@ -668,12 +713,8 @@
RelocInfo::kNoPosition);
}
- if (IsBindingContext() &&
- descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
- scope()->is_arrow_scope()) {
- RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
- scope()->outer_scope(), scope());
- }
+ // Initializer may have been parsed in the wrong scope.
+ RewriteParameterScopes(initializer);
PatternContext old_context = SetAssignmentContextIfNeeded(initializer);
RecurseIntoSubpattern(node->target(), value);