Skip to content

Commit dba19cd

Browse files
add test and fix crash
1 parent 47604f7 commit dba19cd

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

src/cursor/abstract_cursor.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ export abstract class AbstractCursor<
686686
async toArray(): Promise<TSchema[]> {
687687
this.signal?.throwIfAborted();
688688

689-
const array: TSchema[] = [];
689+
let array: TSchema[] = [];
690690
// at the end of the loop (since readBufferedDocuments is called) the buffer will be empty
691691
// then, the 'await of' syntax will run a getMore call
692692
for await (const document of this) {
@@ -697,7 +697,9 @@ export abstract class AbstractCursor<
697697
array.push(await this.transformDocument(doc));
698698
}
699699
} else {
700-
array.push(...docs);
700+
// Note: previous versions of this logic used `array.push(...)`, which adds each item
701+
// to the callstack. For large arrays, this can exceed the maximum call size.
702+
array = array.concat(docs);
701703
}
702704
}
703705
return array;

test/integration/node-specific/abstract_cursor.test.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,8 @@ describe('class AbstractCursor', function () {
428428

429429
afterEach(async function () {
430430
sinon.restore();
431-
await cursor.close();
432-
await client.close();
431+
await cursor?.close();
432+
await client?.close();
433433
});
434434

435435
it('iterates per batch not per document', async () => {
@@ -439,6 +439,39 @@ describe('class AbstractCursor', function () {
439439
const numDocuments = numBatches * batchSize;
440440
expect(nextSpy.callCount).to.be.lessThan(numDocuments);
441441
});
442+
443+
it(
444+
'does not exceed stack size for large arrays',
445+
// $documents was added in 6.0
446+
{ requires: { mongodb: '>=6.0' } },
447+
async function () {
448+
await client
449+
.db()
450+
.aggregate([
451+
{
452+
$documents: [
453+
{
454+
doc: 'foo'
455+
}
456+
]
457+
},
458+
{
459+
$set: {
460+
field: {
461+
$reduce: {
462+
input: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
463+
initialValue: [0],
464+
in: { $concatArrays: ['$$value', '$$value'] }
465+
}
466+
}
467+
}
468+
},
469+
{ $unwind: '$field' },
470+
{ $limit: 1000000 }
471+
])
472+
.toArray();
473+
}
474+
);
442475
});
443476

444477
describe('externally provided timeout contexts', function () {

0 commit comments

Comments
 (0)