Node.js should delete __proto__ while we still have a chance (before we hit 1.0)

1,734 views
Skip to first unread message

Andrew Kelley

unread,
Sep 19, 2013, 3:35:59 PM9/19/13
to nod...@googlegroups.com
I'm sure this has been discussed before but I don't know where.

Here are some facts:

1. Putting user data (and other kinds of data if you're not careful) inside an object is a huge security problem. Domenic explains this quite well in the readme of his dict module: https://github.com/domenic/dict
2. Object.getPrototypeOf() is available as a perfect substitution for __proto__. It does exactly what you want, without the security risk.
3. Developers *will* use __proto__ if it is available, and they *will* put user data in objects.

Here is an opinion:

DELETE IT FOREVER!!

Andrew Kelley

unread,
Sep 19, 2013, 3:47:34 PM9/19/13
to nod...@googlegroups.com
mscdex on IRC pointed out that according to MDN docs, Object.getPrototypeOf() is read-only.

Well this appears to be incorrect for node.js:


my output:
bar - new method
foo - new implementation

Alexandre Morgaut

unread,
Sep 19, 2013, 3:48:45 PM9/19/13
to nod...@googlegroups.com

I'm not here to say it would be a bad thing but it might be hard to delete __proto__ for 2 reasons:
1. it is part of the V8 engine
2. it is planned to be standardized in ECMAScript 6

some want to have it unavailable in "strict mode"... will see
for sure, since ECMAScript 5, we'd better use getPrototypeOf() but such good practice will probably have to be enforced by Lint tools instead of having __proto__ removed

Alexandre Morgaut

unread,
Sep 19, 2013, 3:54:04 PM9/19/13
to nod...@googlegroups.com
getPrototypeOf() is "meant" to be readonly
for consistency with __proto__ a new setPrototypeOf() method is considered in ECMAScript 6

Alexandre Morgaut

unread,
Sep 19, 2013, 3:58:00 PM9/19/13
to nod...@googlegroups.com
Let me be more detailed, I omitted to look at your gist before answering (shame on me)

getPrototypeOf() return the reference to the prototype object which can or not be "configurable"
setPrototypeOf() would let you change the reference of the internal instance prototype to another object

Rick Waldron

unread,
Sep 19, 2013, 4:24:02 PM9/19/13
to nod...@googlegroups.com
On Thu, Sep 19, 2013 at 3:54 PM, Alexandre Morgaut <alexandr...@gmail.com> wrote:
getPrototypeOf() is "meant" to be readonly

No it's not. Object.getPrototypeOf(foo) returns a reference to foo's [[Prototype]] (otherwise known as __proto__). It does no configuration of the object before returning.
 
for consistency with __proto__ a new setPrototypeOf() method is considered in ECMAScript 6

Yes, considered and has consensus, so it's perfectly valid to create a "polyfill" for setPrototypeOf http://webreflection.blogspot.com/2013/05/objectsetprototypeofo-proto-is-in-es6.html

Rick

Gagle

unread,
Sep 19, 2013, 5:08:19 PM9/19/13
to nod...@googlegroups.com
Node.js is javascript, if you remove __proto__ then it's not javascript. That being said, sorry but imo Domenic's dict module is based on a poor design. The "in" operator is fucking-terrible-uber-extremly slow thing compared with a comparison with undefined:

var o = {}
"a" in o; //slow and dangerous as the dict module says
o.a === undefined; //Fast and safe, o.__proto__ === undefined -> false

speedy test

File: in-object.js

Node v0.10.18
V8 v3.14.5.9
Speedy v0.0.8

Benchmarks: 2
Timeout: 1000ms (1s 0ms)
Samples: 3
Total time per benchmark: ~3000ms (3s 0ms)
Total time: ~6000ms (6s 0ms)

Higher is better (ops/sec)

in
  16,279,539 ± 0.0%
undefined
  151,203,277 ± 0.0%

Elapsed time: 6053ms (6s 53ms)

Andrew Kelley

unread,
Sep 19, 2013, 5:11:11 PM9/19/13
to nod...@googlegroups.com


On Thursday, September 19, 2013 5:08:19 PM UTC-4, Gagle wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

 
That being said, sorry but imo Domenic's dict module is based on a poor design.

How is this relevant to the conversation?

Rick Waldron

unread,
Sep 19, 2013, 5:33:28 PM9/19/13
to nod...@googlegroups.com
On Thu, Sep 19, 2013 at 5:08 PM, Gagle <gagl...@gmail.com> wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

Funny thing to say about something that is not actually part of the language. Check yourself before wreck yourself?

 
That being said, sorry but imo Domenic's dict module is based on a poor design. The "in" operator is fucking-terrible-uber-extremly slow thing compared with a comparison with undefined:


If only there was a public website that he could post the code, which would allow you to modify it and send him your changes...


Rick

Dean Landolt

unread,
Sep 19, 2013, 5:43:40 PM9/19/13
to nod...@googlegroups.com
On Thu, Sep 19, 2013 at 5:33 PM, Rick Waldron <waldro...@gmail.com> wrote:



On Thu, Sep 19, 2013 at 5:08 PM, Gagle <gagl...@gmail.com> wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

Funny thing to say about something that is not actually part of the language. Check yourself before wreck yourself?


Wait, is it in or out? I know at one point it was spec'd for es6, right? Don't get me wrong -- I'd love to hear that it got the axe, especially in light of Object.setPrototypeOf, but I haven't seen anything about that.
 
 
 
That being said, sorry but imo Domenic's dict module is based on a poor design. The "in" operator is fucking-terrible-uber-extremly slow thing compared with a comparison with undefined:


If only there was a public website that he could post the code, which would allow you to modify it and send him your changes...


Rick

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Rick Waldron

unread,
Sep 19, 2013, 8:03:29 PM9/19/13
to nod...@googlegroups.com


On Thursday, September 19, 2013, Dean Landolt wrote:



On Thu, Sep 19, 2013 at 5:33 PM, Rick Waldron <waldro...@gmail.com> wrote:



On Thu, Sep 19, 2013 at 5:08 PM, Gagle <gagl...@gmail.com> wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

Funny thing to say about something that is not actually part of the language. Check yourself before wreck yourself?


Wait, is it in or out? I know at one point it was spec'd for es6, right? Don't get me wrong -- I'd love to hear that it got the axe, especially in light of Object.setPrototypeOf, but I haven't seen anything about that.

Sometime before July and then formally agreed on in July, then any back to an annex.

Rick

Nathan Rajlich

unread,
Sep 20, 2013, 12:28:54 AM9/20/13
to nodejs
Andrew, long story short, it's out of our hands. __proto__ is implemented by v8 and we just use it as-is. If v8 decides to remove __proto__ then node would adopt that at some point, but it's not going to go out of its way to change the language past the defaults.

Andrew Kelley

unread,
Sep 20, 2013, 12:32:47 AM9/20/13
to nod...@googlegroups.com
Makes sense.

I wonder if creating a fork of v8 without __proto__ and drumming up public knowledge would do anything to affect the minds of the decision-makers - whoever they might be. (In my opinion v8 and ecmascript committee are somewhat chicken and egg)

On Friday, September 20, 2013 12:28:54 AM UTC-4, Nathan Rajlich wrote:
Andrew, long story short, it's out of our hands. __proto__ is implemented by v8 and we just use it as-is. If v8 decides to remove __proto__ then node would adopt that at some point, but it's not going to go out of its way to change the language past the defaults.
On Thu, Sep 19, 2013 at 5:03 PM, Rick Waldron <waldro...@gmail.com> wrote:


On Thursday, September 19, 2013, Dean Landolt wrote:



On Thu, Sep 19, 2013 at 5:33 PM, Rick Waldron <waldro...@gmail.com> wrote:



On Thu, Sep 19, 2013 at 5:08 PM, Gagle <gagl...@gmail.com> wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

Funny thing to say about something that is not actually part of the language. Check yourself before wreck yourself?


Wait, is it in or out? I know at one point it was spec'd for es6, right? Don't get me wrong -- I'd love to hear that it got the axe, especially in light of Object.setPrototypeOf, but I haven't seen anything about that.

Sometime before July and then formally agreed on in July, then any back to an annex.

Rick
 
That being said, sorry but imo Domenic's dict module is based on a poor design. The "in" operator is fucking-terrible-uber-extremly slow thing compared with a comparison with undefined:


If only there was a public website that he could post the code, which would allow you to modify it and send him your changes...


Rick

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.

Gagle

unread,
Sep 20, 2013, 6:01:38 AM9/20/13
to nod...@googlegroups.com


El jueves, 19 de septiembre de 2013 23:33:28 UTC+2, Rick Waldron escribió:



On Thu, Sep 19, 2013 at 5:08 PM, Gagle <gagl...@gmail.com> wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

Funny thing to say about something that is not actually part of the language. Check yourself before wreck yourself?

V8 implements the __proto__ property, and V8 is a javascript engine. I don't care if it's not part of the ecma spec. Furthermore, as Nathan Rajlich says, we cannot do anything. If you begin changing things then I propose to remove the strict equal operator (===) and fix the equal operator (==) to work like ===.
 
 
That being said, sorry but imo Domenic's dict module is based on a poor design. The "in" operator is fucking-terrible-uber-extremly slow thing compared with a comparison with undefined:


If only there was a public website that he could post the code, which would allow you to modify it and send him your changes...


Why should I do this? Being open source doesn't mean that I have to redesign and reimplement the whole project of other people.

Nothing to say to Andrew.

mks

unread,
Sep 20, 2013, 7:19:52 AM9/20/13
to nod...@googlegroups.com
If you don't find a place for a writable __proto__ in **your** use case, just don't use it.

Andrew Kelley

unread,
Sep 20, 2013, 8:00:05 AM9/20/13
to nod...@googlegroups.com
mks unfortunately I cannot responsibly ignore it. Whether or not I have a use case for it does nothing to change the security issues (refer to the original post in this thread).


On Fri, Sep 20, 2013 at 7:19 AM, mks <vladimiro...@gmail.com> wrote:
If you don't find a place for a writable __proto__ in **your** use case, just don't use it.

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to a topic in the Google Groups "nodejs" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nodejs/HvwsNAuAN2Q/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nodejs+un...@googlegroups.com.

Arnout Kazemier

unread,
Sep 20, 2013, 8:04:43 AM9/20/13
to nod...@googlegroups.com
If you want to use it for hashes, just use:

var obj = Object.create(null);

Which fixes everything.. I don't see any "security" issues in that git repo either. Only developer stupidity. 
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.

Rick Waldron

unread,
Sep 20, 2013, 8:32:27 AM9/20/13
to nod...@googlegroups.com


On Friday, September 20, 2013, Nathan Rajlich wrote:
Andrew, long story short, it's out of our hands. __proto__ is implemented by v8 and we just use it as-is. If v8 decides to remove __proto__ then node would adopt that at some point, but it's not going to go out of its way to change the language past the defaults.

I would add "for the win"

;)

