Remove usage of the internal _parent context variable in loops

This commit is contained in:
Fabien Potencier
2024-07-27 09:15:01 +02:00
parent c28f68f807
commit 1b9baa764b
2 changed files with 20 additions and 25 deletions
+5 -6
View File
@@ -39,6 +39,7 @@ class ForNode extends Node
{
$iteratorVar = $compiler->getVarName();
$functionVar = $compiler->getVarName();
$parentVar = $compiler->getVarName();
$compiler
->addDebugInfo($this)
@@ -48,11 +49,11 @@ class ForNode extends Node
->write("\$$functionVar = function (\$$iteratorVar, &\$context, \$blocks, &\$$functionVar, \$depth) {\n")
->indent()
->write("\$macros = \$this->macros;\n")
->write("\$context['_parent'] = \$context;\n")
->write("\$$parentVar = \$context;\n")
;
if ($this->getAttribute('with_loop')) {
$compiler->write("\$context['loop'] = new \Twig\Runtime\LoopContext(\$$iteratorVar, \$context['_parent'], \$blocks, \$$functionVar, \$depth);\n");
$compiler->write("\$context['loop'] = new \Twig\Runtime\LoopContext(\$$iteratorVar, \$$parentVar, \$blocks, \$$functionVar, \$depth);\n");
}
$compiler
@@ -77,13 +78,11 @@ class ForNode extends Node
;
}
$compiler->write("\$_parent = \$context['_parent'];\n");
// remove some "private" loop variables (needed for nested loops)
$compiler->write('unset($context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
$compiler->write('unset($context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'loop\']);'."\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, \$$parentVar) + \$$parentVar;\n");
$compiler
->write("return; yield;\n")
+15 -19
View File
@@ -59,13 +59,12 @@ class ForTest extends NodeTestCase
\$__internal_compile_0 = new \Twig\Runtime\LoopIterator({$this->getVariableGetter('items')});
\$__internal_compile_1 = function (\$__internal_compile_0, &\$context, \$blocks, &\$__internal_compile_1, \$depth) {
\$macros = \$this->macros;
\$context['_parent'] = \$context;
\$__internal_compile_2 = \$context;
foreach (\$__internal_compile_0 as \$context["key"] => \$context["item"]) {
yield {$this->getVariableGetter('foo')};
}
\$_parent = \$context['_parent'];
unset(\$context['key'], \$context['item'], \$context['_parent'], \$context['loop']);
\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
unset(\$context['key'], \$context['item'], \$context['loop']);
\$context = array_intersect_key(\$context, \$__internal_compile_2) + \$__internal_compile_2;
return; yield;
};
\Closure::bind(\$__internal_compile_1, \$this, self::class);
@@ -86,14 +85,13 @@ EOF
\$__internal_compile_0 = new \Twig\Runtime\LoopIterator({$this->getVariableGetter('values')});
\$__internal_compile_1 = function (\$__internal_compile_0, &\$context, \$blocks, &\$__internal_compile_1, \$depth) {
\$macros = \$this->macros;
\$context['_parent'] = \$context;
\$context['loop'] = new \Twig\Runtime\LoopContext(\$__internal_compile_0, \$context['_parent'], \$blocks, \$__internal_compile_1, \$depth);
\$__internal_compile_2 = \$context;
\$context['loop'] = new \Twig\Runtime\LoopContext(\$__internal_compile_0, \$__internal_compile_2, \$blocks, \$__internal_compile_1, \$depth);
foreach (\$__internal_compile_0 as \$context["k"] => \$context["v"]) {
yield {$this->getVariableGetter('foo')};
}
\$_parent = \$context['_parent'];
unset(\$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
unset(\$context['k'], \$context['v'], \$context['loop']);
\$context = array_intersect_key(\$context, \$__internal_compile_2) + \$__internal_compile_2;
return; yield;
};
\Closure::bind(\$__internal_compile_1, \$this, self::class);
@@ -114,14 +112,13 @@ EOF
\$__internal_compile_0 = new \Twig\Runtime\LoopIterator({$this->getVariableGetter('values')});
\$__internal_compile_1 = function (\$__internal_compile_0, &\$context, \$blocks, &\$__internal_compile_1, \$depth) {
\$macros = \$this->macros;
\$context['_parent'] = \$context;
\$context['loop'] = new \Twig\Runtime\LoopContext(\$__internal_compile_0, \$context['_parent'], \$blocks, \$__internal_compile_1, \$depth);
\$__internal_compile_2 = \$context;
\$context['loop'] = new \Twig\Runtime\LoopContext(\$__internal_compile_0, \$__internal_compile_2, \$blocks, \$__internal_compile_1, \$depth);
foreach (\$__internal_compile_0 as \$context["k"] => \$context["v"]) {
yield {$this->getVariableGetter('foo')};
}
\$_parent = \$context['_parent'];
unset(\$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
unset(\$context['k'], \$context['v'], \$context['loop']);
\$context = array_intersect_key(\$context, \$__internal_compile_2) + \$__internal_compile_2;
return; yield;
};
\Closure::bind(\$__internal_compile_1, \$this, self::class);
@@ -142,17 +139,16 @@ EOF
\$__internal_compile_0 = new \Twig\Runtime\LoopIterator({$this->getVariableGetter('values')});
\$__internal_compile_1 = function (\$__internal_compile_0, &\$context, \$blocks, &\$__internal_compile_1, \$depth) {
\$macros = \$this->macros;
\$context['_parent'] = \$context;
\$context['loop'] = new \Twig\Runtime\LoopContext(\$__internal_compile_0, \$context['_parent'], \$blocks, \$__internal_compile_1, \$depth);
\$__internal_compile_2 = \$context;
\$context['loop'] = new \Twig\Runtime\LoopContext(\$__internal_compile_0, \$__internal_compile_2, \$blocks, \$__internal_compile_1, \$depth);
foreach (\$__internal_compile_0 as \$context["k"] => \$context["v"]) {
yield {$this->getVariableGetter('foo')};
}
if (0 === \$__internal_compile_0->getIndex0()) {
yield {$this->getVariableGetter('foo')};
}
\$_parent = \$context['_parent'];
unset(\$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
\$context = array_intersect_key(\$context, \$_parent) + \$_parent;
unset(\$context['k'], \$context['v'], \$context['loop']);
\$context = array_intersect_key(\$context, \$__internal_compile_2) + \$__internal_compile_2;
return; yield;
};
\Closure::bind(\$__internal_compile_1, \$this, self::class);