-
-
Notifications
You must be signed in to change notification settings - Fork 8
Description
Currently, nextv() can only signal the natural end of an iterator by yielding an empty array. In the fallback _nextv() implementation below, when _next() signals end by yielding an undefined key and/or value (line 147), this means _nextv() does not signal end (line 148, unless acc is empty). Consequently, a consumer will call nextv() again, which means we call _next() again (line 160) which has already signaled end.
Whether that's a problem depends on implementation. It is in many-level (the replacement for multileveldown that I'm working on atm, and can easily have its own fix) and could be in others too. It's not a problem for implementations written so far (memory-level, classic-level, browser-level) because those implement their own optimized _nextv().
Solution: set a new private kEnded property to true on line 148, and check that it's false before calling _next(). A seek() should reset it to false. Maybe use kEnded in more places, as a general protection.
abstract-level/abstract-iterator.js
Lines 142 to 161 in 601b47c
| _nextv (size, options, callback) { | |
| const acc = [] | |
| const onnext = (err, key, value) => { | |
| if (err) { | |
| return callback(err) | |
| } else if (this[kLegacy] ? key === undefined && value === undefined : key === undefined) { | |
| return callback(null, acc) | |
| } | |
| acc.push(this[kLegacy] ? [key, value] : key) | |
| if (acc.length === size) { | |
| callback(null, acc) | |
| } else { | |
| this._next(onnext) | |
| } | |
| } | |
| this._next(onnext) | |
| } |
Metadata
Metadata
Assignees
Labels
Type
Projects
Status