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

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`).

---
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/64

Received on Friday, 28 August 2015 17:11:17 UTC