From 0197736dfc22adbe441ec50c16cf5c69c2655e76 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 6 Jun 2026 09:31:56 +0200 Subject: [PATCH] Reduce memory usage of the context restoration compiled at the end of for loops --- CHANGELOG | 1 + src/Node/ForNode.php | 5 ++++- tests/Node/ForTest.php | 12 ++++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e89fde984..972517c8c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ # 3.28.0 (2026-XX-XX) + * Reduce memory usage and speed up the context restoration compiled at the end of `for` loops * Report the column number in syntax errors and expose it via `Error::getTemplateColumn()` * Track the source offset of each token and expose it via `Token::getOffset()` * Fix nested `block()` calls to resolve against the overriding template when a block rendered through `block(name, template)` calls `parent()` diff --git a/src/Node/ForNode.php b/src/Node/ForNode.php index 2c86622d4..fda40719f 100644 --- a/src/Node/ForNode.php +++ b/src/Node/ForNode.php @@ -115,6 +115,9 @@ class ForNode extends Node $compiler->raw(");\n"); // keep the values set in the inner context for variables defined in the outer context - $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n"); + $compiler + ->write("\$context = array_intersect_key(\$context, \$_parent);\n") + ->write("\$context += \$_parent;\n") + ; } } diff --git a/tests/Node/ForTest.php b/tests/Node/ForTest.php index 2fcf0fa7c..9a642073c 100644 --- a/tests/Node/ForTest.php +++ b/tests/Node/ForTest.php @@ -77,7 +77,8 @@ foreach (\$context['_seq'] as \$context["key"] => \$context["item"]) { } \$_parent = \$context['_parent']; unset(\$context['_seq'], \$context['key'], \$context['item'], \$context['_parent']); -\$context = array_intersect_key(\$context, \$_parent) + \$_parent; +\$context = array_intersect_key(\$context, \$_parent); +\$context += \$_parent; EOF ]; @@ -119,7 +120,8 @@ foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) { } \$_parent = \$context['_parent']; unset(\$context['_seq'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']); -\$context = array_intersect_key(\$context, \$_parent) + \$_parent; +\$context = array_intersect_key(\$context, \$_parent); +\$context += \$_parent; EOF ]; @@ -161,7 +163,8 @@ foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) { } \$_parent = \$context['_parent']; unset(\$context['_seq'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']); -\$context = array_intersect_key(\$context, \$_parent) + \$_parent; +\$context = array_intersect_key(\$context, \$_parent); +\$context += \$_parent; EOF ]; @@ -210,7 +213,8 @@ if (!\$context['_iterated']) { } \$_parent = \$context['_parent']; unset(\$context['_seq'], \$context['k'], \$context['v'], \$context['_parent'], \$context['_iterated'], \$context['loop']); -\$context = array_intersect_key(\$context, \$_parent) + \$_parent; +\$context = array_intersect_key(\$context, \$_parent); +\$context += \$_parent; EOF ];