8024174: Setting __proto__ property in Object literal should be supported
Reviewed-by: jlaskey, lagergren
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Sep 04 14:29:07 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Sep 04 19:58:16 2013 +0530
@@ -1361,6 +1361,7 @@
final List<Expression> values = new ArrayList<>();
boolean hasGettersSetters = false;
+ Expression protoNode = null;
for (PropertyNode propertyNode: elements) {
final Expression value = propertyNode.getValue();
@@ -1369,6 +1370,9 @@
if (value == null) {
hasGettersSetters = true;
+ } else if (key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
+ protoNode = value;
+ continue;
}
keys.add(key);
@@ -1410,8 +1414,13 @@
}
method.dup();
- globalObjectPrototype();
- method.invoke(ScriptObject.SET_PROTO);
+ if (protoNode != null) {
+ load(protoNode);
+ method.invoke(ScriptObject.SET_PROTO_CHECK);
+ } else {
+ globalObjectPrototype();
+ method.invoke(ScriptObject.SET_PROTO);
+ }
if (hasGettersSetters) {
for (final PropertyNode propertyNode : elements) {
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Sep 04 14:29:07 2013 +0530
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java Wed Sep 04 19:58:16 2013 +0530
@@ -88,7 +88,7 @@
public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess {
/** __proto__ special property name */
- static final String PROTO_PROPERTY_NAME = "__proto__";
+ public static final String PROTO_PROPERTY_NAME = "__proto__";
/** Search fall back routine name for "no such method" */
static final String NO_SUCH_METHOD_NAME = "__noSuchMethod__";
@@ -155,6 +155,9 @@
/** Method handle for setting the proto of a ScriptObject */
public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class);
+ /** Method handle for setting the proto of a ScriptObject after checking argument */
+ public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class);
+
/** Method handle for setting the user accessors of a ScriptObject */
public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8024174.js Wed Sep 04 19:58:16 2013 +0530
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8024174: Setting __proto__ property in Object literal should be supported *
+ * @test
+ * @run
+ */
+
+var p = { foo: function() { print("p.foo"); } };
+
+var obj = {
+ __proto__ : p,
+ bar: 44
+};
+
+if (obj.__proto__ !== p || Object.getPrototypeOf(obj) !== p) {
+ fail("obj.__proto__ was not set inside literal");
+}
+
+if (typeof(obj.foo) !== 'function' || obj.foo !== p.foo) {
+ fail("'obj' failed to inherit 'foo' from 'p'");
+}
+
+var obj2 = {
+ __proto__: null
+};
+
+if (obj2.__proto__ !== null || Object.getPrototypeOf(obj2) !== null) {
+ fail("obj2.__proto__ was not set to null inside literal");
+}