@@ -83,6 +83,9 @@ function QueryCursor(query) {
83
83
// Max out the number of documents we'll populate in parallel at 5000.
84
84
this . options . _populateBatchSize = Math . min ( this . options . batchSize , 5000 ) ;
85
85
}
86
+ if ( query . _mongooseOptions . _asyncIterator ) {
87
+ this . _mongooseOptions . _asyncIterator = true ;
88
+ }
86
89
87
90
if ( model . collection . _shouldBufferCommands ( ) && model . collection . buffer ) {
88
91
model . collection . queue . push ( [
@@ -379,29 +382,6 @@ QueryCursor.prototype.addCursorFlag = function(flag, value) {
379
382
return this ;
380
383
} ;
381
384
382
- /*!
383
- * ignore
384
- */
385
-
386
- QueryCursor . prototype . transformNull = function ( val ) {
387
- if ( arguments . length === 0 ) {
388
- val = true ;
389
- }
390
- this . _mongooseOptions . transformNull = val ;
391
- return this ;
392
- } ;
393
-
394
- /*!
395
- * ignore
396
- */
397
-
398
- QueryCursor . prototype . _transformForAsyncIterator = function ( ) {
399
- if ( this . _transforms . indexOf ( _transformForAsyncIterator ) === - 1 ) {
400
- this . map ( _transformForAsyncIterator ) ;
401
- }
402
- return this ;
403
- } ;
404
-
405
385
/**
406
386
* Returns an asyncIterator for use with [`for/await/of` loops](https://thecodebarbarian.com/getting-started-with-async-iterators-in-node-js).
407
387
* You do not need to call this function explicitly, the JavaScript runtime
@@ -433,19 +413,13 @@ QueryCursor.prototype._transformForAsyncIterator = function() {
433
413
*/
434
414
435
415
if ( Symbol . asyncIterator != null ) {
436
- QueryCursor . prototype [ Symbol . asyncIterator ] = function ( ) {
437
- return this . transformNull ( ) . _transformForAsyncIterator ( ) ;
416
+ QueryCursor . prototype [ Symbol . asyncIterator ] = function queryCursorAsyncIterator ( ) {
417
+ // Set so QueryCursor knows it should transform results for async iterators into `{ value, done }` syntax
418
+ this . _mongooseOptions . _asyncIterator = true ;
419
+ return this ;
438
420
} ;
439
421
}
440
422
441
- /*!
442
- * ignore
443
- */
444
-
445
- function _transformForAsyncIterator ( doc ) {
446
- return doc == null ? { done : true } : { value : doc , done : false } ;
447
- }
448
-
449
423
/**
450
424
* Get the next doc from the underlying cursor and mongooseify it
451
425
* (populate, etc.)
@@ -456,16 +430,38 @@ function _transformForAsyncIterator(doc) {
456
430
457
431
function _next ( ctx , cb ) {
458
432
let callback = cb ;
459
- if ( ctx . _transforms . length ) {
460
- callback = function ( err , doc ) {
461
- if ( err || ( doc === null && ! ctx . _mongooseOptions . transformNull ) ) {
462
- return cb ( err , doc ) ;
433
+
434
+ // Create a custom callback to handle transforms, async iterator, and transformNull
435
+ callback = function ( err , doc ) {
436
+ if ( err ) {
437
+ return cb ( err ) ;
438
+ }
439
+
440
+ // Handle null documents - if asyncIterator, we need to return `done: true`, otherwise just
441
+ // skip. In either case, avoid transforms.
442
+ if ( doc === null ) {
443
+ if ( ctx . _mongooseOptions . _asyncIterator ) {
444
+ return cb ( null , { done : true } ) ;
445
+ } else {
446
+ return cb ( null , null ) ;
463
447
}
464
- cb ( err , ctx . _transforms . reduce ( function ( doc , fn ) {
448
+ }
449
+
450
+ // Apply transforms
451
+ if ( ctx . _transforms . length && doc !== null ) {
452
+ doc = ctx . _transforms . reduce ( function ( doc , fn ) {
465
453
return fn . call ( ctx , doc ) ;
466
- } , doc ) ) ;
467
- } ;
468
- }
454
+ } , doc ) ;
455
+ }
456
+
457
+ // This option is set in `Symbol.asyncIterator` code paths.
458
+ // For async iterator, we need to convert to {value, done} format
459
+ if ( ctx . _mongooseOptions . _asyncIterator ) {
460
+ return cb ( null , { value : doc , done : false } ) ;
461
+ }
462
+
463
+ return cb ( null , doc ) ;
464
+ } ;
469
465
470
466
if ( ctx . _error ) {
471
467
return immediate ( function ( ) {
0 commit comments