[dom] DOMTokenList#toggle: don't treat everything non-undefined as true

mzgol has just created a new issue for https://github.com/whatwg/dom:

== DOMTokenList#toggle: don't treat everything non-undefined as true 
==
According to the 3rd & 4th step at 
https://dom.spec.whatwg.org/#dom-domtokenlist-toggle, 
`DOMTokenList#toggle` treats every non-`false` value of the second 
argument as `true`. In particular:

```js
var div = document.createElement('div');
div.classList.add('a'); // <div class="a'></div>
div.classList.toggle('a', undefined); // <div class="a'></div>
div.classList.toggle('a', undefined); // <div class="a'></div>
```

So, according to the spec, these should be 
`div.classList.contains('a')` results after the first & second `toggle
 invocation:
```
1: true
2: true
```
This is because `force` is passed and is not `false` so the first 
sub-step of the 3rd step doesn't apply.

Now, these are the results in popular browsers:
Chrome 44, Safari 8, Edge:
```
1: false
2: false
```
Firefox 40, IE 11:
```
1: false
2: true
```

Now, if you change `undefined` to `null` in both those cases, all 
browsers return:
```
1: false
2: false
```

This indicates all browsers cast the `force` value to a boolean and 
only some of them make an exception for `undefined`, treating it as an
 argument not passed.

IMO the Firefox & IE 11 behavior is the most sensible one. This allows
 to proxy the `toggle` method without checking the number of arguments
 passed:
```js
function proxyClassListToggle(node, value, force) {
    // I don't want to do this
    if (typeof force === 'boolean') {
        node.classList.toggle(value, force);
    } else {
        node.classList.toggle(value);
    }
}
proxyClassListToggle(node, 'a');
```

In any case, the currently specced behavior is not matching reality 
and is surprising (I'd certainly not expect `undefined` to be treated 
as `true`).

See https://github.com/whatwg/dom/issues/64

Received on Friday, 28 August 2015 17:10:52 UTC