Small Proposal "!in"

Mike Samuel mikesamuel at gmail.com
Thu Jul 19 12:22:53 UTC 2018


On Thu, Jul 19, 2018 at 7:32 AM Andy Earnshaw <andyearnshaw at gmail.com>
wrote:

> Although I support the idea of `!in` (for the same reasons as T.J. Crowder
> mentioned, plus it's useful for duck typing), what some browsers do isn't a
> great argument as modern browsers follow the spec more closely with regards
> to inherited accessors like this and you'd never be able to use `!in` for
> an older browser.  However, you do have a point in that accessors can live
> anywhere in the prototype chain and an object's properties may not
> necessarily be 'owned' by the object in question:
>
>     document.createElement('input').hasOwnProperty('type')
>     // false
>

'string' === typeof document.createElement('input').type
// true


> So far, the main argument against has been that `hasOwnProperty()` is
> recommended over `in` as a more robust check.  I don't see how this is a
> valid concern, they clearly have different use cases and you're not going
> to solve that problem be excluding a negated `in` from the spec (`!(a in
> b)` is still easier to type than `!b.hasOwnProperty(a)`).  There are plenty
> of valid use cases for `in`, not least duck typing as mentioned before:
>

Agree re "not solving that problem by"
When I'm duck typing, I typically am testing typeof or truthiness of a
property, not just presence.

    function feed(duck) {
>         if ('quackPitch' in duck && duck.canSwim) {
>             duck.give(defrostedPeas);
>         }
>     }
>

This code is brittle.  An attacker may be able to deny service by getting
`{ "quackPitch": true, "canSwim": true }` to a JSON decoder, but would not
be able to trigger an exception if you tested with typeof instead of in.

function robustFeed(duck) {
  if (duck.canSwim && typeof duck.give === 'function') {
    duck.give(defrostedPeas);
  }
}

`in` provides a weak, confusable kind of duck typing.
JSON decoding attacks allow forging objects that satisfy `in` predicates,
encouraging conflating
objects from an untrusted source with objects from trusted code.
These forgeries often would not pass stronger predicates that test for the
typeof required properties.


> `!in` and `!instanceof` would be great additions to the operator sets.
>

Agree re !instanceof.  I'm still not seeing where developers do and should
use `in` or `!in` on a regular basis.


> On Thu, 19 Jul 2018 at 12:06 Tobias Buschor <tobias.buschor at shwups.ch>
> wrote:
>
>> There are valid use-cases.
>> As an example, some browsers have "onfocus" as an own property of
>> "window", some as an inherited.
>>
>> ```js
>> if ('onfocus' !in window) {
>>     // polyfill onfocus...
>> }
>> ```
>>
>>
>> Am Mi., 18. Juli 2018 um 18:32 Uhr schrieb Mike Samuel <
>> mikesamuel at gmail.com>:
>>
>>>
>>>
>>> On Wed, Jul 18, 2018 at 12:21 PM Michael Theriot <
>>> michael.lee.theriot at gmail.com> wrote:
>>>
>>>> I think it is irrelevant; the operator already exists and I would
>>>> assume if you want the negation of it you are using it correctly in the
>>>> first place. Otherwise are you not just arguing for its removal altogether?
>>>> But to answer your question one case that comes to mind is trapping get/has
>>>> in a proxy handler.
>>>
>>>
>>> Why should we assume that only people who consistently use `in`
>>> correctly would want the negation?  It seems that people who use it
>>> incorrectly because they are confused about the precise semantics or don't
>>> care might want the negation too.  If there are more of the latter then we
>>> should not assume what you assume.
>>>
>>> Proxy handler code is important, but very few developers will ever write
>>> a proxy handler over their careers, so this seems like a marginal use case.
>>> Besides, Reflect.has is probably a better choice in a proxy handler.
>>>
>>> I am not arguing for removing `in`.  That would break the web.  I am
>>> just arguing for prioritizing changes that provide features that more
>>> closely match the semantics developers typically want over making it more
>>> convenient to write code that seems to work in casual testing but has
>>> subtly wrong semantics.
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>> On Wednesday, July 18, 2018, Mike Samuel <mikesamuel at gmail.com> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Wed, Jul 18, 2018 at 11:05 AM Michael Theriot <
>>>>> michael.lee.theriot at gmail.com> wrote:
>>>>>
>>>>>> I think `in` and `instanceof` could both benefit from having negated
>>>>>> versions.
>>>>>>
>>>>>> Assuming the developer is using `in` correctly, hasOwnProperty
>>>>>> concerns are irrelevant. Either way they would attempt to use !(a in b),
>>>>>> not !hasOwnProperty.
>>>>>>
>>>>>
>>>>> Why should we assume the developer is using `in` correctly?
>>>>> Apologies if I buried my question at the end.  It was, what are the
>>>>> use cases for `in` that would not be better served by an ergonomic, infix
>>>>> hasOwnProperty?
>>>>>
>>>>>
>>>>> Same reason we don't use...
>>>>>> !(a == b) // a != b
>>>>>> !(a === b) // a !== b
>>>>>>
>>>>>
>>>>>
>>>>>> !(a > b) // a <= b
>>>>>> (!(a > b) && !(a == b)) // a < b
>>>>>>
>>>>>
>>>>> I'm not sure this is relevant to your larger point, and I've already
>>>>> conceded ergonomics, but
>>>>> these last two are not equivalent because NaN is weird.
>>>>>
>>>>> a = NaN, b = 0
>>>>> [!(a > b), a <= b]  // [true, false]
>>>>> [!(a > b) && !(a == b), a < b]  // [true, false]
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> On Thursday, June 28, 2018, Tobias Buschor <tobias.buschor at shwups.ch>
>>>>>> wrote:
>>>>>>
>>>>>>> I dont like to write:
>>>>>>> if ( !('x' in obj) &&  !('y' in obj) ) {
>>>>>>>      doit()
>>>>>>> }
>>>>>>>
>>>>>>> I was even tempted to write it that way:
>>>>>>> if ('x' in obj  ||  'y' in obj) { } else {
>>>>>>>      doit()
>>>>>>> }
>>>>>>>
>>>>>>> What about a !in operator to write it like this?
>>>>>>> if ('x' !in obj  &&  'y' !in obj) {
>>>>>>>      doit()
>>>>>>> }
>>>>>>>
>>>>>>> _______________________________________________
>>>>>> es-discuss mailing list
>>>>>> es-discuss at mozilla.org
>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>
>>>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>>
>> --
>> Freundliche Grüsse
>> Tobias Buschor
>>
>> schwups GmbH
>> Hauptstr. 33
>> 9424 Rheineck/SG
>>
>> +41 76 321 23 21 <+41%2076%20321%2023%2021>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20180719/d9750fbc/attachment-0001.html>


More information about the es-discuss mailing list