bug #15159 [2.6] Towards 100% HHVM compat (nicolas-grekas)

This PR was merged into the 2.6 branch.

Discussion
----------

[2.6] Towards 100% HHVM compat

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #9917, #11418
| License       | MIT
| Doc PR        | -

Failing components:
- [x] HttpFoundation
- [x] HttpKernel
- [x] VarDumper

Related HHVM issues:
- https://github.com/facebook/hhvm/issues/5563

Commits
-------

8a78255 [2.6] Towards 100% HHVM compat
This commit is contained in:
Fabien Potencier 2015-07-01 13:18:19 +02:00
commit a83487821f
9 changed files with 114 additions and 68 deletions

View File

@ -95,34 +95,58 @@ class JsonResponse extends Response
*/ */
public function setData($data = array()) public function setData($data = array())
{ {
$errorHandler = null; if (defined('HHVM_VERSION')) {
$errorHandler = set_error_handler(function () use (&$errorHandler) { // HHVM does not trigger any warnings and let exceptions
if (JSON_ERROR_NONE !== json_last_error()) { // thrown from a JsonSerializable object pass through.
return; // If only PHP did the same...
$data = json_encode($data, $this->encodingOptions);
} else {
try {
if (PHP_VERSION_ID < 50400) {
// PHP 5.3 triggers annoying warnings for some
// types that can't be serialized as JSON (INF, resources, etc.)
// but doesn't provide the JsonSerializable interface.
set_error_handler('var_dump', 0);
$data = @json_encode($data, $this->encodingOptions);
} else {
// PHP 5.4 and up wrap exceptions thrown by JsonSerializable
// objects in a new exception that needs to be removed.
// Fortunately, PHP 5.5 and up do not trigger any warning anymore.
if (PHP_VERSION_ID < 50500) {
// Clear json_last_error()
json_encode(null);
$errorHandler = set_error_handler('var_dump');
restore_error_handler();
set_error_handler(function () use ($errorHandler) {
if (JSON_ERROR_NONE === json_last_error()) {
return $errorHandler && false !== call_user_func_array($errorHandler, func_get_args());
}
});
}
$data = json_encode($data, $this->encodingOptions);
}
if (PHP_VERSION_ID < 50500) {
restore_error_handler();
}
} catch (\Exception $e) {
if (PHP_VERSION_ID < 50500) {
restore_error_handler();
}
if (PHP_VERSION_ID >= 50400 && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) {
throw $e->getPrevious() ?: $e;
}
throw $e;
} }
if ($errorHandler) {
call_user_func_array($errorHandler, func_get_args());
}
});
try {
// Clear json_last_error()
json_encode(null);
$this->data = json_encode($data, $this->encodingOptions);
restore_error_handler();
} catch (\Exception $exception) {
restore_error_handler();
throw $exception;
} }
if (JSON_ERROR_NONE !== json_last_error()) { if (JSON_ERROR_NONE !== json_last_error()) {
throw new \InvalidArgumentException($this->transformJsonError()); throw new \InvalidArgumentException($this->transformJsonError());
} }
$this->data = $data;
return $this->update(); return $this->update();
} }

View File

@ -1242,15 +1242,9 @@ class Response
{ {
$status = ob_get_status(true); $status = ob_get_status(true);
$level = count($status); $level = count($status);
$flags = PHP_VERSION_ID >= 50400 ? PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE) : -1;
while ($level-- > $targetLevel while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || $flags === ($s['flags'] & $flags) : $s['del'])) {
&& (!empty($status[$level]['del'])
|| (isset($status[$level]['flags'])
&& ($status[$level]['flags'] & PHP_OUTPUT_HANDLER_REMOVABLE)
&& ($status[$level]['flags'] & ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE))
)
)
) {
if ($flush) { if ($flush) {
ob_end_flush(); ob_end_flush();
} else { } else {

View File

@ -203,9 +203,8 @@ class JsonResponseTest extends \PHPUnit_Framework_TestCase
} }
/** /**
* @expectedException Exception * @expectedException \Exception
* @expectedExceptionMessage Failed calling Symfony\Component\HttpFoundation\Tests\JsonSerializableObject::jsonSerialize() * @expectedExceptionMessage This error is expected
* @link http://php.net/manual/en/jsonserializable.jsonserialize.php#114688
*/ */
public function testSetContentJsonSerializeError() public function testSetContentJsonSerializeError()
{ {
@ -224,9 +223,7 @@ if (interface_exists('JsonSerializable')) {
{ {
public function jsonSerialize() public function jsonSerialize()
{ {
trigger_error('This error is expected', E_USER_WARNING); throw new \Exception('This error is expected');
return array();
} }
} }
} }

View File

@ -118,7 +118,7 @@ class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase
$bag->clearCookie('foo'); $bag->clearCookie('foo');
$this->assertContains('Set-Cookie: foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/; httponly', explode("\r\n", $bag->__toString())); $this->assertRegExp('#^Set-Cookie: foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/; httponly#m', $bag->__toString());
} }
public function testClearCookieSecureNotHttpOnly() public function testClearCookieSecureNotHttpOnly()
@ -127,7 +127,7 @@ class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase
$bag->clearCookie('foo', '/', null, true, false); $bag->clearCookie('foo', '/', null, true, false);
$this->assertContains("Set-Cookie: foo=deleted; expires=".gmdate("D, d-M-Y H:i:s T", time() - 31536001)."; path=/; secure", explode("\r\n", $bag->__toString())); $this->assertRegExp('#^Set-Cookie: foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/; secure#m', $bag->__toString());
} }
public function testReplace() public function testReplace()

