@@ -28,7 +28,7 @@ protected function doClone($var)
28
28
$ i = 0 ; // Current iteration position in $queue
29
29
$ len = 1 ; // Length of $queue
30
30
$ pos = 0 ; // Number of cloned items past the first level
31
- $ refs = 0 ; // Hard references counter
31
+ $ refsCounter = 0 ; // Hard references counter
32
32
$ queue = array (array ($ var )); // This breadth-first queue is the return value
33
33
$ arrayRefs = array (); // Map of queue indexes to stub array objects
34
34
$ hardRefs = array (); // Map of original zval hashes to stub objects
@@ -60,27 +60,32 @@ protected function doClone($var)
60
60
for ($ i = 0 ; $ i < $ len ; ++$ i ) {
61
61
$ indexed = true ; // Whether the currently iterated array is numerically indexed or not
62
62
$ j = -1 ; // Position in the currently iterated array
63
- $ step = $ queue [$ i ]; // Copy of the currently iterated array used for hard references detection
64
- foreach ($ step as $ k => $ v ) {
63
+ $ fromObjCast = array_keys ($ queue [$ i ]);
64
+ $ fromObjCast = array_keys (array_flip ($ fromObjCast )) !== $ fromObjCast ;
65
+ $ refs = $ vals = $ fromObjCast ? array_values ($ queue [$ i ]) : $ queue [$ i ];
66
+ foreach ($ queue [$ i ] as $ k => $ v ) {
65
67
// $k is the original key
66
68
// $v is the original value or a stub object in case of hard references
67
- if ($ indexed && $ k !== ++$ j ) {
69
+ if ($ k !== ++$ j ) {
68
70
$ indexed = false ;
69
71
}
72
+ if ($ fromObjCast ) {
73
+ $ k = $ j ;
74
+ }
70
75
if ($ useExt ) {
71
- $ zval = symfony_zval_info ($ k , $ step );
76
+ $ zval = symfony_zval_info ($ k , $ refs );
72
77
} else {
73
- $ step [$ k ] = $ cookie ;
74
- if ($ zval ['zval_isref ' ] = $ queue [ $ i ] [$ k ] === $ cookie ) {
78
+ $ refs [$ k ] = $ cookie ;
79
+ if ($ zval ['zval_isref ' ] = $ vals [$ k ] === $ cookie ) {
75
80
$ zval ['zval_hash ' ] = $ v instanceof Stub ? spl_object_hash ($ v ) : null ;
76
81
}
77
82
$ zval ['type ' ] = gettype ($ v );
78
83
}
79
84
if ($ zval ['zval_isref ' ]) {
80
- $ queue [ $ i ][ $ k ] = &$ stub ; // Break hard references to make $queue completely
85
+ $ vals [ $ k ] = &$ stub ; // Break hard references to make $queue completely
81
86
unset($ stub ); // independent from the original structure
82
87
if (isset ($ hardRefs [$ zval ['zval_hash ' ]])) {
83
- $ queue [ $ i ][ $ k ] = $ useExt ? ($ v = $ hardRefs [$ zval ['zval_hash ' ]]) : ($ step [$ k ] = $ v );
88
+ $ vals [ $ k ] = $ useExt ? ($ v = $ hardRefs [$ zval ['zval_hash ' ]]) : ($ refs [$ k ] = $ v );
84
89
if ($ v ->value instanceof Stub && (Stub::TYPE_OBJECT === $ v ->value ->type || Stub::TYPE_RESOURCE === $ v ->value ->type )) {
85
90
++$ v ->value ->refCount ;
86
91
}
@@ -204,18 +209,18 @@ protected function doClone($var)
204
209
if (isset ($ stub )) {
205
210
if ($ zval ['zval_isref ' ]) {
206
211
if ($ useExt ) {
207
- $ queue [ $ i ] [$ k ] = $ hardRefs [$ zval ['zval_hash ' ]] = $ v = new Stub ();
212
+ $ vals [$ k ] = $ hardRefs [$ zval ['zval_hash ' ]] = $ v = new Stub ();
208
213
$ v ->value = $ stub ;
209
214
} else {
210
- $ step [$ k ] = new Stub ();
211
- $ step [$ k ]->value = $ stub ;
212
- $ h = spl_object_hash ($ step [$ k ]);
213
- $ queue [ $ i ][ $ k ] = $ hardRefs [$ h ] = &$ step [$ k ];
215
+ $ refs [$ k ] = new Stub ();
216
+ $ refs [$ k ]->value = $ stub ;
217
+ $ h = spl_object_hash ($ refs [$ k ]);
218
+ $ vals [ $ k ] = $ hardRefs [$ h ] = &$ refs [$ k ];
214
219
$ values [$ h ] = $ v ;
215
220
}
216
- $ queue [ $ i ][ $ k ]->handle = ++$ refs ;
221
+ $ vals [ $ k ]->handle = ++$ refsCounter ;
217
222
} else {
218
- $ queue [ $ i ] [$ k ] = $ stub ;
223
+ $ vals [$ k ] = $ stub ;
219
224
}
220
225
221
226
if ($ a ) {
@@ -243,19 +248,38 @@ protected function doClone($var)
243
248
$ stub = $ a = null ;
244
249
} elseif ($ zval ['zval_isref ' ]) {
245
250
if ($ useExt ) {
246
- $ queue [ $ i ] [$ k ] = $ hardRefs [$ zval ['zval_hash ' ]] = new Stub ();
247
- $ queue [ $ i ] [$ k ]->value = $ v ;
251
+ $ vals [$ k ] = $ hardRefs [$ zval ['zval_hash ' ]] = new Stub ();
252
+ $ vals [$ k ]->value = $ v ;
248
253
} else {
249
- $ step [$ k ] = $ queue [ $ i ] [$ k ] = new Stub ();
250
- $ step [$ k ]->value = $ v ;
251
- $ h = spl_object_hash ($ step [$ k ]);
252
- $ hardRefs [$ h ] = &$ step [$ k ];
254
+ $ refs [$ k ] = $ vals [$ k ] = new Stub ();
255
+ $ refs [$ k ]->value = $ v ;
256
+ $ h = spl_object_hash ($ refs [$ k ]);
257
+ $ hardRefs [$ h ] = &$ refs [$ k ];
253
258
$ values [$ h ] = $ v ;
254
259
}
255
- $ queue [$ i ][$ k ]->handle = ++$ refs ;
260
+ $ vals [$ k ]->handle = ++$ refsCounter ;
261
+ }
262
+ }
263
+
264
+ if ($ fromObjCast ) {
265
+ $ refs = $ vals ;
266
+ $ vals = array ();
267
+ $ j = -1 ;
268
+ foreach ($ queue [$ i ] as $ k => $ v ) {
269
+ foreach (array ($ k => $ v ) as $ a => $ v ) {
270
+ }
271
+ if ($ a !== $ k ) {
272
+ $ vals = (object ) $ vals ;
273
+ $ vals ->{$ k } = $ refs [++$ j ];
274
+ $ vals = (array ) $ vals ;
275
+ } else {
276
+ $ vals [$ k ] = $ refs [++$ j ];
277
+ }
256
278
}
257
279
}
258
280
281
+ $ queue [$ i ] = $ vals ;
282
+
259
283
if (isset ($ arrayRefs [$ i ])) {
260
284
if ($ indexed ) {
261
285
$ arrayRefs [$ i ]->class = Stub::ARRAY_INDEXED ;
0 commit comments