Rick Waldron

unread,
Sep 20, 2013, 8:40:50 AM9/20/13
to nod...@googlegroups.com


On Friday, September 20, 2013, Andrew Kelley wrote:
Makes sense.

I wonder if creating a fork of v8 without __proto__ and drumming up public knowledge would do anything to affect the minds of the decision-makers - whoever they might be. (In my opinion v8 and ecmascript committee are somewhat chicken and egg)

Hi! Right here!

I don't know why you say "chicken and egg"... V8 implementors are on TC39 and have a lot of say in the future of the language. That said, V8 won't be removing __proto__ anytime soon. It's simple browser game theory: removing means breaking compatibility with a lot of code written specifically for mobile (Safari, Chrome, Firefox)—seems like a bad way to build market share, don't you think?

Honestly, I think you're just being over dramatic. __proto__ will always be non-standard, but isn't going anywhere, anytime soon. A fork will quickly wither and die, but good luck trying.

Rick

Rick Waldron

unread,
Sep 20, 2013, 8:43:07 AM9/20/13
to nod...@googlegroups.com


On Friday, September 20, 2013, Gagle wrote:


El jueves, 19 de septiembre de 2013 23:33:28 UTC+2, Rick Waldron escribió:



On Thu, Sep 19, 2013 at 5:08 PM, Gagle <gagl...@gmail.com> wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

