minor #28295 [VarExporter] optimize dumped code in time and space (nicolas-grekas)
This PR was merged into the 4.2-dev branch.
Discussion
----------
[VarExporter] optimize dumped code in time and space
| Q | A
| ------------- | ---
| Branch? | master
| Bug fix? | no
| New feature? | no
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | -
| License | MIT
| Doc PR | -
Let's squeeze some more µs when running exported code.
On a simple case run 100k times with a few objects, I go from 1.8s to 1.5s.
The generated exports are also a bit smaller if it matters.
This works by:
- using local variables instead of manually dealing with a stack
- creating more optimized object hydrators for internal classes
This PR also fixes handling of hard references that are bound to external variables.
Commits
-------
07e90d71d8
[VarExporter] optimize dumped code in time and space
This commit is contained in:
commit
cabbf51af4
@ -48,10 +48,11 @@ class Exporter
|
|||||||
$refs[$k] = $value = $values[$k];
|
$refs[$k] = $value = $values[$k];
|
||||||
if ($value instanceof Reference && 0 > $value->id) {
|
if ($value instanceof Reference && 0 > $value->id) {
|
||||||
$valuesAreStatic = false;
|
$valuesAreStatic = false;
|
||||||
|
++$value->count;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$refsPool[] = array(&$refs[$k], $value, &$value);
|
$refsPool[] = array(&$refs[$k], $value, &$value);
|
||||||
$refs[$k] = $values[$k] = new Reference(-\count($refsPool));
|
$refs[$k] = $values[$k] = new Reference(-\count($refsPool), $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (\is_array($value)) {
|
if (\is_array($value)) {
|
||||||
@ -80,12 +81,13 @@ class Exporter
|
|||||||
Registry::getClassReflector($class);
|
Registry::getClassReflector($class);
|
||||||
serialize(Registry::$prototypes[$class]);
|
serialize(Registry::$prototypes[$class]);
|
||||||
}
|
}
|
||||||
|
$reflector = Registry::$reflectors[$class];
|
||||||
$proto = Registry::$prototypes[$class];
|
$proto = Registry::$prototypes[$class];
|
||||||
|
|
||||||
if ($value instanceof \ArrayIterator || $value instanceof \ArrayObject) {
|
if ($value instanceof \ArrayIterator || $value instanceof \ArrayObject) {
|
||||||
// ArrayIterator and ArrayObject need special care because their "flags"
|
// ArrayIterator and ArrayObject need special care because their "flags"
|
||||||
// option changes the behavior of the (array) casting operator.
|
// option changes the behavior of the (array) casting operator.
|
||||||
$proto = Registry::$cloneable[$class] ? clone Registry::$prototypes[$class] : Registry::$reflectors[$class]->newInstanceWithoutConstructor();
|
$proto = Registry::$cloneable[$class] ? clone Registry::$prototypes[$class] : $reflector->newInstanceWithoutConstructor();
|
||||||
$properties = self::getArrayObjectProperties($value, $arrayValue, $proto);
|
$properties = self::getArrayObjectProperties($value, $arrayValue, $proto);
|
||||||
} elseif ($value instanceof \SplObjectStorage) {
|
} elseif ($value instanceof \SplObjectStorage) {
|
||||||
// By implementing Serializable, SplObjectStorage breaks internal references,
|
// By implementing Serializable, SplObjectStorage breaks internal references,
|
||||||
@ -116,21 +118,30 @@ class Exporter
|
|||||||
foreach ($arrayValue as $name => $v) {
|
foreach ($arrayValue as $name => $v) {
|
||||||
$n = (string) $name;
|
$n = (string) $name;
|
||||||
if ('' === $n || "\0" !== $n[0]) {
|
if ('' === $n || "\0" !== $n[0]) {
|
||||||
$c = $class;
|
$c = '*';
|
||||||
|
$properties[$c][$n] = $v;
|
||||||
|
unset($sleep[$n]);
|
||||||
} elseif ('*' === $n[1]) {
|
} elseif ('*' === $n[1]) {
|
||||||
$c = $class;
|
|
||||||
$n = substr($n, 3);
|
$n = substr($n, 3);
|
||||||
|
$c = $reflector->getProperty($n)->class;
|
||||||
|
if ('Error' === $c) {
|
||||||
|
$c = 'TypeError';
|
||||||
|
} elseif ('Exception' === $c) {
|
||||||
|
$c = 'ErrorException';
|
||||||
|
}
|
||||||
|
$properties[$c][$n] = $v;
|
||||||
|
unset($sleep[$n]);
|
||||||
} else {
|
} else {
|
||||||
$i = strpos($n, "\0", 2);
|
$i = strpos($n, "\0", 2);
|
||||||
$c = substr($n, 1, $i - 1);
|
$c = substr($n, 1, $i - 1);
|
||||||
$n = substr($n, 1 + $i);
|
$n = substr($n, 1 + $i);
|
||||||
}
|
|
||||||
if (null === $sleep) {
|
if (null === $sleep) {
|
||||||
$properties[$c][$n] = $v;
|
$properties[$c][$n] = $v;
|
||||||
} elseif (isset($sleep[$n]) && $c === $class) {
|
} elseif (isset($sleep[$n]) && $c === $class) {
|
||||||
$properties[$c][$n] = $v;
|
$properties[$c][$n] = $v;
|
||||||
unset($sleep[$n]);
|
unset($sleep[$n]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (\array_key_exists($name, $proto) && $proto[$name] === $v) {
|
if (\array_key_exists($name, $proto) && $proto[$name] === $v) {
|
||||||
unset($properties[$c][$n]);
|
unset($properties[$c][$n]);
|
||||||
}
|
}
|
||||||
@ -173,11 +184,14 @@ class Exporter
|
|||||||
|
|
||||||
if ($value instanceof Reference) {
|
if ($value instanceof Reference) {
|
||||||
if (0 <= $value->id) {
|
if (0 <= $value->id) {
|
||||||
return '\\'.Registry::class.'::$objects['.$value->id.']';
|
return '$o['.$value->id.']';
|
||||||
|
}
|
||||||
|
if (!$value->count) {
|
||||||
|
return self::export($value->value, $indent);
|
||||||
}
|
}
|
||||||
$value = -$value->id;
|
$value = -$value->id;
|
||||||
|
|
||||||
return '&\\'.Registry::class.'::$references['.$value.']';
|
return '&$r['.$value.']';
|
||||||
}
|
}
|
||||||
$subIndent = $indent.' ';
|
$subIndent = $indent.' ';
|
||||||
|
|
||||||
@ -213,9 +227,11 @@ class Exporter
|
|||||||
$code = '';
|
$code = '';
|
||||||
foreach ($value as $k => $v) {
|
foreach ($value as $k => $v) {
|
||||||
$code .= $subIndent;
|
$code .= $subIndent;
|
||||||
if ($k !== ++$j) {
|
if (!\is_int($k) || 1 !== $k - $j) {
|
||||||
$code .= self::export($k, $subIndent).' => ';
|
$code .= self::export($k, $subIndent).' => ';
|
||||||
$j = INF;
|
}
|
||||||
|
if (\is_int($k)) {
|
||||||
|
$j = $k;
|
||||||
}
|
}
|
||||||
$code .= self::export($v, $subIndent).",\n";
|
$code .= self::export($v, $subIndent).",\n";
|
||||||
}
|
}
|
||||||
@ -224,54 +240,92 @@ class Exporter
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($value instanceof Values) {
|
if ($value instanceof Values) {
|
||||||
$code = '';
|
$code = $subIndent."\$r = [],\n";
|
||||||
foreach ($value->values as $k => $v) {
|
foreach ($value->values as $k => $v) {
|
||||||
$code .= $subIndent.'\\'.Registry::class.'::$references['.$k.'] = '.self::export($v, $subIndent).",\n";
|
$code .= $subIndent.'$r['.$k.'] = '.self::export($v, $subIndent).",\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "[\n".$code.$indent.']';
|
return "[\n".$code.$indent.']';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($value instanceof Registry) {
|
if ($value instanceof Registry) {
|
||||||
|
return self::exportRegistry($value, $indent, $subIndent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value instanceof Hydrator) {
|
||||||
|
return self::exportHydrator($value, $indent, $subIndent);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \UnexpectedValueException(sprintf('Cannot export value of type "%s".', \is_object($value) ? \get_class($value) : \gettype($value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function exportRegistry(Registry $value, string $indent, string $subIndent): string
|
||||||
|
{
|
||||||
$code = '';
|
$code = '';
|
||||||
$reflectors = array();
|
$reflectors = array();
|
||||||
$serializables = array();
|
$serializables = array();
|
||||||
|
$seen = array();
|
||||||
|
$prototypesAccess = 0;
|
||||||
|
$factoriesAccess = 0;
|
||||||
|
$r = '\\'.Registry::class;
|
||||||
|
$j = -1;
|
||||||
|
|
||||||
foreach ($value as $k => $class) {
|
foreach ($value as $k => $class) {
|
||||||
if (':' === ($class[1] ?? null)) {
|
if (':' === ($class[1] ?? null)) {
|
||||||
$serializables[$k] = $class;
|
$serializables[$k] = $class;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$c = '\\'.$class.'::class';
|
$code .= $subIndent.(1 !== $k - $j ? $k.' => ' : '');
|
||||||
$reflectors[$class] = '\\'.Registry::class.'::$reflectors['.$c.'] ?? \\'.Registry::class.'::getClassReflector('.$c.', '
|
$j = $k;
|
||||||
.self::export(Registry::$instantiableWithoutConstructor[$class]).', '
|
$eol = ",\n";
|
||||||
.self::export(Registry::$cloneable[$class])
|
$c = '[\\'.$class.'::class]';
|
||||||
.')';
|
|
||||||
|
|
||||||
|
if ($seen[$class] ?? false) {
|
||||||
if (Registry::$cloneable[$class]) {
|
if (Registry::$cloneable[$class]) {
|
||||||
$code .= $subIndent.'clone \\'.Registry::class.'::$prototypes['.$c."],\n";
|
++$prototypesAccess;
|
||||||
} elseif (Registry::$instantiableWithoutConstructor[$class]) {
|
$code .= 'clone $p'.$c;
|
||||||
$code .= $subIndent.'\\'.Registry::class.'::$reflectors['.$c."]->newInstanceWithoutConstructor(),\n";
|
|
||||||
} else {
|
} else {
|
||||||
$code .= $subIndent.'\\'.Registry::class.'::$reflectors['.$c."]->newInstance(),\n";
|
++$factoriesAccess;
|
||||||
|
$code .= '$f'.$c.'()';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ($reflectors) {
|
|
||||||
$code = "[\n".$subIndent.implode(",\n".$subIndent, $reflectors).",\n".$indent."], [\n".$code.$indent.'], ';
|
|
||||||
$code .= !$serializables ? "[\n".$indent.']' : self::export($serializables, $indent);
|
|
||||||
} else {
|
} else {
|
||||||
$code = '[], []';
|
$seen[$class] = true;
|
||||||
$code .= ', '.self::export($serializables, $indent);
|
if (Registry::$cloneable[$class]) {
|
||||||
|
$code .= 'clone ('.($prototypesAccess++ ? '$p' : '($p =& '.$r.'::$prototypes)').$c.' ?? '.$r.'::p';
|
||||||
|
} else {
|
||||||
|
$code .= '('.($factoriesAccess++ ? '$f' : '($f =& '.$r.'::$factories)').$c.' ?? '.$r.'::f';
|
||||||
|
$eol = '()'.$eol;
|
||||||
|
}
|
||||||
|
$code .= '('.substr($c, 1, -1).', '.self::export(Registry::$instantiableWithoutConstructor[$class]).'))';
|
||||||
|
}
|
||||||
|
$code .= $eol;
|
||||||
}
|
}
|
||||||
|
|
||||||
return '\\'.Registry::class.'::push('.$code.')';
|
if (1 === $prototypesAccess) {
|
||||||
|
$code = str_replace('($p =& '.$r.'::$prototypes)', $r.'::$prototypes', $code);
|
||||||
|
}
|
||||||
|
if (1 === $factoriesAccess) {
|
||||||
|
$code = str_replace('($f =& '.$r.'::$factories)', $r.'::$factories', $code);
|
||||||
|
}
|
||||||
|
if ('' !== $code) {
|
||||||
|
$code = "\n".$code.$indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($value instanceof Configurator) {
|
if ($serializables) {
|
||||||
|
$code = $r.'::unserialize(['.$code.'], '.self::export($serializables, $indent).')';
|
||||||
|
} else {
|
||||||
|
$code = '['.$code.']';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '$o = '.$code;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function exportHydrator(Hydrator $value, string $indent, string $subIndent): string
|
||||||
|
{
|
||||||
$code = '';
|
$code = '';
|
||||||
foreach ($value->properties as $class => $properties) {
|
foreach ($value->properties as $class => $properties) {
|
||||||
$code .= $subIndent.' \\'.$class.'::class => '.self::export($properties, $subIndent.' ').",\n";
|
$c = '*' !== $class ? '\\'.$class.'::class' : "'*'";
|
||||||
|
$code .= $subIndent.' '.$c.' => '.self::export($properties, $subIndent.' ').",\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
$code = array(
|
$code = array(
|
||||||
@ -282,24 +336,14 @@ class Exporter
|
|||||||
self::export($value->wakeups, $subIndent),
|
self::export($value->wakeups, $subIndent),
|
||||||
);
|
);
|
||||||
|
|
||||||
return '\\'.\get_class($value)."::pop(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')';
|
return '\\'.\get_class($value)."::hydrate(\n".$subIndent.implode(",\n".$subIndent, $code)."\n".$indent.')';
|
||||||
}
|
|
||||||
|
|
||||||
throw new \UnexpectedValueException(sprintf('Cannot export value of type "%s".', \is_object($value) ? \get_class($value) : \gettype($value)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the state of an ArrayIterator or ArrayObject instance.
|
|
||||||
*
|
|
||||||
* For performance this method is public and has no type-hints.
|
|
||||||
*
|
|
||||||
* @param \ArrayIterator|\ArrayObject $value
|
* @param \ArrayIterator|\ArrayObject $value
|
||||||
* @param array &$arrayValue
|
* @param \ArrayIterator|\ArrayObject $proto
|
||||||
* @param object $proto
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
*/
|
||||||
public static function getArrayObjectProperties($value, &$arrayValue, $proto)
|
private static function getArrayObjectProperties($value, array &$arrayValue, $proto): array
|
||||||
{
|
{
|
||||||
$reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject';
|
$reflector = $value instanceof \ArrayIterator ? 'ArrayIterator' : 'ArrayObject';
|
||||||
$reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector);
|
$reflector = Registry::$reflectors[$reflector] ?? Registry::getClassReflector($reflector);
|
||||||
|
@ -16,9 +16,9 @@ namespace Symfony\Component\VarExporter\Internal;
|
|||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
class Configurator
|
class Hydrator
|
||||||
{
|
{
|
||||||
public static $configurators = array();
|
public static $hydrators = array();
|
||||||
|
|
||||||
public $registry;
|
public $registry;
|
||||||
public $values;
|
public $values;
|
||||||
@ -35,12 +35,10 @@ class Configurator
|
|||||||
$this->wakeups = $wakeups;
|
$this->wakeups = $wakeups;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function pop($objects, $values, $properties, $value, $wakeups)
|
public static function hydrate($objects, $values, $properties, $value, $wakeups)
|
||||||
{
|
{
|
||||||
list(Registry::$objects, Registry::$references) = \array_pop(Registry::$stack);
|
|
||||||
|
|
||||||
foreach ($properties as $class => $vars) {
|
foreach ($properties as $class => $vars) {
|
||||||
(self::$configurators[$class] ?? self::getConfigurator($class))($vars, $objects);
|
(self::$hydrators[$class] ?? self::getHydrator($class))($vars, $objects);
|
||||||
}
|
}
|
||||||
foreach ($wakeups as $i) {
|
foreach ($wakeups as $i) {
|
||||||
$objects[$i]->__wakeup();
|
$objects[$i]->__wakeup();
|
||||||
@ -49,18 +47,22 @@ class Configurator
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getConfigurator($class)
|
public static function getHydrator($class)
|
||||||
{
|
{
|
||||||
$classReflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class);
|
if ('*' === $class) {
|
||||||
|
return self::$hydrators[$class] = static function ($properties, $objects) {
|
||||||
if (!$classReflector->isInternal()) {
|
|
||||||
return self::$configurators[$class] = \Closure::bind(function ($properties, $objects) {
|
|
||||||
foreach ($properties as $name => $values) {
|
foreach ($properties as $name => $values) {
|
||||||
foreach ($values as $i => $v) {
|
foreach ($values as $i => $v) {
|
||||||
$objects[$i]->$name = $v;
|
$objects[$i]->$name = $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, null, $class);
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$classReflector = Registry::$reflectors[$class] ?? Registry::getClassReflector($class);
|
||||||
|
|
||||||
|
if (!$classReflector->isInternal()) {
|
||||||
|
return self::$hydrators[$class] = (self::$hydrators['*'] ?? self::getHydrator('*'))->bindTo(null, $class);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($class) {
|
switch ($class) {
|
||||||
@ -68,7 +70,7 @@ class Configurator
|
|||||||
case 'ArrayObject':
|
case 'ArrayObject':
|
||||||
$constructor = $classReflector->getConstructor();
|
$constructor = $classReflector->getConstructor();
|
||||||
|
|
||||||
return self::$configurators[$class] = static function ($properties, $objects) use ($constructor) {
|
return self::$hydrators[$class] = static function ($properties, $objects) use ($constructor) {
|
||||||
foreach ($properties as $name => $values) {
|
foreach ($properties as $name => $values) {
|
||||||
if ("\0" !== $name) {
|
if ("\0" !== $name) {
|
||||||
foreach ($values as $i => $v) {
|
foreach ($values as $i => $v) {
|
||||||
@ -81,8 +83,16 @@ class Configurator
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
case 'ErrorException':
|
||||||
|
return self::$hydrators[$class] = (self::$hydrators['*'] ?? self::getHydrator('*'))->bindTo(null, new class() extends \ErrorException {
|
||||||
|
});
|
||||||
|
|
||||||
|
case 'TypeError':
|
||||||
|
return self::$hydrators[$class] = (self::$hydrators['*'] ?? self::getHydrator('*'))->bindTo(null, new class() extends \Error {
|
||||||
|
});
|
||||||
|
|
||||||
case 'SplObjectStorage':
|
case 'SplObjectStorage':
|
||||||
return self::$configurators[$class] = static function ($properties, $objects) {
|
return self::$hydrators[$class] = static function ($properties, $objects) {
|
||||||
foreach ($properties as $name => $values) {
|
foreach ($properties as $name => $values) {
|
||||||
if ("\0" === $name) {
|
if ("\0" === $name) {
|
||||||
foreach ($values as $i => $v) {
|
foreach ($values as $i => $v) {
|
||||||
@ -100,23 +110,18 @@ class Configurator
|
|||||||
}
|
}
|
||||||
|
|
||||||
$propertyReflectors = array();
|
$propertyReflectors = array();
|
||||||
foreach ($classReflector->getProperties(\ReflectionProperty::IS_PROTECTED | \ReflectionProperty::IS_PRIVATE) as $propertyReflector) {
|
foreach ($classReflector->getProperties() as $propertyReflector) {
|
||||||
if (!$propertyReflector->isStatic()) {
|
if (!$propertyReflector->isStatic()) {
|
||||||
$propertyReflector->setAccessible(true);
|
$propertyReflector->setAccessible(true);
|
||||||
$propertyReflectors[$propertyReflector->name] = $propertyReflector;
|
$propertyReflectors[$propertyReflector->name] = $propertyReflector;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$configurators[$class] = static function ($properties, $objects) use ($propertyReflectors) {
|
return self::$hydrators[$class] = static function ($properties, $objects) use ($propertyReflectors) {
|
||||||
foreach ($properties as $name => $values) {
|
foreach ($properties as $name => $values) {
|
||||||
if (isset($propertyReflectors[$name])) {
|
$p = $propertyReflectors[$name];
|
||||||
foreach ($values as $i => $v) {
|
foreach ($values as $i => $v) {
|
||||||
$propertyReflectors[$name]->setValue($objects[$i], $v);
|
$p->setValue($objects[$i], $v);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foreach ($values as $i => $v) {
|
|
||||||
$objects[$i]->$name = $v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -19,9 +19,12 @@ namespace Symfony\Component\VarExporter\Internal;
|
|||||||
class Reference
|
class Reference
|
||||||
{
|
{
|
||||||
public $id;
|
public $id;
|
||||||
|
public $value;
|
||||||
|
public $count = 0;
|
||||||
|
|
||||||
public function __construct(int $id)
|
public function __construct(int $id, $value = null)
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
|
$this->value = $value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,9 @@ namespace Symfony\Component\VarExporter\Internal;
|
|||||||
*/
|
*/
|
||||||
class Registry
|
class Registry
|
||||||
{
|
{
|
||||||
public static $stack = array();
|
|
||||||
public static $objects = array();
|
|
||||||
public static $references = array();
|
|
||||||
public static $reflectors = array();
|
public static $reflectors = array();
|
||||||
public static $prototypes = array();
|
public static $prototypes = array();
|
||||||
|
public static $factories = array();
|
||||||
public static $cloneable = array();
|
public static $cloneable = array();
|
||||||
public static $instantiableWithoutConstructor = array();
|
public static $instantiableWithoutConstructor = array();
|
||||||
|
|
||||||
@ -33,28 +31,33 @@ class Registry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function push($reflectors, $objects, $serializables)
|
public static function unserialize($objects, $serializables)
|
||||||
{
|
{
|
||||||
self::$stack[] = array(self::$objects, self::$references);
|
|
||||||
self::$references = array();
|
|
||||||
|
|
||||||
if (!$serializables) {
|
|
||||||
return self::$objects = $objects;
|
|
||||||
}
|
|
||||||
$unserializeCallback = ini_set('unserialize_callback_func', __CLASS__.'::getClassReflector');
|
$unserializeCallback = ini_set('unserialize_callback_func', __CLASS__.'::getClassReflector');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
foreach ($serializables as $k => $v) {
|
foreach ($serializables as $k => $v) {
|
||||||
$objects[$k] = unserialize($v);
|
$objects[$k] = unserialize($v);
|
||||||
}
|
}
|
||||||
} catch (\Throwable $e) {
|
|
||||||
list(self::$objects, self::$references) = array_pop(self::$stack);
|
|
||||||
throw $e;
|
|
||||||
} finally {
|
} finally {
|
||||||
ini_set('unserialize_callback_func', $unserializeCallback);
|
ini_set('unserialize_callback_func', $unserializeCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self::$objects = $objects;
|
return $objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function p($class, $instantiableWithoutConstructor)
|
||||||
|
{
|
||||||
|
self::getClassReflector($class, $instantiableWithoutConstructor, true);
|
||||||
|
|
||||||
|
return self::$prototypes[$class];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function f($class, $instantiableWithoutConstructor)
|
||||||
|
{
|
||||||
|
$reflector = self::$reflectors[$class] ?? self::getClassReflector($class, $instantiableWithoutConstructor, false);
|
||||||
|
|
||||||
|
return self::$factories[$class] = \Closure::fromCallable(array($reflector, $instantiableWithoutConstructor ? 'newInstanceWithoutConstructor' : 'newInstance'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getClassReflector($class, $instantiableWithoutConstructor = null, $cloneable = null)
|
public static function getClassReflector($class, $instantiableWithoutConstructor = null, $cloneable = null)
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\ArrayIterator::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\ArrayIterator::class, true, true),
|
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes[\ArrayIterator::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\ArrayIterator::class, true)),
|
||||||
], [
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\ArrayIterator::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
\ArrayIterator::class => [
|
\ArrayIterator::class => [
|
||||||
@ -20,6 +17,6 @@ return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyArrayObject::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\Symfony\Component\VarExporter\Tests\MyArrayObject::class, true, true),
|
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes[\Symfony\Component\VarExporter\Tests\MyArrayObject::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\Symfony\Component\VarExporter\Tests\MyArrayObject::class, true)),
|
||||||
], [
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\Symfony\Component\VarExporter\Tests\MyArrayObject::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
\ArrayObject::class => [
|
\ArrayObject::class => [
|
||||||
@ -20,6 +17,6 @@ return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\ArrayObject::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\ArrayObject::class, true, true),
|
clone (($p =& \Symfony\Component\VarExporter\Internal\Registry::$prototypes)[\ArrayObject::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\ArrayObject::class, true)),
|
||||||
], [
|
clone $p[\ArrayObject::class],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\ArrayObject::class],
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\ArrayObject::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
\ArrayObject::class => [
|
\ArrayObject::class => [
|
||||||
@ -15,16 +12,18 @@ return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
|||||||
[
|
[
|
||||||
[
|
[
|
||||||
1,
|
1,
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
],
|
],
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
],
|
||||||
|
'*' => [
|
||||||
'foo' => [
|
'foo' => [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[1],
|
$o[1],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyCloneable::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\Symfony\Component\VarExporter\Tests\MyCloneable::class, true, false),
|
(($f =& \Symfony\Component\VarExporter\Internal\Registry::$factories)[\Symfony\Component\VarExporter\Tests\MyCloneable::class] ?? \Symfony\Component\VarExporter\Internal\Registry::f(\Symfony\Component\VarExporter\Tests\MyCloneable::class, true))(),
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyNotCloneable::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\Symfony\Component\VarExporter\Tests\MyNotCloneable::class, true, false),
|
($f[\Symfony\Component\VarExporter\Tests\MyNotCloneable::class] ?? \Symfony\Component\VarExporter\Internal\Registry::f(\Symfony\Component\VarExporter\Tests\MyNotCloneable::class, true))(),
|
||||||
], [
|
],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyCloneable::class]->newInstanceWithoutConstructor(),
|
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyNotCloneable::class]->newInstanceWithoutConstructor(),
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[],
|
[],
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[1],
|
$o[1],
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\DateTime::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\DateTime::class, true, true),
|
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes[\DateTime::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\DateTime::class, true)),
|
||||||
], [
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\DateTime::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
\DateTime::class => [
|
'*' => [
|
||||||
'date' => [
|
'date' => [
|
||||||
'1970-01-01 00:00:00.000000',
|
'1970-01-01 00:00:00.000000',
|
||||||
],
|
],
|
||||||
@ -21,7 +18,7 @@ return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
[
|
[
|
||||||
1 => 0,
|
1 => 0,
|
||||||
]
|
]
|
||||||
|
30
src/Symfony/Component/VarExporter/Tests/Fixtures/error.php
Normal file
30
src/Symfony/Component/VarExporter/Tests/Fixtures/error.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
|
$o = [
|
||||||
|
(\Symfony\Component\VarExporter\Internal\Registry::$factories[\Error::class] ?? \Symfony\Component\VarExporter\Internal\Registry::f(\Error::class, true))(),
|
||||||
|
],
|
||||||
|
null,
|
||||||
|
[
|
||||||
|
\TypeError::class => [
|
||||||
|
'file' => [
|
||||||
|
\dirname(__DIR__).\DIRECTORY_SEPARATOR.'VarExporterTest.php',
|
||||||
|
],
|
||||||
|
'line' => [
|
||||||
|
234,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
\Error::class => [
|
||||||
|
'trace' => [
|
||||||
|
[
|
||||||
|
'file' => \dirname(__DIR__).\DIRECTORY_SEPARATOR.'VarExporterTest.php',
|
||||||
|
'line' => 123,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
$o[0],
|
||||||
|
[
|
||||||
|
1 => 0,
|
||||||
|
]
|
||||||
|
);
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
[
|
||||||
|
123,
|
||||||
|
],
|
||||||
|
];
|
@ -1,15 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([], [], []),
|
$o = [],
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$references[1] = [
|
$r = [],
|
||||||
&\Symfony\Component\VarExporter\Internal\Registry::$references[1],
|
$r[1] = [
|
||||||
|
&$r[1],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
[
|
[
|
||||||
&\Symfony\Component\VarExporter\Internal\Registry::$references[1],
|
&$r[1],
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\stdClass::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\stdClass::class, true, true),
|
clone (\Symfony\Component\VarExporter\Internal\Registry::$prototypes[\stdClass::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\stdClass::class, true)),
|
||||||
], [
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\stdClass::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$references[1] = \Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$r = [],
|
||||||
|
$r[1] = $o[0],
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
[
|
[
|
||||||
&\Symfony\Component\VarExporter\Internal\Registry::$references[1],
|
&$r[1],
|
||||||
&\Symfony\Component\VarExporter\Internal\Registry::$references[1],
|
&$r[1],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([], [], [
|
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
|
||||||
'O:20:"SomeNotExistingClass":0:{}',
|
'O:20:"SomeNotExistingClass":0:{}',
|
||||||
]),
|
]),
|
||||||
null,
|
null,
|
||||||
[],
|
[],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,34 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyPrivateValue::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\Symfony\Component\VarExporter\Tests\MyPrivateValue::class, true, true),
|
clone (($p =& \Symfony\Component\VarExporter\Internal\Registry::$prototypes)[\Symfony\Component\VarExporter\Tests\MyPrivateValue::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\Symfony\Component\VarExporter\Tests\MyPrivateValue::class, true)),
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyPrivateChildValue::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\Symfony\Component\VarExporter\Tests\MyPrivateChildValue::class, true, true),
|
clone ($p[\Symfony\Component\VarExporter\Tests\MyPrivateChildValue::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\Symfony\Component\VarExporter\Tests\MyPrivateChildValue::class, true)),
|
||||||
], [
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\Symfony\Component\VarExporter\Tests\MyPrivateValue::class],
|
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\Symfony\Component\VarExporter\Tests\MyPrivateChildValue::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Tests\MyPrivateValue::class => [
|
\Symfony\Component\VarExporter\Tests\MyPrivateValue::class => [
|
||||||
'prot' => [
|
'prot' => [
|
||||||
123,
|
123,
|
||||||
|
123,
|
||||||
],
|
],
|
||||||
'priv' => [
|
'priv' => [
|
||||||
234,
|
234,
|
||||||
234,
|
234,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
\Symfony\Component\VarExporter\Tests\MyPrivateChildValue::class => [
|
|
||||||
'prot' => [
|
|
||||||
1 => 123,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[1],
|
$o[1],
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([], [], [
|
$o = \Symfony\Component\VarExporter\Internal\Registry::unserialize([], [
|
||||||
'C:50:"Symfony\\Component\\VarExporter\\Tests\\MySerializable":3:{123}',
|
'C:50:"Symfony\\Component\\VarExporter\\Tests\\MySerializable":3:{123}',
|
||||||
]),
|
]),
|
||||||
null,
|
null,
|
||||||
[],
|
[],
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
],
|
],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,25 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\SplObjectStorage::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\SplObjectStorage::class, true, true),
|
clone (($p =& \Symfony\Component\VarExporter\Internal\Registry::$prototypes)[\SplObjectStorage::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\SplObjectStorage::class, true)),
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\stdClass::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\stdClass::class, true, true),
|
clone ($p[\stdClass::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\stdClass::class, true)),
|
||||||
], [
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\SplObjectStorage::class],
|
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\stdClass::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
\SplObjectStorage::class => [
|
\SplObjectStorage::class => [
|
||||||
"\0" => [
|
"\0" => [
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[1],
|
$o[1],
|
||||||
345,
|
345,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
@ -1,28 +1,28 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return \Symfony\Component\VarExporter\Internal\Configurator::pop(
|
return \Symfony\Component\VarExporter\Internal\Hydrator::hydrate(
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::push([
|
$o = [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$reflectors[\Symfony\Component\VarExporter\Tests\MyWakeup::class] ?? \Symfony\Component\VarExporter\Internal\Registry::getClassReflector(\Symfony\Component\VarExporter\Tests\MyWakeup::class, true, true),
|
clone (($p =& \Symfony\Component\VarExporter\Internal\Registry::$prototypes)[\Symfony\Component\VarExporter\Tests\MyWakeup::class] ?? \Symfony\Component\VarExporter\Internal\Registry::p(\Symfony\Component\VarExporter\Tests\MyWakeup::class, true)),
|
||||||
], [
|
clone $p[\Symfony\Component\VarExporter\Tests\MyWakeup::class],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\Symfony\Component\VarExporter\Tests\MyWakeup::class],
|
],
|
||||||
clone \Symfony\Component\VarExporter\Internal\Registry::$prototypes[\Symfony\Component\VarExporter\Tests\MyWakeup::class],
|
|
||||||
], [
|
|
||||||
]),
|
|
||||||
null,
|
null,
|
||||||
[
|
[
|
||||||
\Symfony\Component\VarExporter\Tests\MyWakeup::class => [
|
'*' => [
|
||||||
'sub' => [
|
'sub' => [
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[1],
|
$o[1],
|
||||||
123,
|
123,
|
||||||
],
|
],
|
||||||
|
'bis' => [
|
||||||
|
1 => 123,
|
||||||
|
],
|
||||||
'baz' => [
|
'baz' => [
|
||||||
1 => 123,
|
1 => 123,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
\Symfony\Component\VarExporter\Internal\Registry::$objects[0],
|
$o[0],
|
||||||
[
|
[
|
||||||
1 => 1,
|
1 => 1,
|
||||||
2 => 0,
|
0,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
namespace Symfony\Component\VarExporter\Tests;
|
namespace Symfony\Component\VarExporter\Tests;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
||||||
use Symfony\Component\VarExporter\Internal\Registry;
|
use Symfony\Component\VarExporter\Internal\Registry;
|
||||||
use Symfony\Component\VarExporter\VarExporter;
|
use Symfony\Component\VarExporter\VarExporter;
|
||||||
use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
|
|
||||||
|
|
||||||
class VarExporterTest extends TestCase
|
class VarExporterTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -28,7 +28,7 @@ class VarExporterTest extends TestCase
|
|||||||
{
|
{
|
||||||
$unserializeCallback = ini_set('unserialize_callback_func', 'var_dump');
|
$unserializeCallback = ini_set('unserialize_callback_func', 'var_dump');
|
||||||
try {
|
try {
|
||||||
Registry::push(array(), array(), array('O:20:"SomeNotExistingClass":0:{}'));
|
Registry::unserialize(array(), array('O:20:"SomeNotExistingClass":0:{}'));
|
||||||
} finally {
|
} finally {
|
||||||
$this->assertSame('var_dump', ini_set('unserialize_callback_func', $unserializeCallback));
|
$this->assertSame('var_dump', ini_set('unserialize_callback_func', $unserializeCallback));
|
||||||
}
|
}
|
||||||
@ -80,10 +80,11 @@ class VarExporterTest extends TestCase
|
|||||||
$this->assertSame($serializedValue, serialize($value));
|
$this->assertSame($serializedValue, serialize($value));
|
||||||
|
|
||||||
$dump = "<?php\n\nreturn ".$marshalledValue.";\n";
|
$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';
|
$fixtureFile = __DIR__.'/Fixtures/'.$testName.'.php';
|
||||||
$this->assertStringEqualsFile($fixtureFile, $dump);
|
$this->assertStringEqualsFile($fixtureFile, $dump);
|
||||||
|
|
||||||
if ('incomplete-class' === $testName) {
|
if ('incomplete-class' === $testName || 'external-references' === $testName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$marshalledValue = include $fixtureFile;
|
$marshalledValue = include $fixtureFile;
|
||||||
@ -146,6 +147,24 @@ class VarExporterTest extends TestCase
|
|||||||
$value[0] = &$value;
|
$value[0] = &$value;
|
||||||
|
|
||||||
yield array('hard-references-recursive', $value);
|
yield array('hard-references-recursive', $value);
|
||||||
|
|
||||||
|
static $value = array(123);
|
||||||
|
|
||||||
|
yield array('external-references', array(&$value), true);
|
||||||
|
|
||||||
|
unset($value);
|
||||||
|
|
||||||
|
$value = new \Error();
|
||||||
|
|
||||||
|
$r = new \ReflectionProperty('Error', 'trace');
|
||||||
|
$r->setAccessible(true);
|
||||||
|
$r->setValue($value, array('file' => __FILE__, 'line' => 123));
|
||||||
|
|
||||||
|
$r = new \ReflectionProperty('Error', 'line');
|
||||||
|
$r->setAccessible(true);
|
||||||
|
$r->setValue($value, 234);
|
||||||
|
|
||||||
|
yield array('error', $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,9 +11,8 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\VarExporter;
|
namespace Symfony\Component\VarExporter;
|
||||||
|
|
||||||
use Symfony\Component\VarExporter\Internal\Configurator;
|
|
||||||
use Symfony\Component\VarExporter\Internal\Exporter;
|
use Symfony\Component\VarExporter\Internal\Exporter;
|
||||||
use Symfony\Component\VarExporter\Internal\Reference;
|
use Symfony\Component\VarExporter\Internal\Hydrator;
|
||||||
use Symfony\Component\VarExporter\Internal\Registry;
|
use Symfony\Component\VarExporter\Internal\Registry;
|
||||||
use Symfony\Component\VarExporter\Internal\Values;
|
use Symfony\Component\VarExporter\Internal\Values;
|
||||||
|
|
||||||
@ -56,9 +55,11 @@ final class VarExporter
|
|||||||
} finally {
|
} finally {
|
||||||
$references = array();
|
$references = array();
|
||||||
foreach ($refsPool as $i => $v) {
|
foreach ($refsPool as $i => $v) {
|
||||||
$v[0] = $v[1];
|
if ($v[0]->count) {
|
||||||
$references[1 + $i] = $v[2];
|
$references[1 + $i] = $v[2];
|
||||||
}
|
}
|
||||||
|
$v[0] = $v[1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($isStaticValue) {
|
if ($isStaticValue) {
|
||||||
@ -85,7 +86,11 @@ final class VarExporter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$value = new Configurator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups);
|
if ($classes || $references) {
|
||||||
|
$value = new Hydrator(new Registry($classes), $references ? new Values($references) : null, $properties, $value, $wakeups);
|
||||||
|
} else {
|
||||||
|
$isStaticValue = true;
|
||||||
|
}
|
||||||
|
|
||||||
return Exporter::export($value);
|
return Exporter::export($value);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user