Wed, 04 Sep 2013 19:58:16 +0530
8024174: Setting __proto__ property in Object literal should be supported
Reviewed-by: jlaskey, lagergren
1.1 --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Sep 04 14:29:07 2013 +0530 1.2 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Sep 04 19:58:16 2013 +0530 1.3 @@ -1361,6 +1361,7 @@ 1.4 final List<Expression> values = new ArrayList<>(); 1.5 1.6 boolean hasGettersSetters = false; 1.7 + Expression protoNode = null; 1.8 1.9 for (PropertyNode propertyNode: elements) { 1.10 final Expression value = propertyNode.getValue(); 1.11 @@ -1369,6 +1370,9 @@ 1.12 1.13 if (value == null) { 1.14 hasGettersSetters = true; 1.15 + } else if (key.equals(ScriptObject.PROTO_PROPERTY_NAME)) { 1.16 + protoNode = value; 1.17 + continue; 1.18 } 1.19 1.20 keys.add(key); 1.21 @@ -1410,8 +1414,13 @@ 1.22 } 1.23 1.24 method.dup(); 1.25 - globalObjectPrototype(); 1.26 - method.invoke(ScriptObject.SET_PROTO); 1.27 + if (protoNode != null) { 1.28 + load(protoNode); 1.29 + method.invoke(ScriptObject.SET_PROTO_CHECK); 1.30 + } else { 1.31 + globalObjectPrototype(); 1.32 + method.invoke(ScriptObject.SET_PROTO); 1.33 + } 1.34 1.35 if (hasGettersSetters) { 1.36 for (final PropertyNode propertyNode : elements) {
2.1 --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Sep 04 14:29:07 2013 +0530 2.2 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Sep 04 19:58:16 2013 +0530 2.3 @@ -88,7 +88,7 @@ 2.4 2.5 public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess { 2.6 /** __proto__ special property name */ 2.7 - static final String PROTO_PROPERTY_NAME = "__proto__"; 2.8 + public static final String PROTO_PROPERTY_NAME = "__proto__"; 2.9 2.10 /** Search fall back routine name for "no such method" */ 2.11 static final String NO_SUCH_METHOD_NAME = "__noSuchMethod__"; 2.12 @@ -155,6 +155,9 @@ 2.13 /** Method handle for setting the proto of a ScriptObject */ 2.14 public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class); 2.15 2.16 + /** Method handle for setting the proto of a ScriptObject after checking argument */ 2.17 + public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class); 2.18 + 2.19 /** Method handle for setting the user accessors of a ScriptObject */ 2.20 public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class); 2.21
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/script/basic/JDK-8024174.js Wed Sep 04 19:58:16 2013 +0530 3.3 @@ -0,0 +1,51 @@ 3.4 +/* 3.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +/** 3.28 + * JDK-8024174: Setting __proto__ property in Object literal should be supported * 3.29 + * @test 3.30 + * @run 3.31 + */ 3.32 + 3.33 +var p = { foo: function() { print("p.foo"); } }; 3.34 + 3.35 +var obj = { 3.36 + __proto__ : p, 3.37 + bar: 44 3.38 +}; 3.39 + 3.40 +if (obj.__proto__ !== p || Object.getPrototypeOf(obj) !== p) { 3.41 + fail("obj.__proto__ was not set inside literal"); 3.42 +} 3.43 + 3.44 +if (typeof(obj.foo) !== 'function' || obj.foo !== p.foo) { 3.45 + fail("'obj' failed to inherit 'foo' from 'p'"); 3.46 +} 3.47 + 3.48 +var obj2 = { 3.49 + __proto__: null 3.50 +}; 3.51 + 3.52 +if (obj2.__proto__ !== null || Object.getPrototypeOf(obj2) !== null) { 3.53 + fail("obj2.__proto__ was not set to null inside literal"); 3.54 +}