__proto__ implementation does not quite match proposed ES6 spec

André Bargull andrebargull at googlemail.com
Wed Sep 18 06:27:03 PDT 2013


Hello,

the issues described below also affect compatibility with other 
Javascript engines. In fact when testing these with SpiderMonkey, V8 or 
JavascriptCore, you'll see all of them report the expected results. More 
inline...


On 9/18/2013 3:01 PM, A. Sundararajan wrote:
> Hi,
>
> Thanks for writing. We are aware of current start of draft spec on 
> this. But, the issue is that if Object.prototype.__proto__ is the way 
> to implement, how will setting __proto__ to null or undefined do? 
Do you mean executing `Object.prototype.__proto__ = null`? This will 
execute the __proto__ [[Set]] accessor property, which then sets 
[[Prototype]] of Object.prototype to `null`. Or do you mean to delete 
the __proto__ accessor on Object.prototype?


> If Object.prototype is not in proto chain of an object, what happens 
> to __proto__ for such objects?
Nothing ;-)  `o = Object.create(null); o.__proto__ = 123;` creates a 
normal data property, no special [[Prototype]] changes whatsoever, i.e. 
`Object.getOwnPropertyDescriptor(o, "__proto__")` returns `{value:123, 
writable:true, enumerable:true, configurable:true}`.


>
> Current __proto__ impl is more of a fall back for scripts that do use 
> __proto__. Since there is no definitive spec yet, it is going to be 
> "wrong" one way or other. If it is finalized by ES6, we'll follow it. 
> For now, I think we'll leave it "as is".
Yeah sure, always hard to tell how TC39 will act. One day feature X is 
the best one ever, next day it's the worst...  -_-
I think the best way to solve this, is to ensure the implementation 
follows the other Javascript engines as much as possible.


- André


>
> Thanks,
> -Sundar
>
> On Wednesday 18 September 2013 05:54 PM, André Bargull wrote:
>> Official support for __proto__ was added recently, but the 
>> implementation does not quite match the proposed ECMAScript 6 
>> specification (rev18).
>>
>> The current consensus in TC39 is as follows:
>>
>> (1) __proto__ in object literals is treated as a special form to set 
>> the [[Prototype]] internal data property of a new object. It is not 
>> possible to disable this functionality (*).
>>
>> (2) Object.prototype.__proto__ is an accessor property with [[Get]] 
>> and [[Set]] accessors. Also [[Enumerable]] is false, [[Configurable]] 
>> is true.
>>
>> (*) Previously it was possible to disable it, see ES6 draft rev14.
>>
>> Certain details may still change over time when the ES6 spec gets 
>> finalized, e.g. should `Object.setPrototypeOf(1,null)` throw a 
>> TypeError because 1 is not an object or should this just perform 
>> argument checks and then return (as proposed in rev18). Also see 
>> https://bugs.ecmascript.org/show_bug.cgi?id=1586 for some recent 
>> changes on this topic.
>>
>>
>> - André
>>
>>
>> Current issues for (1):
>>
>> 1.1:
>> jjs> ({__proto__: (print("first"),{}), a: (print("second"),0)})
>>
>> Expected: print "first" and then "second"
>> Actual: "second" and then "first"
>>
>> 1.2:
>> jjs> ({__proto__: null})
>>
>> Expected: [[Prototype]] is set to null
>> Actual: jjs is terminated (also reproducible with `jjs> 
>> Object.create(null)`)
>> Exception in thread "main" ECMAScript Exception: TypeError: Cannot 
>> get default string value
>>     at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:56)
>>     at 
>> jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:212)
>>     at 
>> jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:184)
>>     at 
>> jdk.nashorn.internal.objects.Global.getDefaultValue(Global.java:585)
>>     at 
>> jdk.nashorn.internal.runtime.ScriptObject.getDefaultValue(ScriptObject.java:1243)
>>     ...
>>
>> 1.3:
>> jjs> ({__proto__: void 0}).__proto__ === Object.prototype
>>
>> Expected: returns true
>> Actual: TypeError: undefined is not an Object
>> (Only Objects or null are allowed, other types are simply ignored. 
>> This was changed in rev17 for backward compatibility reasons)
>>
>> 1.4:
>> jjs> ({__proto__: 0})
>> Exception in thread "main" java.lang.AssertionError: int is not 
>> compatible with object
>>     at 
>> jdk.nashorn.internal.codegen.MethodEmitter.popType(MethodEmitter.java:235)
>>     at 
>> jdk.nashorn.internal.codegen.MethodEmitter.fixParamStack(MethodEmitter.java:1109)
>>     at 
>> jdk.nashorn.internal.codegen.MethodEmitter.invoke(MethodEmitter.java:1128)
>>     at 
>> jdk.nashorn.internal.codegen.MethodEmitter.invokevirtual(MethodEmitter.java:1168)
>>     at 
>> jdk.nashorn.internal.codegen.CompilerConstants$3.invoke(CompilerConstants.java:394)
>>     ...
>>
>>
>> Current issues for (2):
>>
>> 2.1:
>> jjs> Object.getOwnPropertyDescriptor(Object.prototype, "__proto__")
>>
>> Expected: return accessor property descriptor
>> Actual: returns undefined
>>
>> 2.2:
>> jjs> (o = {}, o.__proto__ = void 0, o.__proto__ === Object.prototype)
>>
>> Expected: returns true
>> Actual: returns false
>> (Only Objects or null are allowed, other types are simply ignored. 
>> This was changed in rev17 for backward compatibility reasons)
>>
>> 2.3:
>> jjs> (o = {}, o.__proto__ = 0, o)
>>
>> Expected: returns o
>> Actual: jjs is terminated
>> jjs> (o = {}, o.__proto__ = 0, o)
>> Exception in thread "main" ECMAScript Exception: TypeError: [object 
>> Object] is not a Number
>>     at jdk.nashorn.internal.runtime.ECMAErrors.error(ECMAErrors.java:56)
>>     at 
>> jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:212)
>>     at 
>> jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:184)
>>     at 
>> jdk.nashorn.internal.runtime.ECMAErrors.typeError(ECMAErrors.java:171)
>>     at 
>> jdk.nashorn.internal.objects.NativeNumber.getNumberValue(NativeNumber.java:341)
>>     ...
>>
>> 2.4:
>> jjs> 12["__proto__"] === Number.prototype
>>
>> Expected: returns true
>> Actual: returns false
>
>



More information about the nashorn-dev mailing list