diff --git a/lib/Twig/Node/Expression/GetAttr.php b/lib/Twig/Node/Expression/GetAttr.php index cee6804fa..68c27ea32 100644 --- a/lib/Twig/Node/Expression/GetAttr.php +++ b/lib/Twig/Node/Expression/GetAttr.php @@ -23,6 +23,27 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression public function compile(Twig_Compiler $compiler) { + // optimize array calls + if ( + (!$compiler->getEnvironment()->isStrictVariables() || $this->getAttribute('ignore_strict_check')) + && !$this->getAttribute('is_defined_test') + && Twig_Template::ARRAY_CALL === $this->getAttribute('type') + ) { + $compiler + ->raw('(is_array(') + ->subcompile($this->getNode('node')) + ->raw(') || ') + ->subcompile($this->getNode('node')) + ->raw(' instanceof ArrayAccess ? (') + ->subcompile($this->getNode('node')) + ->raw('[') + ->subcompile($this->getNode('attribute')) + ->raw('] ?? null) : null)') + ; + + return; + } + $compiler->raw('twig_get_attribute($this->env, $this->source, '); if ($this->getAttribute('ignore_strict_check')) { diff --git a/test/Twig/Tests/Node/Expression/GetAttrTest.php b/test/Twig/Tests/Node/Expression/GetAttrTest.php index 2764478c4..f7925c060 100644 --- a/test/Twig/Tests/Node/Expression/GetAttrTest.php +++ b/test/Twig/Tests/Node/Expression/GetAttrTest.php @@ -37,7 +37,7 @@ class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Test_NodeTestCase $tests[] = array($node, sprintf('%s%s, "bar", array())', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))); $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::ARRAY_CALL, 1); - $tests[] = array($node, sprintf('%s%s, "bar", array(), "array")', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))); + $tests[] = array($node, sprintf('(is_array(%s) || ($context["foo"] ?? null) instanceof ArrayAccess ? (($context["foo"] ?? null)["bar"] ?? null) : null)', $this->getVariableGetter('foo', 1), $this->getVariableGetter('foo', 1))); $args = new Twig_Node_Expression_Array(array(), 1); $args->addElement(new Twig_Node_Expression_Name('foo', 1));