[VarExporter] fix support for PHP 7.4

This commit is contained in:
Nicolas Grekas 2019-08-07 18:46:18 +02:00
parent dd153d8dce
commit 1a036dc9ff
15 changed files with 208 additions and 71 deletions

View File

@ -155,7 +155,7 @@ class Exporter
}
$sleep[$n] = false;
}
if (!\array_key_exists($name, $proto) || $proto[$name] !== $v) {
if (!\array_key_exists($name, $proto) || $proto[$name] !== $v || "\x00Error\x00trace" === $name || "\x00Exception\x00trace" === $name) {
$properties[$c][$n] = $v;
}
}
@ -291,7 +291,7 @@ class Exporter
continue;
}
if (!Registry::$instantiableWithoutConstructor[$class]) {
if (is_subclass_of($class, 'Serializable')) {
if (is_subclass_of($class, 'Serializable') && !method_exists($class, '__unserialize')) {
$serializables[$k] = 'C:'.\strlen($class).':"'.$class.'":0:{}';
} else {
$serializables[$k] = 'O:'.\strlen($class).':"'.$class.'":0:{}';

View File

@ -75,7 +75,7 @@ class Registry
} elseif (!$isClass || $reflector->isAbstract()) {
throw new NotInstantiableTypeException($class);
} elseif ($reflector->name !== $class) {
$reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, $instantiableWithoutConstructor, $cloneable);
$reflector = self::$reflectors[$name = $reflector->name] ?? self::getClassReflector($name, false, $cloneable);
self::$cloneable[$class] = self::$cloneable[$name];
self::$instantiableWithoutConstructor[$class] = self::$instantiableWithoutConstructor[$name];
self::$prototypes[$class] = self::$prototypes[$name];
@ -86,7 +86,7 @@ class Registry
$proto = $reflector->newInstanceWithoutConstructor();
$instantiableWithoutConstructor = true;
} catch (\ReflectionException $e) {
$proto = $reflector->implementsInterface('Serializable') && (\PHP_VERSION_ID < 70400 || !method_exists($class, '__unserialize')) ? 'C:' : 'O:';
$proto = $reflector->implementsInterface('Serializable') && !method_exists($class, '__unserialize') ? 'C:' : 'O:';
if ('C:' === $proto && !$reflector->getMethod('unserialize')->isInternal()) {
$proto = null;
} elseif (false === $proto = @unserialize($proto.\strlen($class).':"'.$class.'":0:{}')) {

View File

@ -0,0 +1,22 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['ArrayIterator'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('ArrayIterator')),
],
null,
[
'ArrayIterator' => [
"\0" => [
[
[
123,
],
1,
],
],
],
],
$o[0],
[]
);

View File

@ -5,18 +5,15 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['ArrayIterator'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('ArrayIterator')),
],
null,
[
'ArrayIterator' => [
"\0" => [
[
[
123,
],
1,
],
],
],
],
[],
$o[0],
[]
[
[
1,
[
123,
],
[],
],
]
);

View File

@ -0,0 +1,22 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\MyArrayObject'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\MyArrayObject')),
],
null,
[
'ArrayObject' => [
"\0" => [
[
[
234,
],
1,
],
],
],
],
$o[0],
[]
);

View File

@ -5,18 +5,17 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\MyArrayObject'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\MyArrayObject')),
],
null,
[],
$o[0],
[
'ArrayObject' => [
"\0" => [
[
[
234,
],
1,
],
[
1,
[
234,
],
[
"\0".'Symfony\\Component\\VarExporter\\Tests\\MyArrayObject'."\0".'unused' => 123,
],
],
],
$o[0],
[]
]
);

View File

@ -0,0 +1,29 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (($p = &\Symfony\Component\VarExporter\Internal\Registry::$prototypes)['ArrayObject'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('ArrayObject')),
clone $p['ArrayObject'],
],
null,
[
'ArrayObject' => [
"\0" => [
[
[
1,
$o[0],
],
0,
],
],
],
'stdClass' => [
'foo' => [
$o[1],
],
],
],
$o[0],
[]
);

View File

@ -6,24 +6,23 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
clone $p['ArrayObject'],
],
null,
[
'ArrayObject' => [
"\0" => [
[
[
1,
$o[0],
],
0,
],
],
],
'stdClass' => [
'foo' => [
$o[1],
],
],
],
[],
$o[0],
[]
[
[
0,
[
1,
$o[0],
],
[
'foo' => $o[1],
],
],
-1 => [
0,
[],
[],
],
]
);

