mirror of
https://github.com/twigphp/Twig.git
synced 2026-10-02 18:07:35 +00:00
Improve macro call performance
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
* Fix `IntlExtension` letting the pattern derived from a date formatter prototype override an explicit locale
|
||||
* Fix `IntlExtension` not honoring the locale of a date formatter prototype configured with no date and time styles
|
||||
* Speed up macro calls
|
||||
* Report a clear error when `random`, `reverse`, `shuffle`, and `split` receive a string that is not valid UTF-8
|
||||
* Fix the deprecation about omitting parentheses when calling a macro being reported twice for the same call
|
||||
* Add the macro name to the deprecation about omitting parentheses when calling a macro
|
||||
|
||||
@@ -53,6 +53,10 @@ final class MacroNamespace
|
||||
*/
|
||||
public function call(string $name, array $arguments, array $context, int $line, Source $source): string|Markup
|
||||
{
|
||||
if (null !== $macro = $this->getDeclared($name)) {
|
||||
return $macro->callLegacy($arguments, $source, $line);
|
||||
}
|
||||
|
||||
if (null === $macro = $this->resolve($name, $context)) {
|
||||
if (!str_starts_with($name, 'macro_') || null === $macro = $this->resolve($bareName = substr($name, \strlen('macro_')), $context)) {
|
||||
throw new RuntimeError(\sprintf('Macro "%s" is not defined in template "%s".', $name, $this->template->getTemplateName()), $line, $source);
|
||||
|
||||
@@ -90,7 +90,7 @@ class MacroReferenceExpression extends AbstractExpression implements SupportDefi
|
||||
->subcompile($this->getNode('arguments'))
|
||||
->raw(', $context, ')
|
||||
->repr($this->getTemplateLine())
|
||||
->raw(', $this->getSourceContext())')
|
||||
->raw(', $this->source)')
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -100,6 +100,11 @@ final class TwigMacro
|
||||
return ($this->body)(...$arguments);
|
||||
}
|
||||
|
||||
// The keys are then exactly the declared names.
|
||||
if (\count($arguments) === \count($this->arguments) && !array_diff_key($arguments, $this->argumentIndexes)) {
|
||||
return ($this->body)(...$this->renameArguments($arguments));
|
||||
}
|
||||
|
||||
$positionalCount = 0;
|
||||
$namedRequired = 0;
|
||||
$sawNamed = false;
|
||||
@@ -142,6 +147,16 @@ final class TwigMacro
|
||||
$this->triggerLegacyDeprecations($arguments, $positionalCount, $source, $lineno);
|
||||
}
|
||||
|
||||
return ($this->body)(...$this->renameArguments($arguments));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, mixed> $arguments
|
||||
*
|
||||
* @return array<int|string, mixed>
|
||||
*/
|
||||
private function renameArguments(array $arguments): array
|
||||
{
|
||||
foreach ($this->renamedArguments as $name => $parameterName) {
|
||||
if (\array_key_exists($name, $arguments)) {
|
||||
$arguments[$parameterName] = $arguments[$name];
|
||||
@@ -149,7 +164,7 @@ final class TwigMacro
|
||||
}
|
||||
}
|
||||
|
||||
return ($this->body)(...$arguments);
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -68,7 +68,7 @@ class MacroReferenceTest extends TestCase
|
||||
$compiler->compile($node);
|
||||
|
||||
$this->assertStringContainsString('->call(', $compiler->getSource());
|
||||
$this->assertStringContainsString('($context["name"] ?? null), [], $context, 1, $this->getSourceContext())', $compiler->getSource());
|
||||
$this->assertStringContainsString('($context["name"] ?? null), [], $context, 1, $this->source)', $compiler->getSource());
|
||||
$this->assertStringNotContainsString("'macro_'.", $compiler->getSource());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,6 +134,39 @@ class TwigMacroTest extends TestCase
|
||||
['Since twig/twig 3.29: Passing the unknown named argument "extra" to the macro "test" is deprecated and will throw in Twig 4.0; declare a variadic argument ("...name") in the macro definition to accept it (in "index.twig" at line 7).'],
|
||||
];
|
||||
|
||||
yield 'unknown named argument is still reported when the argument count matches the signature' => [
|
||||
['name' => false, 'value' => false],
|
||||
false,
|
||||
static function (&$captured) {
|
||||
return static function ($name = null, $value = null, ...$varargs) use (&$captured) {
|
||||
$captured = [$name, $value, $varargs];
|
||||
|
||||
return '';
|
||||
};
|
||||
},
|
||||
['name' => 'a', 'extra' => 'b'],
|
||||
['a', null, ['extra' => 'b']],
|
||||
[
|
||||
'Since twig/twig 3.29: Not passing a value for the "value" argument of macro "test" is deprecated and the argument will be required in Twig 4.0; give it a default value in the macro definition or pass a value when calling it (in "index.twig" at line 7).',
|
||||
'Since twig/twig 3.29: Passing the unknown named argument "extra" to the macro "test" is deprecated and will throw in Twig 4.0; declare a variadic argument ("...name") in the macro definition to accept it (in "index.twig" at line 7).',
|
||||
],
|
||||
];
|
||||
|
||||
yield 'named arguments covering the whole signature bind to their parameter, reserved names included' => [
|
||||
['context' => false, 'value' => false],
|
||||
false,
|
||||
static function (&$captured) {
|
||||
return static function ($͜context = null, $value = null, ...$varargs) use (&$captured) {
|
||||
$captured = [$͜context, $value, $varargs];
|
||||
|
||||
return '';
|
||||
};
|
||||
},
|
||||
['value' => 'b', 'context' => 'a'],
|
||||
['a', 'b', []],
|
||||
[],
|
||||
];
|
||||
|
||||
yield 'null named argument value satisfies a required argument' => [
|
||||
['name' => false],
|
||||
false,
|
||||
|
||||
Reference in New Issue
Block a user