archives

« Bugzilla Issues Index

#3395 — 7.4.7.5 IteratorClose should throw if hasReturn and !iterator.return().done


The current implementation of IteratorClose(iterator, completion) is as follows:

Assert: Type(iterator) is Object.
Assert: completion is a Completion Record.
Let hasReturn be HasProperty(iterator, "return").
ReturnIfAbrupt(hasReturn).
If hasReturn is true, then
Let innerResult be Invoke(iterator, "return", ( )).
If completion.[[type]] is not throw and innerResult.[[type]] is throw, then
Return innerResult.
Return completion.

Per David Herman's recommendation, we should report an error if innerResult.[[type]] is normal and ToObject(innerResult.[[value]]).done is not true:

Assert: Type(iterator) is Object.
Assert: completion is a Completion Record.
Let hasReturn be HasProperty(iterator, "return").
ReturnIfAbrupt(hasReturn).
If hasReturn is true, then
Let innerResult be Invoke(iterator, "return", ( )).
If completion.[[type]] is throw, then
Return completion.
If innerResult.[[type]] is throw, then
Return innerResult.
If innerResult.[[type]] is normal, then
Let done be Get(ToObject(innerResult.[[value]]), "done").
If done is not true, throw a TypeError exception.
Return completion.


Motivation: https://speakerdeck.com/dherman/closing-iterators


After discussion in the TC39 meeting of 28 January 2015, it was decided an exception should NOT be thrown by the for-of loop when the result of the iterator.return() call is an object with a falsy .done property. Note that an exception should still be thrown if the result of the .return() call is not an object.

Iterator implementors who really want an exception to be thrown if .return() is called early can implement their own return method that throws an exception.