From ec59953f4cb34c15cac4d98f587094556860847c Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 17 Sep 2015 03:14:14 +0200 Subject: [PATCH 1/6] [EventDispatcher] fix memory leak in a getListeners --- .../Component/EventDispatcher/EventDispatcher.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index a2435e9978..67097e5662 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -61,6 +61,10 @@ class EventDispatcher implements EventDispatcherInterface public function getListeners($eventName = null) { if (null !== $eventName) { + if (!isset($this->listeners[$eventName])) { + return array(); + } + if (!isset($this->sorted[$eventName])) { $this->sortListeners($eventName); } @@ -177,9 +181,7 @@ class EventDispatcher implements EventDispatcherInterface { $this->sorted[$eventName] = array(); - if (isset($this->listeners[$eventName])) { - krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); - } + krsort($this->listeners[$eventName]); + $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); } } From a7b7f5479eabfe00c462fc7640d712ec99fdda5f Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 17 Sep 2015 03:42:05 +0200 Subject: [PATCH 2/6] [EventDispatcher] skip one lazy loading call --- .../ContainerAwareEventDispatcher.php | 19 ++------------ .../EventDispatcher/EventDispatcher.php | 26 +++++++------------ 2 files changed, 11 insertions(+), 34 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index aedad6ef77..8782d8e87b 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -103,7 +103,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher } /** - * @see EventDispatcherInterface::hasListeners() + * {@inheritdoc} */ public function hasListeners($eventName = null) { @@ -119,7 +119,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher } /** - * @see EventDispatcherInterface::getListeners() + * {@inheritdoc} */ public function getListeners($eventName = null) { @@ -155,21 +155,6 @@ class ContainerAwareEventDispatcher extends EventDispatcher } } - /** - * {@inheritdoc} - * - * Lazily loads listeners for this event from the dependency injection - * container. - * - * @throws \InvalidArgumentException if the service is not defined - */ - public function dispatch($eventName, Event $event = null) - { - $this->lazyLoad($eventName); - - return parent::dispatch($eventName, $event); - } - public function getContainer() { return $this->container; diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index 67097e5662..54a279fb40 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -33,9 +33,7 @@ class EventDispatcher implements EventDispatcherInterface private $sorted = array(); /** - * @see EventDispatcherInterface::dispatch() - * - * @api + * {@inheritdoc} */ public function dispatch($eventName, Event $event = null) { @@ -46,17 +44,15 @@ class EventDispatcher implements EventDispatcherInterface $event->setDispatcher($this); $event->setName($eventName); - if (!isset($this->listeners[$eventName])) { - return $event; + if ($listeners = $this->getListeners($eventName)) { + $this->doDispatch($listeners, $eventName, $event); } - $this->doDispatch($this->getListeners($eventName), $eventName, $event); - return $event; } /** - * @see EventDispatcherInterface::getListeners() + * {@inheritdoc} */ public function getListeners($eventName = null) { @@ -82,7 +78,7 @@ class EventDispatcher implements EventDispatcherInterface } /** - * @see EventDispatcherInterface::hasListeners() + * {@inheritdoc} */ public function hasListeners($eventName = null) { @@ -90,9 +86,7 @@ class EventDispatcher implements EventDispatcherInterface } /** - * @see EventDispatcherInterface::addListener() - * - * @api + * {@inheritdoc} */ public function addListener($eventName, $listener, $priority = 0) { @@ -101,7 +95,7 @@ class EventDispatcher implements EventDispatcherInterface } /** - * @see EventDispatcherInterface::removeListener() + * {@inheritdoc} */ public function removeListener($eventName, $listener) { @@ -117,9 +111,7 @@ class EventDispatcher implements EventDispatcherInterface } /** - * @see EventDispatcherInterface::addSubscriber() - * - * @api + * {@inheritdoc} */ public function addSubscriber(EventSubscriberInterface $subscriber) { @@ -137,7 +129,7 @@ class EventDispatcher implements EventDispatcherInterface } /** - * @see EventDispatcherInterface::removeSubscriber() + * {@inheritdoc} */ public function removeSubscriber(EventSubscriberInterface $subscriber) { From 549f43b03a50951b64e748bc91c24644cd872e3b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 20 Sep 2015 23:33:09 +0200 Subject: [PATCH 3/6] [Console] Add clock mock to fix transient test on HHVM --- .../Component/Console/Tests/ClockMock.php | 41 +++++++++++++++++++ .../Tests/Helper/ProgressHelperTest.php | 13 ++++++ .../HttpFoundation/Tests/ClockMock.php | 2 +- .../HttpFoundation/Tests/CookieTest.php | 6 +-- .../Tests/ResponseHeaderBagTest.php | 6 +-- .../Stopwatch/Tests/StopwatchEventTest.php | 6 +-- .../Stopwatch/Tests/StopwatchTest.php | 6 +-- 7 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/ClockMock.php diff --git a/src/Symfony/Component/Console/Tests/ClockMock.php b/src/Symfony/Component/Console/Tests/ClockMock.php new file mode 100644 index 0000000000..0e9231662e --- /dev/null +++ b/src/Symfony/Component/Console/Tests/ClockMock.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Tests; + +function time() +{ + return Tests\time(); +} + +namespace Symfony\Component\Console\Tests; + +function with_clock_mock($enable = null) +{ + static $enabled; + + if (null === $enable) { + return $enabled; + } + + $enabled = $enable; +} + +function time() +{ + if (!with_clock_mock()) { + return \time(); + } + + return $_SERVER['REQUEST_TIME']; +} diff --git a/src/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php index 2d2ec82b12..785fa31b7b 100644 --- a/src/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/ProgressHelperTest.php @@ -13,9 +13,22 @@ namespace Symfony\Component\Console\Tests\Helper; use Symfony\Component\Console\Helper\ProgressHelper; use Symfony\Component\Console\Output\StreamOutput; +use Symfony\Component\Console\Tests; + +require_once __DIR__.'/../ClockMock.php'; class ProgressHelperTest extends \PHPUnit_Framework_TestCase { + protected function setUp() + { + Tests\with_clock_mock(true); + } + + protected function tearDown() + { + Tests\with_clock_mock(false); + } + public function testAdvance() { $progress = new ProgressHelper(); diff --git a/src/Symfony/Component/HttpFoundation/Tests/ClockMock.php b/src/Symfony/Component/HttpFoundation/Tests/ClockMock.php index c74605fe95..aa954db429 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ClockMock.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ClockMock.php @@ -11,7 +11,7 @@ namespace Symfony\Component\HttpFoundation; -function time($asFloat = false) +function time() { return Tests\time(); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php index 9d794c3d6f..378e1c5c57 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -23,16 +23,14 @@ require_once __DIR__.'/ClockMock.php'; */ class CookieTest extends \PHPUnit_Framework_TestCase { - public function setUp() + protected function setUp() { with_clock_mock(true); - parent::setUp(); } - public function tearDown() + protected function tearDown() { with_clock_mock(false); - parent::tearDown(); } public function invalidNames() diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php index ef5979f1f2..161937b31d 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php @@ -18,16 +18,14 @@ require_once __DIR__.'/ClockMock.php'; class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase { - public function setUp() + protected function setUp() { with_clock_mock(true); - parent::setUp(); } - public function tearDown() + protected function tearDown() { with_clock_mock(false); - parent::tearDown(); } /** diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php index bf5d8805ad..f67d9dc16d 100644 --- a/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchEventTest.php @@ -24,16 +24,14 @@ class StopwatchEventTest extends \PHPUnit_Framework_TestCase { const DELTA = 37; - public function setUp() + protected function setUp() { with_clock_mock(true); - parent::setUp(); } - public function tearDown() + protected function tearDown() { with_clock_mock(false); - parent::tearDown(); } public function testGetOrigin() diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php index 0b89f27054..b7835c6a02 100644 --- a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php @@ -24,16 +24,14 @@ class StopwatchTest extends \PHPUnit_Framework_TestCase { const DELTA = 20; - public function setUp() + protected function setUp() { with_clock_mock(true); - parent::setUp(); } - public function tearDown() + protected function tearDown() { with_clock_mock(false); - parent::tearDown(); } public function testStart() From 93ffa61e425d59373ddf42f5c09224e20e09d3f3 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 21 Sep 2015 01:46:31 +0200 Subject: [PATCH 4/6] Fix the phpdoc in the CssSelector TranslatorInterface --- .../Component/CssSelector/XPath/TranslatorInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php b/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php index 1d9d1c88ee..bc19ae8634 100644 --- a/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php +++ b/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php @@ -29,7 +29,7 @@ interface TranslatorInterface * @param string $cssExpr * @param string $prefix * - * @return XPathExpr + * @return string */ public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::'); @@ -39,7 +39,7 @@ interface TranslatorInterface * @param SelectorNode $selector * @param string $prefix * - * @return XPathExpr + * @return string */ public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::'); } From d5abe0b114ed5f919c86c39cd4dc45fbd89693a8 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 21 Sep 2015 01:59:10 +0200 Subject: [PATCH 5/6] [CssSelector] Optimize regexs matching simple selectors --- .../CssSelector/Parser/Shortcut/ClassParser.php | 15 +++++++-------- .../CssSelector/Parser/Shortcut/ElementParser.php | 13 ++++++------- .../CssSelector/Parser/Shortcut/HashParser.php | 15 +++++++-------- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php index 142bd16315..83f8d13d9c 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php @@ -33,15 +33,14 @@ class ClassParser implements ParserInterface { // Matches an optional namespace, optional element, and required class // $source = 'test|input.ab6bd_field'; - // $matches = array (size=5) - // 0 => string 'test:input.ab6bd_field' (length=22) - // 1 => string 'test:' (length=5) - // 2 => string 'test' (length=4) - // 3 => string 'input' (length=5) - // 4 => string 'ab6bd_field' (length=11) - if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?\.([\w-]+)$/i', trim($source), $matches)) { + // $matches = array (size=4) + // 0 => string 'test|input.ab6bd_field' (length=22) + // 1 => string 'test' (length=4) + // 2 => string 'input' (length=5) + // 3 => string 'ab6bd_field' (length=11) + if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+\.([\w-]++)$/i', trim($source), $matches)) { return array( - new SelectorNode(new ClassNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4])), + new SelectorNode(new ClassNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), ); } diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php index f62d25960c..00e443553b 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php @@ -32,13 +32,12 @@ class ElementParser implements ParserInterface { // Matches an optional namespace, required element or `*` // $source = 'testns|testel'; - // $matches = array (size=4) - // 0 => string 'testns:testel' (length=13) - // 1 => string 'testns:' (length=7) - // 2 => string 'testns' (length=6) - // 3 => string 'testel' (length=6) - if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)$/i', trim($source), $matches)) { - return array(new SelectorNode(new ElementNode($matches[2] ?: null, $matches[3]))); + // $matches = array (size=3) + // 0 => string 'testns|testel' (length=13) + // 1 => string 'testns' (length=6) + // 2 => string 'testel' (length=6) + if (preg_match('/^(?:([a-z]++)\|)?([\w-]++|\*)$/i', trim($source), $matches)) { + return array(new SelectorNode(new ElementNode($matches[1] ?: null, $matches[2]))); } return array(); diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php index fde614149b..3dbad79d5b 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php @@ -33,15 +33,14 @@ class HashParser implements ParserInterface { // Matches an optional namespace, optional element, and required id // $source = 'test|input#ab6bd_field'; - // $matches = array (size=5) - // 0 => string 'test:input#ab6bd_field' (length=22) - // 1 => string 'test:' (length=5) - // 2 => string 'test' (length=4) - // 3 => string 'input' (length=5) - // 4 => string 'ab6bd_field' (length=11) - if (preg_match('/^(([a-z]+)\|)?([\w-]+|\*)?#([\w-]+)$/i', trim($source), $matches)) { + // $matches = array (size=4) + // 0 => string 'test|input#ab6bd_field' (length=22) + // 1 => string 'test' (length=4) + // 2 => string 'input' (length=5) + // 3 => string 'ab6bd_field' (length=11) + if (preg_match('/^(?:([a-z]++)\|)?+([\w-]++|\*)?+#([\w-]++)$/i', trim($source), $matches)) { return array( - new SelectorNode(new HashNode(new ElementNode($matches[2] ?: null, $matches[3] ?: null), $matches[4])), + new SelectorNode(new HashNode(new ElementNode($matches[1] ?: null, $matches[2] ?: null), $matches[3])), ); } From 84fbfb0131fbd737c670550e49f329a640c43985 Mon Sep 17 00:00:00 2001 From: Kasperki Date: Sun, 20 Sep 2015 16:57:53 +0300 Subject: [PATCH 6/6] Finnish translation fix --- .../Component/Form/Resources/translations/validators.fi.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf b/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf index d223bb05ca..4eb393aee9 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.fi.xlf @@ -12,7 +12,7 @@ The CSRF token is invalid. Please try to resubmit the form. - CSRF tarkiste on virheellinen. Olen hyvä ja yritä lähettää lomake uudestaan. + CSRF tarkiste on virheellinen. Ole hyvä ja yritä lähettää lomake uudestaan.