diff --git a/src/Node/Expression/MacroReferenceExpression.php b/src/Node/Expression/MacroReferenceExpression.php index fd7f1e733..ba1d556b4 100644 --- a/src/Node/Expression/MacroReferenceExpression.php +++ b/src/Node/Expression/MacroReferenceExpression.php @@ -29,6 +29,16 @@ class MacroReferenceExpression extends AbstractExpression implements SupportDefi parent::__construct(['template' => $template, 'arguments' => $arguments], ['name' => $name], $lineno); } + public function __clone() + { + // The template node must not be deep-cloned because its name is + // lazily generated during compilation and must stay in sync with + // the AssignTemplateVariable that populates the $macros array. + $template = $this->nodes['template']; + parent::__clone(); + $this->nodes['template'] = $template; + } + public function compile(Compiler $compiler): void { if ($this->definedTest) { diff --git a/tests/TemplateTest.php b/tests/TemplateTest.php index ddfb70401..7102db9a7 100644 --- a/tests/TemplateTest.php +++ b/tests/TemplateTest.php @@ -150,6 +150,43 @@ class TemplateTest extends TestCase ]; } + /** + * @dataProvider getNullCoalesceWithImportedMacroData + */ + public function testNullCoalesceWithImportedMacro(array $templates, string $expected) + { + $twig = new Environment(new ArrayLoader($templates)); + + $this->assertSame($expected, trim($twig->render('index.twig'))); + } + + public static function getNullCoalesceWithImportedMacroData(): array + { + return [ + 'from import' => [ + [ + 'index.twig' => '{% from "helper.twig" import foo %}{{ foo("bar") ?? "" }}', + 'helper.twig' => '{% macro foo(param) %}{{ param }}{% endmacro %}', + ], + 'bar', + ], + 'from import with undefined macro falls back' => [ + [ + 'index.twig' => '{% from "helper.twig" import foo, nonexistent %}{{ nonexistent("bar") ?? "fallback" }}', + 'helper.twig' => '{% macro foo(param) %}{{ param }}{% endmacro %}', + ], + 'fallback', + ], + 'from import used multiple times' => [ + [ + 'index.twig' => '{% from "helper.twig" import foo %}{{ foo("a") ?? "" }}-{{ foo("b") ?? "" }}', + 'helper.twig' => '{% macro foo(param) %}{{ param }}{% endmacro %}', + ], + 'a-b', + ], + ]; + } + public function testRenderBlockWithUndefinedBlock() { $twig = new Environment(new ArrayLoader());