JDK-8042364 : Make __proto__ ES6 draft compliant
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u40
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-05-04
  • Updated: 2014-08-01
  • Resolved: 2014-05-06
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u20Fixed 9 b13Fixed

all right, you might think __proto__ is my obsession but for fuck sake not a single engine got it right so far ... and it's perfectly spec'd in ES6 too so I don't know what is with nashorn here ...
// how to fix nashorn
    configurable: true,
    get: function () {
      return Object.getPrototypeOf(this);
    set: function (proto) {
      Object.setPrototypeOf(this, proto);
Are You Asking Why?
Here the answer: nashorn is broken, since it does not expose __proto__ quirks anywhere.
'__proto__' in {} is false
Object.getOwnPropertyNames(Object.prototype).indexOf('__proto__') is a -1 negative
Object.getOwnPropertyDescriptor(Object.prototype, '__proto__') is null
Basically even most common basic features detections for '__proto__' are screwed, so that not a single library can trust its own code ... how cool is that ...
Broken null Objects Too
The worst of the worst comes with null objects, where the infamous property makes dictionaries pointless, not secure, and unreliable ... I start thinking the web world was not even ready for dictionaries, it's taking forever to have a reliable one
var o = Object.create(null);
// it's a null object
// nothing should affect it
o.__proto__ = [];

// but nashorn is brilliant
// as old Android 2.1 phones here
o instanceof Array; // true
Congratulation, you never understood what was the purpose of __proto__
Quick Specs Recap
So, since it's apparently the first rocket science problem ever, here a quick summary of how stupidly simple is the __proto__ spec:
if it's a literal expression, not wrapped in quotes, it defines inheritance at runtime: {__proto__:[]} which is an instanceof Array VS {"__proto__":[]} which is just valid JSON and won't even affect inheritance
if accessed through the Object.prototype, where whatever object that inherits from null should NOT be involved, and where __proto__ has not been defined as own property, it behaves as described in the first snippet I've created to fix nashorn
everything else is an epic fail
So please fix this madness once for all ... it's about reading specs and implementing them properly, even if Appendix B of whatever status ES6 is ... or GTFO!
verify on jdk9 b25 and jdk1.8.0_40-ea-b01

Nashorn implements __proto__ as a special property everywhere. It is not related to Object.prototype in any way. __proto__ is treated as special by property linking process. ES6 draft spec reference and details: URL: https://people.mozilla.org/~jorendorff/es6-draft.html __proto__ is specified in two places. 1) Object.prototype.__proto__ https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.__proto__ Every object that inherits from Object.prototype gets "__proto__" property because of this. Object.prototype.__proto__ property getter/setter functions delegate to built-in proto getter and setter. 2) But step (1) does not cover __proto__ within object literals That part is specified @ https://people.mozilla.org/~jorendorff/es6-draft.html#sec-__proto___-property-names-in-object-initializers __proto__ within object literals is treated as "special" and builtin prototype set method is called. Example: var obj = { __proto__: p } print(Object.getPrototypeOf(obj) == p); // prints true var obj2 = { "__proto__" : p } print(Object.getPrototype(obj2) !== p); // prints "false" as __proto__ is not identifier in this case. A normal "__proto__" property is created in this case. If we implement ES6 draft as referred above, we'll break tests that may set __proto__ to be null and then try to access __proto__ on an object. Or access __proto__ on objects not inheriting from Object.prototype directly or indirectly. Everything else (setting/getting __proto__ on objects inheriting from Object.prototype, setting __proto__ within object literals) should work as expected.