Commit 1f1af42d authored by caitpotter88's avatar caitpotter88 Committed by Commit bot

[parser] parenthesized Literals are not valid AssignmentPatterns

Encode "parenthesized" status of parenthesized Expressions to prevent
them from being treated as Patterns.

BUG=v8:4657, v8:811
LOG=N
R=rossberg@chromium.org, adamk@chromium.org, littledan@chromium.org

Review URL: https://codereview.chromium.org/1570793002

Cr-Commit-Position: refs/heads/master@{#33190}
parent 23235b5f
......@@ -365,6 +365,14 @@ class Expression : public AstNode {
BailoutId id() const { return BailoutId(local_id(0)); }
TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); }
// Parenthesized expressions in the form `( Expression )`.
void set_is_parenthesized() {
bit_field_ = ParenthesizedField::update(bit_field_, true);
}
bool is_parenthesized() const {
return ParenthesizedField::decode(bit_field_);
}
protected:
Expression(Zone* zone, int pos)
: AstNode(pos),
......@@ -387,6 +395,8 @@ class Expression : public AstNode {
int base_id_;
Bounds bounds_;
class ToBooleanTypesField : public BitField16<uint16_t, 0, 9> {};
class ParenthesizedField
: public BitField16<bool, ToBooleanTypesField::kNext, 1> {};
uint16_t bit_field_;
// Ends with 16-bit field; deriving classes in turn begin with
// 16-bit fields for optimum packing efficiency.
......
......@@ -1365,6 +1365,7 @@ ParserBase<Traits>::ParsePrimaryExpression(ExpressionClassifier* classifier,
Expect(Token::RPAREN, CHECK_OK);
if (peek() != Token::ARROW) {
ValidateExpression(classifier, CHECK_OK);
expr->set_is_parenthesized();
}
return expr;
}
......@@ -2041,7 +2042,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, int flags,
ExpressionClassifier::CoverInitializedNameProduction);
bool maybe_pattern =
expression->IsObjectLiteral() || expression->IsArrayLiteral();
(expression->IsObjectLiteral() || expression->IsArrayLiteral()) &&
!expression->is_parenthesized();
if (!Token::IsAssignmentOp(peek())) {
// Parsed conditional expression only (no assignment).
......
......@@ -2366,7 +2366,9 @@ void Parser::ParseVariableDeclarations(VariableDeclarationContext var_context,
}
}
bool is_pattern = pattern->IsObjectLiteral() || pattern->IsArrayLiteral();
bool is_pattern =
(pattern->IsObjectLiteral() || pattern->IsArrayLiteral()) &&
!pattern->is_parenthesized();
Scanner::Location variable_loc = scanner()->location();
const AstRawString* single_name =
......
......@@ -591,7 +591,8 @@ PreParser::Statement PreParser::ParseVariableDeclarations(
}
}
is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral();
is_pattern = (pattern.IsObjectLiteral() || pattern.IsArrayLiteral()) &&
!pattern.is_parenthesized();
bool is_for_iteration_variable =
var_context == kForStatement &&
......
......@@ -279,6 +279,12 @@ class PreParserExpression {
int position() const { return RelocInfo::kNoPosition; }
void set_function_token_position(int position) {}
// Parenthesized expressions in the form `( Expression )`.
void set_is_parenthesized() {
code_ = ParenthesizedField::update(code_, true);
}
bool is_parenthesized() const { return ParenthesizedField::decode(code_); }
private:
enum Type {
kExpression,
......@@ -306,6 +312,13 @@ class PreParserExpression {
// The first three bits are for the Type.
typedef BitField<Type, 0, 3> TypeField;
// The high order bit applies only to nodes which would inherit from the
// Expression ASTNode --- This is by necessity, due to the fact that
// Expression nodes may be represented as multiple Types, not exclusively
// through kExpression.
// TODO(caitp, adamk): clean up PreParserExpression bitfields.
typedef BitField<bool, 31, 1> ParenthesizedField;
// The rest of the bits are interpreted depending on the value
// of the Type field, so they can share the storage.
typedef BitField<ExpressionType, TypeField::kNext, 3> ExpressionTypeField;
......
......@@ -7043,6 +7043,21 @@ TEST(DestructuringAssignmentNegativeTests) {
"[...x,]",
"[x, y, ...z = 1]",
"[...z = 1]",
// v8:4657
"({ x: x4, x: (x+=1e4) })",
"(({ x: x4, x: (x+=1e4) }))",
"({ x: x4, x: (x+=1e4) } = {})",
"(({ x: x4, x: (x+=1e4) } = {}))",
"(({ x: x4, x: (x+=1e4) }) = {})",
"({ x: y } = {})",
"(({ x: y } = {}))",
"(({ x: y }) = {})",
"([a])",
"(([a]))",
"([a] = [])",
"(([a] = []))",
"(([a]) = [])",
NULL};
// clang-format on
static const ParserFlag always_flags[] = {
......
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