Skip to content

Commit 7166503

Browse files
ajkleinCommit bot
authored andcommitted
Do all parsing for try/catch destructuring inside the appropriate scopes
Previously, any expressions inside destructuring patterns in a catch would be parsed in the surrounding scope, instead of in the catch's scope. This change fixes that by entering not only the catch scope, but also the block scope inside it. [email protected] BUG=v8:5106, v8:5112 Review-Url: https://codereview.chromium.org/2110193002 Cr-Commit-Position: refs/heads/master@{#37415}
1 parent 3cfc9f2 commit 7166503

3 files changed

Lines changed: 51 additions & 21 deletions

File tree

src/parsing/parser.cc

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2999,40 +2999,40 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
29992999
catch_scope = NewScope(scope_, CATCH_SCOPE);
30003000
catch_scope->set_start_position(scanner()->location().beg_pos);
30013001

3002-
ExpressionClassifier pattern_classifier(this);
3003-
Expression* pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
3004-
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
3005-
3006-
const AstRawString* name = ast_value_factory()->dot_catch_string();
3007-
bool is_simple = pattern->IsVariableProxy();
3008-
if (is_simple) {
3009-
auto proxy = pattern->AsVariableProxy();
3010-
scope_->RemoveUnresolved(proxy);
3011-
name = proxy->raw_name();
3012-
}
3013-
3014-
catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
3015-
Variable::NORMAL);
3016-
3017-
Expect(Token::RPAREN, CHECK_OK);
3018-
30193002
{
30203003
CollectExpressionsInTailPositionToListScope
30213004
collect_tail_call_expressions_scope(
30223005
function_state_, &tail_call_expressions_in_catch_block);
30233006
BlockState block_state(&scope_, catch_scope);
30243007

3025-
// TODO(adamk): Make a version of ParseBlock that takes a scope and
3026-
// a block.
30273008
catch_block =
30283009
factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
3029-
Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
30303010

3011+
// Create a block scope to hold any lexical declarations created
3012+
// as part of destructuring the catch parameter.
3013+
Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
30313014
block_scope->set_start_position(scanner()->location().beg_pos);
30323015
{
30333016
BlockState block_state(&scope_, block_scope);
30343017
Target target(&this->target_stack_, catch_block);
30353018

3019+
ExpressionClassifier pattern_classifier(this);
3020+
Expression* pattern =
3021+
ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
3022+
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
3023+
3024+
const AstRawString* name = ast_value_factory()->dot_catch_string();
3025+
bool is_simple = pattern->IsVariableProxy();
3026+
if (is_simple) {
3027+
auto proxy = pattern->AsVariableProxy();
3028+
scope_->RemoveUnresolved(proxy);
3029+
name = proxy->raw_name();
3030+
}
3031+
catch_variable = catch_scope->DeclareLocal(
3032+
name, VAR, kCreatedInitialized, Variable::NORMAL);
3033+
3034+
Expect(Token::RPAREN, CHECK_OK);
3035+
30363036
if (!is_simple) {
30373037
DeclarationDescriptor descriptor;
30383038
descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
@@ -3054,6 +3054,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
30543054
catch_block->statements()->Add(init_block, zone());
30553055
}
30563056

3057+
// TODO(adamk): This should call ParseBlock in order to properly
3058+
// add an additional block scope for the catch body.
30573059
Expect(Token::LBRACE, CHECK_OK);
30583060
while (peek() != Token::RBRACE) {
30593061
Statement* stat = ParseStatementListItem(CHECK_OK);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2016 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
function* g1() {
6+
try {
7+
throw {};
8+
} catch ({a = class extends (yield) {}}) {
9+
}
10+
}
11+
g1().next(); // crashes without fix
12+
13+
function* g2() {
14+
let x = function(){};
15+
try {
16+
throw {};
17+
} catch ({b = class extends x {}}) {
18+
}
19+
}
20+
g2().next(); // crashes without fix
21+
22+
function* g3() {
23+
let x = 42;
24+
try {
25+
throw {};
26+
} catch ({c = (function() { return x })()}) {
27+
}
28+
}
29+
g3().next(); // throws a ReferenceError without fix

test/test262/test262.status

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@
322322

323323
# https://bugs.chromium.org/p/v8/issues/detail?id=5112
324324
'language/statements/try/scope-catch-block-lex-open': [FAIL],
325-
'language/statements/try/scope-catch-param-lex-open': [FAIL],
326325

327326
# https://bugs.chromium.org/p/v8/issues/detail?id=5012
328327
'intl402/Intl/getCanonicalLocales/*': [FAIL],

0 commit comments

Comments
 (0)