View File

@ -0,0 +1,11 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'C:54:"Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator":49:{a:2:{i:0;i:123;i:1;s:21:"x:i:0;a:0:{};m:a:0:{}";}}',
]),
null,
[],
$o[0],
[]
);

View File

@ -1,11 +1,17 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'C:54:"Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator":49:{a:2:{i:0;i:123;i:1;s:21:"x:i:0;a:0:{};m:a:0:{}";}}',
]),
$o = [
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes['Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('Symfony\\Component\\VarExporter\\Tests\\FinalArrayIterator')),
],
null,
[],
$o[0],
[]
[
[
0,
[],
[],
],
]
);

View File

@ -0,0 +1,27 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'O:46:"Symfony\\Component\\VarExporter\\Tests\\FinalError":1:{s:12:"'."\0".'Error'."\0".'trace";a:0:{}}',
]),
null,
[
'TypeError' => [
'file' => [
\dirname(__DIR__).\DIRECTORY_SEPARATOR.'VarExporterTest.php',
],
'line' => [
123,
],
],
'Error' => [
'trace' => [
[],
],
],
],
$o[0],
[
1 => 0,
]
);

View File

@ -1,9 +1,9 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
'O:46:"Symfony\\Component\\VarExporter\\Tests\\FinalError":1:{s:12:"'."\0".'Error'."\0".'trace";a:0:{}}',
]),
$o = [
(\Symfony\Component\VarExporter\Internal\Registry::$factories['Symfony\\Component\\VarExporter\\Tests\\FinalError'] ?? \Symfony\Component\VarExporter\Internal\Registry::f('Symfony\\Component\\VarExporter\\Tests\\FinalError'))(),
],
null,
[
'TypeError' => [
@ -14,6 +14,11 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
123,
],
],
'Error' => [
'trace' => [
[],
],
],
],
$o[0],
[

View File

@ -0,0 +1,21 @@
<?php
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
$o = [
clone (($p = &\Symfony\Component\VarExporter\Internal\Registry::$prototypes)['SplObjectStorage'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('SplObjectStorage')),
clone ($p['stdClass'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('stdClass')),
],
null,
[
'SplObjectStorage' => [
"\0" => [
[
$o[1],
345,
],
],
],
],
$o[0],
[]
);

View File

@ -6,16 +6,15 @@ return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
clone ($p['stdClass'] ?? \Symfony\Component\VarExporter\Internal\Registry::p('stdClass')),
],
null,
[
'SplObjectStorage' => [
"\0" => [
[
$o[1],
345,
],
],
],
],
[],
$o[0],
[]
[
[
[
$o[1],
345,
],
[],
],
]
);

View File

@ -12,7 +12,6 @@
namespace Symfony\Component\VarExporter\Tests;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Warning;
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
use Symfony\Component\VarExporter\Internal\Registry;
use Symfony\Component\VarExporter\VarExporter;
@ -76,10 +75,6 @@ class VarExporterTest extends TestCase
*/
public function testExport(string $testName, $value, bool $staticValueExpected = false)
{
if (\PHP_VERSION_ID >= 70400 && \in_array($testName, ['spl-object-storage', 'array-object-custom', 'array-iterator', 'array-object', 'final-array-iterator'])) {
throw new Warning('PHP 7.4 breaks this test.');
}
$dumpedValue = $this->getDump($value);
$isStaticValue = true;
$marshalledValue = VarExporter::export($value, $isStaticValue);
@ -91,7 +86,12 @@ class VarExporterTest extends TestCase
$dump = "<?php\n\nreturn ".$marshalledValue.";\n";
$dump = str_replace(var_export(__FILE__, true), "\\dirname(__DIR__).\\DIRECTORY_SEPARATOR.'VarExporterTest.php'", $dump);
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'.php';
if (\PHP_VERSION_ID < 70400 && \in_array($testName, ['array-object', 'array-iterator', 'array-object-custom', 'spl-object-storage', 'final-array-iterator', 'final-error'], true)) {
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'-legacy.php';
} else {
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'.php';
}
$this->assertStringEqualsFile($fixtureFile, $dump);
if ('incomplete-class' === $testName || 'external-references' === $testName) {