Funny thing to say about something that is not actually part of the language. Check yourself before wreck yourself?

V8 implements the __proto__ property, and V8 is a javascript engine. I don't care if it's not part of the ecma spec. Furthermore, as Nathan Rajlich says, we cannot do anything. If you begin changing things then I propose to remove the strict equal operator (===) and fix the equal operator (==) to work like ===.

Sure, let me put that on my "Break The Whole Web" todo list.

You've just wrecked yourself twice in row. Care to go for a hat-trick?

Rick 

 
 
That being said, sorry but imo Domenic's dict module is based on a poor design. The "in" operator is fucking-terrible-uber-extremly slow thing compared with a comparison with undefined:


If only there was a public website that he could post the code, which would allow you to modify it and send him your changes...


Why should I do this? Being open source doesn't mean that I have to redesign and reimplement the whole project of other people.

Nothing to say to Andrew.

--

Gagle

unread,
Sep 20, 2013, 8:49:47 AM9/20/13
to nod...@googlegroups.com

are you a slow kiddy?


El viernes, 20 de septiembre de 2013 14:43:07 UTC+2, Rick Waldron escribió:


On Friday, September 20, 2013, Gagle wrote:


El jueves, 19 de septiembre de 2013 23:33:28 UTC+2, Rick Waldron escribió:



On Thu, Sep 19, 2013 at 5:08 PM, Gagle <gagl...@gmail.com> wrote:
Node.js is javascript, if you remove __proto__ then it's not javascript.

Funny thing to say about something that is not actually part of the language. Check yourself before wreck yourself?

V8 implements the __proto__ property, and V8 is a javascript engine. I don't care if it's not part of the ecma spec. Furthermore, as Nathan Rajlich says, we cannot do anything. If you begin changing things then I propose to remove the strict equal operator (===) and fix the equal operator (==) to work like ===.

Sure, let me put that on my "Break The Whole Web" todo list.

You've just wrecked yourself twice in row. Care to go for a hat-trick?

Rick 

 
 
That being said, sorry but imo Domenic's dict module is based on a poor design. The "in" operator is fucking-terrible-uber-extremly slow thing compared with a comparison with undefined:


If only there was a public website that he could post the code, which would allow you to modify it and send him your changes...


Why should I do this? Being open source doesn't mean that I have to redesign and reimplement the whole project of other people.

Nothing to say to Andrew.

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to

For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+unsubscribe@googlegroups.com.

Rick Waldron

