My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Friday, April 19, 2013

A Journey To V8 ObjectSetProto Native Function

Update ^_^

whatever story you are interested about in this post, one is that I've proposed a patch to V8 engine (please star it so it gets in faster) to accept a --expose-proto-setter flag at runtime able to expose the proper __proto__ setter so that my node JS pull request could start warning modules using __proto__ instead of Object.setPrototypeOf(target, proto).
What can I say ... open source is beautiful, you can potentially patch everything you want for anything you need ... even behind stubborn, politics, or decisions nobody agreed on :P
Now back to the original post ...


first thing: I write HTML manually in the textarea instead of Markdown, yeah!!!
Why? 'cause nobody on the internet moves fast ... really, no-bloody-body!
so ... back to manual tags writing instead of broken meaningless layout created via magic html editor ... yeeeeeeah!

The Story ...

I know this is getting boring and annoying, and I swear I wish I could say it's the last post but every day there's something more and this story is getting both entertaining and ridiculous!
I gonna tell you how I ended up blocked in Zepto.js repository, and how the rest of reasonable developers are acting instead.
This time, the experiment, is me reporting this story and nothing else. I give you links, I give you facts!

Quick note: they keep telling me I should let it go, but "I cannot sleep anymore" because of this so here my attempt to describe the whole story! Have a coffee, some new tab link to click and dig into, and please, please, keep reading ... also because you might realize ...

It's Not Just Me !

Isaac Z. Schlueter, the man behind node.js, twitted this

@littlecalculist So, why hasn't that been removed in favor of Object.setPrototypeOf? Got a link to discussions, or a shorthand version?

The conversation keeps going and has one conclusion

@izs one-line fix: delete Object.prototype.__proto__; // put this in a module called "raygun-neutralizer" :)

Ha ha ha .. so funny the future of JavaScript comes with a foot-raygun included, don't you think? ^_^

V8 *Is* Based On An Object.setPrototypeOf Equivalent

Breaking news, uh? The internal ObjectSetProto function simply wraps exactly what I've proposed in es-discuss as Object.setPrototypeOf(target, proto).
In V8 internals represented as return %SetPrototype(this, obj);
So here the first thing: the engine of miracles needs such power but we, stupid JavaScripters, how do we dare!

A Poisoned __proto__

Not only this is the less consistent and the most ridiculous property ever introduced in Javascript, this is also intentionally poisoned as broken in Google engine.
These are a couple of quotes in my last attempt to make people reasonable in es-discuss, the first one is from Alex Russell, in this reply:

Assuming "this property" is __proto__, that ship sailed in V8 a long ago and there's zero chance of it ever being removed. It they want to remove it, they can simply fork V8 or ask for a build flag for it.

Not only this is alarming me, as V8 incapable of making changes if considered dangerous as security problems would be, but turned also out that Alex was wrong since today __proto__ is configurable so you can delete it..
.. and all you need to do, after forking, is to build putting a comment here.

set: desc.getSet(),// === ObjectSetProto ? ObjectPoisonProto
                   // : desc.getSet(),

That's it, after that you can have both __proto__ and a usable descriptor of it.
At this point, after a line change in V8 source code, all node.js could do to have a better environment is to do this during the sturtup:

(function(setPrototypeOf){
  if (setPrototypeOf in Object) return;
  var set = Object.getOwnPropertyDescriptor(
    Object.prototype, '__proto__'
  ).set;
  Object.defineProperty(
    Object,
    setPrototypeOf,
    {
      enumerable: false,
      configurable: true,
      value: function setPrototypeOf(target, proto) {
        set.call(target, proto);
        return target;
      }
    }
  );
  // TA-DAAAAAAA!!!
  delete Object.prototype.__proto__;
  // problem solved
}('setPrototypeOf'));

// example
var a = {},
    b = Object.setPrototypeOf({}, a);

a.isPrototypeOf(b); // true!

Above scenario does not look like so hard to implement, isn't it Brendan?
However, another concern was about all npm modules will be broken without considering node has versioning so that no, not a single npm will be broken and updated modules could easily swap to this new API maintaining the environment nice, still fast, and clean!

Moreover, the Object.setPrototypeOf equivalent, called ObjectSetProto and wrapping %SetPrototype(this, proto) in V8, is used to set all __proto__ properties, how cool is that?!

InstallGetterSetter($Object.prototype, "__proto__",
    ObjectGetProto, /* ARE YOU READY???? */ ObjectSetProto);

In few words, my proposal is naturally part of the language ... uh wait, this specific features has been commented as:

an added, _de novo_ API that no one wants, which is an ambient capability on Object, is bad and it won't happen

... it was here!
How would any developer want more power under her/his hands ... don't you dare thinking about it!

A Bit More Background

Brendan Eich excellently summarized with all links the story behind this property.
In few words, this property has been discussed and nobody wanted it.
They better preferred to quickly, dirty, spec it as configurable, at least, and as non present in Object.create(null) objects, so that finally some project could directly get rid of it and drop it via
delete Object.prototype.__proto__;
as mentioned before.
Moreover, this is another quote from Brendan the same es-discuss post:

Because @izs tweeted something you think Node is going to fork V8? Get real!

... So I Tried To Get Real ...

The change required to make that possible in V8 is a 10 seconds task, network push a part ... anyway ...

In Isaac slides you can read at page 26 that:

not developing a language removes a huge burden. Let TC-39 and V8 fight those battles for us!

