Object.getOwnPropertyDescriptors(O) ? // plural
Further rational:
- Symmetry with defineProperty/defineProperties.
- One of the benefits of defineProperties (and create) is that they handle errors such that the failure of any individual property doesn't necessarily fail all the remaining ones. It is, of course, possible for a developer to define their own getOwnPropertyDescriptors to also behave this way, but it's not an obvious concern and is usually overlooked
actually, since Object.getOwnPropertyDescriptor
accepts Symbols
too as
second argument, the equivalent with current ES6 would be even more prolix
than that
var shallowCopy = Object.create(
Object.getPrototypeOf(originalObject),
Object.getOwnPropertyNames(originalObject).concat(
Object.getOwnPropertySymbols(originalObject)
).reduce(function (descriptors, name) {
descriptors[name] = Object.getOwnPropertyDescriptor(
originalObject, name
);
return descriptors;
}, {})
);
assuming Symbols will be definable through descriptors ... all this VS
var shallowCopy = Object.create(
Object.getPrototypeOf(originalObject),
Object.getOwnPropertyDescriptors(originalObject)
);
which I believe is a win.
Brandon I take your answer as +1, thanks.
I've also "gisted" a possible/basic polyfill here: gist.github.com/WebReflection/9317065
up ?
Apparently this triggered an @rwaldron which seems to be super-effective
In agenda for April's meeting.
Thanks
Sent from my Windows Phone
From: C. Scott Ananian <cscott at cscott.net>
Sent: 3/4/2014 6:16 To: Andrea Giammarchi <andrea.giammarchi at gmail.com>
Cc: es-discuss at mozilla.org list <es-discuss at mozilla.org>
Subject: Re: Object.getOwnPropertyDescriptors(O) ? // plural
Have you filed a bugzilla ticket for this? That seems the best way to ensure it will get discussed at the next TC39 meeting and resolved one way or the other.
On Tue, Mar 4, 2014 at 12:30 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:
Apparently this triggered an @rwaldron which seems to be super-effective
In agenda for April's meeting.
Yep: tc39/agendas/blob/master/2014/04.md
Going to try, but it's so late in the game that I really can't promise anything--I think it's simple enough that we can get away with it. I will write up a proposed normative spec (likely based on Andrea's work) before I present, I've found that's a pretty powerful way to make a case for late additions ;)
Question: should the returned array include property descriptors for properties whose key is a symbol?
yes, because Object.getOwnPropertyDescriptor(O, k)
accepts both
propertyName
and Symbol
as second argument. The plural, and to be
consistent with the shallowCopy example, should return a list of both.
This is also because all descriptors returned by
Object.getOwnPropertySymbols
can be used same way
Object.getOwnPropertyNames
... so, unless Object.defineProperty(O, k, d)
does not accept k
as Symbol
(basically breaking this proposal via
Object.create
) I don't see why the plural version should not return
descriptors for both kind of properties.
My 2 cents
On Tue, Mar 4, 2014 at 12:48 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:
yes, because
Object.getOwnPropertyDescriptor(O, k)
accepts bothpropertyName
andSymbol
as second argument. The plural, and to be consistent with the shallowCopy example, should return a list of both.This is also because all descriptors returned by
Object.getOwnPropertySymbols
can be used same wayObject.getOwnPropertyNames
... so, unlessObject.defineProperty(O, k, d)
does not acceptk
asSymbol
(basically breaking this proposal viaObject.create
) I don't see why the plural version should not return descriptors for both kind of properties.My 2 cents
Makes sense to me
On Mar 4, 2014, at 9:34 AM, Rick Waldron wrote:
On Tue, Mar 4, 2014 at 12:30 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com> wrote: Apparently this triggered an @rwaldron which seems to be super-effective
In agenda for April's meeting.
Yep: tc39/agendas/blob/master/2014/04.md
Going to try, but it's so late in the game that I really can't promise anything—I think it's simple enough that we can get away with it. I will write up a proposed normative spec (likely based on Andrea's work) before I present, I've found that's a pretty powerful way to make a case for late additions ;)
I like this cloning idiom, but I don't see why we would consider this for ES6, it isn't something that is critical or can't be implemented via ES code. It would be much more appropriate to queue it up for the 2015 train.
ES6: let's wrap this sucker up!
I mixed up ... sorry, let me recap:
Object.getOwnPropertyNames(O)
list ofproperties
andObject.getOwnPropertySymbols(O)
list ofSymbols
can be both used, per each item of each list, withObject.getOwnPropertyDescriptor(O, propertyOrSymbol)
Object.getOwnPropertyDescriptor(O, propertyOrSymbol)
accepts, as second argument, only as aproperty
name or aSymbol
, otherwise it throws as specified here- accordingly, the most meaningful collection as
Object
of descriptors the proposed pluralObject.getOwnPropertyDescriptors(O)
should return is a collection that includes descriptors for bothproperties
andSymbols
I hope this makes sense. Thanks again Rick for, at least, trying and helping out with this.
On Tue, Mar 4, 2014 at 1:03 PM, Allen Wirfs-Brock <allen at wirfs-brock.com>wrote:
On Mar 4, 2014, at 9:34 AM, Rick Waldron wrote:
On Tue, Mar 4, 2014 at 12:30 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:
Apparently this triggered an @rwaldron which seems to be super-effective
In agenda for April's meeting.
Yep: tc39/agendas/blob/master/2014/04.md
Going to try, but it's so late in the game that I really can't promise anything--I think it's simple enough that we can get away with it. I will write up a proposed normative spec (likely based on Andrea's work) before I present, I've found that's a pretty powerful way to make a case for late additions ;)
I like this cloning idiom, but I don't see why we would consider this for ES6, it isn't something that is critical or can't be implemented via ES code. It would be much more appropriate to queue it up for the 2015 train.
ES6: let's wrap this sucker up!
I agree with this, but time permitting I want to at least get something presented.
this boilerplate is error prone and prolix plus it cannot be optimized in core so it's also very slow.
With the introduction of classes, Symbols, and all ES6 new entries, I feel
like the for(var key in object)
loop is dead but developers have no way
to clone objects in the right way and in one shot possibly
optimized/optimizable in core.
I understand it's very late but I wonder, with Rick help, if a "brutal"
copy and paste of a very simple spec that feels natural as complement of
the singular Object.getOwnPropertyDescriptor(O, k)
would be considered
... I certainly don't want waste Rick time with this, neither yours, of
course.
So, in case ES6 is not an option, I wonder if we could have a slot in ES7 so that the polyfill could be adopted and developers life made easier.
I really hope I didn't need in ES6 to write this:
var shallowCopy = Object.create(
Object.getPrototypeOf(originalObject),
Object.getOwnPropertyNames(originalObject).concat(
Object.getOwnPropertySymbols(originalObject)
).reduce(function (descriptors, name) {
descriptors[name] = Object.getOwnPropertyDescriptor(
originalObject, name
);
return descriptors;
}, {})
);
Thanks in advance for any outcome.
On Mar 4, 2014, at 10:17 AM, Rick Waldron wrote:
I like this cloning idiom, but I don't see why we would consider this for ES6, it isn't something that is critical or can't be implemented via ES code. It would be much more appropriate to queue it up for the 2015 train.
ES6: let's wrap this sucker up!
I agree with this, but time permitting I want to at least get something presented.
Presenting is cool, actually necessary to get in on the next train. But unless something is really critical, let's not try to squeeze it into ES6
Allen, as developer, being unable to shallow-copy
in JavaScript for other
N years is actually critical.
Luckily it's not so difficult to polyfill but if you have Rick presenting something like this I really hope there would be an exception or at least a remote possibility it'd squeeze in :-)
I'd be very happy in any case if considered for the future.
Once again, a huge thanks for Rick effort and André too helping with the simplified yet more accurate version of the proposal.
Best
On Tue, Mar 4, 2014 at 2:40 PM, Andrea Giammarchi < andrea.giammarchi at gmail.com> wrote:
Allen, as developer, being unable to
shallow-copy
in JavaScript for other N years is actually critical.Luckily it's not so difficult to polyfill but if you have Rick presenting something like this I really hope there would be an exception or at least a remote possibility it'd squeeze in :-)
I'd be very happy in any case if considered for the future.
Once again, a huge thanks for Rick effort and André too helping with the simplified yet more accurate version of the proposal.
I've updated the agenda to use this version--my draft design that returned an array was "meh", but I couldn't put my finger on why, this addresses that problem.
"thing" ... no "things", just this one ... pliiiiiiiiiz :-)
Also please note that this proposal simplifies Object.assign(target, source) too since latter one is basically:
Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(source)
);
So, in order of priority or what is needed the most, I think with
Object.getOwnPropertyDescriptors(O)
we can solve more than
Object.assign(target, source)
but bear in mind I am not pushing back the
latter one anyhow.
IMO this proposal is just very, very related to ES6 changes due Symbols but
it should have probably been in ES5 too because there was defined
Object.getOwnPropertyDescriptor
which has been indeed upgraded to accept
ES6 Symbols
too.
The spec as it is kinda a no-brainer, ready for copy and paste once reviewed, and simple enough I believe the implementation is straight forward, and I won't mind pushing a patch for V8 to start playing with.
All this, of course, if everyone agrees and there is a consensus at the next meeting after Rick presentation.
Best
Le 5 mars 2014 à 00:18, Andrea Giammarchi <andrea.giammarchi at gmail.com> a écrit :
Also please note that this proposal simplifies Object.assign(target, source) too since latter one is basically:
Object.defineProperties( target, Object.getOwnPropertyDescriptors(source) );
No. Object.assign
(1) uses the semantics of the assignment operator =
(for example, it makes a difference in case of setters), and (2) copies only enumerable properties. Did you think about Object.mixin
?
You are right, I've realized it after posting ... Object.assign(target, source)
via Get
and Put
is basically the equivalent of a classic
for/in
with hasOwnProperty
check ... well, once again, in ES6
Object.getOwnPropertyDescriptors(O)
seems to be a solution for other
cases too (shallow copy of properties, shallow clone, not just for/in) plus
yes, Object.mixin(target, source)
might be simplified as well via this
proposal, that's a good point ... so 3 problems solved at once! :-)
Object.getOwnPropertyDescriptors(obj) makes sense to me. As noted somewhere upstream, it's symmetrical to Object.defineProperties.
When I designed traits.js, which was heavily based on property descriptors, I even added it to the library's public API, under the slightly shorter name Object.getOwnProperties(obj), cf. traitsjs.org/api.html
Brendan asked me whether Object.getOwnPropertyDescriptors would necessitate a derived trap for proxies. I think the answer is no, just like Object.defineProperties(proxy) triggers just the proxy's getOwnPropertyNames trap, and then the defineProperty trap for each property, Object.getOwnPropertyDescriptors(proxy) would trigger the getOwnPropertyNames trap, followed by calls to the getOwnPropertyDescriptor trap for each individual property.
Cheers, Tom
2014-03-05 1:38 GMT+01:00 Andrea Giammarchi <andrea.giammarchi at gmail.com>:
Thanks for clarification Tom, I've also added the main two features this method in the first gist I've posted but here a quick recap:
// for shallow object copy
var shallowCopy = Object.create(
Object.getPrototypeOf(origin),
Object.getOwnPropertyDescriptors(origin)
);
// for traits / mixin
Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(origin)
);
// respecting ES5 symmetry
Object.defineProperty(O, name, descriptor);
descriptor as Object.getOwnPropertyDescriptor(O, name)
Object.defineProperties(O, descriptors);
descriptors as Object.getOwnPropertyDescriptors(O)
Hope this one help presenting the what, the why, and the how.
Best
2014-03-05 20:11 GMT+01:00 C. Scott Ananian <ecmascript at cscott.net>:
On Wed, Mar 5, 2014 at 1:39 PM, Tom Van Cutsem <tomvc.be at gmail.com> wrote:
Object.getOwnPropertyDescriptors(proxy) would trigger the getOwnPropertyNames trap, followed by calls to the getOwnPropertyDescriptor trap for each individual property.
[[OwnPropertyKeys]],
ownKeys
trap.
Yes, according to the current draft spec. I have a pending discussion with
Allen that we actually need to reintroduce a [[GetOwnPropertyNames]]
internal method / getOwnPropertyNames trap, as the ownKeys
trap doesn't
do any invariant checking, which is needed for a reliable Object.isFrozen
test.
, Tom
If you use a getOwnPropertyNames trap, then you also need a getOwnPropertySymbols trap to implement getOwnPropertyDescriptors.
I would rephrase into this:
if you need a getOwnPropertyNames trap, you might need for consistency a getOwnPropertySymbols independently from getOwnPropertyDescriptors since these methods are already available.
I also would like to add a couple of links to support the fact getOwnPropertyDescriptors is needed, and has been asked for, since quite a while: this was 11th of November 2011 ... I didn't know it, and now that I do I wonder why this has been post-poned for so long and never discussed again.
esdiscuss/2011-November/018275
Best
I would rephrase into this:
if you need a getOwnPropertyNames trap, you might need for consistency a getOwnPropertySymbols independently from getOwnPropertyDescriptors since these methods are already available.
While it shares the same name with Object.getOwnPropertyNames(), this getOwnPropertyNames trap is supposed to return string and symbol keyed properties, see esdiscuss.org/topic/ownpropertykeys .
I also would like to add a couple of links to support the fact getOwnPropertyDescriptors is needed, and has been asked for, since quite a while: this was 11th of November 2011 ... I didn't know it, and now that I do I wonder why this has been post-poned for so long and never discussed again.
Or even earlier, strawman:extended_object_api from 2010.
André Bargull <mailto:andre.bargull at udo.edu> March 6, 2014 at 1:21 PM
I would rephrase into this:
if you need a getOwnPropertyNames trap, you might need for consistency a getOwnPropertySymbols independently from getOwnPropertyDescriptors since these methods are already available.
While it shares the same name with Object.getOwnPropertyNames(), this getOwnPropertyNames trap is supposed to return string and symbol keyed properties, see esdiscuss.org/topic/ownpropertykeys .
Should the trap end in Keys not Names?
Thanks Andrew, I wonder if I should update the proposed spec somehow, but I thought as it is combines both Names and Symbols as abstract.
Please let me know and I'll update.
Best
autocomplete misspelled Andre' , apologies
On 3/6/2014 10:24 PM, Brendan Eich wrote:
André Bargull <mailto:andre.bargull at udo.edu> March 6, 2014 at 1:21 PM
I would rephrase into this:
if you need a getOwnPropertyNames trap, you might need for consistency a getOwnPropertySymbols independently from getOwnPropertyDescriptors since these methods are already available.
While it shares the same name with Object.getOwnPropertyNames(), this getOwnPropertyNames trap is supposed to return string and symbol keyed properties, see esdiscuss.org/topic/ownpropertykeys .
Should the trap end in Keys not Names?
/be
Only if [[OwnPropertyKeys]] gets renamed to something else, because having both [[GetOwnPropertyKeys]] and [[OwnPropertyKeys]] seems unnecessarily confusing.
On 3/6/2014 11:35 PM, Andrea Giammarchi wrote:
autocomplete misspelled Andre' , apologies
No worries! :-)
On Thu, Mar 6, 2014 at 2:34 PM, Andrea Giammarchi <andrea.giammarchi at gmail.com <mailto:andrea.giammarchi at gmail.com>> wrote:
Thanks Andrew, I wonder if I should update the proposed spec somehow, but I thought as it is combines both Names and Symbols as abstract.
You mean this proposal gist.github.com/WebReflection/9353781, right? It does not need to be changed, because the [[OwnPropertyKeys]] internal method returns string and symbol valued property keys. Or to be more correct, it returns string and symbol valued property keys for ordinary objects. Proxy objects are currently allowed to return any value from their [[OwnPropertyKeys]] internal method, because the result value of the "ownKeys" trap is not checked at all. (Except of a simple type check to ensure it is an object.)
The proposed [[GetOwnPropertyNames]] internal method is supposed to be a more restrictive version of [[OwnPropertyKeys]] to ensure Proxy objects don't lie about their properties. This is only required for certain integrity critical methods, like for example Object.isFrozen().
got it, thanks again.
On Thu, Mar 6, 2014 at 6:31 PM, André Bargull <andre.bargull at udo.edu> wrote:
On 3/6/2014 11:35 PM, Andrea Giammarchi wrote: The proposed [[GetOwnPropertyNames]] internal method is supposed to be a more restrictive version of [[OwnPropertyKeys]] to ensure Proxy objects don't lie about their properties.
[[SafeOwnPropertyKeys]] or [[CheckedOwnPropertyKeys]] seems like a more accurate and less confusing name, since it returns keys not names.
2014-03-07 0:51 GMT+01:00 C. Scott Ananian <ecmascript at cscott.net>:
On Thu, Mar 6, 2014 at 6:31 PM, André Bargull <andre.bargull at udo.edu> wrote:
On 3/6/2014 11:35 PM, Andrea Giammarchi wrote: The proposed [[GetOwnPropertyNames]] internal method is supposed to be a more restrictive version of [[OwnPropertyKeys]] to ensure Proxy objects don't lie about their properties.
[[SafeOwnPropertyKeys]] or [[CheckedOwnPropertyKeys]] seems like a more accurate and less confusing name, since it returns keys not names.
The result is only "checked" for proxies, but the name of internal methods should make sense for all types of objects.
From an API point of view, the more significant difference may be that [[OwnPropertyKeys]] returns an iterable, while [[CheckedOwnPropertyKeys]] would return an array of strings and symbols. I don't think there is currently a good naming convention to distinguish things that return an iterable versus things that return an array.
I searched the spec for all clients of [[OwnPropertyKeys]], they are:
Object.assign(target, source) // to iterate over all own props (strings and symbols) of source Object.keys(O) // to construct array of strings (of enumerable properties) Reflect.ownKeys(O) // to get iterator over strings and symbols
// the following should be reliable primitives, thus should use the "checked" version that returns an array: Object.getOwnPropertyNames(O) // to construct array of strings Object.getOwnPropertySymbols(O) // to construct array of symbols Object.{freeze,seal}(O) // to reliably redefine all own props Object.{isFrozen,isSealed}(O) // to reliably test all own props
Given that most of the functions that use [[OwnPropertyKeys]] need to either construct an array anyway, or want reliable results, I wonder whether we shouldn't just change [[OwnPropertyKeys]] to include the checks and return an array instead of an iterable. That way we avoid having two internal methods that do more or less the same thing.
I was also a bit puzzled by the iterator return value. I expected
that it would handle mutation (adding new properties) during traveral
the way that the Map
and Set
iterators do. I was surprised to see
that all the users turned the iterator into an array; none seemed to
handle concurrent mutation. So why not return an Array
?
Tom Van Cutsem wrote:
Given that most of the functions that use [[OwnPropertyKeys]] need to either construct an array anyway, or want reliable results, I wonder whether we shouldn't just change [[OwnPropertyKeys]] to include the checks and return an array instead of an iterable. That way we avoid having two internal methods that do more or less the same thing.
+1.
I wonder if by any chance this could sneak into ES6 ... we have only singular version here: people.mozilla.org/~jorendorff/es6-draft.html#sec-object.getownpropertydescriptor
rationale The easiest way to create a shallow copy of a generic object could be:
var shallowCopy = Object.create( Object.getPrototypeOf(originalObject), Object.getOwnPropertyDescriptors(originalObject) );
Today what we have to do this instead:
var shallowCopy = Object.create( Object.getPrototypeOf(originalObject), Object.getOwnPropertyNames(originalObject).reduce( function (descriptors, name) { descriptors[name] = Object.getOwnPropertyDescriptor( originalObject, name ); return descriptors; }, {}) );
I see latter pattern as sort of unnecessary overhead that could be also much faster in core and polyfilled in the meanwhile.
Thoughts ?
Cheers