View File

@ -45,13 +45,11 @@ class PdoCasterTest extends \PHPUnit_Framework_TestCase
'ORACLE_NULLS' => $attr['ORACLE_NULLS'], 'ORACLE_NULLS' => $attr['ORACLE_NULLS'],
'CLIENT_VERSION' => $pdo->getAttribute(\PDO::ATTR_CLIENT_VERSION), 'CLIENT_VERSION' => $pdo->getAttribute(\PDO::ATTR_CLIENT_VERSION),
'SERVER_VERSION' => $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), 'SERVER_VERSION' => $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION),
'STATEMENT_CLASS' => array( 'STATEMENT_CLASS' => array('PDOStatement'),
'PDOStatement',
array($pdo),
),
'DEFAULT_FETCH_MODE' => $attr['DEFAULT_FETCH_MODE'], 'DEFAULT_FETCH_MODE' => $attr['DEFAULT_FETCH_MODE'],
), ),
); );
unset($cast["\0~\0attributes"]['STATEMENT_CLASS'][1]);
$this->assertSame($xCast, $cast); $this->assertSame($xCast, $cast);
} }

View File

@ -28,7 +28,7 @@ class CliDumperTest extends \PHPUnit_Framework_TestCase
$cloner = new VarCloner(); $cloner = new VarCloner();
$cloner->addCasters(array( $cloner->addCasters(array(
':stream' => function ($res, $a) { ':stream' => function ($res, $a) {
unset($a['uri']); unset($a['uri'], $a['wrapper_data']);
return $a; return $a;
}, },
@ -40,12 +40,12 @@ class CliDumperTest extends \PHPUnit_Framework_TestCase
$out = ob_get_clean(); $out = ob_get_clean();
$out = preg_replace('/[ \t]+$/m', '', $out); $out = preg_replace('/[ \t]+$/m', '', $out);
$intMax = PHP_INT_MAX; $intMax = PHP_INT_MAX;
$res1 = (int) $var['res']; $res = (int) $var['res'];
$res2 = (int) $var[8];
$r = defined('HHVM_VERSION') ? '' : '#%d';
$this->assertStringMatchesFormat( $this->assertStringMatchesFormat(
<<<EOTXT <<<EOTXT
array:25 [ array:24 [
"number" => 1 "number" => 1
0 => &1 null 0 => &1 null
"const" => 1.1 "const" => 1.1
@ -58,7 +58,7 @@ array:25 [
"str" => "déjà\\n" "str" => "déjà\\n"
7 => b"é\\x00" 7 => b"é\\x00"
"[]" => [] "[]" => []
"res" => stream resource {@{$res1} "res" => stream resource {@{$res}
wrapper_type: "plainfile" wrapper_type: "plainfile"
stream_type: "STDIO" stream_type: "STDIO"
mode: "r" mode: "r"
@ -69,12 +69,11 @@ array:25 [
eof: false eof: false
options: [] options: []
} }
8 => Unknown resource @{$res2}
"obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d
+foo: "foo" +foo: "foo"
+"bar": "bar" +"bar": "bar"
} }
"closure" => Closure {#%d "closure" => Closure {{$r}
reflection: """ reflection: """
Closure [ <user%S> %s Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {\\n Closure [ <user%S> %s Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {\\n
@@ {$var['file']} {$var['line']} - {$var['line']}\\n @@ {$var['file']} {$var['line']} - {$var['line']}\\n
@ -93,7 +92,7 @@ array:25 [
"recurs" => &4 array:1 [ "recurs" => &4 array:1 [
0 => &4 array:1 [&4] 0 => &4 array:1 [&4]
] ]
9 => &1 null 8 => &1 null
"sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d} "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d}
"snobj" => &3 {#%d} "snobj" => &3 {#%d}
"snobj2" => {#%d} "snobj2" => {#%d}
@ -101,6 +100,35 @@ array:25 [
b"bin-key-é" => "" b"bin-key-é" => ""
] ]
EOTXT
,
$out
);
}
public function testClosedResource()
{
if (defined('HHVM_VERSION') && HHVM_VERSION_ID < 30600) {
$this->markTestSkipped();
}
$var = fopen(__FILE__, 'r');
fclose($var);
$dumper = new CliDumper('php://output');
$dumper->setColors(false);
$cloner = new VarCloner();
$data = $cloner->cloneVar($var);
ob_start();
$dumper->dump($data);
$out = ob_get_clean();
$res = (int) $var;
$this->assertStringMatchesFormat(
<<<EOTXT
Unknown resource @{$res}
EOTXT EOTXT
, ,
$out $out
@ -114,6 +142,13 @@ EOTXT
$dumper = new CliDumper(); $dumper = new CliDumper();
$dumper->setColors(false); $dumper->setColors(false);
$cloner = new VarCloner(); $cloner = new VarCloner();
$cloner->addCasters(array(
':stream' => function ($res, $a) {
unset($a['wrapper_data']);
return $a;
},
));
$cloner->addCasters(array( $cloner->addCasters(array(
':stream' => function () { ':stream' => function () {
throw new \Exception('Foobar'); throw new \Exception('Foobar');
@ -128,12 +163,13 @@ EOTXT
rewind($out); rewind($out);
$out = stream_get_contents($out); $out = stream_get_contents($out);
$r = defined('HHVM_VERSION') ? '' : '#%d';
$this->assertStringMatchesFormat( $this->assertStringMatchesFormat(
<<<EOTXT <<<EOTXT
stream resource {@{$ref} stream resource {@{$ref}
wrapper_type: "PHP" wrapper_type: "PHP"
stream_type: "MEMORY" stream_type: "MEMORY"
mode: "w+b" mode: "%s+b"
unread_bytes: 0 unread_bytes: 0
seekable: true seekable: true
uri: "php://memory" uri: "php://memory"
@ -141,11 +177,11 @@ stream resource {@{$ref}
blocked: true blocked: true
eof: false eof: false
options: [] options: []
: Symfony\Component\VarDumper\Exception\ThrowingCasterException {#%d : Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r}
#message: "Unexpected Exception thrown from a caster: Foobar" #message: "Unexpected Exception thrown from a caster: Foobar"
trace: array:1 [ trace: array:1 [
0 => array:2 [ 0 => array:2 [
"call" => "%s{closure}()" "call" => "%slosure%s()"
"file" => "{$file}:{$line}" "file" => "{$file}:{$line}"
] ]
] ]
@ -173,9 +209,10 @@ EOTXT
rewind($out); rewind($out);
$out = stream_get_contents($out); $out = stream_get_contents($out);
$r = defined('HHVM_VERSION') ? '' : '#%d';
$this->assertStringMatchesFormat( $this->assertStringMatchesFormat(
<<<EOTXT <<<EOTXT
{#%d {{$r}
+"foo": &1 "foo" +"foo": &1 "foo"
+"bar": &1 "foo" +"bar": &1 "foo"
} }

View File

@ -13,8 +13,6 @@ $foo = new DumbFoo();
$foo->bar = 'bar'; $foo->bar = 'bar';
$g = fopen(__FILE__, 'r'); $g = fopen(__FILE__, 'r');
$h = fopen(__FILE__, 'r');
fclose($h);
$var = array( $var = array(
'number' => 1, null, 'number' => 1, null,
@ -22,7 +20,6 @@ $var = array(
'str' => "déjà\n", "\xE9\x00", 'str' => "déjà\n", "\xE9\x00",
'[]' => array(), '[]' => array(),
'res' => $g, 'res' => $g,
$h,
'obj' => $foo, 'obj' => $foo,
'closure' => function ($a, \PDO &$b = null) {}, 'closure' => function ($a, \PDO &$b = null) {},
'line' => __LINE__ - 1, 'line' => __LINE__ - 1,
@ -40,4 +37,4 @@ $var['snobj2'] = $var['nobj'][0];
$var['file'] = __FILE__; $var['file'] = __FILE__;
$var["bin-key-\xE9"] = ''; $var["bin-key-\xE9"] = '';
unset($g, $h, $r); unset($g, $r);

View File

@ -29,7 +29,7 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
$cloner = new VarCloner(); $cloner = new VarCloner();
$cloner->addCasters(array( $cloner->addCasters(array(
':stream' => function ($res, $a) { ':stream' => function ($res, $a) {
unset($a['uri']); unset($a['uri'], $a['wrapper_data']);
return $a; return $a;
}, },
@ -44,12 +44,12 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
$intMax = PHP_INT_MAX; $intMax = PHP_INT_MAX;
preg_match('/sf-dump-\d+/', $out, $dumpId); preg_match('/sf-dump-\d+/', $out, $dumpId);
$dumpId = $dumpId[0]; $dumpId = $dumpId[0];
$res1 = (int) $var['res']; $res = (int) $var['res'];
$res2 = (int) $var[8];
$r = defined('HHVM_VERSION') ? '' : '<a class=sf-dump-ref>#%d</a>';
$this->assertStringMatchesFormat( $this->assertStringMatchesFormat(
<<<EOTXT <<<EOTXT
<foo></foo><bar><span class=sf-dump-note>array:25</span> [<samp> <foo></foo><bar><span class=sf-dump-note>array:24</span> [<samp>
"<span class=sf-dump-key>number</span>" => <span class=sf-dump-num>1</span> "<span class=sf-dump-key>number</span>" => <span class=sf-dump-num>1</span>
<span class=sf-dump-key>0</span> => <a class=sf-dump-ref href=#{$dumpId}-ref01 title="2 occurrences">&amp;1</a> <span class=sf-dump-const>null</span> <span class=sf-dump-key>0</span> => <a class=sf-dump-ref href=#{$dumpId}-ref01 title="2 occurrences">&amp;1</a> <span class=sf-dump-const>null</span>
"<span class=sf-dump-key>const</span>" => <span class=sf-dump-num>1.1</span> "<span class=sf-dump-key>const</span>" => <span class=sf-dump-num>1.1</span>
@ -62,7 +62,7 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
"<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">d&#233;j&#224;</span>\\n" "<span class=sf-dump-key>str</span>" => "<span class=sf-dump-str title="5 characters">d&#233;j&#224;</span>\\n"
<span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">&#233;</span>\\x00" <span class=sf-dump-key>7</span> => b"<span class=sf-dump-str title="2 binary or non-UTF-8 characters">&#233;</span>\\x00"
"<span class=sf-dump-key>[]</span>" => [] "<span class=sf-dump-key>[]</span>" => []
"<span class=sf-dump-key>res</span>" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res1}</a><samp> "<span class=sf-dump-key>res</span>" => <span class=sf-dump-note>stream resource</span> <a class=sf-dump-ref>@{$res}</a><samp>
<span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>" <span class=sf-dump-meta>wrapper_type</span>: "<span class=sf-dump-str title="9 characters">plainfile</span>"
<span class=sf-dump-meta>stream_type</span>: "<span class=sf-dump-str title="5 characters">STDIO</span>" <span class=sf-dump-meta>stream_type</span>: "<span class=sf-dump-str title="5 characters">STDIO</span>"
<span class=sf-dump-meta>mode</span>: "<span class=sf-dump-str>r</span>" <span class=sf-dump-meta>mode</span>: "<span class=sf-dump-str>r</span>"
@ -73,12 +73,11 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
<span class=sf-dump-meta>eof</span>: <span class=sf-dump-const>false</span> <span class=sf-dump-meta>eof</span>: <span class=sf-dump-const>false</span>
<span class=sf-dump-meta>options</span>: [] <span class=sf-dump-meta>options</span>: []
</samp>} </samp>}
<span class=sf-dump-key>8</span> => <span class=sf-dump-note>Unknown resource</span> <a class=sf-dump-ref>@{$res2}</a>
"<span class=sf-dump-key>obj</span>" => <abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="2 occurrences">#%d</a><samp id={$dumpId}-ref2%d> "<span class=sf-dump-key>obj</span>" => <abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="2 occurrences">#%d</a><samp id={$dumpId}-ref2%d>
+<span class=sf-dump-public title="Public property">foo</span>: "<span class=sf-dump-str title="3 characters">foo</span>" +<span class=sf-dump-public title="Public property">foo</span>: "<span class=sf-dump-str title="3 characters">foo</span>"
+"<span class=sf-dump-public title="Runtime added dynamic property">bar</span>": "<span class=sf-dump-str title="3 characters">bar</span>" +"<span class=sf-dump-public title="Runtime added dynamic property">bar</span>": "<span class=sf-dump-str title="3 characters">bar</span>"
</samp>} </samp>}
"<span class=sf-dump-key>closure</span>" => <span class=sf-dump-note>Closure</span> {<a class=sf-dump-ref>#%d</a><samp> "<span class=sf-dump-key>closure</span>" => <span class=sf-dump-note>Closure</span> {{$r}<samp>
<span class=sf-dump-meta>reflection</span>: """ <span class=sf-dump-meta>reflection</span>: """
<span class=sf-dump-str title="%d characters">Closure [ &lt;user%S&gt; %s Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {</span>\\n <span class=sf-dump-str title="%d characters">Closure [ &lt;user%S&gt; %s Symfony\Component\VarDumper\Tests\Fixture\{closure} ] {</span>\\n
<span class=sf-dump-str title="%d characters"> @@ {$var['file']} {$var['line']} - {$var['line']}</span>\\n <span class=sf-dump-str title="%d characters"> @@ {$var['file']} {$var['line']} - {$var['line']}</span>\\n
@ -97,7 +96,7 @@ class HtmlDumperTest extends \PHPUnit_Framework_TestCase
"<span class=sf-dump-key>recurs</span>" => <a class=sf-dump-ref href=#{$dumpId}-ref04 title="2 occurrences">&amp;4</a> <span class=sf-dump-note>array:1</span> [<samp id={$dumpId}-ref04> "<span class=sf-dump-key>recurs</span>" => <a class=sf-dump-ref href=#{$dumpId}-ref04 title="2 occurrences">&amp;4</a> <span class=sf-dump-note>array:1</span> [<samp id={$dumpId}-ref04>
<span class=sf-dump-index>0</span> => <a class=sf-dump-ref href=#{$dumpId}-ref04 title="2 occurrences">&amp;4</a> <span class=sf-dump-note>array:1</span> [<a class=sf-dump-ref href=#{$dumpId}-ref04 title="2 occurrences">&amp;4</a>] <span class=sf-dump-index>0</span> => <a class=sf-dump-ref href=#{$dumpId}-ref04 title="2 occurrences">&amp;4</a> <span class=sf-dump-note>array:1</span> [<a class=sf-dump-ref href=#{$dumpId}-ref04 title="2 occurrences">&amp;4</a>]
</samp>] </samp>]
<span class=sf-dump-key>9</span> => <a class=sf-dump-ref href=#{$dumpId}-ref01 title="2 occurrences">&amp;1</a> <span class=sf-dump-const>null</span> <span class=sf-dump-key>8</span> => <a class=sf-dump-ref href=#{$dumpId}-ref01 title="2 occurrences">&amp;1</a> <span class=sf-dump-const>null</span>
"<span class=sf-dump-key>sobj</span>" => <abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="2 occurrences">#%d</a>} "<span class=sf-dump-key>sobj</span>" => <abbr title="Symfony\Component\VarDumper\Tests\Fixture\DumbFoo" class=sf-dump-note>DumbFoo</abbr> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="2 occurrences">#%d</a>}
"<span class=sf-dump-key>snobj</span>" => <a class=sf-dump-ref href=#{$dumpId}-ref03 title="2 occurrences">&amp;3</a> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>} "<span class=sf-dump-key>snobj</span>" => <a class=sf-dump-ref href=#{$dumpId}-ref03 title="2 occurrences">&amp;3</a> {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>}
"<span class=sf-dump-key>snobj2</span>" => {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>} "<span class=sf-dump-key>snobj2</span>" => {<a class=sf-dump-ref href=#{$dumpId}-ref2%d title="3 occurrences">#%d</a>}

View File

@ -81,7 +81,7 @@ Symfony\Component\VarDumper\Cloner\Data Object
[class] => stdClass [class] => stdClass
[value] => [value] =>
[cut] => 0 [cut] => 0
[handle] => %d [handle] => %i
[refCount] => 0 [refCount] => 0
[position] => 1 [position] => 1
) )
@ -96,7 +96,7 @@ Symfony\Component\VarDumper\Cloner\Data Object
[class] => stdClass [class] => stdClass
[value] => [value] =>
[cut] => 0 [cut] => 0
[handle] => %d [handle] => %i
[refCount] => 0 [refCount] => 0
[position] => 2 [position] => 2
) )
@ -107,7 +107,7 @@ Symfony\Component\VarDumper\Cloner\Data Object
[class] => stdClass [class] => stdClass
[value] => [value] =>
[cut] => 0 [cut] => 0
[handle] => %d [handle] => %i
[refCount] => 0 [refCount] => 0
[position] => 3 [position] => 3
) )