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

Reland "Set .name of anonymous functions on the RHS of logical assignment."

This is a reland of c342ba82

Original change's description:
> Set .name of anonymous functions on the RHS of logical assignment.
> 
> https://github.com/tc39/proposal-logical-assignment/pull/24 reached
> consensus in June TC39.
> 
> Drive-by refactoring of testing for logical assignment ops using
> IsInRange.
> 
> Bug: v8:10579
> Change-Id: I5a203ba552a905cd28f75c5d223998431a1966ce
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2225809
> Reviewed-by: Marja Hölttä <marja@chromium.org>
> Commit-Queue: Shu-yu Guo <syg@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#68101}

Bug: v8:10579
Change-Id: I321cf0e29515a146844abc05250e9b50ad651caf
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2227255
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68161}
parent f6ce085a
......@@ -2755,8 +2755,7 @@ ParserBase<Impl>::ParseAssignmentExpressionCoverGrammar() {
Token::Value op = peek();
if (!Token::IsArrowOrAssignmentOp(op)) return expression;
if ((op == Token::ASSIGN_NULLISH || op == Token::ASSIGN_OR ||
op == Token::ASSIGN_AND) &&
if (Token::IsLogicalAssignmentOp(op) &&
!flags().allow_harmony_logical_assignment()) {
return expression;
}
......@@ -2830,13 +2829,8 @@ ParserBase<Impl>::ParseAssignmentExpressionCoverGrammar() {
ExpressionT right = ParseAssignmentExpression();
if (op == Token::ASSIGN) {
// We try to estimate the set of properties set by constructors. We define a
// new property whenever there is an assignment to a property of 'this'. We
// should probably only add properties if we haven't seen them before.
// Otherwise we'll probably overestimate the number of properties.
if (impl()->IsThisProperty(expression)) function_state_->AddProperty();
// Anonymous function name inference applies to =, ||=, &&=, and ??=.
if (op == Token::ASSIGN || Token::IsLogicalAssignmentOp(op)) {
impl()->CheckAssigningFunctionLiteralToProperty(expression, right);
// Check if the right hand side is a call to avoid inferring a
......@@ -2850,10 +2844,20 @@ ParserBase<Impl>::ParseAssignmentExpressionCoverGrammar() {
impl()->SetFunctionNameFromIdentifierRef(right, expression);
} else {
fni_.RemoveLastFunction();
}
if (op == Token::ASSIGN) {
// We try to estimate the set of properties set by constructors. We define a
// new property whenever there is an assignment to a property of 'this'. We
// should probably only add properties if we haven't seen them before.
// Otherwise we'll probably overestimate the number of properties.
if (impl()->IsThisProperty(expression)) function_state_->AddProperty();
} else {
// Only initializers (i.e. no compound assignments) are allowed in patterns.
expression_scope()->RecordPatternError(
Scanner::Location(lhs_beg_pos, end_position()),
MessageTemplate::kInvalidDestructuringTarget);
fni_.RemoveLastFunction();
}
return factory()->NewAssignment(op, expression, right, op_position);
......
......@@ -284,6 +284,10 @@ class V8_EXPORT_PRIVATE Token {
return base::IsInRange(token, INIT, ASSIGN_SUB);
}
static bool IsLogicalAssignmentOp(Value token) {
return base::IsInRange(token, ASSIGN_NULLISH, ASSIGN_AND);
}
static bool IsBinaryOp(Value op) { return base::IsInRange(op, COMMA, SUB); }
static bool IsCompareOp(Value op) { return base::IsInRange(op, EQ, IN); }
......
......@@ -1573,6 +1573,7 @@ enum ParserFlag {
kAllowHarmonyPrivateMethods,
kAllowHarmonyDynamicImport,
kAllowHarmonyImportMeta,
kAllowHarmonyLogicalAssignment,
};
enum ParserSyncTestResult {
......@@ -1586,6 +1587,8 @@ void SetGlobalFlags(base::EnumSet<ParserFlag> flags) {
i::FLAG_harmony_private_methods = flags.contains(kAllowHarmonyPrivateMethods);
i::FLAG_harmony_dynamic_import = flags.contains(kAllowHarmonyDynamicImport);
i::FLAG_harmony_import_meta = flags.contains(kAllowHarmonyImportMeta);
i::FLAG_harmony_logical_assignment =
flags.contains(kAllowHarmonyLogicalAssignment);
}
void SetParserFlags(i::UnoptimizedCompileFlags* compile_flags,
......@@ -1597,6 +1600,8 @@ void SetParserFlags(i::UnoptimizedCompileFlags* compile_flags,
flags.contains(kAllowHarmonyDynamicImport));
compile_flags->set_allow_harmony_import_meta(
flags.contains(kAllowHarmonyImportMeta));
compile_flags->set_allow_harmony_logical_assignment(
flags.contains(kAllowHarmonyLogicalAssignment));
}
void TestParserSyncWithFlags(i::Handle<i::String> source,
......@@ -11741,6 +11746,36 @@ TEST(HashbangSyntaxErrors) {
SyntaxErrorTest(other_context_data, hashbang_data);
}
TEST(LogicalAssignmentDestructuringErrors) {
// clang-format off
const char* context_data[][2] = {
{ "if (", ") { foo(); }" },
{ "(", ")" },
{ "foo(", ")" },
{ nullptr, nullptr }
};
const char* error_data[] = {
"[ x ] ||= [ 2 ]",
"[ x ||= 2 ] = [ 2 ]",
"{ x } ||= { x: 2 }",
"{ x: x ||= 2 ] = { x: 2 }",
"[ x ] &&= [ 2 ]",
"[ x &&= 2 ] = [ 2 ]",
"{ x } &&= { x: 2 }",
"{ x: x &&= 2 ] = { x: 2 }",
R"JS([ x ] ??= [ 2 ])JS",
R"JS([ x ??= 2 ] = [ 2 ])JS",
R"JS({ x } ??= { x: 2 })JS",
R"JS({ x: x ??= 2 ] = { x: 2 })JS",
nullptr
};
// clang-format on
static const ParserFlag flags[] = {kAllowHarmonyLogicalAssignment};
RunParserSyncTest(context_data, error_data, kError, nullptr, 0, flags,
arraysize(flags));
}
} // namespace test_parsing
} // namespace internal
} // namespace v8
// Copyright 2020 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-logical-assignment
{
let x = undefined;
x ??= function() {};
assertEquals(x.name, "x");
}
{
let y = false;
y ||= function() {};
assertEquals(y.name, "y");
}
{
let z = true;
z &&= function() {};
assertEquals(z.name, "z");
}
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