So I didn't even bother him with this discussion ... I mean, he's doing the right thing: let other specialists solve problems for you so you can focus on something else .. right ?
The reality is that even if I send that patch to V8, they will not accept it, not even if Microsoft will agree as the right direction to promote a better standard!
The parody about this de-facto utopia is that all current IE browsers do not support __proto__.
IE is desperate to be part of the not finalized yet spec, and this is probably why the leaked version 11 shows __proto__ shenanigans in the wild .. and those specs are not final ...!

The Very Sad Result Of Thomas Fuchs Reaction

Since I've been fighting, blogging, and discussing this problem for months, and since many times they came back to me or others saying that:

It wasn't Node.js that drove that -- it was the "mobile (iOS WebKit first) web" that wanted __proto__ due to libraries such as Zepto.

So I've tried to reply at some point like:

I think zepto is using that to modify runtime NodeList results after querySelectorAll but in any case it was not me saying that __proto__ isn't used already...

The discussion goes on and on until I think one action is better than many words, right?

What Allen Wirfs-Brock Said

The good @awbjs, who writes ECMAScript Specifications, took kindly some of his time to reply to my post entitled Yet Another Reason To Drop __proto__.
This is his comment:

__proto__ wasn't TC39's mistake and everybody who participates on TC39 is aware of how terrible it is.
...
If you want to eliminate __proto__ you will have to eliminate its usage. Write a shim for Object.setPrototypeOf:
...
Then evangelize web developers like crazy to update all their existing deployed code to use this shim instead of directly using __proto__.
...
Good luck (seriously)

Challenge Accepted! ... so here the big drama ... that Allen "Good luck (seriously)" "benediction" transpiled in my mind as:

What the hack ... what does he mean with "goog luck (seriusly)", that JavaScript community is made by passive bigot developers that cannot change simple things?
Of course we are as good developers as those you can find in any other language ... let me demonstrate it describing the situation in a pull request commit with all tests greens and zero side effects!

The Community Reaction

Sure that once described the problem in Zepto.js repository, and I swear never a Zepto.js developer I know ever showed up in es-discuss or my blog, I've simply committed a patch that was tests approved and changing two lines of code promoting Object.setPrototypeOf instead of __proto__.
Long story short:

Here the Thomas rant, accusing me of trolling, after (kinda obviously) him not being aware of anything I've been written 'till now:

It's not about not agreeing with you. It's the form of how you imply or directly state that we're, I quote, "passive bigots" and that somehow __proto__ is insecure and "may" be removed and other weasel words that imply that we don't know what we're doing and you're a white knight to rescue us from ourselves. No, thank you. Please troll someone else.

Now, whatever Thomas thought was good to demonstrate with his reaction, which is simply, in my opinion, "the ball here is mine, nobody plays if I'm pissed off" ... since he decided to block me from the whole repository, all I could do is to write an answer in the same gist that is describing the current madness behind that property.
Really Thomas ... what can I say, congrats!

Thomas, Not Flex Box Again, Please!

So if IE will spec a document that's still a draft, and just to make for the broken web __proto__ can create, don't blame anyone if IE will implement that as broken as it is now almost spec'd!
Version 9 won't have it and neither 10, the current one in 2013!
If Zepto.js decides IE is not a target browser, this does not mean every library should decide the same!
Isn't one of our duty, as Web developers, to make the Web available to as many people as possible?
jQuery released today version 2 and IE9 and IE10 are supported, as easy as that .. or maybe that was the reason you were so nervous?
If Zepto wants to shoot in its foot saying __proto__ or nothing .. deal with that, you have less targets there and of course, you know that!
I mean, you better support IE9 and 10 in both Desktop and mobile for a while in any case, don't you?
So since this is the best moment to drop that mistake and go for a better, less obtrusive, pattern, why wouldn't you?

Update On The Repository

I am still blocked as if I've been trolling Zepto since ever but at least now Thomas rant is gone and there is a statement from Mislav Marohnić there I cannot comment but that makes sense for that library, except when it comes to talking about standards, since __proto__ is not even standard yet:

We generally don't pull contributions that don't improve anything. If, for instance, IE implemented the standard API but doesn't support __proto__, we would pull this. But we don't gain anything tangible with this change. We only believe in standards if they actually result in some benefit. We don't know what the "future of JS" is going to be, so we're making this neat little library that works in the present. When the future of JS arrives, I'm sure we'll adapt accordingly.

Revelation: Why Is Dropping Proto So Important To Me!!!

First of all, as I've said, is not just me ...
Secondly, __proto__ cannot be polyfilled while a modern Object.setPrototypeOf method could be much easier and consistently polyfilled across current browsers.
ES6 specifications aren't going out anny time soon so it's not too late to put a simple method out there able to make the future a bit brighter .. for node.js, for quickly updated browsers, for JavaScript, your favorite programming language.
You don't want too much power in a function? You shouldn't care since the language behind that function has it, so you are just thinking you should be limited, no matter how good or powerful or evil the function will be.
Thanks for reading until here, really appreciated!

5 comments:

Adrien Risser said...

As I said on github, fully supporting you.
(I know it pains you a bit, but reader-friendly HTML is welcomed back~)

njy said...

Good job, and keep up the discussion!

njy said...

Good job, and keep up the discussion!

Steven Roussey said...

Personally, I always saw __proto__ as a Gecko only thing that leaked into user space like window.Components did in Firefox el al. I guess I always thought it was there for me to use as part of Firebug. I do find it odd that anyone uses it since it doesn't work on IE, though it does allow interesting magic stuff to happen, which by the way, is bad for performance of the JIT. Mozilla looked at removing it for that reason (check bugzilla for details).

tobi said...

Thank you for putting so much energy into the future of javascript!

And please keep us up to date.