@@ -77,6 +77,92 @@ const DONE_ITERATOR_RESULT = new Set().keys().next();
7777// Tsh = Timestamp + Hash
7878// Tshs = Timestamp + Hash combinations
7979
80+ class SnapshotIterator {
81+ constructor ( next ) {
82+ this . next = next ;
83+ }
84+ }
85+
86+ class SnapshotIterable {
87+ constructor ( snapshot , getMaps ) {
88+ this . snapshot = snapshot ;
89+ this . getMaps = getMaps ;
90+ }
91+
92+ [ Symbol . iterator ] ( ) {
93+ let state = 0 ;
94+ /** @type {IterableIterator<string> } */
95+ let it ;
96+ /** @type {(Snapshot) => (Map<string, any> | Set<string>)[] } */
97+ let getMaps ;
98+ /** @type {(Map<string, any> | Set<string>)[] } */
99+ let maps ;
100+ /** @type {Snapshot } */
101+ let snapshot ;
102+ let queue ;
103+ return new SnapshotIterator ( ( ) => {
104+ for ( ; ; ) {
105+ switch ( state ) {
106+ case 0 :
107+ snapshot = this . snapshot ;
108+ getMaps = this . getMaps ;
109+ maps = getMaps ( snapshot ) ;
110+ state = 1 ;
111+ /* falls through */
112+ case 1 :
113+ if ( maps . length > 0 ) {
114+ const map = maps . pop ( ) ;
115+ if ( map !== undefined ) {
116+ it = map . keys ( ) ;
117+ state = 2 ;
118+ } else {
119+ break ;
120+ }
121+ } else {
122+ state = 3 ;
123+ break ;
124+ }
125+ /* falls through */
126+ case 2 : {
127+ const result = it . next ( ) ;
128+ if ( ! result . done ) return result ;
129+ state = 1 ;
130+ break ;
131+ }
132+ case 3 : {
133+ const children = snapshot . children ;
134+ if ( children !== undefined ) {
135+ if ( children . size === 1 ) {
136+ // shortcut for a single child
137+ // avoids allocation of queue
138+ for ( const child of children ) snapshot = child ;
139+ maps = getMaps ( snapshot ) ;
140+ state = 1 ;
141+ break ;
142+ }
143+ if ( queue === undefined ) queue = [ ] ;
144+ for ( const child of children ) {
145+ queue . push ( child ) ;
146+ }
147+ }
148+ if ( queue !== undefined && queue . length > 0 ) {
149+ snapshot = queue . pop ( ) ;
150+ maps = getMaps ( snapshot ) ;
151+ state = 1 ;
152+ break ;
153+ } else {
154+ state = 4 ;
155+ }
156+ }
157+ /* falls through */
158+ case 4 :
159+ return DONE_ITERATOR_RESULT ;
160+ }
161+ }
162+ } ) ;
163+ }
164+ }
165+
80166class Snapshot {
81167 constructor ( ) {
82168 this . _flags = 0 ;
@@ -283,63 +369,7 @@ class Snapshot {
283369 * @returns {Iterable<string> } iterable
284370 */
285371 _createIterable ( getMaps ) {
286- let snapshot = this ;
287- return {
288- [ Symbol . iterator ] ( ) {
289- let state = 0 ;
290- /** @type {IterableIterator<string> } */
291- let it ;
292- let maps = getMaps ( snapshot ) ;
293- const queue = [ ] ;
294- return {
295- next ( ) {
296- for ( ; ; ) {
297- switch ( state ) {
298- case 0 :
299- if ( maps . length > 0 ) {
300- const map = maps . pop ( ) ;
301- if ( map !== undefined ) {
302- it = map . keys ( ) ;
303- state = 1 ;
304- } else {
305- break ;
306- }
307- } else {
308- state = 2 ;
309- break ;
310- }
311- /* falls through */
312- case 1 : {
313- const result = it . next ( ) ;
314- if ( ! result . done ) return result ;
315- state = 0 ;
316- break ;
317- }
318- case 2 : {
319- const children = snapshot . children ;
320- if ( children !== undefined ) {
321- for ( const child of children ) {
322- queue . push ( child ) ;
323- }
324- }
325- if ( queue . length > 0 ) {
326- snapshot = queue . pop ( ) ;
327- maps = getMaps ( snapshot ) ;
328- state = 0 ;
329- break ;
330- } else {
331- state = 3 ;
332- }
333- }
334- /* falls through */
335- case 3 :
336- return DONE_ITERATOR_RESULT ;
337- }
338- }
339- }
340- } ;
341- }
342- } ;
372+ return new SnapshotIterable ( this , getMaps ) ;
343373 }
344374
345375 /**
0 commit comments