Commit 5f782db9 authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

[parser] don't rewrite destructuring assignments in params for lazy top level arrow functions

Remove destructuring assignments (parsed during arrow function formal
parameters) from queue for rewriting if parsing a lazy top-level arrow function.

Built ontop of https://chromium-review.googlesource.com/c/464769/

BUG=chromium:706234, chromium:706761, v8:6182
R=marja@chromium.org, adamk@chromium.org, vogelheim@chromium.org

Change-Id: Ib35196b907350d1d78e4c3fcbf4cc971bf200948
Reviewed-on: https://chromium-review.googlesource.com/465415
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44393}
parent d6a92013
......@@ -1496,7 +1496,11 @@ void DeclarationScope::ResetAfterPreparsing(AstValueFactory* ast_value_factory,
DCHECK(is_function_scope());
// Reset all non-trivial members.
if (!aborted || !IsArrowFunction(function_kind_)) {
// Do not remove parameters when lazy parsing an Arrow Function has failed,
// as the formal parameters are not re-parsed.
params_.Clear();
}
decls_.Clear();
locals_.Clear();
inner_scope_ = nullptr;
......
......@@ -395,6 +395,17 @@ class ParserBase {
return scope()->promise_var();
}
void RewindDestructuringAssignments(int pos) {
destructuring_assignments_to_rewrite_.Rewind(pos);
}
void SetDestructuringAssignmentsScope(int pos, Scope* scope) {
for (int i = pos; i < destructuring_assignments_to_rewrite_.length();
++i) {
destructuring_assignments_to_rewrite_[i].scope = scope;
}
}
const ZoneList<DestructuringAssignment>&
destructuring_assignments_to_rewrite() const {
return destructuring_assignments_to_rewrite_;
......@@ -1108,9 +1119,14 @@ class ParserBase {
ExpressionT ParseMemberExpression(bool* is_async, bool* ok);
ExpressionT ParseMemberExpressionContinuation(ExpressionT expression,
bool* is_async, bool* ok);
// `rewritable_length`: length of the destructuring_assignments_to_rewrite()
// queue in the parent function state, prior to parsing of formal parameters.
// If the arrow function is lazy, any items added during formal parameter
// parsing are removed from the queue.
ExpressionT ParseArrowFunctionLiteral(bool accept_IN,
const FormalParametersT& parameters,
bool* ok);
int rewritable_length, bool* ok);
void ParseAsyncFunctionBody(Scope* scope, StatementListT body,
FunctionKind kind, FunctionBodyType type,
bool accept_IN, int pos, bool* ok);
......@@ -2711,6 +2727,8 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
this, classifier()->duplicate_finder());
Scope::Snapshot scope_snapshot(scope());
int rewritable_length =
function_state_->destructuring_assignments_to_rewrite().length();
bool is_async = peek() == Token::ASYNC &&
!scanner()->HasAnyLineTerminatorAfterNext() &&
......@@ -2762,6 +2780,7 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
// Because the arrow's parameters were parsed in the outer scope,
// we need to fix up the scope chain appropriately.
scope_snapshot.Reparent(scope);
function_state_->SetDestructuringAssignmentsScope(rewritable_length, scope);
FormalParametersT parameters(scope);
if (!classifier()->is_simple_parameter_list()) {
......@@ -2776,7 +2795,8 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
if (duplicate_loc.IsValid()) {
classifier()->RecordDuplicateFormalParameterError(duplicate_loc);
}
expression = ParseArrowFunctionLiteral(accept_IN, parameters, CHECK_OK);
expression = ParseArrowFunctionLiteral(accept_IN, parameters,
rewritable_length, CHECK_OK);
DiscardExpressionClassifier();
classifier()->RecordPatternError(arrow_loc,
MessageTemplate::kUnexpectedToken,
......@@ -4146,7 +4166,8 @@ bool ParserBase<Impl>::IsTrivialExpression() {
template <typename Impl>
typename ParserBase<Impl>::ExpressionT
ParserBase<Impl>::ParseArrowFunctionLiteral(
bool accept_IN, const FormalParametersT& formal_parameters, bool* ok) {
bool accept_IN, const FormalParametersT& formal_parameters,
int rewritable_length, bool* ok) {
const RuntimeCallStats::CounterId counters[2][2] = {
{&RuntimeCallStats::ParseBackgroundArrowFunctionLiteral,
&RuntimeCallStats::ParseArrowFunctionLiteral},
......@@ -4276,6 +4297,14 @@ ParserBase<Impl>::ParseArrowFunctionLiteral(
}
impl()->CheckConflictingVarDeclarations(formal_parameters.scope, CHECK_OK);
if (is_lazy_top_level_function) {
FunctionState* parent_state = function_state.outer();
DCHECK_NOT_NULL(parent_state);
DCHECK_GE(parent_state->destructuring_assignments_to_rewrite().length(),
rewritable_length);
parent_state->RewindDestructuringAssignments(rewritable_length);
}
impl()->RewriteDestructuringAssignments();
}
......
......@@ -891,6 +891,8 @@ 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();
{
// Parsing patterns as variable reference expression creates
// NewUnresolved references in current scope. Enter arrow function
......@@ -925,7 +927,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
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Lazy top-level arrow function which must be re-parsed and eagerly compiled.
var f = ({ x } = { x: 1 }) => {
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;
};
f();
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
var fn = ({foo = {} = {}}) => { return foo; }
if (true) {
fn({});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment