Skip to content

Commit d4cbe21

Browse files
committed
Optimize inline helpers which don't use options
This makes it possible to use native PHP functions as inline helpers with first-class callable syntax, since the function will no longer be passed an extra options argument.
1 parent 97e6bdb commit d4cbe21

2 files changed

Lines changed: 24 additions & 10 deletions

File tree

src/Runtime.php

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -467,15 +467,29 @@ public static function dynhbch(RuntimeContext $cx, string $name, array $position
467467
*/
468468
public static function hbch(RuntimeContext $cx, \Closure $helper, string $name, array $positional, array $hash, mixed &$_this): mixed
469469
{
470-
$options = new HelperOptions(
471-
scope: $_this,
472-
data: $cx->frame,
473-
name: $name,
474-
hash: $hash,
475-
);
476-
$args = $positional;
477-
$args[] = $options;
478-
return $helper(...$args);
470+
/** @var \WeakMap<\Closure, int>|null $paramCounts */
471+
static $paramCounts = null;
472+
$paramCounts ??= new \WeakMap();
473+
474+
$numParams = $paramCounts[$helper] ?? null;
475+
if ($numParams === null) {
476+
// Cache the number of parameters for the closure so HelperOptions doesn't have to be instantiated
477+
// when it isn't used. This can boost runtime performance by 20% for complex templates.
478+
$rf = new \ReflectionFunction($helper);
479+
$params = $rf->getParameters();
480+
$numParams = $params && end($params)->isVariadic() ? 0 : $rf->getNumberOfParameters();
481+
$paramCounts[$helper] = $numParams;
482+
}
483+
if ($numParams === 0 || $numParams > count($positional)) {
484+
$positional[] = new HelperOptions(
485+
scope: $_this,
486+
data: $cx->frame,
487+
name: $name,
488+
hash: $hash,
489+
);
490+
}
491+
492+
return $helper(...$positional);
479493
}
480494

481495
/**

tests/RegressionTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public static function helperProvider(): array
202202
'desc' => 'LNC#49 - custom helper alias',
203203
'template' => '{{date_format date "M j, Y"}}',
204204
'helpers' => [
205-
'date_format' => fn($date, $format) => date_format($date, $format),
205+
'date_format' => date_format(...),
206206
],
207207
'data' => ['date' => new \DateTime('2014-06-06')],
208208
'expected' => 'Jun 6, 2014',

0 commit comments

Comments
 (0)