Automatic iterator.return() in contexts other than for and yield*

# Jason Orendorff (10 years ago)

In some cases a for loop will implicitly call iterator.return():

function gen() {
    try { yield 0; }
    finally { console.log("return was called"); }
}

for (let x of gen())
    throw "fail";  // logs "return was called"

This is to support iterators that want to clean up after themselves.

Destructuring assignment doesn't call .return():

let obj = {set x(v) { throw "fail"; }}
[obj.x] = gen();  // return() is not called

Neither do the Map/Set/WeakMap/WeakSet constructors:

class MySet extends Set {
    add(v) { throw "fail"; }
}

let m = new MySet(gen());  // return() is not called

Anyone remember the rationale for this? It seems like we should have just one iteration protocol, and it should be "what for loops do", including iterator.finish(). The collection constructors should be as mannerly as for, right?

Anyone remember the reasoning? Is it something to consider changing in ES7?

# Domenic Denicola (10 years ago)

If I recall this came up previously and Allen said it was a bug. (Everything should use .return().) Hopefully he can confirm.

# Allen Wirfs-Brock (10 years ago)

Yes, there are still a couple of bugs related to this that I hope to get to before the ES6 spec is totally locked down.

# Jason Orendorff (10 years ago)

Great! Thanks for the quick response.

(I felt bad posting about it because I know it's come up before; but I couldn't figure out the magic word to search for: "iterator", "return", "for", "of", "exception" are all too common. Maybe we should invent search keywords for each of these issues, as they come up. This one can be #breakupprotocol. Would work in bugzilla too, if someone cared to annotate...)

# Allen Wirfs-Brock (10 years ago)

added ecmascript#3576 for the destructuring case which didn't already have a ticket.

(also fixed it, array destructuring now now does an IteratorClose on any iterator it creates using GetIterator)