mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-16 12:26:30 +00:00
minor #2618 Optimized compilation for arrays when using a['b'] notation (fabpot)
This PR was squashed before being merged into the 2.x branch (closes #2618). Discussion ---------- Optimized compilation for arrays when using a['b'] notation Under certain conditions, and thanks to the `??` operator, it's possible to optimize array calls (and avoid the call to `twig_get_attribute()`). On my local machine, code is almost twice as fast, which is nice if you are using a lot of `a["b"]` calls of nested ones. refs #2547 Commits -------6f7ea45coptimized nested array callsf3b8f4a8added some testsd501e0e5optimized compilation for arrays when using a['b'] notation under certain conditions
This commit is contained in:
@@ -23,6 +23,30 @@ 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')
|
||||
) {
|
||||
$var = '$'.$compiler->getVarName();
|
||||
$compiler
|
||||
->raw('(('.$var.' = ')
|
||||
->subcompile($this->getNode('node'))
|
||||
->raw(') && is_array(')
|
||||
->raw($var)
|
||||
->raw(') || ')
|
||||
->raw($var)
|
||||
->raw(' instanceof ArrayAccess ? (')
|
||||
->raw($var)
|
||||
->raw('[')
|
||||
->subcompile($this->getNode('attribute'))
|
||||
->raw('] ?? null) : null)')
|
||||
;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$compiler->raw('twig_get_attribute($this->env, $this->source, ');
|
||||
|
||||
if ($this->getAttribute('ignore_strict_check')) {
|
||||
|
||||
@@ -37,8 +37,11 @@ Twig supports array notation
|
||||
{% set ary = { (a): 'a', (b): 'b', 'c': 'c', (a ~ b): 'd' } %}
|
||||
{{ ary|keys|join(',') }}
|
||||
{{ ary|join(',') }}
|
||||
|
||||
{# ArrayAccess #}
|
||||
{{ array_access['a'] }}
|
||||
--DATA--
|
||||
return array('bar' => 'bar', 'foo' => array('bar' => 'bar'))
|
||||
return array('bar' => 'bar', 'foo' => array('bar' => 'bar'), 'array_access' => new ArrayObject(array('a' => 'b')))
|
||||
--EXPECT--
|
||||
1,2
|
||||
foo,bar
|
||||
@@ -59,3 +62,5 @@ FOO,BAR,
|
||||
|
||||
1,foo,c,1foo
|
||||
a,b,c,d
|
||||
|
||||
b
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
--TEST--
|
||||
Twig supports array notation
|
||||
--TEMPLATE--
|
||||
{# empty array #}
|
||||
{{ []|join(',') }}
|
||||
|
||||
{{ [1, 2]|join(',') }}
|
||||
{{ ['foo', "bar"]|join(',') }}
|
||||
{{ {0: 1, 'foo': 'bar'}|join(',') }}
|
||||
{{ {0: 1, 'foo': 'bar'}|keys|join(',') }}
|
||||
|
||||
{{ {0: 1, foo: 'bar'}|join(',') }}
|
||||
{{ {0: 1, foo: 'bar'}|keys|join(',') }}
|
||||
|
||||
{# nested arrays #}
|
||||
{% set a = [1, 2, [1, 2], {'foo': {'foo': 'bar'}}] %}
|
||||
{{ a[2]|join(',') }}
|
||||
{{ a[3]["foo"]|join(',') }}
|
||||
|
||||
{# works even if [] is used inside the array #}
|
||||
{{ [foo[bar]]|join(',') }}
|
||||
|
||||
{# elements can be any expression #}
|
||||
{{ ['foo'|upper, bar|upper, bar == foo]|join(',') }}
|
||||
|
||||
{# arrays can have a trailing , like in PHP #}
|
||||
{{
|
||||
[
|
||||
1,
|
||||
2,
|
||||
]|join(',')
|
||||
}}
|
||||
|
||||
{# keys can be any expression #}
|
||||
{% set a = 1 %}
|
||||
{% set b = "foo" %}
|
||||
{% set ary = { (a): 'a', (b): 'b', 'c': 'c', (a ~ b): 'd' } %}
|
||||
{{ ary|keys|join(',') }}
|
||||
{{ ary|join(',') }}
|
||||
|
||||
{# ArrayAccess #}
|
||||
{{ array_access['a'] }}
|
||||
--DATA--
|
||||
return array('bar' => 'bar', 'foo' => array('bar' => 'bar'), 'array_access' => new ArrayObject(array('a' => 'b')))
|
||||
--CONFIG--
|
||||
return array('strict_variables' => false)
|
||||
--EXPECT--
|
||||
1,2
|
||||
foo,bar
|
||||
1,bar
|
||||
0,foo
|
||||
|
||||
1,bar
|
||||
0,foo
|
||||
|
||||
1,2
|
||||
bar
|
||||
|
||||
bar
|
||||
|
||||
FOO,BAR,
|
||||
|
||||
1,2
|
||||
|
||||
1,foo,c,1foo
|
||||
a,b,c,d
|
||||
|
||||
b
|
||||
@@ -37,7 +37,8 @@ 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, '(($__internal_%s = // line 1'."\n".
|
||||
'($context["foo"] ?? null)) && is_array($__internal_%s) || $__internal_%s instanceof ArrayAccess ? ($__internal_%s["bar"] ?? null) : null)', null, true);
|
||||
|
||||
$args = new Twig_Node_Expression_Array(array(), 1);
|
||||
$args->addElement(new Twig_Node_Expression_Name('foo', 1));
|
||||
|
||||
Reference in New Issue
Block a user