diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h index 57955ae15d..773a4f9822 100644 --- a/src/parsing/parser-base.h +++ b/src/parsing/parser-base.h @@ -3211,12 +3211,15 @@ typename ParserBase::ExpressionT ParserBase::ParseUnaryExpression( classifier()->RecordFormalParameterInitializerError( scanner()->peek_location(), MessageTemplate::kAwaitExpressionFormalParameter); - int await_pos = peek_position(); Consume(Token::AWAIT); ExpressionT value = ParseUnaryExpression(CHECK_OK); + classifier()->RecordBindingPatternError( + Scanner::Location(await_pos, scanner()->location().end_pos), + MessageTemplate::kInvalidDestructuringTarget); + ExpressionT expr = factory()->NewAwait(value, await_pos); impl()->RecordSuspendSourceRange(expr, PositionAfterSemicolon()); return expr; diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index 984f464a95..b8c1e17ed7 100644 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -8570,6 +8570,64 @@ TEST(AsyncAwaitErrors) { RunParserSyncTest(async_body_context_data, async_body_error_data, kError); } +TEST(Regress7173) { + // Await expression is an invalid destructuring target, and should not crash + + // clang-format off + const char* error_context_data[][2] = { + { "'use strict'; async function f() {", "}" }, + { "async function f() {", "}" }, + { "'use strict'; function f() {", "}" }, + { "function f() {", "}" }, + { "let f = async() => {", "}" }, + { "let f = () => {", "}" }, + { "'use strict'; async function* f() {", "}" }, + { "async function* f() {", "}" }, + { "'use strict'; function* f() {", "}" }, + { "function* f() {", "}" }, + { nullptr, nullptr } + }; + + const char* error_data[] = { + "var [await f] = [];", + "let [await f] = [];", + "const [await f] = [];", + + "var [...await f] = [];", + "let [...await f] = [];", + "const [...await f] = [];", + + "var { await f } = {};", + "let { await f } = {};", + "const { await f } = {};", + + "var { ...await f } = {};", + "let { ...await f } = {};", + "const { ...await f } = {};", + + "var { f: await f } = {};", + "let { f: await f } = {};", + "const { f: await f } = {};" + + "var { f: ...await f } = {};", + "let { f: ...await f } = {};", + "const { f: ...await f } = {};" + + "var { [f]: await f } = {};", + "let { [f]: await f } = {};", + "const { [f]: await f } = {};", + + "var { [f]: ...await f } = {};", + "let { [f]: ...await f } = {};", + "const { [f]: ...await f } = {};", + + nullptr + }; + // clang-format on + + RunParserSyncTest(error_context_data, error_data, kError); +} + TEST(AsyncAwaitFormalParameters) { // clang-format off const char* context_for_formal_parameters[][2] = { diff --git a/test/message/fail/array-binding-pattern-await1.js b/test/message/fail/array-binding-pattern-await1.js new file mode 100644 index 0000000000..09afccc09f --- /dev/null +++ b/test/message/fail/array-binding-pattern-await1.js @@ -0,0 +1,9 @@ +// Copyright 2017 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. + +async function f() { + let [await b] = []; + return b; +} +f(); diff --git a/test/message/fail/array-binding-pattern-await1.out b/test/message/fail/array-binding-pattern-await1.out new file mode 100644 index 0000000000..9ebe2433ed --- /dev/null +++ b/test/message/fail/array-binding-pattern-await1.out @@ -0,0 +1,4 @@ +*%(basename)s:6: SyntaxError: Invalid destructuring assignment target + let [await b] = []; + ^^^^^^^ +SyntaxError: Invalid destructuring assignment target diff --git a/test/message/fail/object-binding-pattern-await1.js b/test/message/fail/object-binding-pattern-await1.js new file mode 100644 index 0000000000..8ef7b25866 --- /dev/null +++ b/test/message/fail/object-binding-pattern-await1.js @@ -0,0 +1,9 @@ +// Copyright 2017 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. + +async function f() { + let { a: await b } = { a: 1 }; + return b; +} +f(); diff --git a/test/message/fail/object-binding-pattern-await1.out b/test/message/fail/object-binding-pattern-await1.out new file mode 100644 index 0000000000..ee7a3eafb6 --- /dev/null +++ b/test/message/fail/object-binding-pattern-await1.out @@ -0,0 +1,4 @@ +*%(basename)s:6: SyntaxError: Invalid destructuring assignment target + let { a: await b } = { a: 1 }; + ^^^^^^^ +SyntaxError: Invalid destructuring assignment target diff --git a/test/message/object-binding-pattern-await-computed-name.js b/test/message/object-binding-pattern-await-computed-name.js new file mode 100644 index 0000000000..1b40d0d4a9 --- /dev/null +++ b/test/message/object-binding-pattern-await-computed-name.js @@ -0,0 +1,9 @@ +// Copyright 2017 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. + +async function f() { + let { [await "a"]: a } = { a: 1 }; + return a; +} +f(); diff --git a/test/message/object-binding-pattern-await-computed-name.out b/test/message/object-binding-pattern-await-computed-name.out new file mode 100644 index 0000000000..e69de29bb2