Reflect.hasOwn() ?

# Axel Rauschmayer (10 years ago)

ECMAScript 6 mostly eliminates the need to call methods generically (no need to use the array-like arguments, Array.from(), spread operator, etc.).

The only exception that comes to my mind is {}.hasOwnProperty.call(obj, key) (which is the only safe way to invoke this method). Would it make sense to provide that as a tool function, e.g. as Reflect.hasOwn()?

# Peter van der Zee (10 years ago)

On Sat, Jul 26, 2014 at 5:43 AM, Axel Rauschmayer <axel at rauschma.de> wrote:

The only exception that comes to my mind is {}.hasOwnProperty.call(obj, key) (which is the only safe way to invoke this method). Would it make sense to provide that as a tool function, e.g. as Reflect.hasOwn()?

That would make it unsafe again. Not so much from random people polluting the global Object, but certainly unsafe from a security perspective.

# Axel Rauschmayer (10 years ago)

With “safe”, I only meant w.r.t. overriding (e.g., obj.hasOwnProperty('foo') fails if obj has an own property whose name is 'hasOwnProperty').

Security-wise, how is {}.hasOwnProperty.call() safer than a hypothetical Reflect.hasOwn()?

# Andrea Giammarchi (10 years ago)

obj.hasOwnProperty('foo') fails with objects that do not inherit from Object.prototype

I'd personally +1 Reflect.hasOwnProperty(genericObject, propertyName) without going fancy with shortcuts if the meaning and the result should be exactly the same as Object.prototype.hasOwnProperty.call(genericObject, propertyName)

My $0.02

# Tom Van Cutsem (10 years ago)

2014-07-26 5:43 GMT+02:00 Axel Rauschmayer <axel at rauschma.de>:

ECMAScript 6 mostly eliminates the need to call methods generically (no need to use the array-like arguments, Array.from(), spread operator, etc.).

The only exception that comes to my mind is {}.hasOwnProperty.call(obj, key) (which is the only safe way to invoke this method). Would it make sense to provide that as a tool function, e.g. as Reflect.hasOwn()?

Reflect.hasOwn was actually included in the Reflect API initially, as the dual to the Proxy "hasOwn" trap. When we decided to remove the trap, we also threw out Reflect.hasOwn (in keeping with the symmetry between these Reflect.* utilities and the Proxy traps).

The rationale to remove Reflect.hasOwn was that it could easily be simulated via (Reflect.getOwnPropertyDescriptor(obj,name) !== undefined). While this conses a throw-away property descriptor object, the overhead was deemed insignificant.

Overall, I'm leaning towards keeping the built-in Reflect API minimal. There's room for many more utility methods (Reflect.getPropertyDescriptors comes to mind) which can all be expressed as a library.

# Kevin Smith (10 years ago)

The rationale to remove Reflect.hasOwn was that it could easily be simulated via (Reflect.getOwnPropertyDescriptor(obj,name) !== undefined). While this conses a throw-away property descriptor object, the overhead was deemed insignificant.

Sounds good.

Still, hanging "hasOwnProperty" off of Object.prototype was a mistake and a is constant source of irritation. Perhaps the mistake could be rectified by hanging the same functionality directly off of Object?

if (Object.hasOwn(obj, "foo")) doSomething();
# Mark S. Miller (10 years ago)

On Fri, Jul 25, 2014 at 9:02 PM, Peter van der Zee <ecma at qfox.nl> wrote:

That would make it unsafe again. Not so much from random people polluting the global Object, but certainly unsafe from a security perspective.

Hi Peter, what is the security issue you are concerned about?

# Andrea Giammarchi (10 years ago)

why would you drop the specificity of the name?

would a Symbol be a valid second argument ?

and what if one day we'd like to introduce a hasOwnValue instead, as similar to Array#contains but for generic objects ?

# Axel Rauschmayer (10 years ago)

Overall, I'm leaning towards keeping the built-in Reflect API minimal. There's room for many more utility methods (Reflect.getPropertyDescriptors comes to mind) which can all be expressed as a library.

After thinking about it some more, I agree w.r.t. these two examples:

  • As far as I can tell, hasOwnProperty is mainly used to implement maps via objects. Map will eliminate this use case.
  • getPropertyDescriptors is useful for cloning objects via Object.create(), where Object.assign can often be used in ES6.
# Kevin Smith (10 years ago)
  • As far as I can tell, hasOwnProperty is mainly used to implement maps via objects. Map will eliminate this use case.

To a certain extent yes, but not completely. Objects-as-maps will still be used quite frequently as object literals passed into functions (as an options object, for example).

