Commit 83f778af authored by Gus Caplan's avatar Gus Caplan Committed by Commit Bot

Add iterator done check in spread destructuring

This fixes the logic in the desugaring of destructuring assignments. In
particular, a spread element would not check if previous `next` results
had already been done, and would always call `next()` again.

Change-Id: I1bd384678722e6cf51c5777fc3b0dd965360291a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2430488
Commit-Queue: Gus Caplan <snek@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70144}
parent 74794fb9
......@@ -3793,6 +3793,7 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment(
if (spread) {
RegisterAllocationScope scope(this);
BytecodeLabel is_done;
// A spread is turned into a loop over the remainer of the iterator.
Expression* target = spread->expression();
......@@ -3809,6 +3810,10 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment(
feedback_index(feedback_spec()->AddLiteralSlot()));
builder()->StoreAccumulatorInRegister(array);
// If done, jump to assigning empty array
builder()->LoadAccumulatorWithRegister(done);
builder()->JumpIfTrue(ToBooleanMode::kConvertToBoolean, &is_done);
// var index = 0;
Register index = register_allocator()->NewRegister();
builder()->LoadLiteral(Smi::zero());
......@@ -3826,6 +3831,7 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment(
next_value_load_slot, next_done_load_slot,
index_slot, element_slot);
builder()->Bind(&is_done);
// Assign the array to the LHS.
builder()->LoadAccumulatorWithRegister(array);
BuildAssignment(lhs_data, op, lookup_hoisting_mode);
......
......@@ -100,7 +100,7 @@ snippet: "
"
frame size: 14
parameter count: 1
bytecode array length: 232
bytecode array length: 236
bytecodes: [
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(2),
......@@ -149,6 +149,8 @@ bytecodes: [
B(Star), R(0),
/* 63 S> */ B(CreateEmptyArrayLiteral), U8(15),
B(Star), R(11),
B(Ldar), R(6),
B(JumpIfToBooleanTrue), U8(44),
B(LdaZero),
B(Star), R(12),
B(LdaTrue),
......@@ -211,8 +213,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
]
handlers: [
[34, 162, 170],
[186, 207, 209],
[34, 166, 174],
[190, 211, 213],
]
---
......
// 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.
'use strict';
let called = 0
const it = {
[Symbol.iterator]() {
return this;
},
next() {
called += 1;
return {
value: 42,
done: true,
};
},
};
const [a, b, ...c] = it;
assertEquals(called, 1);
assertEquals(a, undefined);
assertEquals(b, undefined);
assertEquals(c.length, 0);
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