Skip to content

Commit e50f980

Browse files
committed
bug #4894 Fix an empty destructuring pattern triggering a PHP fatal error instead of a SyntaxError (fabpot)
This PR was merged into the 3.x branch. Discussion ---------- Fix an empty destructuring pattern triggering a PHP fatal error instead of a SyntaxError Commits ------- a2b0233 Fix an empty destructuring pattern triggering a PHP fatal error instead of a SyntaxError
2 parents cd25fe5 + a2b0233 commit e50f980

3 files changed

Lines changed: 23 additions & 0 deletions

File tree

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# 3.29.0 (2026-XX-XX)
22

33
* Add documentation comments to attach metadata to nodes (experimental)
4+
* Fix an empty destructuring pattern triggering a PHP fatal error instead of a `SyntaxError`
45
* Fix sequence destructuring of iterators throwing a `TypeError`
56
* Add `TempestMarkdown` to use `tempest/markdown` as the `markdown_to_html` converter
67
* Fix imported macros not resolving their own template-level macro imports

src/ExpressionParser/Infix/AssignmentExpressionParser.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ public function parse(Parser $parser, AbstractExpression $left, Token $token): A
5050
};
5151

5252
if ($left instanceof ArrayExpression) {
53+
if (!$left->getKeyValuePairs()) {
54+
throw new SyntaxError('Cannot destructure to an empty list of variables.', $token->getLine(), $parser->getStream()->getSourceContext());
55+
}
5356
foreach ($left->getKeyValuePairs() as $i => $pair) {
5457
if ($pair['value'] instanceof ContextVariable && !$pair['value'] instanceof AssignContextVariable) {
5558
$left->setNode(2 * $i + 1, new AssignContextVariable($pair['value']->getAttribute('name'), $pair['value']->getTemplateLine()));

tests/ExpressionParserTest.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,25 @@ public function testSequenceDestructuringUsesAssignmentTargets(): void
268268
$this->assertSame('third', $pairs[2]['value']->getAttribute('name'));
269269
}
270270

271+
/**
272+
* @dataProvider getEmptyDestructuringTests
273+
*/
274+
#[DataProvider('getEmptyDestructuringTests')]
275+
public function testEmptyDestructuringThrows(string $template): void
276+
{
277+
$env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]);
278+
279+
$this->expectException(SyntaxError::class);
280+
$this->expectExceptionMessage('Cannot destructure to an empty list of variables');
281+
$env->compileSource(new Source($template, 'index'));
282+
}
283+
284+
public static function getEmptyDestructuringTests()
285+
{
286+
yield ['{% do [] = values %}'];
287+
yield ['{% do {} = values %}'];
288+
}
289+
271290
public function testObjectDestructuringUsesAssignmentTargets(): void
272291
{
273292
$env = new Environment(new ArrayLoader(), ['cache' => false, 'autoescape' => false]);

0 commit comments

Comments
 (0)