unread,
Sep 20, 2013, 9:16:35 AM9/20/13
to nod...@googlegroups.com


On Friday, September 20, 2013, Gagle wrote:

are you a slow kiddy?


Considering your previous statements' absurdity, there is no way anyone would know you were being sarcastic. Nice try spinning though.

Rick 



nodejs+un...@googlegroups.com

For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.

Gagle

unread,
Sep 20, 2013, 9:24:52 AM9/20/13
to nod...@googlegroups.com
This thread is absurd on its own. Peace.

El viernes, 20 de septiembre de 2013 15:16:35 UTC+2, Rick Waldron escribió:


mks

unread,
Sep 20, 2013, 9:40:04 AM9/20/13
to nod...@googlegroups.com
I don't see the security problem here. If you store arbitrary keys in an instance of Object you are doing it wrong. Use an hash table for that. {} is not an hash table. Object.create(null) is more likely, or you just have to implement it or another data structure that does the job (js is supposed to be low-level, relatively speaking).
The hypothesis of domenic "You're probably used to stuffing…" doesn't apply (I hope) to most programmers that use javascript for a living. If it does, maybe it is better to fix some code before killing features of the language.

Norman Paniagua

unread,
Sep 20, 2013, 10:08:09 AM9/20/13
to nod...@googlegroups.com
@mks this is new for me, how do you implement hash table any example, blog, tutorial about it? Also will be cool to read articles speaking about __proto__ with their pros cons.

Regards

Jorge Chamorro

unread,
Sep 20, 2013, 2:35:42 PM9/20/13
to nod...@googlegroups.com
On 20/09/2013, at 15:40, mks wrote:

> {} is not an hash table. Object.create(null) is more likely

That, *and* kill the __proto__, if not:

hash= Object.create(null);
key= '__proto__';

hash[key]= 27;
hash[key]
null //What?

Or worse:

hash[key]= this;
'require' in hash
true //What?
'console' in hash
true //What?
'Array' in hash
true //What?

etc.
--
( Jorge )();

Adam Crabtree

unread,
Sep 20, 2013, 4:03:33 PM9/20/13
to nod...@googlegroups.com
Removing __proto__ is both naive and misinformed for several reasons.

Further, there is nothing in Domenic's dict project that suggests the presence of __proto__ is itself a problem. At best, it implies its use will somehow "ruin your day" with a link to a google docs bug[1] that merely illustrates the need for Object.create(null), which has *nothing* to do with Google Docs *using* __proto__. It also doesn't address any of the functionality __proto__ provides, which is of course expected b/c that's not the point of the dict module.

To be fair to Domenic, we're almost certainly recontextualizing his points, so they especially don't apply here at all.

At any rate, here's a list of reasons removing __proto__ is a bad idea:

1. Node.js === V8, and since V8 has __proto__ there's plenty of code (both libraries and application code) that use __proto__. Do you have a good reason why having it will cause more damage than breaking all existing code that does?

2. I really hope it's not removed from strict mode until the language provides equivalent functionality. Think Object.create is sufficient? What about Function.create, Error.create or even Array.create? I've had handful of cases both in library code and application code where the best solution was to use __proto__ and several times where it was the only solution[2,3]. 

3. Even if Function.create and Error.create existed, what about reassigning after creation in cases where your application code did not create it?

Let's not fork to create a handcuffed version of the language.

Cheers,


--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.



--
Better a little with righteousness
       than much gain with injustice.
Proverbs 16:8

Mark Hahn

unread,
Sep 20, 2013, 4:58:19 PM9/20/13
to nodejs
hash[key] --> null    //What?

There are scores of WTFs in javascript.  I'm sure you've seen the website. It's not the job of node to fix javascript.  It's a waste of time talking about it.

Jorge Chamorro

unread,
Sep 20, 2013, 6:14:12 PM9/20/13
to nod...@googlegroups.com
On 20/09/2013, at 22:03, Adam Crabtree wrote:

> Removing __proto__ is both naive and misinformed for several reasons.

Yes, I totally agree.

I just meant to say -in my reply to @mks- that `hash= Object.create(null)` does *not* make `hash` a perfect hash table, unless you deactivate *its* __proto__ too.

The ability to do that is in the table for ES.next, ISTM.

Cheers,
--
( Jorge )();

Andrew Kelley

unread,
Sep 20, 2013, 9:28:06 PM9/20/13
to nod...@googlegroups.com
3rd-eden:
Wow! How did I not know about this before? Thank you for this.

To be clear, no sarcasm here. I'm really happy to have learned about this.

Floby

unread,
Sep 21, 2013, 8:21:04 AM9/21/13
to nod...@googlegroups.com
My understanding of this thread is that we should fork an incredibly complex library to remove functionality from it because some readme on github said so.

__proto__ is perfectly fine. Don't break it.

Jorge Chamorro

unread,
Sep 21, 2013, 11:47:42 AM9/21/13
to nod...@googlegroups.com
On 21/09/2013, at 03:28, Andrew Kelley wrote:

