You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Iterator.prototype.take must call IteratorClose on the underlying iterator when the take limit is reached on the normal completion path. Currently the limit-reached branch in DoAdvanceNext and DoDirectNext sets FDone := True and returns a done result without closing the source iterator.
Why
Per TC39 Iterator Helpers specification, when remaining reaches 0 the take helper executes IteratorClose(iterated, NormalCompletion(undefined)). Without this, generators and other resource-holding iterators used as the source of .take(n) won't have their finally blocks run until GC or an explicit .return() call.
Current behavior
function*gen(){try{yield1;yield2;yield3;}finally{console.log("closed");}}constarr=gen().take(1).toArray();// prints [1], "closed" never logged
The Close method on TGocciaLazyTakeIteratorValue does close the source, but it is only invoked by explicit .return() calls or GC — not on the normal limit-reached path.
Expected behavior
When the take limit is reached, DoAdvanceNext/DoDirectNext should close the source iterator before returning the done result, so generator finally blocks and other cleanup run immediately:
constarr=gen().take(1).toArray();// prints [1], then "closed"
Scope notes
File:source/units/Goccia.Values.Iterator.Lazy.pas — TGocciaLazyTakeIteratorValue.DoAdvanceNext (line ~273) and DoDirectNext (line ~292)
Use CloseIteratorPreservingError(FSourceIterator) so a throwing Close doesn't mask the done result
Add a JS test verifying generator finally blocks run when the take limit is reached
Summary
Iterator.prototype.takemust call IteratorClose on the underlying iterator when the take limit is reached on the normal completion path. Currently the limit-reached branch inDoAdvanceNextandDoDirectNextsetsFDone := Trueand returns a done result without closing the source iterator.Why
Per TC39 Iterator Helpers specification, when
remainingreaches 0 the take helper executesIteratorClose(iterated, NormalCompletion(undefined)). Without this, generators and other resource-holding iterators used as the source of.take(n)won't have their finally blocks run until GC or an explicit.return()call.Current behavior
The
Closemethod onTGocciaLazyTakeIteratorValuedoes close the source, but it is only invoked by explicit.return()calls or GC — not on the normal limit-reached path.Expected behavior
When the take limit is reached,
DoAdvanceNext/DoDirectNextshould close the source iterator before returning the done result, so generator finally blocks and other cleanup run immediately:Scope notes
source/units/Goccia.Values.Iterator.Lazy.pas—TGocciaLazyTakeIteratorValue.DoAdvanceNext(line ~273) andDoDirectNext(line ~292)CloseIteratorPreservingError(FSourceIterator)so a throwing Close doesn't mask the done result