Revert "Revert of [es6] Implement destructuring binding in try/catch"
Reland try/catch destructuring with a fix for the MemorySanitizer failure: initialization_pos needs to be initialized in the DeclarationDescriptor. This is a one line fix to http://crrev.com/a316db995e6e4253664920652ed4e5a38b2caeba BUG=v8:811 LOG=y Review URL: https://codereview.chromium.org/1411323008 Cr-Commit-Position: refs/heads/master@{#31834}
This commit is contained in:
parent
760eb0a9f4
commit
80a1e004f4
@ -255,6 +255,7 @@ class AstValue : public ZoneObject {
|
||||
F(dot_module, ".module") \
|
||||
F(dot_result, ".result") \
|
||||
F(dot_switch_tag, ".switch_tag") \
|
||||
F(dot_catch, ".catch") \
|
||||
F(empty, "") \
|
||||
F(eval, "eval") \
|
||||
F(let, "let") \
|
||||
|
@ -1073,7 +1073,8 @@ FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
|
||||
// unchanged if the property already exists.
|
||||
InsertSloppyBlockFunctionVarBindings(scope, &ok);
|
||||
}
|
||||
if (ok && (is_strict(language_mode()) || allow_harmony_sloppy())) {
|
||||
if (ok && (is_strict(language_mode()) || allow_harmony_sloppy() ||
|
||||
allow_harmony_destructuring())) {
|
||||
CheckConflictingVarDeclarations(scope_, &ok);
|
||||
}
|
||||
|
||||
@ -3157,21 +3158,79 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
|
||||
Scope* catch_scope = NULL;
|
||||
Variable* catch_variable = NULL;
|
||||
Block* catch_block = NULL;
|
||||
const AstRawString* name = NULL;
|
||||
if (tok == Token::CATCH) {
|
||||
Consume(Token::CATCH);
|
||||
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
catch_scope = NewScope(scope_, CATCH_SCOPE);
|
||||
catch_scope->set_start_position(scanner()->location().beg_pos);
|
||||
name = ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
|
||||
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
ExpressionClassifier pattern_classifier;
|
||||
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);
|
||||
BlockState block_state(&scope_, catch_scope);
|
||||
catch_block = ParseBlock(NULL, CHECK_OK);
|
||||
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
|
||||
{
|
||||
BlockState block_state(&scope_, catch_scope);
|
||||
|
||||
// TODO(adamk): Make a version of ParseScopedBlock that takes a scope and
|
||||
// a block.
|
||||
catch_block =
|
||||
factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
|
||||
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);
|
||||
|
||||
if (!is_simple) {
|
||||
DeclarationDescriptor descriptor;
|
||||
descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
|
||||
descriptor.parser = this;
|
||||
descriptor.declaration_scope = scope_;
|
||||
descriptor.scope = scope_;
|
||||
descriptor.hoist_scope = nullptr;
|
||||
descriptor.mode = LET;
|
||||
descriptor.is_const = false;
|
||||
descriptor.needs_init = true;
|
||||
descriptor.declaration_pos = pattern->position();
|
||||
descriptor.initialization_pos = pattern->position();
|
||||
descriptor.init_op = Token::INIT_LET;
|
||||
|
||||
DeclarationParsingResult::Declaration decl(
|
||||
pattern, pattern->position(),
|
||||
factory()->NewVariableProxy(catch_variable));
|
||||
|
||||
PatternRewriter::DeclareAndInitializeVariables(
|
||||
catch_block, &descriptor, &decl, nullptr, CHECK_OK);
|
||||
}
|
||||
|
||||
Expect(Token::LBRACE, CHECK_OK);
|
||||
while (peek() != Token::RBRACE) {
|
||||
Statement* stat = ParseStatementListItem(CHECK_OK);
|
||||
if (stat && !stat->IsEmpty()) {
|
||||
catch_block->statements()->Add(stat, zone());
|
||||
}
|
||||
}
|
||||
Consume(Token::RBRACE);
|
||||
}
|
||||
block_scope->set_end_position(scanner()->location().end_pos);
|
||||
block_scope = block_scope->FinalizeBlockScope();
|
||||
catch_block->set_scope(block_scope);
|
||||
}
|
||||
|
||||
catch_scope->set_end_position(scanner()->location().end_pos);
|
||||
tok = peek();
|
||||
@ -4371,7 +4430,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
|
||||
if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) {
|
||||
InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
|
||||
}
|
||||
if (is_strict(language_mode) || allow_harmony_sloppy()) {
|
||||
if (is_strict(language_mode) || allow_harmony_sloppy() ||
|
||||
allow_harmony_destructuring()) {
|
||||
CheckConflictingVarDeclarations(scope, CHECK_OK);
|
||||
}
|
||||
}
|
||||
|
@ -1039,9 +1039,12 @@ PreParser::Statement PreParser::ParseTryStatement(bool* ok) {
|
||||
if (tok == Token::CATCH) {
|
||||
Consume(Token::CATCH);
|
||||
Expect(Token::LPAREN, CHECK_OK);
|
||||
ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
|
||||
ExpressionClassifier pattern_classifier;
|
||||
ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
|
||||
ValidateBindingPattern(&pattern_classifier, CHECK_OK);
|
||||
Expect(Token::RPAREN, CHECK_OK);
|
||||
{
|
||||
// TODO(adamk): Make this CATCH_SCOPE
|
||||
Scope* with_scope = NewScope(scope_, WITH_SCOPE);
|
||||
BlockState block_state(&scope_, with_scope);
|
||||
ParseBlock(CHECK_OK);
|
||||
|
@ -6514,6 +6514,7 @@ TEST(DestructuringPositiveTests) {
|
||||
{"function f(argument1, ", ") {}"},
|
||||
{"var f = (", ") => {};"},
|
||||
{"var f = (argument1,", ") => {};"},
|
||||
{"try {} catch(", ") {}"},
|
||||
{NULL, NULL}};
|
||||
|
||||
// clang-format off
|
||||
@ -6575,6 +6576,7 @@ TEST(DestructuringNegativeTests) {
|
||||
{"var f = (", ") => {};"},
|
||||
{"var f = ", " => {};"},
|
||||
{"var f = (argument1,", ") => {};"},
|
||||
{"try {} catch(", ") {}"},
|
||||
{NULL, NULL}};
|
||||
|
||||
// clang-format off
|
||||
|
11
test/message/try-catch-lexical-conflict.js
Normal file
11
test/message/try-catch-lexical-conflict.js
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2015 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-destructuring
|
||||
|
||||
"use strict";
|
||||
try {
|
||||
} catch ({x}) {
|
||||
let x;
|
||||
}
|
4
test/message/try-catch-lexical-conflict.out
Normal file
4
test/message/try-catch-lexical-conflict.out
Normal file
@ -0,0 +1,4 @@
|
||||
*%(basename)s:10: SyntaxError: Identifier 'x' has already been declared
|
||||
let x;
|
||||
^
|
||||
SyntaxError: Identifier 'x' has already been declared
|
10
test/message/try-catch-variable-conflict.js
Normal file
10
test/message/try-catch-variable-conflict.js
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2015 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-destructuring
|
||||
|
||||
try {
|
||||
} catch ({x}) {
|
||||
var x;
|
||||
}
|
4
test/message/try-catch-variable-conflict.out
Normal file
4
test/message/try-catch-variable-conflict.out
Normal file
@ -0,0 +1,4 @@
|
||||
*%(basename)s:9: SyntaxError: Identifier 'x' has already been declared
|
||||
var x;
|
||||
^
|
||||
SyntaxError: Identifier 'x' has already been declared
|
@ -1098,8 +1098,36 @@
|
||||
function(){ eval("(class{foo(a, {}) {'use strict';}});") }, SyntaxError);
|
||||
})();
|
||||
|
||||
|
||||
(function TestLegacyConstDestructuringInForLoop() {
|
||||
var result;
|
||||
for (const {foo} of [{foo: 1}]) { result = foo; }
|
||||
assertEquals(1, result);
|
||||
})();
|
||||
|
||||
|
||||
(function TestCatch() {
|
||||
"use strict";
|
||||
|
||||
// For testing proper scoping.
|
||||
var foo = "hello", bar = "world", baz = 42;
|
||||
|
||||
try {
|
||||
throw {foo: 1, bar: 2};
|
||||
} catch ({foo, bar, baz = 3}) {
|
||||
assertEquals(1, foo);
|
||||
assertEquals(2, bar);
|
||||
assertEquals(3, baz);
|
||||
}
|
||||
|
||||
try {
|
||||
throw [1, 2, 3];
|
||||
} catch ([foo, ...bar]) {
|
||||
assertEquals(1, foo);
|
||||
assertEquals([2, 3], bar);
|
||||
}
|
||||
|
||||
assertEquals("hello", foo);
|
||||
assertEquals("world", bar);
|
||||
assertEquals(42, baz);
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user