> 3rd-eden:
> Wow! How did I not know about this before? Thank you for this.
>
> To be clear, no sarcasm here. I'm really happy to have learned about this.

I'm happy that you're happy, but even with Object.create(null) you aren't safe, because what you get still has a working __proto__

--
( Jorge )();

Tim Caswell

unread,
Sep 21, 2013, 12:09:06 PM9/21/13
to nod...@googlegroups.com
If you really want a safe map where any key is allowed and doesn't conflict with builtin javascript properties, just implement your own map.  Here is a very simple one that allows storing *any* value as keys.  This includes the string "__proto__" as well as non-strings.

If you want something faster and your pretty sure that "__proto__" will never be used as a key and all other keys are strings, then use native objects with Object.create(null).  Mostly safe is good enough for a large number of cases.  Including generating prime numbers for RSA private keys for your online bank.

function map() {
  var keys = [];
  var values = [];
  return { get: get, set: set };
  function get(key) {
    return values[keys.indexOf(key)];
  }
  function set(key, value) {
    var index = keys.indexOf(key);
    if (index < 0) {
      index = keys.length;
      keys[index] = key;
    }
    return values[index] = value;
  }
}


Ben Noordhuis

unread,
Sep 21, 2013, 1:43:43 PM9/21/13
to nod...@googlegroups.com
On Sat, Sep 21, 2013 at 6:09 PM, Tim Caswell <t...@creationix.com> wrote:
> If you really want a safe map where any key is allowed and doesn't conflict
> with builtin javascript properties, just implement your own map. Here is a
> very simple one that allows storing *any* value as keys. This includes the
> string "__proto__" as well as non-strings.
>
> If you want something faster and your pretty sure that "__proto__" will
> never be used as a key and all other keys are strings, then use native
> objects with Object.create(null). Mostly safe is good enough for a large
> number of cases. Including generating prime numbers for RSA private keys
> for your online bank.
>
> function map() {
> var keys = [];
> var values = [];
> return { get: get, set: set };
> function get(key) {
> return values[keys.indexOf(key)];
> }
> function set(key, value) {
> var index = keys.indexOf(key);
> if (index < 0) {
> index = keys.length;
> keys[index] = key;
> }
> return values[index] = value;
> }
> }

That's O(n) lookup time though - rather worse than the O(log n) or
O(1) characteristics of a JS dictionary.

A common trick is to use a normal dictionary but only access it with
custom getters and setters that auto-prefix keys with (for example)
'x'. That way, '__proto__' becomes 'x__proto__' and that's safe.

Jorge Chamorro

unread,
Sep 21, 2013, 2:39:42 PM9/21/13
to nod...@googlegroups.com
On 21/09/2013, at 19:43, Ben Noordhuis wrote:
> On Sat, Sep 21, 2013 at 6:09 PM, Tim Caswell <t...@creationix.com> wrote:
>>
>>
>> function map() {
>> var keys = [];
>> var values = [];
>> return { get: get, set: set };
>> function get(key) {
>> return values[keys.indexOf(key)];
>> }
>> function set(key, value) {
>> var index = keys.indexOf(key);
>> if (index < 0) {
>> index = keys.length;
>> keys[index] = key;
>> }
>> return values[index] = value;
>> }
>> }
>
> That's O(n) lookup time though - rather worse than the O(log n) or
> O(1) characteristics of a JS dictionary.

Yes, those `.indexOf(key)` can be a pain in the ass.

--
( Jorge )();

Andrew Kelley

unread,
Sep 21, 2013, 3:24:40 PM9/21/13
to nod...@googlegroups.com
You're right. I only tested that the object created had a null __proto__:

> n = Object.create(null);
undefined
> n.__proto__
null

That's nice, but trying to assign a property of __proto__ to it fails:

> n['__proto__'] = "foo"
'foo'
> n['__proto__']
null

WTF. That's still a problem. Object.create(null) solves nothing.




Andrew Kelley

unread,
Sep 21, 2013, 3:31:51 PM9/21/13
to nod...@googlegroups.com
Adam -

I am interested in the code where using __proto__ was the only solution. This would be a counter-example to my initial claim #2. What happens if you replace foo.__proto__ with Object.getPrototypeOf(foo)? 




You received this message because you are subscribed to a topic in the Google Groups "nodejs" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nodejs/HvwsNAuAN2Q/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nodejs+un...@googlegroups.com.

Tim Caswell

unread,
Sep 21, 2013, 3:33:11 PM9/21/13
to nod...@googlegroups.com

Yes, indexOf is O(n), hence why I called mine a "map" and not a "hash".  But if all your keys are strings, Ben's version is faster in almost all cases with lots of keys (though slower for small collections), but still nowhere as fast as native js lookup because of line caches in the engine's JIT.  Also all three alternatives have unique capabilities.  If you want to store a non-string as a key you have to use a map.

Jorge Chamorro

