diff --git a/src/Node/BlockNode.php b/src/Node/BlockNode.php index f8ce56e9b..d5d87bc0a 100644 --- a/src/Node/BlockNode.php +++ b/src/Node/BlockNode.php @@ -40,7 +40,7 @@ class BlockNode extends Node $compiler ->subcompile($this->getNode('body')) - ->write("return; yield '';\n") // needed when body doesn't yield anything + ->write("yield from [];\n") ->outdent() ->write("}\n\n") ; diff --git a/src/Node/CaptureNode.php b/src/Node/CaptureNode.php index 2801efb5d..0ee31a8f2 100644 --- a/src/Node/CaptureNode.php +++ b/src/Node/CaptureNode.php @@ -36,7 +36,7 @@ class CaptureNode extends Node ->raw("(function () use (&\$context, \$macros, \$blocks) {\n") ->indent() ->subcompile($this->getNode('body')) - ->write("return; yield '';\n") + ->write("yield from [];\n") ->outdent() ->write('})(), false))') ; diff --git a/src/Node/ModuleNode.php b/src/Node/ModuleNode.php index 4b95fb6b1..ff92bba9c 100644 --- a/src/Node/ModuleNode.php +++ b/src/Node/ModuleNode.php @@ -346,7 +346,7 @@ final class ModuleNode extends Node $compiler->subcompile($this->getNode('display_end')); if (!$this->hasNode('parent')) { - $compiler->write("return; yield '';\n"); // ensure at least one yield call even for templates with no output + $compiler->write("yield from [];\n"); } $compiler diff --git a/tests/EnvironmentTest.php b/tests/EnvironmentTest.php index 71c1f112a..91c5aa32c 100644 --- a/tests/EnvironmentTest.php +++ b/tests/EnvironmentTest.php @@ -177,19 +177,26 @@ class EnvironmentTest extends TestCase // force compilation $twig = new Environment($loader = new ArrayLoader(['index' => '{{ foo }}']), $options); + $twig->addExtension($extension = new class extends AbstractExtension { + public bool $throw = false; + + public function getFilters(): array + { + if ($this->throw) { + throw new \RuntimeException('Extension are not supposed to be initialized.'); + } + + return parent::getFilters(); + } + }); $key = $cache->generateKey('index', $twig->getTemplateClass('index')); $cache->write($key, $twig->compileSource(new Source('{{ foo }}', 'index'))); // check that extensions won't be initialized when rendering a template that is already in the cache - $twig = $this - ->getMockBuilder(Environment::class) - ->setConstructorArgs([$loader, $options]) - ->setMethods(['initExtensions']) - ->getMock() - ; - - $twig->expects($this->never())->method('initExtensions'); + $twig = new Environment($loader, $options); + $extension->throw = true; + $twig->addExtension($extension); // render template $output = $twig->render('index', ['foo' => 'bar']); diff --git a/tests/Node/BlockTest.php b/tests/Node/BlockTest.php index 41df7146c..26cc3d248 100644 --- a/tests/Node/BlockTest.php +++ b/tests/Node/BlockTest.php @@ -41,7 +41,7 @@ public function block_foo(array \$context, array \$blocks = []): iterable { \$macros = \$this->macros; yield "foo"; - return; yield ''; + yield from []; } EOF , new Environment(new ArrayLoader()), diff --git a/tests/Node/MacroTest.php b/tests/Node/MacroTest.php index ef36774f7..405046b37 100644 --- a/tests/Node/MacroTest.php +++ b/tests/Node/MacroTest.php @@ -36,8 +36,6 @@ class MacroTest extends NodeTestCase public function getTests() { - $tests = []; - $arguments = new Node([ 'foo' => new ConstantExpression(null, 1), 'bar' => new ConstantExpression('Foo', 1), @@ -46,7 +44,7 @@ class MacroTest extends NodeTestCase $body = new BodyNode([new TextNode('foo', 1)]); $node = new MacroNode('foo', $body, $arguments, 1); - $text[] = [$node, << [$node, <<env->getCharset()); + yield from []; + })(), false))) ? '' : new Markup(\$tmp, \$this->env->getCharset()); } EOF - , new Environment(new ArrayLoader()), + , new Environment(new ArrayLoader(), ['use_yield' => true]), ]; - return $tests; + yield 'with use_yield = false' => [$node, <<macros; + \$context = \$this->env->mergeGlobals([ + "foo" => \$__foo__, + "bar" => \$__bar__, + "varargs" => \$__varargs__, + ]); + + \$blocks = []; + + return ('' === \$tmp = \\Twig\\Extension\\CoreExtension::captureOutput((function () use (&\$context, \$macros, \$blocks) { + yield "foo"; + yield from []; + })())) ? '' : new Markup(\$tmp, \$this->env->getCharset()); +} +EOF + , new Environment(new ArrayLoader(), ['use_yield' => false]), + ]; } } diff --git a/tests/Node/ModuleTest.php b/tests/Node/ModuleTest.php index 0b7dd5ddb..10c4d7fa5 100644 --- a/tests/Node/ModuleTest.php +++ b/tests/Node/ModuleTest.php @@ -103,7 +103,7 @@ class __TwigTemplate_%x extends Template \$macros = \$this->macros; // line 1 yield "foo"; - return; yield ''; + yield from []; } /** diff --git a/tests/Node/SetTest.php b/tests/Node/SetTest.php index bdab5cb5a..bd49847c5 100644 --- a/tests/Node/SetTest.php +++ b/tests/Node/SetTest.php @@ -56,7 +56,7 @@ EOF // line 1 \$context["foo"] = ('' === \$tmp = implode('', iterator_to_array((function () use (&\$context, \$macros, \$blocks) { yield "foo"; - return; yield ''; + yield from []; })(), false))) ? '' : new Markup(\$tmp, \$this->env->getCharset()); EOF , new Environment(new ArrayLoader()),