I think that there is still a need here. Since we are really interested in keys, what about this:

Object.hasKey(obj, someKey);

which would be a more ergonomic and efficient way of saying:

Object.keys(obj).some(key => key === someKey)

?

# Axel Rauschmayer (10 years ago)

On Jul 26, 2014, at 20:36 , Kevin Smith <zenparsing at gmail.com> wrote:

  • As far as I can tell, hasOwnProperty is mainly used to implement maps via objects. Map will eliminate this use case.

To a certain extent yes, but not completely. Objects-as-maps will still be used quite frequently as object literals passed into functions (as an options object, for example).

I think that there is still a need here.

Yes, but it’s much less urgent.

Since we are really interested in keys, what about this:

Object.hasKey(obj, someKey);

Ah, good point! I hadn’t thought of symbols as property keys.

which would be a more ergonomic and efficient way of saying:

Object.keys(obj).some(key => key === someKey)

Did you mean Reflect.ownKeys()? How about:

Reflect.ownKeys(obj).indexOf(someKey) >= 0

Or, maybe in ES7:

Reflect.ownKeys(obj).contains(someKey)
# Kevin Smith (10 years ago)

Did you mean Reflect.ownKeys()?

I meant Object.keys. That will eliminate the inconsistency between Object.keys usage and hasOwnProperty usage that crops up sometimes:

joyent/node#7587

When dealing with objects-as-maps, it's usually just the key-ness that you're interested in, not whether the property is inherited or not.

# Kevin Smith (10 years ago)

I meant Object.keys. That will eliminate the inconsistency between Object.keys usage and hasOwnProperty usage that crops up sometimes:

Nevermind. Brain-stall. Sorry about the noise.

# Boris Zbarsky (10 years ago)

On 7/26/14, 5:33 AM, Tom Van Cutsem wrote:

The rationale to remove Reflect.hasOwn was that it could easily be simulated via (Reflect.getOwnPropertyDescriptor(obj,name) !== undefined). While this conses a throw-away property descriptor object, the overhead was deemed insignificant.

That depends on how much work an implementation has to perform to produce the value of a value property, doesn't it.

In the case of some DOM objects that work can be fairly significant (e.g. O(N) in size of the document).

On the other hand, maybe performance of Reflect.* is just not that critical.

# Tab Atkins Jr. (10 years ago)

On Sat, Jul 26, 2014 at 11:36 AM, Kevin Smith <zenparsing at gmail.com> wrote:

  • As far as I can tell, hasOwnProperty is mainly used to implement maps via objects. Map will eliminate this use case.

To a certain extent yes, but not completely. Objects-as-maps will still be used quite frequently as object literals passed into functions (as an options object, for example).

In that case, though, you don't want to use hasOwnProperty; you want to allow property bags to express properties on the proto (for example, as getters). So this particular use-case of objects-as-maps is irrelevant for the question at hand.

I think that there is still a need here. Since we are really interested in keys, what about this:

Object.hasKey(obj, someKey);

which would be a more ergonomic and efficient way of saying:

Object.keys(obj).some(key => key === someKey)

This is identical to obj.key !== undefined, unless you're allowing undefined to be passed explicitly as a valid argument for some reason.

# Peter van der Zee (10 years ago)

On Sat, Jul 26, 2014 at 5:14 PM, Mark S. Miller <erights at google.com> wrote:

Hi Peter, what is the security issue you are concerned about?

Unless Reflect is completely sealed out of the box, you can never know whether properties on it are the actual built-ins. That's all.

# David Bruant (10 years ago)

Le 27/07/2014 13:35, Peter van der Zee a écrit :

On Sat, Jul 26, 2014 at 5:14 PM, Mark S. Miller <erights at google.com> wrote:

Hi Peter, what is the security issue you are concerned about? Unless Reflect is completely sealed out of the box, you can never know whether properties on it are the actual built-ins. That's all.

You can deeply freeze it yourself before any other script accesses it.

Even without doing so, let's say Reflect is not sealed. If you change it yourself (by code you wrote or imported), you know what to expect (or you didn't audit code you import, but them, you also know you can only expect the worst). If you don't change Reflect yourself, then it's third-party code which is. But then, why did you let this third-party code access to the capability of modifying the built-ins? You could set up a proxy in your own domain, fetch thrid-party scripts from there and serve them to your own domain confined (with Caja or else).

