Skip to content

Commit b198693

Browse files
Merge branch '5.4' into 6.0
* 5.4: [VarDumper] fix dumping typed references from properties [VarDumper] minor optim on PHP 8.1 Update README.md [Messenger] [Redis] Allow authentication with user and password [Cache] Throw ValueError in debug mode when serialization fails [FrameworkBundle] Avoid secrets:decrypt-to-local command to fail fix missing classes Mattermost Notifier option to post in an other channel [Messenger] Add WorkerMetadata to Worker class
2 parents 8eea4e8 + 083f2bc commit b198693

File tree

3 files changed

+94
-44
lines changed

3 files changed

+94
-44
lines changed

Cloner/VarCloner.php

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ protected function doClone(mixed $var): array
2727
$len = 1; // Length of $queue
2828
$pos = 0; // Number of cloned items past the minimum depth
2929
$refsCounter = 0; // Hard references counter
30-
$queue = [[$var]]; // This breadth-first queue is the return value
31-
$hardRefs = []; // Map of original zval ids to stub objects
32-
$objRefs = []; // Map of original object handles to their stub object counterpart
33-
$objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning
34-
$resRefs = []; // Map of original resource handles to their stub object counterpart
35-
$values = []; // Map of stub objects' ids to original values
30+
$queue = [[$var]]; // This breadth-first queue is the return value
31+
$hardRefs = []; // Map of original zval ids to stub objects
32+
$objRefs = []; // Map of original object handles to their stub object counterpart
33+
$objects = []; // Keep a ref to objects to ensure their handle cannot be reused while cloning
34+
$resRefs = []; // Map of original resource handles to their stub object counterpart
35+
$values = []; // Map of stub objects' ids to original values
3636
$maxItems = $this->maxItems;
3737
$maxString = $this->maxString;
3838
$minDepth = $this->minDepth;
@@ -63,25 +63,23 @@ protected function doClone(mixed $var): array
6363
foreach ($vals as $k => $v) {
6464
// $v is the original value or a stub object in case of hard references
6565

66-
$zvalIsRef = null !== \ReflectionReference::fromArrayElement($vals, $k);
66+
$zvalRef = ($r = \ReflectionReference::fromArrayElement($vals, $k)) ? $r->getId() : null;
6767

68-
if ($zvalIsRef) {
68+
if ($zvalRef) {
6969
$vals[$k] = &$stub; // Break hard references to make $queue completely
7070
unset($stub); // independent from the original structure
71-
if ($v instanceof Stub && isset($hardRefs[spl_object_id($v)])) {
72-
$vals[$k] = $refs[$k] = $v;
71+
if (null !== $vals[$k] = $hardRefs[$zvalRef] ?? null) {
72+
$v = $vals[$k];
7373
if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
7474
++$v->value->refCount;
7575
}
7676
++$v->refCount;
7777
continue;
7878
}
79-
$refs[$k] = $vals[$k] = new Stub();
80-
$refs[$k]->value = $v;
81-
$h = spl_object_id($refs[$k]);
82-
$hardRefs[$h] = &$refs[$k];
83-
$values[$h] = $v;
79+
$vals[$k] = new Stub();
80+
$vals[$k]->value = $v;
8481
$vals[$k]->handle = ++$refsCounter;
82+
$hardRefs[$zvalRef] = $vals[$k];
8583
}
8684
// Create $stub when the original value $v can not be used directly
8785
// If $v is a nested structure, put that structure in array $a
@@ -122,39 +120,46 @@ protected function doClone(mixed $var): array
122120
continue 2;
123121
}
124122
$stub = $arrayStub;
123+
124+
if (\PHP_VERSION_ID >= 80100) {
125+
$stub->class = array_is_list($v) ? Stub::ARRAY_INDEXED : Stub::ARRAY_ASSOC;
126+
$a = $v;
127+
break;
128+
}
129+
125130
$stub->class = Stub::ARRAY_INDEXED;
126131

127132
$j = -1;
128133
foreach ($v as $gk => $gv) {
129134
if ($gk !== ++$j) {
130135
$stub->class = Stub::ARRAY_ASSOC;
136+
$a = $v;
137+
$a[$gid] = true;
131138
break;
132139
}
133140
}
134-
$a = $v;
135-
136-
if (Stub::ARRAY_ASSOC === $stub->class) {
137-
// Copies of $GLOBALS have very strange behavior,
138-
// let's detect them with some black magic
139-
if (\PHP_VERSION_ID < 80100 && ($a[$gid] = true) && isset($v[$gid])) {
140-
unset($v[$gid]);
141-
$a = [];
142-
foreach ($v as $gk => &$gv) {
143-
if ($v === $gv) {
144-
unset($v);
145-
$v = new Stub();
146-
$v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0];
147-
$v->handle = -1;
148-
$gv = &$hardRefs[spl_object_id($v)];
149-
$gv = $v;
150-
}
151141

152-
$a[$gk] = &$gv;
142+
// Copies of $GLOBALS have very strange behavior,
143+
// let's detect them with some black magic
144+
if (isset($v[$gid])) {
145+
unset($v[$gid]);
146+
$a = [];
147+
foreach ($v as $gk => &$gv) {
148+
if ($v === $gv && !isset($hardRefs[\ReflectionReference::fromArrayElement($v, $gk)->getId()])) {
149+
unset($v);
150+
$v = new Stub();
151+
$v->value = [$v->cut = \count($gv), Stub::TYPE_ARRAY => 0];
152+
$v->handle = -1;
153+
$gv = &$a[$gk];
154+
$hardRefs[\ReflectionReference::fromArrayElement($a, $gk)->getId()] = &$gv;
155+
$gv = $v;
153156
}
154-
unset($gv);
155-
} else {
156-
$a = $v;
157+
158+
$a[$gk] = &$gv;
157159
}
160+
unset($gv);
161+
} else {
162+
$a = $v;
158163
}
159164
break;
160165

@@ -244,10 +249,10 @@ protected function doClone(mixed $var): array
244249
}
245250
}
246251

247-
if ($zvalIsRef) {
248-
$refs[$k]->value = $stub;
249-
} else {
252+
if (!$zvalRef) {
250253
$vals[$k] = $stub;
254+
} else {
255+
$hardRefs[$zvalRef]->value = $stub;
251256
}
252257
}
253258

Tests/Cloner/VarClonerTest.php

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -496,12 +496,55 @@ public function testPhp74()
496496
[p1] => 123
497497
[p2] => Symfony\Component\VarDumper\Cloner\Stub Object
498498
(
499-
[type] => 4
500-
[class] => stdClass
501-
[value] =>
499+
[type] => 1
500+
[class] =>
501+
[value] => Symfony\Component\VarDumper\Cloner\Stub Object
502+
(
503+
[type] => 4
504+
[class] => stdClass
505+
[value] =>
506+
[cut] => 0
507+
[handle] => %i
508+
[refCount] => 1
509+
[position] => 0
510+
[attr] => Array
511+
(
512+
)
513+
514+
)
515+
502516
[cut] => 0
503-
[handle] => %i
504-
[refCount] => 0
517+
[handle] => 1
518+
[refCount] => 1
519+
[position] => 0
520+
[attr] => Array
521+
(
522+
)
523+
524+
)
525+
526+
[p3] => Symfony\Component\VarDumper\Cloner\Stub Object
527+
(
528+
[type] => 1
529+
[class] =>
530+
[value] => Symfony\Component\VarDumper\Cloner\Stub Object
531+
(
532+
[type] => 4
533+
[class] => stdClass
534+
[value] =>
535+
[cut] => 0
536+
[handle] => %i
537+
[refCount] => 1
538+
[position] => 0
539+
[attr] => Array
540+
(
541+
)
542+
543+
)
544+
545+
[cut] => 0
546+
[handle] => 1
547+
[refCount] => 1
505548
[position] => 0
506549
[attr] => Array
507550
(

Tests/Fixtures/Php74.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ class Php74
66
{
77
public $p1 = 123;
88
public \stdClass $p2;
9+
public \stdClass $p3;
910

1011
public function __construct()
1112
{
1213
$this->p2 = new \stdClass();
14+
$this->p3 = &$this->p2;
1315
}
1416
}

0 commit comments

Comments
 (0)