Commit bd82cdbd authored by Shu-yu Guo's avatar Shu-yu Guo Committed by Commit Bot

[parser] Disallow `for (async of expr)`

Implements https://github.com/tc39/ecma262/issues/2034

Currently the token sequence `for (async of` is ambiguous. It can be the
prefix for either `(async of => {};;);` or `for (async of foo);`. This
CL disallows the token sequence.

Note that `for await (async of` is still allowed, since there is no
C-style `for await (;;)`, and thus no ambiguity.

Bug: v8:11412
Change-Id: I3fede83a69420996baa2bc8b6c1cff000535d990
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2683221
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72607}
parent 36dedea6
......@@ -391,6 +391,7 @@ namespace internal {
T(ForInOfLoopInitializer, \
"% loop variable declaration may not have an initializer.") \
T(ForOfLet, "The left-hand side of a for-of loop may not start with 'let'.") \
T(ForOfAsync, "The left-hand side of a for-of loop may not be 'async'.") \
T(ForInOfLoopMultiBindings, \
"Invalid left-hand side in % loop: Must have a single binding.") \
T(GeneratorInSingleStatementContext, \
......
......@@ -5928,12 +5928,18 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement(
ExpressionParsingScope parsing_scope(impl());
AcceptINScope scope(this, false);
expression = ParseExpressionCoverGrammar();
// `for (async of` is disallowed but `for (async.x of` is allowed, so
// check if the token is ASYNC after parsing the expression.
bool expression_is_async = scanner()->current_token() == Token::ASYNC;
// Initializer is reference followed by in/of.
lhs_end_pos = end_position();
is_for_each = CheckInOrOf(&for_info.mode);
if (is_for_each) {
if (starts_with_let && for_info.mode == ForEachStatement::ITERATE) {
impl()->ReportMessageAt(next_loc, MessageTemplate::kForOfLet);
if ((starts_with_let || expression_is_async) &&
for_info.mode == ForEachStatement::ITERATE) {
impl()->ReportMessageAt(next_loc, starts_with_let
? MessageTemplate::kForOfLet
: MessageTemplate::kForOfAsync);
return impl()->NullStatement();
}
if (expression->IsPattern()) {
......
......@@ -557,7 +557,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
return property != nullptr && property->IsPrivateReference();
}
// This returns true if the expression is an indentifier (wrapped
// This returns true if the expression is an identifier (wrapped
// inside a variable proxy). We exclude the case of 'this', which
// has been converted to a variable proxy.
V8_INLINE static bool IsIdentifier(Expression* expression) {
......
......@@ -83,7 +83,7 @@ bytecodes: [
B(Mov), R(this), R(0),
B(Mov), R(context), R(2),
/* 48 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
/* 53 S> */ B(Wide), B(LdaSmi), I16(275),
/* 53 S> */ B(Wide), B(LdaSmi), I16(276),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......@@ -114,7 +114,7 @@ bytecodes: [
B(Mov), R(this), R(0),
B(Mov), R(context), R(2),
/* 41 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
/* 46 S> */ B(Wide), B(LdaSmi), I16(274),
/* 46 S> */ B(Wide), B(LdaSmi), I16(275),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......@@ -145,7 +145,7 @@ bytecodes: [
B(Mov), R(this), R(0),
B(Mov), R(context), R(2),
/* 48 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
/* 53 S> */ B(Wide), B(LdaSmi), I16(275),
/* 53 S> */ B(Wide), B(LdaSmi), I16(276),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......@@ -176,7 +176,7 @@ bytecodes: [
B(Mov), R(this), R(0),
B(Mov), R(context), R(2),
/* 41 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
/* 46 S> */ B(Wide), B(LdaSmi), I16(274),
/* 46 S> */ B(Wide), B(LdaSmi), I16(275),
B(Star), R(4),
B(LdaConstant), U8(0),
B(Star), R(5),
......
......@@ -56,7 +56,7 @@ bytecodes: [
B(Mov), R(this), R(0),
B(Mov), R(context), R(2),
/* 44 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
/* 49 S> */ B(Wide), B(LdaSmi), I16(273),
/* 49 S> */ B(Wide), B(LdaSmi), I16(274),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......@@ -88,7 +88,7 @@ bytecodes: [
B(Mov), R(this), R(0),
B(Mov), R(context), R(2),
/* 44 E> */ B(CallRuntime), U16(Runtime::kAddPrivateBrand), R(0), U8(3),
/* 49 S> */ B(Wide), B(LdaSmi), I16(273),
/* 49 S> */ B(Wide), B(LdaSmi), I16(274),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......
......@@ -24,7 +24,7 @@ bytecodes: [
B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(271),
B(Wide), B(LdaSmi), I16(272),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -55,7 +55,7 @@ frame size: 2
parameter count: 1
bytecode array length: 16
bytecodes: [
/* 56 S> */ B(Wide), B(LdaSmi), I16(273),
/* 56 S> */ B(Wide), B(LdaSmi), I16(274),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -82,7 +82,7 @@ frame size: 2
parameter count: 1
bytecode array length: 16
bytecodes: [
/* 56 S> */ B(Wide), B(LdaSmi), I16(273),
/* 56 S> */ B(Wide), B(LdaSmi), I16(274),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -121,7 +121,7 @@ bytecodes: [
/* 94 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(271),
B(Wide), B(LdaSmi), I16(272),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -143,7 +143,7 @@ bytecodes: [
/* 109 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(1),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(272),
B(Wide), B(LdaSmi), I16(273),
B(Star), R(3),
B(LdaConstant), U8(0),
B(Star), R(4),
......@@ -158,7 +158,7 @@ bytecodes: [
/* 133 E> */ B(TestReferenceEqual), R(this),
B(Mov), R(this), R(0),
B(JumpIfTrue), U8(18),
B(Wide), B(LdaSmi), I16(271),
B(Wide), B(LdaSmi), I16(272),
B(Star), R(2),
B(LdaConstant), U8(0),
B(Star), R(3),
......@@ -188,7 +188,7 @@ frame size: 2
parameter count: 1
bytecode array length: 16
bytecodes: [
/* 60 S> */ B(Wide), B(LdaSmi), I16(275),
/* 60 S> */ B(Wide), B(LdaSmi), I16(276),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -214,7 +214,7 @@ frame size: 2
parameter count: 1
bytecode array length: 16
bytecodes: [
/* 53 S> */ B(Wide), B(LdaSmi), I16(274),
/* 53 S> */ B(Wide), B(LdaSmi), I16(275),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -240,7 +240,7 @@ frame size: 2
parameter count: 1
bytecode array length: 16
bytecodes: [
/* 60 S> */ B(Wide), B(LdaSmi), I16(275),
/* 60 S> */ B(Wide), B(LdaSmi), I16(276),
B(Star), R(0),
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -266,7 +266,7 @@ frame size: 3
parameter count: 1
bytecode array length: 16
bytecodes: [
/* 46 S> */ B(Wide), B(LdaSmi), I16(274),
/* 46 S> */ B(Wide), B(LdaSmi), I16(275),
B(Star), R(1),
B(LdaConstant), U8(0),
B(Star), R(2),
......
......@@ -587,9 +587,6 @@
'intl402/DateTimeFormat/prototype/formatRange/date-same-returns-single-date': [FAIL],
'intl402/DateTimeFormat/prototype/formatRangeToParts/date-same-returns-single-date': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=11412
'language/statements/for-of/head-lhs-async-invalid': [FAIL],
######################## NEEDS INVESTIGATION ###########################
# https://bugs.chromium.org/p/v8/issues/detail?id=7833
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment