From 91b87e7a2884b3322f48dd9cf532eb0e8b462029 Mon Sep 17 00:00:00 2001 From: aperez Date: Thu, 29 Jan 2015 07:53:07 -0800 Subject: [PATCH] Do not create unresolved variables when parsing arrow functions lazily Arrow function parameter lists are parsed as expressions. When an identifier is found a VariableProxy is created and added to the list of unresolved variables for the scope. When parsing a function lazily, the scope has been already resolved, so with this patch only the VariableProxy is created, without adding it as an unresolved variable in the scope. BUG=v8:3501 LOG=Y Review URL: https://codereview.chromium.org/880253004 Cr-Commit-Position: refs/heads/master@{#26328} --- src/parser.cc | 18 +++++++++++++++++- src/parser.h | 1 + test/mjsunit/regress/regress-3501.js | 11 +++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 test/mjsunit/regress/regress-3501.js diff --git a/src/parser.cc b/src/parser.cc index 9539d3891f..93af5028b8 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -723,7 +723,14 @@ Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name, PrintF("# Variable %.*s ", name->length(), name->raw_data()); #endif Interface* interface = Interface::NewUnknown(parser_->zone()); - return scope->NewUnresolved(factory, name, interface, pos); + + // Arrow function parameters are parsed as an expression. When + // parsing lazily, it is enough to create a VariableProxy in order + // for Traits::DeclareArrowParametersFromExpression() to be able to + // pick the names of the parameters. + return parser_->parsing_lazy_arrow_parameters_ + ? factory->NewVariableProxy(name, false, interface, pos) + : scope->NewUnresolved(factory, name, interface, pos); } @@ -788,6 +795,7 @@ Parser::Parser(CompilationInfo* info, ParseInfo* parse_info) target_stack_(NULL), cached_parse_data_(NULL), info_(info), + parsing_lazy_arrow_parameters_(false), has_pending_error_(false), pending_error_message_(NULL), pending_error_arg_(NULL), @@ -1061,6 +1069,10 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) { bool ok = true; if (shared_info->is_arrow()) { + // The first expression being parsed is the parameter list of the arrow + // function. Setting this avoids prevents ExpressionFromIdentifier() + // from creating unresolved variables in already-resolved scopes. + parsing_lazy_arrow_parameters_ = true; Expression* expression = ParseExpression(false, &ok); DCHECK(expression->IsFunctionLiteral()); result = expression->AsFunctionLiteral(); @@ -3430,6 +3442,10 @@ int ParserTraits::DeclareArrowParametersFromExpression( Expression* expression, Scope* scope, Scanner::Location* dupe_loc, bool* ok) { int num_params = 0; + // Always reset the flag: It only needs to be set for the first expression + // parsed as arrow function parameter list, becauseonly top-level functions + // are parsed lazily. + parser_->parsing_lazy_arrow_parameters_ = false; *ok = CheckAndDeclareArrowParameter(this, expression, scope, &num_params, dupe_loc); return num_params; diff --git a/src/parser.h b/src/parser.h index e998771831..dedc45aae7 100644 --- a/src/parser.h +++ b/src/parser.h @@ -888,6 +888,7 @@ class Parser : public ParserBase { ParseData* cached_parse_data_; CompilationInfo* info_; + bool parsing_lazy_arrow_parameters_; // for lazily parsed arrow functions. // Pending errors. bool has_pending_error_; diff --git a/test/mjsunit/regress/regress-3501.js b/test/mjsunit/regress/regress-3501.js new file mode 100644 index 0000000000..4b449e458f --- /dev/null +++ b/test/mjsunit/regress/regress-3501.js @@ -0,0 +1,11 @@ +// Copyright 2014 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. + +// Flags: --harmony-arrow-functions + +// See: http://code.google.com/p/v8/issues/detail?id=3501 + +"use strict"; +let lift = f => (x, k) => k (f (x)); +lift(isNaN);