Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8042364

Make __proto__ ES6 draft compliant

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P2
    • Resolution: Fixed
    • Affects Version/s: 8u40
    • Fix Version/s: 9
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Resolved In Build:
      b13
    • CPU:
      generic
    • OS:
      generic
    • Verification:
      Verified

      Backports

        Description

        http://webreflection.blogspot.ca/2014/05/fixing-java-nashorn-proto.html

        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
        Object.defineProperty(
          Object.prototype,
          '__proto__',
          {
            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!

          Activity

          Hide
          sundar Sundararajan Athijegannathan added a comment -
          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.
          Show
          sundar Sundararajan Athijegannathan added a comment - 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.
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/dev/nashorn/rev/d16c80270f7d
          User: sundar
          Date: 2014-05-06 12:24:52 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/dev/nashorn/rev/d16c80270f7d User: sundar Date: 2014-05-06 12:24:52 +0000
          Hide
          hgupdate HG Updates added a comment -
          URL: http://hg.openjdk.java.net/jdk9/jdk9/nashorn/rev/d16c80270f7d
          User: lana
          Date: 2014-05-14 17:13:27 +0000
          Show
          hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/nashorn/rev/d16c80270f7d User: lana Date: 2014-05-14 17:13:27 +0000
          Hide
          slugovoy Sergey Lugovoy (Inactive) added a comment -
          verify on jdk9 b25 and jdk1.8.0_40-ea-b01
          Show
          slugovoy Sergey Lugovoy (Inactive) added a comment - verify on jdk9 b25 and jdk1.8.0_40-ea-b01

            People

            • Assignee:
              sundar Sundararajan Athijegannathan
              Reporter:
              jlaskey Jim Laskey
            • Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: