@@ -121,15 +121,15 @@ namespace ts {
121
121
export function shimMap ( ) : new < T > ( ) => Map < T > {
122
122
123
123
interface MapEntry < T > {
124
- key ?: string ;
124
+ readonly key ?: string ;
125
125
value ?: T ;
126
126
127
- // Linked list references
127
+ // Linked list references for iterators.
128
128
nextEntry ?: MapEntry < T > ;
129
129
previousEntry ?: MapEntry < T > ;
130
130
131
131
/**
132
- * Specifies if the iterator should skip the next entry.
132
+ * Specifies if iterators should skip the next entry.
133
133
* This will be set when an entry is deleted.
134
134
* See https://github.com/Microsoft/TypeScript/pull/27292 for more information.
135
135
*/
@@ -146,7 +146,7 @@ namespace ts {
146
146
}
147
147
148
148
public next ( ) : { value : U , done : false } | { value : never , done : true } {
149
- // Navigate to the next element .
149
+ // Navigate to the next entry .
150
150
while ( this . currentEntry ) {
151
151
const skipNext = ! ! this . currentEntry . skipNext ;
152
152
this . currentEntry = this . currentEntry . nextEntry ;
@@ -172,16 +172,22 @@ namespace ts {
172
172
// Linked list references for iterators.
173
173
// See https://github.com/Microsoft/TypeScript/pull/27292
174
174
// for more information.
175
- private readonly linkedListStart : MapEntry < T > ;
176
- private linkedListEnd : MapEntry < T > ;
175
+
176
+ /**
177
+ * The first entry in the linked list.
178
+ * Note that this is only a stub that serves as starting point
179
+ * for iterators and doesn't contain a key and a value.
180
+ */
181
+ private readonly firstEntry : MapEntry < T > ;
182
+ private lastEntry : MapEntry < T > ;
177
183
178
184
constructor ( ) {
179
- // Create a (stub) start element that will not
180
- // contain a key and value .
181
- this . linkedListStart = { } ;
182
- // When the map is empty, the end element is the same as the
183
- // start element .
184
- this . linkedListEnd = this . linkedListStart ;
185
+ // Create a first (stub) map entry that will not contain a key
186
+ // and value but serves as starting point for iterators .
187
+ this . firstEntry = { } ;
188
+ // When the map is empty, the last entry is the same as the
189
+ // first one .
190
+ this . lastEntry = this . firstEntry ;
185
191
}
186
192
187
193
get ( key : string ) : T | undefined {
@@ -193,17 +199,19 @@ namespace ts {
193
199
if ( ! this . has ( key ) ) {
194
200
this . size ++ ;
195
201
196
- // Append the new element at the end of the linked list.
202
+ // Create a new entry that will be appended at the
203
+ // end of the linked list.
197
204
const newEntry : MapEntry < T > = {
198
205
key,
199
206
value
200
207
} ;
201
208
this . data [ key ] = newEntry ;
202
209
203
- const previousEndElement = this . linkedListEnd ;
204
- previousEndElement . nextEntry = newEntry ;
205
- newEntry . previousEntry = previousEndElement ;
206
- this . linkedListEnd = newEntry ;
210
+ // Adjust the references.
211
+ const previousLastEntry = this . lastEntry ;
212
+ previousLastEntry . nextEntry = newEntry ;
213
+ newEntry . previousEntry = previousLastEntry ;
214
+ this . lastEntry = newEntry ;
207
215
}
208
216
else {
209
217
this . data [ key ] . value = value ;
@@ -231,13 +239,17 @@ namespace ts {
231
239
}
232
240
233
241
// When the deleted entry was the last one, we need to
234
- // adust the endElement reference.
235
- if ( this . linkedListEnd === entry ) {
236
- this . linkedListEnd = previousEntry ;
242
+ // adust the lastEntry reference.
243
+ if ( this . lastEntry === entry ) {
244
+ this . lastEntry = previousEntry ;
237
245
}
238
246
239
- // Adjust the forward reference of the deleted element
240
- // in case an iterator still references it.
247
+ // Adjust the forward reference of the deleted entry
248
+ // in case an iterator still references it. This allows us
249
+ // to throw away the entry, but when an active iterator
250
+ // (which points to the current entry) continues, it will
251
+ // navigate to the entry that originally came before the
252
+ // current one and skip it.
241
253
entry . previousEntry = undefined ;
242
254
entry . nextEntry = previousEntry ;
243
255
entry . skipNext = true ;
@@ -256,30 +268,30 @@ namespace ts {
256
268
// in the middle of the list don't continue with deleted entries,
257
269
// but can continue with new entries added after the clear()
258
270
// operation.
259
- const startEntry = this . linkedListStart ;
260
- let currentEntry = startEntry . nextEntry ;
271
+ const firstEntry = this . firstEntry ;
272
+ let currentEntry = firstEntry . nextEntry ;
261
273
while ( currentEntry ) {
262
274
const nextEntry = currentEntry . nextEntry ;
263
275
currentEntry . previousEntry = undefined ;
264
- currentEntry . nextEntry = startEntry ;
276
+ currentEntry . nextEntry = firstEntry ;
265
277
currentEntry . skipNext = true ;
266
278
267
279
currentEntry = nextEntry ;
268
280
}
269
- this . linkedListStart . nextEntry = undefined ;
270
- this . linkedListEnd = this . linkedListStart ;
281
+ firstEntry . nextEntry = undefined ;
282
+ this . lastEntry = firstEntry ;
271
283
}
272
284
273
285
keys ( ) : Iterator < string > {
274
- return new MapIterator ( this . linkedListStart , key => key ) ;
286
+ return new MapIterator ( this . firstEntry , key => key ) ;
275
287
}
276
288
277
289
values ( ) : Iterator < T > {
278
- return new MapIterator ( this . linkedListStart , ( _key , value ) => value ) ;
290
+ return new MapIterator ( this . firstEntry , ( _key , value ) => value ) ;
279
291
}
280
292
281
293
entries ( ) : Iterator < [ string , T ] > {
282
- return new MapIterator ( this . linkedListStart , ( key , value ) => [ key , value ] as [ string , T ] ) ;
294
+ return new MapIterator ( this . firstEntry , ( key , value ) => [ key , value ] as [ string , T ] ) ;
283
295
}
284
296
285
297
forEach ( action : ( value : T , key : string ) => void ) : void {
0 commit comments