unread,
Sep 21, 2013, 3:33:59 PM9/21/13
to nod...@googlegroups.com
On 21/09/2013, at 21:24, Andrew Kelley wrote:

> You're right. I only tested that the object created had a null __proto__:
>
> > n = Object.create(null);
> undefined
> > n.__proto__
> null
>
> That's nice, but trying to assign a property of __proto__ to it fails:
>
> > n['__proto__'] = "foo"
> 'foo'
> > n['__proto__']
> null
>
> WTF. That's still a problem. Object.create(null) solves nothing.
>

See Ben's message, that's currently the best way to workaround the '__proto__' magic property.

--
( Jorge )();

Andrew Kelley

unread,
Sep 21, 2013, 3:52:15 PM9/21/13
to nod...@googlegroups.com

On Sat, Sep 21, 2013 at 3:33 PM, Tim Caswell <t...@creationix.com> wrote:

If you want to store a non-string as a key you have to use a map.


You can also assign a unique id field to the objects you are putting in the container. Then you can use a native object.

Jorge Chamorro

unread,
Sep 22, 2013, 7:05:23 AM9/22/13
to nod...@googlegroups.com
On 21/09/2013, at 21:33, Tim Caswell wrote:
>
> Yes, indexOf is O(n), hence why I called mine a "map" and not a "hash". But if all your keys are strings, Ben's version is faster in almost all cases with lots of keys (though slower for small collections), but still nowhere as fast as native js lookup because of line caches in the engine's JIT. Also all three alternatives have unique capabilities. If you want to store a non-string as a key you have to use a map.
>
> Isn't computer science fun!
>
> http://jsperf.com/homegrown-map-hash-vs-native

Awesome :-)

Thank you,
--
( Jorge )();

Adam Crabtree

unread,
Sep 24, 2013, 1:11:19 PM9/24/13
to nod...@googlegroups.com
The situations I'm talking about were both cases where I needed to set the __proto__ of a function to inherit from another object or function. One is an instance where Function.create is insufficient because I did not create the originating function.

Andrew Kelley

unread,
Sep 24, 2013, 1:14:10 PM9/24/13
to nod...@googlegroups.com
Adam -

Please read my question again: What happens if you replace foo.__proto__ with Object.getPrototypeOf(foo)? 

Adam Crabtree

unread,
Sep 24, 2013, 1:34:42 PM9/24/13
to nod...@googlegroups.com
Object.getPrototypeOf would not help me at all since it would not allow me to assign a *new* __proto__ to a function I just created, but I *am* mistaken, Function.create() would be sufficient in my cases.

There's still more flexibility in __proto__ to reassign __proto__, which Function.create and Object.getPrototypeOf would not provide.

Rick Waldron

unread,
Sep 24, 2013, 2:55:57 PM9/24/13
to nod...@googlegroups.com
On Tue, Sep 24, 2013 at 1:11 PM, Adam Crabtree <atcra...@gmail.com> wrote:
The situations I'm talking about were both cases where I needed to set the __proto__ of a function to inherit from another object or function. One is an instance where Function.create is insufficient because I did not create the originating function.

Function.create? There is no built in class-side create method of the Function object. Do you mean Object.create? I'd be interested in understanding more about your use case for changing the [[Prototype]] of objects you don't own (I assume, since your messages says "insufficient because I did not create the originating function.")

Rick

Rick Waldron

unread,
Sep 24, 2013, 2:58:58 PM9/24/13
to nod...@googlegroups.com
On Tue, Sep 24, 2013 at 1:34 PM, Adam Crabtree <atcra...@gmail.com> wrote:
Object.getPrototypeOf would not help me at all since it would not allow me to assign a *new* __proto__ to a function I just created, but I *am* mistaken, Function.create() would be sufficient in my cases.

There's still more flexibility in __proto__ to reassign __proto__, which Function.create and Object.getPrototypeOf would not provide.

I'm certain you mean Object.create, but otherwise I understand where you're going. Though this point was clear in your previous message, I'm still interested in understanding what circumstances your program is in where it needs to re-assign the [[Prototype]] of objects it doesn't own. 

Anyway, the solution you need is Object.setPrototypeOf(), which is specified for inclusion in ES6.

Rick

Adam Crabtree

unread,
Sep 24, 2013, 3:45:49 PM9/24/13
to nod...@googlegroups.com
There's a combination of things going on here:

1. There has been discussion on ESDiscuss[1] of __proto__ and the insufficiencies of Object.create, specifically when you want to set the __proto__ of something other than an Object (e.g., Functions, Errors, Arrays, etc...). I don't know what the current state of this feature is, but I know it at least has been raised and acknowledged as a gap in functionality that __proto__ fills[2,3].

2. I was mistaken earlier when I said Function.create would be insufficient for my use cases (and thus would require `fn.__proto__ = ...`). In fact, in both of my use cases I am setting the proto of functions I have created, and therefore a Function.create (where it to exist, see the next point) would be sufficient.

