mirror of
https://github.com/twigphp/Twig.git
synced 2026-08-17 08:50:50 +00:00
Fix unbounded memoisation of IntlDateFormatter / NumberFormatter
This commit is contained in:
committed by
Fabien Potencier
parent
b675555ea2
commit
6add9066fc
@@ -145,6 +145,8 @@ final class IntlExtension extends AbstractExtension
|
||||
'monetary_grouping_separator' => \NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL,
|
||||
];
|
||||
|
||||
private const MAX_CACHED_FORMATTERS = 100;
|
||||
|
||||
private $dateFormatters = [];
|
||||
private $numberFormatters = [];
|
||||
private $dateFormatterPrototype;
|
||||
@@ -441,6 +443,9 @@ final class IntlExtension extends AbstractExtension
|
||||
$hash = $locale.'|'.$dateFormatValue.'|'.$timeFormatValue.'|'.$timezoneName.'|'.$calendar.'|'.$pattern;
|
||||
|
||||
if (!isset($this->dateFormatters[$hash])) {
|
||||
if (\count($this->dateFormatters) >= self::MAX_CACHED_FORMATTERS) {
|
||||
array_shift($this->dateFormatters);
|
||||
}
|
||||
$this->dateFormatters[$hash] = new \IntlDateFormatter($locale, $dateFormatValue, $timeFormatValue, $timezone, $calendar, $pattern);
|
||||
}
|
||||
|
||||
@@ -487,6 +492,9 @@ final class IntlExtension extends AbstractExtension
|
||||
$hash = $locale.'|'.$style.'|'.json_encode($attrs).'|'.json_encode($textAttrs).'|'.json_encode($symbols);
|
||||
|
||||
if (!isset($this->numberFormatters[$hash])) {
|
||||
if (\count($this->numberFormatters) >= self::MAX_CACHED_FORMATTERS) {
|
||||
array_shift($this->numberFormatters);
|
||||
}
|
||||
$this->numberFormatters[$hash] = new \NumberFormatter($locale, self::NUMBER_STYLES[$style]);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,4 +96,35 @@ class IntlExtensionTest extends TestCase
|
||||
$ext->formatDateTime($env, new \DateTime('2020-02-20T13:37:00+00:00'), 'short', 'short', 'yyyy-MM-dd HH:mm:ss', 'UTC', 'gregorian', 'en_US')
|
||||
);
|
||||
}
|
||||
|
||||
public function testDateFormatterCacheIsBounded()
|
||||
{
|
||||
$ext = new IntlExtension();
|
||||
$env = new Environment(new ArrayLoader());
|
||||
$date = new \DateTime('2020-02-20T13:37:00+00:00');
|
||||
|
||||
for ($i = 0; $i < 250; ++$i) {
|
||||
$ext->formatDateTime($env, $date, 'medium', 'medium', 'yyyy-MM-dd-'.$i, 'UTC', 'gregorian', 'en_US');
|
||||
}
|
||||
|
||||
$cache = (new \ReflectionProperty(IntlExtension::class, 'dateFormatters'))->getValue($ext);
|
||||
$this->assertLessThanOrEqual(100, \count($cache));
|
||||
$this->assertSame(
|
||||
'2020-02-20-249',
|
||||
$ext->formatDateTime($env, $date, 'medium', 'medium', 'yyyy-MM-dd-249', 'UTC', 'gregorian', 'en_US')
|
||||
);
|
||||
}
|
||||
|
||||
public function testNumberFormatterCacheIsBounded()
|
||||
{
|
||||
$ext = new IntlExtension();
|
||||
|
||||
for ($i = 0; $i < 250; ++$i) {
|
||||
$ext->formatNumber(1, ['multiplier' => $i + 1], 'decimal', 'default', 'en_US');
|
||||
}
|
||||
|
||||
$cache = (new \ReflectionProperty(IntlExtension::class, 'numberFormatters'))->getValue($ext);
|
||||
$this->assertLessThanOrEqual(100, \count($cache));
|
||||
$this->assertGreaterThan(1, \count($cache));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user