optimized macro calls when auto-escaping is on (closes #779)
authorFabien Potencier <fabien.potencier@gmail.com>
Sat, 21 Jul 2012 21:20:56 +0000 (23:20 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Sat, 21 Jul 2012 21:28:53 +0000 (23:28 +0200)
CHANGELOG
lib/Twig/Node/Macro.php
lib/Twig/NodeVisitor/Escaper.php
lib/Twig/NodeVisitor/SafeAnalysis.php
test/Twig/Tests/Node/MacroTest.php

index ddf2ff2..1777748 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 * 1.9.1 (2012-XX-XX)
 
+ * optimized macro calls when auto-escaping is on
  * fixed wrong parent class for Twig_Function_Node
  * made Twig_Loader_Chain more explicit about problems
 
index 823131e..e0c3dca 100644 (file)
@@ -76,7 +76,7 @@ class Twig_Node_Macro extends Twig_Node
             ->write("throw \$e;\n")
             ->outdent()
             ->write("}\n\n")
-            ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n")
+            ->write("return ob_get_clean();\n")
             ->outdent()
             ->write("}\n\n")
         ;
index 5b1249d..cc9a58b 100644 (file)
@@ -22,6 +22,7 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
     protected $safeAnalysis;
     protected $traverser;
     protected $defaultStrategy = false;
+    protected $safeVars = array();
 
     public function __construct()
     {
@@ -42,10 +43,13 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
             if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
                 $this->defaultStrategy = $defaultStrategy;
             }
+            $this->safeVars = array();
         } elseif ($node instanceof Twig_Node_AutoEscape) {
             $this->statusStack[] = $node->getAttribute('value');
         } elseif ($node instanceof Twig_Node_Block) {
             $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env);
+        } elseif ($node instanceof Twig_Node_Import) {
+            $this->safeVars[] = $node->getNode('var')->getAttribute('name');
         }
 
         return $node;
@@ -63,6 +67,7 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
     {
         if ($node instanceof Twig_Node_Module) {
             $this->defaultStrategy = false;
+            $this->safeVars = array();
         } elseif ($node instanceof Twig_Node_Expression_Filter) {
             return $this->preEscapeFilterNode($node, $env);
         } elseif ($node instanceof Twig_Node_Print) {
@@ -129,6 +134,9 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
             if (null === $this->traverser) {
                 $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis));
             }
+
+            $this->safeAnalysis->setSafeVars($this->safeVars);
+
             $this->traverser->traverse($expression);
             $safe = $this->safeAnalysis->getSafe($expression);
         }
index 7cc2e22..7dc65c0 100644 (file)
@@ -3,6 +3,12 @@
 class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
 {
     protected $data = array();
+    protected $safeVars = array();
+
+    public function setSafeVars($safeVars)
+    {
+        $this->safeVars = $safeVars;
+    }
 
     public function getSafe(Twig_NodeInterface $node)
     {
@@ -85,6 +91,14 @@ class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
             } else {
                 $this->setSafe($node, array());
             }
+        } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) {
+            $name = $node->getNode('node')->getAttribute('name');
+            // attributes on template instances are safe
+            if ('_self' == $name || in_array($name, $this->safeVars)) {
+                $this->setSafe($node, array('all'));
+            } else {
+                $this->setSafe($node, array());
+            }
         } else {
             $this->setSafe($node, array());
         }
index 5930728..3dd57a6 100644 (file)
@@ -61,7 +61,7 @@ public function getfoo(\$foo = null)
         throw \$e;
     }
 
-    return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());
+    return ob_get_clean();
 }
 EOF
             ),