3. Regarding times where I may want to assign the proto of objects, functions, arrays, errors, I don't own, I personally don't have a usecase ATM, but I can easily imagine how that would be incredibly useful for any type of library that shims, wraps or augments core or any built-ins to extend their functionality seamlessly. If these sorts of libraries don't already exist, I would hate to unnecessarily break the requisite functionality before they have a chance to.

Cheers,
Adam Crabtree



--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Adam Crabtree

unread,
Sep 24, 2013, 3:46:40 PM9/24/13
to nod...@googlegroups.com
* (where it to exist, see the next point) => (were it to exist, see the previous point)

Rick Waldron

unread,
Sep 24, 2013, 4:15:49 PM9/24/13
to nod...@googlegroups.com
On Tue, Sep 24, 2013 at 3:45 PM, Adam Crabtree <atcra...@gmail.com> wrote:
There's a combination of things going on here:

1. There has been discussion on ESDiscuss[1]

2 years ago, and never discussed again. 
 
of __proto__ and the insufficiencies of Object.create, specifically when you want to set the __proto__ of something other than an Object (e.g., Functions, Errors, Arrays, etc...).

Yes, I think we're all aware of this.

I don't know what the current state of this feature is, but I know it at least has been raised and acknowledged as a gap in functionality that __proto__ fills[2,3].

The current state is the __proto__ will remain in an annex of the spec and be superseded by Object.setPrototypeOf(target, source) 

 

2. I was mistaken earlier when I said Function.create would be insufficient for my use cases (and thus would require `fn.__proto__ = ...`). In fact, in both of my use cases I am setting the proto of functions I have created, and therefore a Function.create (where it to exist, see the next point) would be sufficient.

Let's stop talking about Function.create. It's not a thing and never will be. The use cases I see on that thread, for Function.create and <| (triangle literal, aka proto operator) are solved using the extends operator with ES6 classes. 
 

3. Regarding times where I may want to assign the proto of objects, functions, arrays, errors, I don't own, I personally don't have a usecase ATM, but I can easily imagine how that would be incredibly useful for any type of library that shims, wraps or augments core or any built-ins to extend their functionality seamlessly. If these sorts of libraries don't already exist, I would hate to unnecessarily break the requisite functionality before they have a chance to.

This is the juicy stuff I was looking for, and yet it's woefully misguided. Anyway, __proto__ isn't going to be removed from v8—like I said earlier about browser game theory: they don't want to be the only engine that doesn't support it, whether it's a standard feature or not. As far as it being standard, __proto__ will exist in an annex and not as part of the core language specification. Again, Object.setPrototypeOf() and Object.getPrototypeOf() will exist in its place.

Rick

Tim Smart

unread,
Sep 24, 2013, 6:21:42 PM9/24/13
to nod...@googlegroups.com
Please don't, `__proto__` is great if not abused. Swapping out the prototype of
an object is extremely useful.

function MyEventEmitter () {
EventEmitter.call(this)
}
MyEventEmitter.prototype.__proto__ = EventEmitter.prototype

Extremely easy inheritance and you don't have to mess with the constructor
property etc. Also allows you to do cool things with the default constructors
without messing with their prototypes.

var superArrayProto = { forEach : myCustomForEachFunction }
superArrayProto.__proto__ = Array.prototype

function makeSuperArray (arr) {
arr.__proto__ = superArrayProto
return arr
}

var superArray = makeSuperArray([])
(myCustomForEachFunction === superArray.forEach) // true

