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( ...@@ -3793,6 +3793,7 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment(
if (spread) { if (spread) {
RegisterAllocationScope scope(this); RegisterAllocationScope scope(this);
BytecodeLabel is_done;
// A spread is turned into a loop over the remainer of the iterator. // A spread is turned into a loop over the remainer of the iterator.
Expression* target = spread->expression(); Expression* target = spread->expression();
...@@ -3809,6 +3810,10 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment( ...@@ -3809,6 +3810,10 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment(
feedback_index(feedback_spec()->AddLiteralSlot())); feedback_index(feedback_spec()->AddLiteralSlot()));
builder()->StoreAccumulatorInRegister(array); builder()->StoreAccumulatorInRegister(array);
// If done, jump to assigning empty array
builder()->LoadAccumulatorWithRegister(done);
builder()->JumpIfTrue(ToBooleanMode::kConvertToBoolean, &is_done);
// var index = 0; // var index = 0;
Register index = register_allocator()->NewRegister(); Register index = register_allocator()->NewRegister();
builder()->LoadLiteral(Smi::zero()); builder()->LoadLiteral(Smi::zero());
...@@ -3826,6 +3831,7 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment( ...@@ -3826,6 +3831,7 @@ void BytecodeGenerator::BuildDestructuringArrayAssignment(
next_value_load_slot, next_done_load_slot, next_value_load_slot, next_done_load_slot,
index_slot, element_slot); index_slot, element_slot);
builder()->Bind(&is_done);
// Assign the array to the LHS. // Assign the array to the LHS.
builder()->LoadAccumulatorWithRegister(array); builder()->LoadAccumulatorWithRegister(array);
BuildAssignment(lhs_data, op, lookup_hoisting_mode); BuildAssignment(lhs_data, op, lookup_hoisting_mode);
......
...@@ -100,7 +100,7 @@ snippet: " ...@@ -100,7 +100,7 @@ snippet: "
" "
frame size: 14 frame size: 14
parameter count: 1 parameter count: 1
bytecode array length: 232 bytecode array length: 236
bytecodes: [ bytecodes: [
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37), /* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
B(Star), R(2), B(Star), R(2),
...@@ -149,6 +149,8 @@ bytecodes: [ ...@@ -149,6 +149,8 @@ bytecodes: [
B(Star), R(0), B(Star), R(0),
/* 63 S> */ B(CreateEmptyArrayLiteral), U8(15), /* 63 S> */ B(CreateEmptyArrayLiteral), U8(15),
B(Star), R(11), B(Star), R(11),
B(Ldar), R(6),
B(JumpIfToBooleanTrue), U8(44),
B(LdaZero), B(LdaZero),
B(Star), R(12), B(Star), R(12),
B(LdaTrue), B(LdaTrue),
...@@ -211,8 +213,8 @@ constant pool: [ ...@@ -211,8 +213,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
] ]
handlers: [ handlers: [
[34, 162, 170], [34, 166, 174],
[186, 207, 209], [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