@@ -77,8 +77,6 @@ internal sealed partial class Deserializer : IDeserializer
77
77
private Queue < PendingSerializationInfo > ? _pendingSerializationInfo ;
78
78
private HashSet < SerializationRecordId > ? _pendingSerializationInfoIds ;
79
79
80
- // Keeping a separate stack for ids for fast infinite loop checks.
81
- private readonly Stack < SerializationRecordId > _parseStack = [ ] ;
82
80
private readonly Stack < ObjectRecordDeserializer > _parserStack = [ ] ;
83
81
84
82
/// <inheritdoc cref="IDeserializer.IncompleteObjects"/>
@@ -183,41 +181,36 @@ private object Deserialize()
183
181
[ RequiresUnreferencedCode ( "Calls DeserializeNew(SerializationRecordId)" ) ]
184
182
private void DeserializeRoot ( SerializationRecordId rootId )
185
183
{
186
- object root = DeserializeNew ( rootId ) ;
184
+ object root = DeserializeNew ( rootId , out _ ) ;
187
185
if ( root is not ObjectRecordDeserializer parser )
188
186
{
189
187
return ;
190
188
}
191
189
192
- _parseStack . Push ( rootId ) ;
193
190
_parserStack . Push ( parser ) ;
194
191
195
192
while ( _parserStack . Count > 0 )
196
193
{
197
194
ObjectRecordDeserializer ? currentParser = _parserStack . Pop ( ) ;
198
- SerializationRecordId currentId = _parseStack . Pop ( ) ;
199
- Debug . Assert ( currentId . Equals ( currentParser . ObjectRecord . Id ) ) ;
200
195
201
196
SerializationRecordId requiredId ;
202
197
while ( ! ( requiredId = currentParser . Continue ( ) ) . Equals ( default ( SerializationRecordId ) ) )
203
198
{
204
199
// Beside ObjectRecordDeserializer, DeserializeNew can return a raw value like int, string or an array.
205
- if ( DeserializeNew ( requiredId ) is ObjectRecordDeserializer requiredParser )
200
+ if ( DeserializeNew ( requiredId , out bool wasAddedToIncompleteObjects ) is ObjectRecordDeserializer requiredParser )
206
201
{
207
202
// The required object is not complete.
208
203
209
- if ( _parseStack . Contains ( requiredId ) )
204
+ if ( ! wasAddedToIncompleteObjects )
210
205
{
211
206
// All objects should be available before they're asked for a second time.
212
207
throw new SerializationException ( SR . Serialization_Cycle ) ;
213
208
}
214
209
215
210
// Push our current parser.
216
- _parseStack . Push ( currentId ) ;
217
211
_parserStack . Push ( currentParser ) ;
218
212
219
213
// Push the required parser so we can complete it.
220
- _parseStack . Push ( requiredId ) ;
221
214
_parserStack . Push ( requiredParser ) ;
222
215
223
216
break ;
@@ -227,7 +220,7 @@ private void DeserializeRoot(SerializationRecordId rootId)
227
220
228
221
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
229
222
[ RequiresUnreferencedCode ( "Calls System.Windows.Forms.BinaryFormat.Deserializer.ObjectRecordParser.Create(SerializationRecordId, IRecord, IDeserializer)" ) ]
230
- object DeserializeNew ( SerializationRecordId id )
223
+ object DeserializeNew ( SerializationRecordId id , out bool wasAddedToIncompleteObjects )
231
224
{
232
225
// Strings, string arrays, and primitive arrays can be completed without creating a
233
226
// parser object. Single primitives don't normally show up as records unless they are top
@@ -249,11 +242,12 @@ object DeserializeNew(SerializationRecordId id)
249
242
if ( value is not null )
250
243
{
251
244
_deserializedObjects . Add ( record . Id , value ) ;
245
+ wasAddedToIncompleteObjects = false ;
252
246
return value ;
253
247
}
254
248
255
249
// Not a simple case, need to do a full deserialization of the record.
256
- _incompleteObjects . Add ( id ) ;
250
+ wasAddedToIncompleteObjects = _incompleteObjects . Add ( id ) ;
257
251
258
252
var deserializer = ObjectRecordDeserializer . Create ( record , this ) ;
259
253
0 commit comments