@@ -321,7 +321,7 @@ function makeTableView(
321321 const hasAutoIncrement = sequences . length > 0 ;
322322
323323 const iter = ( ) =>
324- new TableIterator ( sys . datastore_table_scan_bsatn ( table_id ) , rowType ) ;
324+ tableIterator ( sys . datastore_table_scan_bsatn ( table_id ) , rowType ) ;
325325
326326 const integrate_generated_columns = hasAutoIncrement
327327 ? ( row : RowType < any > , ret_buf : Uint8Array ) => {
@@ -436,7 +436,7 @@ function makeTableView(
436436 find : ( colVal : IndexVal < any , any > ) : RowType < any > | null => {
437437 if ( numColumns === 1 ) colVal = [ colVal ] ;
438438 const args = serializeBound ( colVal ) ;
439- const iter = new TableIterator (
439+ const iter = tableIterator (
440440 sys . datastore_index_scan_range_bsatn ( index_id , ...args ) ,
441441 rowType
442442 ) ;
@@ -508,10 +508,10 @@ function makeTableView(
508508 return [ prefix , prefix_elems , rstart , rend ] ;
509509 } ;
510510 index = {
511- filter : ( range : any ) : IterableIterator < RowType < any > > => {
511+ filter : ( range : any ) : IteratorObject < RowType < any > > => {
512512 if ( numColumns === 1 ) range = [ range ] ;
513513 const args = serializeRange ( range ) ;
514- return new TableIterator (
514+ return tableIterator (
515515 sys . datastore_index_scan_range_bsatn ( index_id , ...args ) ,
516516 rowType
517517 ) ;
@@ -544,60 +544,70 @@ function hasOwn<K extends PropertyKey>(
544544 return Object . hasOwn ( o , k ) ;
545545}
546546
547- class TableIterator implements IterableIterator < any , undefined > {
548- #id: u32 | - 1 ;
549- #reader: BinaryReader ;
550- #ty: AlgebraicType ;
551- constructor ( id : u32 , ty : AlgebraicType ) {
552- this . #id = id ;
553- this . #reader = new BinaryReader ( new Uint8Array ( ) ) ;
554- this . #ty = ty ;
555- }
556- [ Symbol . iterator ] ( ) : typeof this {
557- return this ;
558- }
559- next ( ) : IteratorResult < any , undefined > {
560- while ( true ) {
561- if ( this . #reader. remaining > 0 ) {
562- const value = AlgebraicType . deserializeValue (
563- this . #reader,
564- this . #ty,
565- MODULE_DEF . typespace
566- ) ;
567- return { value } ;
568- }
569- if ( this . #id === - 1 ) {
570- return { value : undefined , done : true } ;
571- }
572- this . #advance_iter( ) ;
547+ function * tableIterator ( id : u32 , ty : AlgebraicType ) : Generator < any , void > {
548+ using iter = new IteratorHandle ( id ) ;
549+ const { typespace } = MODULE_DEF ;
550+
551+ let buf ;
552+ while ( ( buf = advanceIter ( iter ) ) != null ) {
553+ const reader = new BinaryReader ( buf ) ;
554+ while ( reader . remaining > 0 ) {
555+ yield AlgebraicType . deserializeValue ( reader , ty , typespace ) ;
573556 }
574557 }
558+ }
575559
576- #advance_iter( ) {
577- let buf_max_len = 0x10000 ;
578- while ( true ) {
579- try {
580- const { 0 : done , 1 : buf } = sys . row_iter_bsatn_advance (
581- this . #id,
582- buf_max_len
583- ) ;
584- if ( done ) this . #id = - 1 ;
585- this . #reader = new BinaryReader ( buf ) ;
586- return ;
587- } catch ( e ) {
588- if ( e && typeof e === 'object' && hasOwn ( e , '__buffer_too_small__' ) ) {
589- buf_max_len = e . __buffer_too_small__ as number ;
590- continue ;
591- }
592- throw e ;
560+ function advanceIter ( iter : IteratorHandle ) : Uint8Array | null {
561+ let buf_max_len = 0x10000 ;
562+ while ( true ) {
563+ try {
564+ return iter . advance ( buf_max_len ) ;
565+ } catch ( e ) {
566+ if ( e && typeof e === 'object' && hasOwn ( e , '__buffer_too_small__' ) ) {
567+ buf_max_len = e . __buffer_too_small__ as number ;
568+ continue ;
593569 }
570+ throw e ;
594571 }
595572 }
573+ }
574+
575+ /** A class to manage the lifecycle of an iterator handle. */
576+ class IteratorHandle implements Disposable {
577+ #id: u32 | - 1 ;
578+
579+ static #finalizationRegistry = new FinalizationRegistry < u32 > (
580+ sys . row_iter_bsatn_close
581+ ) ;
582+
583+ constructor ( id : u32 ) {
584+ this . #id = id ;
585+ IteratorHandle . #finalizationRegistry. register ( this , id , this ) ;
586+ }
587+
588+ /** Unregister this object with the finalization registry and return the id */
589+ #detach( ) {
590+ const id = this . #id;
591+ this . #id = - 1 ;
592+ IteratorHandle . #finalizationRegistry. unregister ( this ) ;
593+ return id ;
594+ }
595+
596+ /** Call `row_iter_bsatn_advance`, returning null if this iterator was already exhausted. */
597+ advance ( buf_max_len : u32 ) : Uint8Array | null {
598+ if ( this . #id === - 1 ) return null ;
599+ const { 0 : done , 1 : buf } = sys . row_iter_bsatn_advance (
600+ this . #id,
601+ buf_max_len
602+ ) ;
603+ if ( done ) this . #detach( ) ;
604+ return buf ;
605+ }
596606
597607 [ Symbol . dispose ] ( ) {
598608 if ( this . #id >= 0 ) {
599- this . # id = - 1 ;
600- sys . row_iter_bsatn_close ( this . # id) ;
609+ const id = this . #detach ( ) ;
610+ sys . row_iter_bsatn_close ( id ) ;
601611 }
602612 }
603613}
0 commit comments