@@ -121,29 +121,62 @@ namespace ts {
121
121
function shimMap ( ) : new < T > ( ) => Map < T > {
122
122
123
123
class MapIterator < T , U extends ( string | T | [ string , T ] ) > {
124
- private data : MapLike < T > ;
125
- private keys : ReadonlyArray < string > ;
126
- private index = 0 ;
124
+ index = 0 ;
125
+
126
+ private shimMap : ShimMap < T > ;
127
127
private selector : ( data : MapLike < T > , key : string ) => U ;
128
- constructor ( data : MapLike < T > , selector : ( data : MapLike < T > , key : string ) => U ) {
129
- this . data = data ;
128
+
129
+ constructor ( shimMap : ShimMap < T > , selector : ( data : MapLike < T > , key : string ) => U ) {
130
+ this . shimMap = shimMap ;
130
131
this . selector = selector ;
131
- this . keys = Object . keys ( data ) ;
132
+
133
+ if ( ! shimMap . iteratorState ) {
134
+ // Create the initial iterator state.
135
+ shimMap . iteratorState = {
136
+ iterators : [ ] ,
137
+ keys : Object . keys ( shimMap . data )
138
+ } ;
139
+ }
140
+
141
+ // Add ourselves to the list of iterators.
142
+ shimMap . iteratorState . iterators . push ( this ) ;
132
143
}
133
144
134
145
public next ( ) : { value : U , done : false } | { value : never , done : true } {
135
- const index = this . index ;
136
- if ( index < this . keys . length ) {
137
- this . index ++ ;
138
- return { value : this . selector ( this . data , this . keys [ index ] ) , done : false } ;
146
+ const iteratorState = this . shimMap . iteratorState ! ;
147
+ if ( this . index != - 1 && this . index < iteratorState . keys . length ) {
148
+ const index = this . index ++ ;
149
+ return { value : this . selector ( this . shimMap . data , iteratorState . keys [ index ] ) , done : false } ;
150
+ }
151
+ else {
152
+ // Ensure subsequent invocations will always return done.
153
+ this . index = - 1 ;
154
+
155
+ // Remove ourselves from the list of iterators.
156
+ iteratorState . iterators . splice (
157
+ iteratorState . iterators . indexOf ( this ) , 1 ) ;
158
+
159
+ if ( iteratorState . iterators . length == 0 ) {
160
+ // No other iterator is active, so clear the iterator state.
161
+ this . shimMap . iteratorState = undefined ;
162
+ }
163
+
164
+ return { value : undefined as never , done : true } ;
139
165
}
140
- return { value : undefined as never , done : true } ;
141
166
}
142
167
}
143
168
144
- return class < T > implements Map < T > {
145
- private data = createDictionaryObject < T > ( ) ;
146
- public size = 0 ;
169
+ class ShimMap < T > implements Map < T > {
170
+ size = 0 ;
171
+
172
+ data = createDictionaryObject < T > ( ) ;
173
+
174
+ iteratorState : {
175
+ readonly keys : string [ ] ;
176
+ readonly iterators : {
177
+ index : number ;
178
+ } [ ] ;
179
+ } | undefined ;
147
180
148
181
get ( key : string ) : T | undefined {
149
182
return this . data [ key ] ;
@@ -152,6 +185,11 @@ namespace ts {
152
185
set ( key : string , value : T ) : this {
153
186
if ( ! this . has ( key ) ) {
154
187
this . size ++ ;
188
+
189
+ if ( this . iteratorState ) {
190
+ // Add the new entry.
191
+ this . iteratorState . keys . push ( key ) ;
192
+ }
155
193
}
156
194
this . data [ key ] = value ;
157
195
return this ;
@@ -166,6 +204,22 @@ namespace ts {
166
204
if ( this . has ( key ) ) {
167
205
this . size -- ;
168
206
delete this . data [ key ] ;
207
+
208
+ if ( this . iteratorState ) {
209
+ // Remove the key and adjust the iterator indexes.
210
+ // Note that this operation isn't very performant as we need to
211
+ // iterate over the "keys" array; however, we expect that no one
212
+ // will delete entries while iterators are still active.
213
+ const keys = this . iteratorState . keys ;
214
+ const keyIndex = keys . indexOf ( key ) ;
215
+ keys . splice ( keyIndex , 1 ) ;
216
+
217
+ const iterators = this . iteratorState . iterators ;
218
+ for ( let i = 0 ; i < iterators . length ; i ++ )
219
+ if ( iterators [ i ] . index > keyIndex )
220
+ iterators [ i ] . index -- ;
221
+ }
222
+
169
223
return true ;
170
224
}
171
225
return false ;
@@ -174,26 +228,41 @@ namespace ts {
174
228
clear ( ) : void {
175
229
this . data = createDictionaryObject < T > ( ) ;
176
230
this . size = 0 ;
231
+
232
+ if ( this . iteratorState ) {
233
+ this . iteratorState . keys . splice ( 0 , this . iteratorState . keys . length ) ;
234
+
235
+ const iterators = this . iteratorState . iterators ;
236
+ for ( let i = 0 ; i < iterators . length ; i ++ )
237
+ iterators [ i ] . index = 0 ;
238
+ }
177
239
}
178
240
179
241
keys ( ) : Iterator < string > {
180
- return new MapIterator ( this . data , ( _data , key ) => key ) ;
242
+ return new MapIterator ( this , ( _data , key ) => key ) ;
181
243
}
182
244
183
245
values ( ) : Iterator < T > {
184
- return new MapIterator ( this . data , ( data , key ) => data [ key ] ) ;
246
+ return new MapIterator ( this , ( data , key ) => data [ key ] ) ;
185
247
}
186
248
187
249
entries ( ) : Iterator < [ string , T ] > {
188
- return new MapIterator ( this . data , ( data , key ) => [ key , data [ key ] ] as [ string , T ] ) ;
250
+ return new MapIterator ( this , ( data , key ) => [ key , data [ key ] ] as [ string , T ] ) ;
189
251
}
190
252
191
253
forEach ( action : ( value : T , key : string ) => void ) : void {
192
- for ( const key in this . data ) {
193
- action ( this . data [ key ] , key ) ;
254
+ const iterator = this . entries ( ) ;
255
+ while ( true ) {
256
+ const { value : entry , done } = iterator . next ( ) ;
257
+ if ( done )
258
+ break ;
259
+
260
+ action ( entry [ 1 ] , entry [ 0 ] ) ;
194
261
}
195
262
}
196
- } ;
263
+ }
264
+
265
+ return ShimMap ;
197
266
}
198
267
199
268
export function length ( array : ReadonlyArray < any > | undefined ) : number {
0 commit comments