Skip to content

Commit 8c04b88

Browse files
heskewclaude
andcommitted
review: align return()/throw() delegation with reviewers' suggested form
Both review bots (gemini-code-assist, claude) suggested the identical shape: always define return()/throw() on the wrapper, delegate to the source when it implements them, otherwise fall back to the protocol defaults (return -> done, throw -> rethrow), marking stopped first so a later next() can't re-enter. Adopt that verbatim so the applied fix matches the inline suggestions exactly. Functionally equivalent to the prior conditional form for the current rocksdb-js query iterator (which implements neither), and still forwards cleanup if a future iterator adds it. Unit test updated for the always-defined defaults. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a70a2eb commit 8c04b88

2 files changed

Lines changed: 34 additions & 24 deletions

File tree

resources/replayLogsGuards.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export function endIteratorOnCorruptFrame<T>(
6363
onCorruptFrame: (error: RangeError) => void
6464
): IterableIterator<T> {
6565
let stopped = false;
66-
const wrapped: IterableIterator<T> = {
66+
return {
6767
[Symbol.iterator]() {
6868
return this;
6969
},
@@ -84,19 +84,19 @@ export function endIteratorOnCorruptFrame<T>(
8484
return { done: true, value: undefined };
8585
}
8686
},
87-
};
88-
// Stay a faithful proxy: delegate the optional return()/throw() so early termination
89-
// (a for-of break, or an outer .return()) still releases whatever the source iterator
90-
// holds. The current rocksdb-js query iterator implements neither, but a future one that
91-
// adds cleanup must not be silently bypassed by this wrapper.
92-
if (iterator.return) {
93-
wrapped.return = (value?: any): IteratorResult<T> => {
87+
// Forward early termination so the source iterator's cleanup (e.g. releasing a
88+
// rocksdb read handle / lock) still runs when a consumer exits a for-of early via
89+
// break/return/throw. Mark stopped first so a later next() can't re-enter. The
90+
// current rocksdb-js query iterator implements neither, hence the protocol defaults.
91+
return(value?: any): IteratorResult<T> {
92+
stopped = true;
93+
if (typeof iterator.return === 'function') return iterator.return(value);
94+
return { done: true, value };
95+
},
96+
throw(error?: any): IteratorResult<T> {
9497
stopped = true;
95-
return iterator.return!(value);
96-
};
97-
}
98-
if (iterator.throw) {
99-
wrapped.throw = (error?: any): IteratorResult<T> => iterator.throw!(error);
100-
}
101-
return wrapped;
98+
if (typeof iterator.throw === 'function') return iterator.throw(error);
99+
throw error;
100+
},
101+
};
102102
}

unitTests/resources/replayLogs.test.js

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,16 +147,26 @@ describe('endIteratorOnCorruptFrame', () => {
147147
assert.strictEqual(threwWith, boom);
148148
});
149149

150-
it('does not synthesize return()/throw() when the underlying iterator lacks them', () => {
151-
const wrapped = endIteratorOnCorruptFrame(
152-
{
153-
next() {
154-
return { done: true, value: undefined };
155-
},
150+
it('return()/throw() fall back to protocol defaults and latch when the underlying lacks them', () => {
151+
let nextCalls = 0;
152+
const source = {
153+
next() {
154+
nextCalls++;
155+
return { done: false, value: 1 };
156156
},
157-
() => {}
157+
};
158+
const wrapped = endIteratorOnCorruptFrame(source, () => {});
159+
160+
// return() defaults to done and latches without ever pulling the source again
161+
assert.deepStrictEqual(wrapped.return('x'), { done: true, value: 'x' });
162+
assert.deepStrictEqual(wrapped.next(), { done: true, value: undefined });
163+
assert.strictEqual(nextCalls, 0);
164+
165+
// throw() rethrows when the source can't handle it
166+
const boom = new Error('boom');
167+
assert.throws(
168+
() => endIteratorOnCorruptFrame({ next: source.next }, () => {}).throw(boom),
169+
(error) => error === boom
158170
);
159-
assert.strictEqual(wrapped.return, undefined);
160-
assert.strictEqual(wrapped.throw, undefined);
161171
});
162172
});

0 commit comments

Comments
 (0)