My point being that there are ways to prevent any non-trusted scripts from modifying Reflect (assuming you stay away from script at src which doesn't allow any form of confinment on the imported script)

For ES6, I'm not clear yet on how the module loader will work with to cross-domain scripts. I believe part of the web platform security model relies on a page not being able to read the content of thrid-party scripts it imports via script at src (IIRC because some websites send private data based on cookies in such scripts, so being able to read the content of such scripts would lead to terrible data leakage). Does the module loader preserves such a guarantee?

# Peter van der Zee (10 years ago)

On Sun, Jul 27, 2014 at 1:57 PM, David Bruant <bruant.d at gmail.com> wrote:

You can deeply freeze it yourself before any other script accesses it.

That's already assuming you are first. You may not be without your knowledge (ISP injection, virus hijack, garden gnomes, etc). At this point you'll be too late.

My point being that there are ways to prevent any non-trusted scripts from modifying Reflect

And I guess I'm saying, "no, there isn't".

It'd be nice if there was some kind of mechanic of detecting/ensuring that some built-in is indeed a built-in. That would take away all of this pain. Maybe including a system module could fix this issue. I doubt I'm the first here to mention that though.

# Mark S. Miller (10 years ago)

Although there is some interesting work in trying to obtain security relevant guarantees from a script that isn't first, where a malicious script may instead have been first (link please if anyone has it), this work did not seem practical to me.

My POV: A realm starts out pervasively malleable. It can only provide practical protection to some scripts within the realm from other scripts in that realm if the first script loaded into that realm is not harmful to this cause, and if a script supportive of that cause (like initSES.js) is loaded before any scripts that may be harmful to that cause.

# Peter van der Zee (10 years ago)

On Sun, Jul 27, 2014 at 6:14 PM, Mark S. Miller <erights at google.com> wrote:

Although there is some interesting work in trying to obtain security relevant guarantees from a script that isn't first, where a malicious script may instead have been first (link please if anyone has it), this work did not seem practical to me.

I'm not familiar with actual deep research in this area for JS.

Seems to me like a syntactic way of including a module that's guaranteed to be a system module (completely sealed of the shelf) would circumvent a lot of these problems. For example, a module that gives you a fresh default global object with all the built-ins guaranteed unchanged. Since the syntax can't really be affected by an earlier script and the language could define a hardcoded system module, this kind of approach seems viable to me. But we're digressing from the topic.

# Rick Waldron (10 years ago)

On Sunday, July 27, 2014, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

On Sat, Jul 26, 2014 at 11:36 AM, Kevin Smith <zenparsing at gmail.com <javascript:;>> wrote:

  • As far as I can tell, hasOwnProperty is mainly used to implement maps

via objects. Map will eliminate this use case.

To a certain extent yes, but not completely. Objects-as-maps will still be used quite frequently as object literals passed into functions (as an options object, for example).

In that case, though, you don't want to use hasOwnProperty; you want to allow property bags to express properties on the proto (for example, as getters). So this particular use-case of objects-as-maps is irrelevant for the question at hand.

I think that there is still a need here. Since we are really interested in keys, what about this:

Object.hasKey(obj, someKey);

which would be a more ergonomic and efficient way of saying:

Object.keys(obj).some(key => key === someKey)

This is identical to obj.key !== undefined,

As long as "key" is enumerable.

# Tom Van Cutsem (10 years ago)

2014-07-27 18:14 GMT+02:00 Mark S. Miller <erights at google.com>:

Although there is some interesting work in trying to obtain security relevant guarantees from a script that isn't first, where a malicious script may instead have been first (link please if anyone has it), this work did not seem practical to me.

Not sure if this is what you had in mind, but Sergio Maffeis has been working on something along these lines:

DefensiveJS (DJS) www.defensivejs.com

"DJS is a defensive subset of JavaScript: code in this subset runs independently of the rest of the JavaScript environment. When propertly wrapped, DJS code can run safely on untrusted pages and keep secrets such as decryption keys."

# Maël Nison (8 years ago)

Previous thread (2 years ago) here: esdiscuss.org/topic/reflect-hasown

It is still incredibly common to check if an object contains a key using:

if (Object.prototype.hasOwnProperty.call(myObject, key))

This syntax is quite verbose, and doesn't really make sense in the first place. As someone said in the previous thread, hasOwnProperty should have never been added to the Object prototype.

According to the discussion, Reflect.hasOwn has been thrown away in order to keep the Reflect API simple, arguing that such a method could easily be replaced by Reflect.getOwnPropertyDescriptor anyway. While this is certainly true, the situation isn't without parallel with Array.prototype.includes, which has been added as least in part in order to help conveying a semantic meaning in the source code.

Since the usage hasn't decreased, what would you think about reconsidering Reflect.hasOwn for adoption?

# Domenic Denicola (8 years ago)

Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. www.2ality.com/2012/11/proto-breaks-webapps.html.

If you are using objects-as-maps safely, you’d use Object.create(null), in which case the in operator works fine and there's no need for hasOwnProperty incantations.

# Maël Nison (8 years ago)

JSON.parse() and object literals are big sources of objects-as-maps. In both of these cases, using the in operator won't give the right answer.

Le mar. 6 sept. 2016 à 22:11, Domenic Denicola <d at domenic.me> a écrit :

# Isiah Meadows (8 years ago)

I'll admit I use them partially out of laziness and partially because engines already optimize for this much better than with actual maps (only string keys). I frequently alias const hasOwn = Object.prototype.hasOwnProperty, so this wouldn't do much for me other than saving a declaration in each file I use it. Honestly, though, I feel it was a design flaw from the start to be on the prototype, but we can't just time travel and fix it.

# Maël Nison (8 years ago)

Removing hasOwnProperty from Object.prototype would break a lot of code, so it's not even an option, but we could at least add Object.hasOwn, since Reflect apparently isn't the right place for this (it's a shame, it would mirror nicely with Reflect.ownKeys).

Doing this would improve a bit the clarity of new codes, and could prevent silly mistakes, the kind we all hate to debug (I've been unable to find a reliable tool that could search for exact matches in a large number of source codes, but I feel like forgetting the .call probably happens every once in a while).

Le mer. 7 sept. 2016 à 06:08, Isiah Meadows <isiahmeadows at gmail.com> a écrit :

# Andrea Giammarchi (8 years ago)

Just my 2 cents.

The tiniest JS utility I know [1] solves verbosity and freeze the method so it's also safe.

// meet callerOf
function callerOf(c) {return c.call.bind(c)}

// how to use it
const hasOwn = callerOf({}.hasOwnProperty);

hasOwn({key: 'value'}, 'key'); // true
hasOwn({value: 'key'}, 'key'); // false

However, since functions also inherit from Object.prototype, I usually write this shortcut to semantically reach the Object.prototype.hasOwnProperty method, avoiding the need of the callerOf utility:

// assign it once per module/scope
var hOP = Object.hasOwnProperty;

// whenever is needed
hOP.call({key: 'value'}, 'key'); // true
hOP.call({value: 'key'}, 'key'); // false

Beside the top level copy&paste operation to define hOP, writing hOP.call(o,k) is less verbose than Reflect.hasOwn(o,k) and strawberry on top, there's nothing else to explain for something that has been misunderstood for a very long time ( hasOwnProperty through Object.prototype vs in )

Best

[1] WebReflection/caller-of#caller

# Caitlin Potter (8 years ago)

On Sep 6, 2016, at 4:10 PM, Domenic Denicola <d at domenic.me> wrote:

Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

I generally disagree with the idea that this doesn’t belong in “Reflect” because it’s not an MOP operation. There are three reasons for this.

  1. only spec editors care about whether an operation is MOP or not. JS authors are concerned with operations and algorithms that are helpful to their work, not whether it’s written as [Op] vs Op(). To a JS author, HasOwnProperty() is just as valid of a reflection mechanism as [HasProperty].

  2. Given what was said above about hasOwn() being a valid and useful reflection mechanism, and as you’ve mentioned, the “Reflect” namespace indicates that it performs reflection tasks, not that it lets you perform spec internal MOP operations.

  3. Even if Reflect were exclusively for MOP operations, it tends to add extra steps which are not part of the MOP operation. These can make the methods more useful for JS consumers, or they can be convenience mechanisms, but either way, it’s not a 1:1 mapping to MOP operations.

I think it belongs in Reflect, as it’s a reflection capability, the MOP status is a moot point (and it’s just a thin wrapper around [[GetOwnProperty]] anyways), and changing Reflect is less likely to break content than changing Object.

In the meantime, var hasOwn = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty) will continue to be a useful workaround for people.

# Domenic Denicola (8 years ago)

Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

A new namespace, or using Object, might be OK. I think that it will still be controversial, since this proposal is in support of an objects-as-maps programming style which has caused many problems in the past and should not be encouraged. See e.g. www.2ality.com/2012/11/proto-breaks-webapps.html.

If you are using objects-as-maps safely, you’d use Object.create(null), in which case the in operator works fine and there's no need for hasOwnProperty incantations.

# Maël Nison (8 years ago)

Previous thread (2 years ago) here: esdiscuss.org/topic/reflect-hasown

It is still incredibly common to check if an object contains a key using:

if (Object.prototype.hasOwnProperty.call(myObject, key))

This syntax is quite verbose, and doesn't really make sense in the first place. As someone said in the previous thread, hasOwnProperty should have never been added to the Object prototype.

According to the discussion, Reflect.hasOwn has been thrown away in order to keep the Reflect API simple, arguing that such a method could easily be replaced by Reflect.getOwnPropertyDescriptor anyway. While this is certainly true, the situation isn't without parallel with Array.prototype.includes, which has been added as least in part in order to help conveying a semantic meaning in the source code.

Since the usage hasn't decreased, what would you think about reconsidering Reflect.hasOwn for adoption?

# Isiah Meadows (8 years ago)

I'll admit I use them partially out of laziness and partially because engines already optimize for this much better than with actual maps (only string keys). I frequently alias const hasOwn = Object.prototype.hasOwnProperty, so this wouldn't do much for me other than saving a declaration in each file I use it. Honestly, though, I feel it was a design flaw from the start to be on the prototype, but we can't just time travel and fix it.

# Maël Nison (8 years ago)

Removing hasOwnProperty from Object.prototype would break a lot of code, so it's not even an option, but we could at least add Object.hasOwn, since Reflect apparently isn't the right place for this (it's a shame, it would mirror nicely with Reflect.ownKeys).

Doing this would improve a bit the clarity of new codes, and could prevent silly mistakes, the kind we all hate to debug (I've been unable to find a reliable tool that could search for exact matches in a large number of source codes, but I feel like forgetting the .call probably happens every once in a while).

Le mer. 7 sept. 2016 à 06:08, Isiah Meadows <isiahmeadows at gmail.com> a écrit :

# Maël Nison (8 years ago)

JSON.parse() and object literals are big sources of objects-as-maps. In both of these cases, using the in operator won't give the right answer.

Le mar. 6 sept. 2016 à 22:11, Domenic Denicola <d at domenic.me> a écrit :

# Andrea Giammarchi (8 years ago)

Just my 2 cents.

The tiniest JS utility I know [1] solves verbosity and freeze the method so it's also safe.

// meet callerOf
function callerOf(c) {return c.call.bind(c)}

// how to use it
const hasOwn = callerOf({}.hasOwnProperty);

hasOwn({key: 'value'}, 'key'); // true
hasOwn({value: 'key'}, 'key'); // false

However, since functions also inherit from Object.prototype, I usually write this shortcut to semantically reach the Object.prototype.hasOwnProperty method, avoiding the need of the callerOf utility:

// assign it once per module/scope
var hOP = Object.hasOwnProperty;

// whenever is needed
hOP.call({key: 'value'}, 'key'); // true
hOP.call({value: 'key'}, 'key'); // false

Beside the top level copy&paste operation to define hOP, writing hOP.call(o,k) is less verbose than Reflect.hasOwn(o,k) and strawberry on top, there's nothing else to explain for something that has been misunderstood for a very long time ( hasOwnProperty through Object.prototype vs in )

Best

[1] WebReflection/caller-of#caller

# Caitlin Potter (8 years ago)

On Sep 6, 2016, at 4:10 PM, Domenic Denicola <d at domenic.me> wrote:

Reflect is a namespace that contains the proxy traps (it’s a bit of an unfortunate name), so we shouldn’t be adding things to it that are not part of the meta-object protocol.

I generally disagree with the idea that this doesn’t belong in “Reflect” because it’s not an MOP operation. There are three reasons for this.

  1. only spec editors care about whether an operation is MOP or not. JS authors are concerned with operations and algorithms that are helpful to their work, not whether it’s written as [Op] vs Op(). To a JS author, HasOwnProperty() is just as valid of a reflection mechanism as [HasProperty].

  2. Given what was said above about hasOwn() being a valid and useful reflection mechanism, and as you’ve mentioned, the “Reflect” namespace indicates that it performs reflection tasks, not that it lets you perform spec internal MOP operations.

  3. Even if Reflect were exclusively for MOP operations, it tends to add extra steps which are not part of the MOP operation. These can make the methods more useful for JS consumers, or they can be convenience mechanisms, but either way, it’s not a 1:1 mapping to MOP operations.

I think it belongs in Reflect, as it’s a reflection capability, the MOP status is a moot point (and it’s just a thin wrapper around [[GetOwnProperty]] anyways), and changing Reflect is less likely to break content than changing Object.

In the meantime, var hasOwn = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty) will continue to be a useful workaround for people.