Commit ff1a155a authored by Caitlin Potter's avatar Caitlin Potter Committed by Commit Bot

[parser] allow patterns within left/right branches of ConditionalExpr

The AssignmentExpressions can legally contain destructuring assignments.

BUG=v8:6098
R=marja@chromium.org, adamk@chromium.org

Change-Id: I99b3a0f4c8d103edfb1dda943ec3e2ab2a5969f7
Reviewed-on: https://chromium-review.googlesource.com/455221
Commit-Queue: Caitlin Potter <caitp@igalia.com>
Reviewed-by: 's avatarAdam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44049}
parent 786c64e8
......@@ -1422,6 +1422,14 @@ class ParserBase {
classifier_ = previous;
}
V8_INLINE void AccumulateNonBindingPatternErrors() {
static const bool kMergeNonPatterns = true;
this->Accumulate(ExpressionClassifier::AllProductions &
~(ExpressionClassifier::BindingPatternProduction |
ExpressionClassifier::LetPatternProduction),
kMergeNonPatterns);
}
// Pops and discards the classifier that is on top of the stack
// without accumulating.
V8_INLINE void Discard() {
......@@ -1912,9 +1920,7 @@ ParserBase<Impl>::ParseExpressionCoverGrammar(bool accept_IN, bool* ok) {
}
// No need to accumulate binding pattern-related errors, since
// an Expression can't be a binding pattern anyway.
impl()->Accumulate(ExpressionClassifier::AllProductions &
~(ExpressionClassifier::BindingPatternProduction |
ExpressionClassifier::LetPatternProduction));
impl()->AccumulateNonBindingPatternErrors();
if (!impl()->IsIdentifier(right)) classifier()->RecordNonSimpleParameter();
if (impl()->IsEmptyExpression(result)) {
// First time through the loop.
......@@ -2948,13 +2954,24 @@ ParserBase<Impl>::ParseConditionalExpression(bool accept_IN,
BindingPatternUnexpectedToken();
ArrowFormalParametersUnexpectedToken();
Consume(Token::CONDITIONAL);
// In parsing the first assignment expression in conditional
// expressions we always accept the 'in' keyword; see ECMA-262,
// section 11.12, page 58.
ExpressionT left = ParseAssignmentExpression(true, CHECK_OK);
ExpressionT left;
{
ExpressionClassifier classifier(this);
// In parsing the first assignment expression in conditional
// expressions we always accept the 'in' keyword; see ECMA-262,
// section 11.12, page 58.
left = ParseAssignmentExpression(true, CHECK_OK);
impl()->AccumulateNonBindingPatternErrors();
}
impl()->RewriteNonPattern(CHECK_OK);
Expect(Token::COLON, CHECK_OK);
ExpressionT right = ParseAssignmentExpression(accept_IN, CHECK_OK);
ExpressionT right;
{
ExpressionClassifier classifier(this);
right = ParseAssignmentExpression(accept_IN, CHECK_OK);
impl()->AccumulateNonBindingPatternErrors();
}
impl()->RewriteNonPattern(CHECK_OK);
return factory()->NewConditional(expression, left, right, pos);
}
......
......@@ -7659,6 +7659,10 @@ TEST(DestructuringAssignmentPositiveTests) {
{"var x, y, z; for (", " of {});"},
{"'use strict'; var x, y, z; for (", " in {});"},
{"'use strict'; var x, y, z; for (", " of {});"},
{"var x, y, z; m(['a']) ? ", " = {} : rhs"},
{"var x, y, z; m(['b']) ? lhs : ", " = {}"},
{"'use strict'; var x, y, z; m(['a']) ? ", " = {} : rhs"},
{"'use strict'; var x, y, z; m(['b']) ? lhs : ", " = {}"},
{NULL, NULL}};
const char* mixed_assignments_context_data[][2] = {
......
// Copyright 2018 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.
const fn = (c) => {
let d = [1, 2], x = [3, 4],
e = null,
f = null;
0 < c.getIn(['a']) ? [e, f] = d : [e, f] = x;
return [e, f];
};
assertEquals([3, 4], fn({ getIn(x) { return false; } }));
assertEquals([1, 2], fn({ getIn(x) { return true; } }));
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