From 38409e5f97c983807bfdc947d2e943d265055833 Mon Sep 17 00:00:00 2001 From: Wleeaf <179125857+wleeaf@users.noreply.github.com> Date: Sun, 25 Oct 2026 16:06:24 +0000 Subject: [PATCH] fix: keep & on foreach targets that are not plain variables foreach can assign by reference to a property, an array element or a static property, not just to a variable. The parser marks such a value with byref, but only the variable printer prints the &, so foreach ($test as $key => &$array[$key]) {} was formatted as `foreach ($test as $key => $array[$key]) {}`, which assigns by value and silently changes what the loop does. The foreach printer now adds the & itself for a byref value that is not a variable. --- src/printer.mjs | 9 +++++++-- tests/foreach/__snapshots__/jsfmt.spec.mjs.snap | 12 ++++++++++++ tests/foreach/foreach.php | 6 ++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/printer.mjs b/src/printer.mjs index a9f06c170..2a00cb2ce 100644 --- a/src/printer.mjs +++ b/src/printer.mjs @@ -2063,6 +2063,11 @@ function printNode(path, options, print) { } case "foreach": { const body = printBodyControlStructure(path, options, print, "body"); + // Only a plain variable prints its own & + const value = + node.value.byref && node.value.kind !== "variable" + ? ["&", print("value")] + : print("value"); // We want to keep dangling comments above the loop to stay consistent. // Any comment positioned between the for statement and the parentheses @@ -2086,8 +2091,8 @@ function printNode(path, options, print) { "as ", group( node.key - ? indent(join([" =>", line], [print("key"), print("value")])) - : print("value") + ? indent(join([" =>", line], [print("key"), value])) + : value ), ]), softline, diff --git a/tests/foreach/__snapshots__/jsfmt.spec.mjs.snap b/tests/foreach/__snapshots__/jsfmt.spec.mjs.snap index 1b0055a93..af79ba8c9 100644 --- a/tests/foreach/__snapshots__/jsfmt.spec.mjs.snap +++ b/tests/foreach/__snapshots__/jsfmt.spec.mjs.snap @@ -72,6 +72,12 @@ foreach ($test as &$i) { $test2 = $i; } +foreach ($test as &$object->property) { +} + +foreach ($test as $key => &$array[$key]) { +} + =====================================output===================================== property) { +} + +foreach ($test as $key => &$array[$key]) { +} + ================================================================================ `; diff --git a/tests/foreach/foreach.php b/tests/foreach/foreach.php index f6ffdfc94..b2e368e45 100644 --- a/tests/foreach/foreach.php +++ b/tests/foreach/foreach.php @@ -63,3 +63,9 @@ foreach ($test as &$i) { $test2 = $i; } + +foreach ($test as &$object->property) { +} + +foreach ($test as $key => &$array[$key]) { +}