Null iterable in for-of?

# Erik Arvidsson (11 years ago)

Somehow I missed when we decided to allow null/undefined as the iterable value in for-of loops.

The following test passes using the spec algorithms:

var c = 0;
for (var x of null) {
  c++;
}
assert.equal(c, 0);

However, if we get a null value here we are most likely just masking an user bug.

I assume the justification is that for-in allows null here? However, for-of is new syntax and we have the chance to get this right this time around.

# Allen Wirfs-Brock (11 years ago)

Yup, there was an issue that was reported and fixed fairly recently pointing out that for-of was inconsistent with for-in in this respect.

I agree that treating null/undefined as an empty collection has a smell. However, in this case my I agree with who ever it was who reported this. that consistancy between for-in and for-of is what we should have for this condition.

BTW, I believe this behavior for for-in was added in ES5. My recollection was that Doug Crockford pushed for it. I don't recall if it was because it matched web reality or simply because he thought it was a good idea.

# Jeff Walden (11 years ago)

On 06/12/2014 03:05 PM, Allen Wirfs-Brock wrote:

I believe this behavior for for-in was added in ES5. My recollection was that Doug Crockford pushed for it. I don't recall if it was because it matched web reality or simply because he thought it was a good idea.

It was added for web compatibility, to track what was originally a SpiderMonkey implementation bug, I believe.

I agree that treating null/undefined as an empty collection has a smell. However, in this case my I agree with who ever it was who reported this. that consistancy between for-in and for-of is what we should have for this condition.

The spec regarding for-of read the other way, before the latest update, precisely because the web compatibility argument was poor justification for for-in working that way, and for-of was an opportunity to do the right thing. (SpiderMonkey implements the throw-on-null/undefined behavior now.) This was a deliberate inconsistency. I would have argued/responded in that bug with WONTFIX.

# André Bargull (11 years ago)

Yup, there was an issue that was reported and fixed fairly recently pointing out that for-of was inconsistent with for-in in this respect.

for-of statement iteration always ignored undefined/null (always = since it was added in rev6). I've only requested in ecmascript#273 to align for-of iteration in statements and comprehensions to have the same behaviour w.r.t. undefined/null.

# André Bargull (11 years ago)

Corrected link: ecmascript#2737

# Brendan Eich (11 years ago)

Jeff Walden wrote:

It was added for web compatibility, to track what was originally a SpiderMonkey implementation bug, I believe.

Actually, if memory serves, IE JScript tolerated null and undefined on right of for-in. SpiderMonkey and my ur-JS implementation, Mocha, did not. Someone with the jwz nostalgia Netscape 2/3 browsers, please test.

I don't think bug-hiding precedent trumps bug-finding, personally. Allen?

# Allen Wirfs-Brock (11 years ago)

On Jun 12, 2014, at 3:18 PM, André Bargull wrote:

ecmascript#2737

Oh, right it's the comprehension consistency I was think of, so yes the ignoring null/undefined isn't a new change.

I don't really care which way we go on this. Clean slate world I'd throw. Messy world - coin flip.

# Brian Di Palma (11 years ago)

throw. Fast fail is better.

# Jeff Walden (11 years ago)

On 06/12/2014 03:25 PM, Brendan Eich wrote:

Actually, if memory serves, IE JScript tolerated null and undefined on right of for-in. SpiderMonkey and my ur-JS implementation, Mocha, did not. Someone with the jwz nostalgia Netscape 2/3 browsers, please test.

Hmm. I'm reciting tribal knowledge that I'm probably misremembering at this point, so I bet you're right.

I don't think bug-hiding precedent trumps bug-finding, personally. Allen?

Agreed.

# Allen Wirfs-Brock (11 years ago)

On Jun 12, 2014, at 5:01 PM, Jeff Walden wrote:

On 06/12/2014 03:25 PM, Brendan Eich wrote:

Actually, if memory serves, IE JScript tolerated null and undefined on right of for-in. SpiderMonkey and my ur-JS implementation, Mocha, did not. Someone with the jwz nostalgia Netscape 2/3 browsers, please test.

Hmm. I'm reciting tribal knowledge that I'm probably misremembering at this point, so I bet you're right.

It isn't listed as a JScript deviation in resources:jscriptdeviationsfromes3.pdf But proposals:bug_fixes says that IE introduced it.

I was probably wrong in pinning this on Crock, as it doesn't show up in his "ES4" wish list. www.crockford.com/javascript/recommend.html

Also see esdiscuss.org/topic/for-in-statement-null-and-undefined if you have any interest in tracing the history of this change.

I don't think bug-hiding precedent trumps bug-finding, personally. Allen?

Agreed.

It sounds like the the tide is swinging towards bug finding rather than consistency in this case. I'm fine with and and will update the spec. accordingly.

# Domenic Denicola (11 years ago)

It sounds like the the tide is swinging towards bug finding rather than consistency in this case. I'm fine with and and will update the spec. accordingly.

The conclusion here wasn't exactly clear to me. Is it the following?

  • for-in continues to do zero iterations
  • for-of throws a TypeError
  • comprehensions throw a TypeError
# Allen Wirfs-Brock (11 years ago)

yes

# Alexander Kit (11 years ago)

Sorry for rising this subject again, but I am somewhat vexed about the changed decision for the exception throwing when null is passed to the for..of statement. I know, that my writing here wont change it now, but I am a little bit uneasy about this dangerous precedent. So why it should not throw any exceptions:

  • First considerations were right: it should behave the same as for..in. After making for..of throwable we lost the consistency. When we treat it from the consumers side, then it is clear, that this statements are equivalent, so they must be equal, when speaking about the null input.
  • For..of is the control flow statement and imho no exceptions should be thrown there, even when the input was invalid. Especially if the input was null - the statement should just not proceed, and this means we have zero iterations and will continue the execution.
  • “likely just masking a bug when passing null“. The main word here is “likely”, and it is not the argument for the exception throwing. What about var foo; var bar = foo + 1 - foo is also undefined and addition is here, so is also likely a bug, and following the logic an exception here should be thrown also. If we continue to think in this direction, then every tiny failure will cause an exception, and this is definitely not good for the web. Exception throwing should be occurred, only when it is definitely the bug or when it can’t be proceeded due to the invalid input data.
  • “Fast fail is better”. Please no, not for the ecmascript, that’s why I love it and that’s how it was designed, please do not change this, especially when there is no need for this, and the arguments above have shown, that this is not the case here.

What I think is the correct behaviour? If the input is iterable it should loop over it, otherwise (null / not iteratable type) should perform nothing and continue with the execution, just like for..in.

Please, do not take this onto your account, this is more like a scream of soul, and I hope I’m wrong ;) Cheers, Alex ​