On Thu, Sep 19, 2013 at 12:35:59PM -0700, Andrew Kelley wrote:
> I'm sure this has been discussed before but I don't know where.
>
> Here are some facts:
>
> 1. Putting user data (and other kinds of data if you're not careful) inside
> an object is a huge security problem. Domenic explains this quite well in
> the readme of his dict module: https://github.com/domenic/dict
> 2. Object.getPrototypeOf() is available as a perfect substitution for
> __proto__. It does exactly what you want, without the security risk.
> 3. Developers *will* use __proto__ if it is available, and they *will* put
> user data in objects.
>
> Here is an opinion:
>
> DELETE IT FOREVER!!

Mark Hahn

unread,
Sep 24, 2013, 9:24:01 PM9/24/13
to nodejs
I don't know why this is in a node discussion group.  Obviously node is not going to change V8.

Elijah Insua

unread,
Sep 24, 2013, 9:33:46 PM9/24/13
to nod...@googlegroups.com
sigh.

Rick Waldron

unread,
Sep 24, 2013, 9:41:38 PM9/24/13
to nod...@googlegroups.com
On Tue, Sep 24, 2013 at 6:21 PM, Tim Smart <t...@fostle.com> wrote:
Please don't, `__proto__` is great if not abused. Swapping out the prototype of
an object is extremely useful.

Top posting sucks.

Rick

Rick Waldron

unread,
Sep 24, 2013, 9:42:51 PM9/24/13
to nod...@googlegroups.com



On Tue, Sep 24, 2013 at 9:33 PM, Elijah Insua <tmp...@gmail.com> wrote:
sigh.

+1
 


On Tue, Sep 24, 2013 at 8:24 PM, Mark Hahn <ma...@reevuit.com> wrote:
I don't know why this is in a node discussion group.  Obviously node is not going to change V8.


It's relevant to the community to have technical discussions about the platform.

Rick

Mark Hahn

unread,
Sep 24, 2013, 10:57:11 PM9/24/13
to nodejs
It's relevant to the community to have technical discussions about the platform.

This forum is about the node platform, not V8.


--

Rick Waldron

unread,
Sep 24, 2013, 11:12:18 PM9/24/13
to nod...@googlegroups.com
On Tue, Sep 24, 2013 at 10:57 PM, Mark Hahn <ma...@reevuit.com> wrote:
It's relevant to the community to have technical discussions about the platform.

This forum is about the node platform, not V8.

If you don't use it already, I suggest switching to gmail—it has an awesome "Undo" feature: https://support.google.com/mail/answer/1284885?hl=en

Rick

Floby

unread,
Sep 25, 2013, 4:04:55 AM9/25/13
to nod...@googlegroups.com
Rick. While we are all posting links without much context, I suggest you click on this one http://en.wikipedia.org/wiki/Etiquette_(technology)#Netiquette

Ben Noordhuis

unread,
Sep 25, 2013, 4:50:50 AM9/25/13
to nod...@googlegroups.com
Rick, please tone down your posts.

Adam Crabtree

unread,
Sep 25, 2013, 6:43:27 PM9/25/13
to nod...@googlegroups.com
Thanks for the clarifications. It seems I was mistaken about Object.setPrototypeOf.

1. I didn't realize in this context[1] "Object" included Functions, Errors, etc...
2. Reinforced by Object.create being object specific.

Given this, it's understandable why you thought I was bizarrely expo on Function.create. At any rate, we're in complete agreement here.




--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Adam Crabtree

unread,
Sep 25, 2013, 6:44:09 PM9/25/13
to nod...@googlegroups.com
*expo => supporting

Rick Waldron

unread,
Sep 25, 2013, 6:53:10 PM9/25/13
to nod...@googlegroups.com
On Wed, Sep 25, 2013 at 6:43 PM, Adam Crabtree <atcra...@gmail.com> wrote:
Thanks for the clarifications. It seems I was mistaken about Object.setPrototypeOf.



Anytime :)

Rick

Claus Reinke

unread,
Sep 26, 2013, 4:57:30 AM9/26/13
to nod...@googlegroups.com
Thinking of "Object.create(null)" as fairly safe, I was quite surprised by
your examples, especially as i could only reproduce them in node, not in
browsers. Further testing indicates these are already fixed in current v8
versions (see below).

Still, good to know what one might run into using not-old node versions.

Claus

$ cat tst/hash-proto-null.html
// <script>
var t = Object.create(null);
var key = "__proto__";
t[key] = 27;
console.log( t[key] );

var t = Object.create(null);
t["__proto__"] = {standard: "yes and no"};
console.log( t.standard, t.__proto__ );
// </script>

$ node tst/hash-proto-null.html
null
yes and no { standard: 'yes and no' }

$ node-v0.11.4/node.exe tst/hash-proto-null.html
27
undefined { standard: 'yes and no' }

$ node -p 'process.versions'
{ http_parser: '1.0',
node: '0.10.10',
v8: '3.14.5.9',
ares: '1.9.0-DEV',
uv: '0.10.10',
zlib: '1.2.3',
modules: '11',
openssl: '1.0.1e' }

$ node-v0.11.4/node.exe -p 'process.versions'
{ http_parser: '1.0',
node: '0.11.4',
v8: '3.20.2',
ares: '1.10.0-DEV',
uv: '0.11.5',
zlib: '1.2.3',
modules: '0x000C',
openssl: '1.0.1e' }

Claus Reinke

unread,
Sep 26, 2013, 5:18:10 AM9/26/13
to nod...@googlegroups.com
>>> Let's stop talking about Function.create. It's not a thing and never
>>> will
>>> be. The use cases I see on that thread, for Function.create and <|
>>> (triangle literal, aka proto operator) are solved using the extends
>>> operator with ES6 classes.

You mean it isn't going to be in the standard. There seems to be a
function.create npm package, though. And without such shims, given
class-side inheritance, won't Function.create default to Object.create
(with semantics differing from the old Function.create discussions)?

Claus



Rick Waldron

unread,
Sep 26, 2013, 4:33:23 PM9/26/13
to nod...@googlegroups.com
On Thu, Sep 26, 2013 at 5:18 AM, Claus Reinke <claus....@talk21.com> wrote:
Let's stop talking about Function.create. It's not a thing and never will
be. The use cases I see on that thread, for Function.create and <|
(triangle literal, aka proto operator) are solved using the extends
operator with ES6 classes.

You mean it isn't going to be in the standard.

Yes, I was replying to a message that linked to a thread on es-discuss.
 
Rick
Reply all
Reply to author
Forward
0 new messages