| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index 7e0d9366116f3b8bd7619a78ceb39e6a6901cd1e..61385929bc5962d2955d32788a117ce2cc88670a 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -1182,7 +1182,7 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
|
| NewScope(scope_, ARROW_SCOPE, FunctionKind::kArrowFunction);
|
| scope->set_start_position(shared_info->start_position());
|
| ExpressionClassifier formals_classifier;
|
| - bool has_rest = false;
|
| + ParserFormalParameterParsingState parsing_state(scope);
|
| {
|
| // Parsing patterns as variable reference expression creates
|
| // NewUnresolved references in current scope. Entrer arrow function
|
| @@ -1190,17 +1190,19 @@ FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
|
| BlockState block_state(&scope_, scope);
|
| if (Check(Token::LPAREN)) {
|
| // '(' StrictFormalParameters ')'
|
| - ParseFormalParameterList(scope, &has_rest, &formals_classifier, &ok);
|
| + ParseFormalParameterList(&parsing_state, &formals_classifier, &ok);
|
| if (ok) ok = Check(Token::RPAREN);
|
| } else {
|
| // BindingIdentifier
|
| - ParseFormalParameter(scope, has_rest, &formals_classifier, &ok);
|
| + const bool is_rest = false;
|
| + ParseFormalParameter(is_rest, &parsing_state, &formals_classifier,
|
| + &ok);
|
| }
|
| }
|
|
|
| if (ok) {
|
| Expression* expression =
|
| - ParseArrowFunctionLiteral(scope, has_rest, formals_classifier, &ok);
|
| + ParseArrowFunctionLiteral(parsing_state, formals_classifier, &ok);
|
| if (ok) {
|
| // Scanning must end at the same position that was recorded
|
| // previously. If not, parsing has been interrupted due to a stack
|
| @@ -1547,7 +1549,7 @@ ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) {
|
| VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
|
| ImportDeclaration* declaration =
|
| factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
|
| - Declare(declaration, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| result->Add(declaration, zone());
|
| if (peek() == Token::RBRACE) break;
|
| Expect(Token::COMMA, CHECK_OK);
|
| @@ -1595,7 +1597,8 @@ Statement* Parser::ParseImportDeclaration(bool* ok) {
|
| VariableProxy* proxy = NewUnresolved(local_name, IMPORT);
|
| import_default_declaration = factory()->NewImportDeclaration(
|
| proxy, ast_value_factory()->default_string(), NULL, scope_, pos);
|
| - Declare(import_default_declaration, true, CHECK_OK);
|
| + Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true,
|
| + CHECK_OK);
|
| }
|
|
|
| const AstRawString* module_instance_binding = NULL;
|
| @@ -1982,7 +1985,9 @@ VariableProxy* Parser::NewUnresolved(const AstRawString* name,
|
| }
|
|
|
|
|
| -Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| +Variable* Parser::Declare(Declaration* declaration,
|
| + DeclarationDescriptor::Kind declaration_kind,
|
| + bool resolve, bool* ok) {
|
| VariableProxy* proxy = declaration->proxy();
|
| DCHECK(proxy->raw_name() != NULL);
|
| const AstRawString* name = proxy->raw_name();
|
| @@ -2041,11 +2046,15 @@ Variable* Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| if (is_strict(language_mode())) {
|
| // In harmony we treat re-declarations as early errors. See
|
| // ES5 16 for a definition of early errors.
|
| - ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
|
| + if (declaration_kind == DeclarationDescriptor::NORMAL) {
|
| + ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
|
| + } else {
|
| + ParserTraits::ReportMessage(MessageTemplate::kStrictParamDupe);
|
| + }
|
| *ok = false;
|
| return nullptr;
|
| }
|
| - Expression* expression = NewThrowTypeError(
|
| + Expression* expression = NewThrowSyntaxError(
|
| MessageTemplate::kVarRedeclaration, name, declaration->position());
|
| declaration_scope->SetIllegalRedeclaration(expression);
|
| } else if (mode == VAR) {
|
| @@ -2155,7 +2164,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
| VariableProxy* proxy = NewUnresolved(name, VAR);
|
| Declaration* declaration =
|
| factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
|
| - Declare(declaration, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
|
| name, extension_, RelocInfo::kNoPosition);
|
| return factory()->NewExpressionStatement(
|
| @@ -2200,7 +2209,7 @@ Statement* Parser::ParseFunctionDeclaration(
|
| VariableProxy* proxy = NewUnresolved(name, mode);
|
| Declaration* declaration =
|
| factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
|
| - Declare(declaration, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| if (names) names->Add(name, zone());
|
| return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
|
| }
|
| @@ -2241,7 +2250,8 @@ Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
|
| Declaration* declaration = factory()->NewVariableDeclaration(
|
| proxy, mode, scope_, pos, is_class_declaration,
|
| scope_->class_declaration_group_start());
|
| - Variable* outer_class_variable = Declare(declaration, true, CHECK_OK);
|
| + Variable* outer_class_variable =
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| proxy->var()->set_initializer_position(position());
|
| // This is needed because a class ("class Name { }") creates two bindings (one
|
| // in the outer scope, and one in the class scope). The method is a function
|
| @@ -2397,6 +2407,7 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
|
| // BindingPattern '=' AssignmentExpression
|
|
|
| parsing_result->descriptor.parser = this;
|
| + parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
|
| parsing_result->descriptor.declaration_pos = peek_position();
|
| parsing_result->descriptor.initialization_pos = peek_position();
|
| parsing_result->descriptor.mode = VAR;
|
| @@ -3328,7 +3339,7 @@ Statement* Parser::DesugarLexicalBindingsInForStatement(
|
| VariableProxy* proxy = NewUnresolved(names->at(i), mode);
|
| Declaration* declaration = factory()->NewVariableDeclaration(
|
| proxy, mode, scope_, RelocInfo::kNoPosition);
|
| - Declare(declaration, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| inner_vars.Add(declaration->proxy()->var(), zone());
|
| VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
|
| Assignment* assignment =
|
| @@ -3784,9 +3795,10 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
|
|
|
|
|
| void ParserTraits::ParseArrowFunctionFormalParameters(
|
| - Scope* scope, Expression* expr, const Scanner::Location& params_loc,
|
| - bool* has_rest, Scanner::Location* duplicate_loc, bool* ok) {
|
| - if (scope->num_parameters() >= Code::kMaxArguments) {
|
| + ParserFormalParameterParsingState* parsing_state, Expression* expr,
|
| + const Scanner::Location& params_loc, Scanner::Location* duplicate_loc,
|
| + bool* ok) {
|
| + if (parsing_state->scope->num_parameters() >= Code::kMaxArguments) {
|
| ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
|
| *ok = false;
|
| return;
|
| @@ -3812,7 +3824,7 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
|
| DCHECK_EQ(binop->op(), Token::COMMA);
|
| Expression* left = binop->left();
|
| Expression* right = binop->right();
|
| - ParseArrowFunctionFormalParameters(scope, left, params_loc, has_rest,
|
| + ParseArrowFunctionFormalParameters(parsing_state, left, params_loc,
|
| duplicate_loc, ok);
|
| if (!*ok) return;
|
| // LHS of comma expression should be unparenthesized.
|
| @@ -3820,30 +3832,25 @@ void ParserTraits::ParseArrowFunctionFormalParameters(
|
| }
|
|
|
| // Only the right-most expression may be a rest parameter.
|
| - DCHECK(!*has_rest);
|
| + DCHECK(!parsing_state->has_rest);
|
|
|
| + bool is_rest = false;
|
| if (expr->IsSpread()) {
|
| - *has_rest = true;
|
| + is_rest = true;
|
| expr = expr->AsSpread()->expression();
|
| }
|
|
|
| - if (!expr->IsVariableProxy()) {
|
| - // TODO(dslomov): support pattern desugaring
|
| - return;
|
| + if (expr->IsVariableProxy()) {
|
| + // When the formal parameter was originally seen, it was parsed as a
|
| + // VariableProxy and recorded as unresolved in the scope. Here we undo that
|
| + // parse-time side-effect for parameters that are single-names (not
|
| + // patterns; for patterns that happens uniformly in
|
| + // PatternRewriter::VisitVariableProxy).
|
| + parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
|
| }
|
| - DCHECK(!expr->AsVariableProxy()->is_this());
|
| -
|
| - const AstRawString* raw_name = expr->AsVariableProxy()->raw_name();
|
| - Scanner::Location param_location(expr->position(),
|
| - expr->position() + raw_name->length());
|
| -
|
| - // When the formal parameter was originally seen, it was parsed as a
|
| - // VariableProxy and recorded as unresolved in the scope. Here we undo that
|
| - // parse-time side-effect.
|
| - parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
|
|
|
| ExpressionClassifier classifier;
|
| - DeclareFormalParameter(scope, expr, &classifier, *has_rest);
|
| + DeclareFormalParameter(parsing_state, expr, &classifier, is_rest);
|
| if (!duplicate_loc->IsValid()) {
|
| *duplicate_loc = classifier.duplicate_formal_parameter_error().location;
|
| }
|
| @@ -3918,7 +3925,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| ZoneList<Statement*>* body = NULL;
|
| int materialized_literal_count = -1;
|
| int expected_property_count = -1;
|
| - ExpressionClassifier formals_classifier;
|
| + DuplicateFinder duplicate_finder(scanner()->unicode_cache());
|
| + ExpressionClassifier formals_classifier(&duplicate_finder);
|
| FunctionLiteral::EagerCompileHint eager_compile_hint =
|
| parenthesized_function_ ? FunctionLiteral::kShouldEagerCompile
|
| : FunctionLiteral::kShouldLazyCompile;
|
| @@ -3944,18 +3952,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| function_state.set_generator_object_variable(temp);
|
| }
|
|
|
| - bool has_rest = false;
|
| Expect(Token::LPAREN, CHECK_OK);
|
| int start_position = scanner()->location().beg_pos;
|
| scope_->set_start_position(start_position);
|
| - num_parameters = ParseFormalParameterList(scope, &has_rest,
|
| - &formals_classifier, CHECK_OK);
|
| + ParserFormalParameterParsingState parsing_state(scope);
|
| + num_parameters =
|
| + ParseFormalParameterList(&parsing_state, &formals_classifier, CHECK_OK);
|
| Expect(Token::RPAREN, CHECK_OK);
|
| int formals_end_position = scanner()->location().end_pos;
|
|
|
| - CheckArityRestrictions(num_parameters, arity_restriction, has_rest,
|
| - start_position, formals_end_position, CHECK_OK);
|
| -
|
| + CheckArityRestrictions(num_parameters, arity_restriction,
|
| + parsing_state.has_rest, start_position,
|
| + formals_end_position, CHECK_OK);
|
| Expect(Token::LBRACE, CHECK_OK);
|
|
|
| // If we have a named function expression, we add a local variable
|
| @@ -4050,8 +4058,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| }
|
| }
|
| if (!is_lazily_parsed) {
|
| - body = ParseEagerFunctionBody(function_name, pos, fvar, fvar_init_op,
|
| - kind, CHECK_OK);
|
| + body = ParseEagerFunctionBody(function_name, pos, parsing_state, fvar,
|
| + fvar_init_op, kind, CHECK_OK);
|
| materialized_literal_count = function_state.materialized_literal_count();
|
| expected_property_count = function_state.expected_property_count();
|
|
|
| @@ -4071,7 +4079,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
| CheckFunctionName(language_mode(), kind, function_name,
|
| name_is_strict_reserved, function_name_location,
|
| CHECK_OK);
|
| - const bool use_strict_params = has_rest || IsConciseMethod(kind);
|
| + const bool use_strict_params =
|
| + !parsing_state.is_simple_parameter_list || IsConciseMethod(kind);
|
| const bool allow_duplicate_parameters =
|
| is_sloppy(language_mode()) && !use_strict_params;
|
| ValidateFormalParameters(&formals_classifier, language_mode(),
|
| @@ -4233,8 +4242,40 @@ Statement* Parser::BuildAssertIsCoercible(Variable* var) {
|
| }
|
|
|
|
|
| +Block* Parser::BuildParameterInitializationBlock(
|
| + const ParserFormalParameterParsingState& formal_parameters, bool* ok) {
|
| + DCHECK(scope_->is_function_scope());
|
| + Block* init_block = nullptr;
|
| + for (auto parameter : formal_parameters.params) {
|
| + if (parameter.pattern == nullptr) continue;
|
| + if (init_block == nullptr) {
|
| + init_block = factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
|
| + }
|
| +
|
| + DeclarationDescriptor descriptor;
|
| + descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
|
| + descriptor.parser = this;
|
| + descriptor.declaration_scope = scope_;
|
| + descriptor.scope = scope_;
|
| + descriptor.mode = LET;
|
| + descriptor.is_const = false;
|
| + descriptor.needs_init = true;
|
| + descriptor.declaration_pos = parameter.pattern->position();
|
| + descriptor.initialization_pos = parameter.pattern->position();
|
| + descriptor.init_op = Token::INIT_LET;
|
| + DeclarationParsingResult::Declaration decl(
|
| + parameter.pattern, parameter.pattern->position(),
|
| + factory()->NewVariableProxy(parameter.var));
|
| + PatternRewriter::DeclareAndInitializeVariables(init_block, &descriptor,
|
| + &decl, nullptr, CHECK_OK);
|
| + }
|
| + return init_block;
|
| +}
|
| +
|
| +
|
| ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| - const AstRawString* function_name, int pos, Variable* fvar,
|
| + const AstRawString* function_name, int pos,
|
| + const ParserFormalParameterParsingState& formal_parameters, Variable* fvar,
|
| Token::Value fvar_init_op, FunctionKind kind, bool* ok) {
|
| // Everything inside an eagerly parsed function will be parsed eagerly
|
| // (see comment above).
|
| @@ -4258,6 +4299,12 @@ ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
|
| AddAssertIsConstruct(body, pos);
|
| }
|
|
|
| + auto init_block =
|
| + BuildParameterInitializationBlock(formal_parameters, CHECK_OK);
|
| + if (init_block != nullptr) {
|
| + body->Add(init_block, zone());
|
| + }
|
| +
|
| // For generators, allocate and yield an iterator on function entry.
|
| if (IsGeneratorFunction(kind)) {
|
| ZoneList<Expression*>* arguments =
|
| @@ -4384,7 +4431,7 @@ ClassLiteral* Parser::ParseClassLiteral(const AstRawString* name,
|
| Declaration* declaration = factory()->NewVariableDeclaration(
|
| proxy, CONST, block_scope, pos, is_class_declaration,
|
| scope_->class_declaration_group_start());
|
| - Declare(declaration, true, CHECK_OK);
|
| + Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
|
| }
|
|
|
| Expression* extends = NULL;
|
|
|