diff --git a/deps/v8/src/parsing/parser.cc b/deps/v8/src/parsing/parser.cc index 7fd6d5b302b0d0..c35e495d099ea1 100644 --- a/deps/v8/src/parsing/parser.cc +++ b/deps/v8/src/parsing/parser.cc @@ -2923,40 +2923,40 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { catch_scope = NewScope(scope_, CATCH_SCOPE); catch_scope->set_start_position(scanner()->location().beg_pos); - ExpressionClassifier pattern_classifier(this); - Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK); - ValidateBindingPattern(&pattern_classifier, CHECK_OK); - - const AstRawString* name = ast_value_factory()->dot_catch_string(); - bool is_simple = pattern->IsVariableProxy(); - if (is_simple) { - auto proxy = pattern->AsVariableProxy(); - scope_->RemoveUnresolved(proxy); - name = proxy->raw_name(); - } - - catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized, - Variable::NORMAL); - - Expect(Token::RPAREN, CHECK_OK); - { CollectExpressionsInTailPositionToListScope collect_expressions_in_tail_position_scope( function_state_, &expressions_in_tail_position_in_catch_block); BlockState block_state(&scope_, catch_scope); - // TODO(adamk): Make a version of ParseBlock that takes a scope and - // a block. catch_block = factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); - Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); + // Create a block scope to hold any lexical declarations created + // as part of destructuring the catch parameter. + Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); block_scope->set_start_position(scanner()->location().beg_pos); { BlockState block_state(&scope_, block_scope); Target target(&this->target_stack_, catch_block); + ExpressionClassifier pattern_classifier(this); + Expression* pattern = + ParsePrimaryExpression(&pattern_classifier, CHECK_OK); + ValidateBindingPattern(&pattern_classifier, CHECK_OK); + + const AstRawString* name = ast_value_factory()->dot_catch_string(); + bool is_simple = pattern->IsVariableProxy(); + if (is_simple) { + auto proxy = pattern->AsVariableProxy(); + scope_->RemoveUnresolved(proxy); + name = proxy->raw_name(); + } + catch_variable = catch_scope->DeclareLocal( + name, VAR, kCreatedInitialized, Variable::NORMAL); + + Expect(Token::RPAREN, CHECK_OK); + if (!is_simple) { DeclarationDescriptor descriptor; descriptor.declaration_kind = DeclarationDescriptor::NORMAL; @@ -2978,6 +2978,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) { catch_block->statements()->Add(init_block, zone()); } + // TODO(adamk): This should call ParseBlock in order to properly + // add an additional block scope for the catch body. Expect(Token::LBRACE, CHECK_OK); while (peek() != Token::RBRACE) { Statement* stat = ParseStatementListItem(CHECK_OK); diff --git a/deps/v8/test/mjsunit/regress/regress-5106.js b/deps/v8/test/mjsunit/regress/regress-5106.js new file mode 100644 index 00000000000000..52d550a8784068 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-5106.js @@ -0,0 +1,29 @@ +// Copyright 2016 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. + +function* g1() { + try { + throw {}; + } catch ({a = class extends (yield) {}}) { + } +} +g1().next(); // crashes without fix + +function* g2() { + let x = function(){}; + try { + throw {}; + } catch ({b = class extends x {}}) { + } +} +g2().next(); // crashes without fix + +function* g3() { + let x = 42; + try { + throw {}; + } catch ({c = (function() { return x })()}) { + } +} +g3().next(); // throws a ReferenceError without fix