[parser] Fix destructured parameters in arrowheads

Always unmark arrowhead parameters as assigned directly after their
initialization as the parser doesn't know when it first sees the
"assignment" that it may be in an arrowhead.

Bug: chromium:1003403, v8:8510
Change-Id: Iad5a4136d5ec06331fc43b81a809fd72cee2dd65
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1815131
Commit-Queue: Dan Elphick <delphick@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63947}
This commit is contained in:
Dan Elphick 2019-09-24 14:29:27 +01:00 committed by Commit Bot
parent 0ceee9ad28
commit f674045458
4 changed files with 34 additions and 1 deletions

View File

@ -84,6 +84,9 @@ class Variable final : public ZoneObject {
MaybeAssignedFlag maybe_assigned() const {
return MaybeAssignedFlagField::decode(bit_field_);
}
void clear_maybe_assigned() {
bit_field_ = MaybeAssignedFlagField::update(bit_field_, kNotAssigned);
}
void SetMaybeAssigned() {
if (mode() == VariableMode::kConst) return;

View File

@ -3599,7 +3599,19 @@ void ParserBase<Impl>::ParseFormalParameter(FormalParametersT* parameters) {
auto declaration_end = scope()->declarations()->end();
int initializer_end = end_position();
for (; declaration_it != declaration_end; ++declaration_it) {
declaration_it->var()->set_initializer_position(initializer_end);
Variable* var = declaration_it->var();
// The first time a variable is initialized (i.e. when the initializer
// position is unset), clear its maybe_assigned flag as it is not a true
// assignment. Since this is done directly on the Variable objects, it has
// no effect on VariableProxy objects appearing on the left-hand side of
// true assignments, so x will be still be marked as maybe_assigned for:
// (x = 1, y = (x = 2)) => {}
// and even:
// (x = (x = 2)) => {}.
if (var->initializer_position() == kNoSourcePosition)
var->clear_maybe_assigned();
var->set_initializer_position(initializer_end);
}
impl()->AddFormalParameter(parameters, pattern, initializer, end_position(),

View File

@ -3608,6 +3608,14 @@ TEST(MaybeAssignedParameters) {
"g(arg)}"},
{true, "function f(arg) {g(arg); eval('arguments[0] = 42'); g(arg)}"},
{true, "function f(arg) {g(arg); g(() => arguments[0] = 42); g(arg)}"},
// default values
{false, "function f({x:arg = 1}) {}"},
{true, "function f({x:arg = 1}, {y:b=(arg=2)}) {}"},
{true, "function f({x:arg = (arg = 2)}) {}"},
{false, "var f = ({x:arg = 1}) => {}"},
{true, "var f = ({x:arg = 1}, {y:b=(arg=2)}) => {}"},
{true, "var f = ({x:arg = (arg = 2)}) => {}"},
};
const char* suffix = "; f";

View File

@ -0,0 +1,10 @@
// Copyright 2019 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: --enable-lazy-source-positions --stress-lazy-source-positions
// Flags: --no-lazy
({ x: b = 0 }) => {
try { b; } catch (e) {}
function a() { b }
}