Skip to content

Commit c7206a9

Browse files
santysisifabpot
authored andcommitted
Fix: prevent "Cannot traverse an already closed generator" error by materializing Traversable input
1 parent 368bfb7 commit c7206a9

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

src/Symfony/Component/Serializer/Encoder/CsvEncoder.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ public function encode(mixed $data, string $format, array $context = []): string
6565
} elseif (empty($data)) {
6666
$data = [[]];
6767
} else {
68+
if ($data instanceof \Traversable) {
69+
// Generators can only be iterated once — convert to array to allow multiple traversals
70+
$data = iterator_to_array($data);
71+
}
6872
// Sequential arrays of arrays are considered as collections
6973
$i = 0;
7074
foreach ($data as $key => $value) {

src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,4 +710,28 @@ public function testEndOfLinePassedInConstructor()
710710
$encoder = new CsvEncoder([CsvEncoder::END_OF_LINE => "\r\n"]);
711711
$this->assertSame("foo,bar\r\nhello,test\r\n", $encoder->encode($value, 'csv'));
712712
}
713+
714+
/** @dataProvider provideIterable */
715+
public function testIterable(mixed $data)
716+
{
717+
$this->assertEquals(<<<'CSV'
718+
foo,bar
719+
hello,"hey ho"
720+
hi,"let's go"
721+
722+
CSV, $this->encoder->encode($data, 'csv'));
723+
}
724+
725+
public static function provideIterable()
726+
{
727+
$data = [
728+
['foo' => 'hello', 'bar' => 'hey ho'],
729+
['foo' => 'hi', 'bar' => 'let\'s go'],
730+
];
731+
732+
yield 'array' => [$data];
733+
yield 'array iterator' => [new \ArrayIterator($data)];
734+
yield 'iterator aggregate' => [new \IteratorIterator(new \ArrayIterator($data))];
735+
yield 'generator' => [(fn (): \Generator => yield from $data)()];
736+
}
713737
}

0 commit comments

Comments
 (0)