8062132: Nashorn incorrectly binds this for constructor created by another function
Reviewed-by: jlaskey, sundar
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Wed Jul 05 20:06:12 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Fri Oct 31 10:06:52 2014 +0100
@@ -84,7 +84,7 @@
private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
/** History of prototypes, used to limit map duplication. */
- private transient WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
+ private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
/** property listeners */
private transient PropertyListeners listeners;
@@ -677,14 +677,14 @@
/**
* Check prototype history for an existing property map with specified prototype.
*
- * @param parentMap New prototype object.
+ * @param proto New prototype object.
*
* @return Existing {@link PropertyMap} or {@code null} if not found.
*/
- private PropertyMap checkProtoHistory(final PropertyMap parentMap) {
+ private PropertyMap checkProtoHistory(final ScriptObject proto) {
final PropertyMap cachedMap;
if (protoHistory != null) {
- final SoftReference<PropertyMap> weakMap = protoHistory.get(parentMap);
+ final SoftReference<PropertyMap> weakMap = protoHistory.get(proto);
cachedMap = (weakMap != null ? weakMap.get() : null);
} else {
cachedMap = null;
@@ -700,15 +700,15 @@
/**
* Add a map to the prototype history.
*
- * @param parentMap Prototype to add (key.)
+ * @param newProto Prototype to add (key.)
* @param newMap {@link PropertyMap} associated with prototype.
*/
- private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) {
+ private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
if (protoHistory == null) {
protoHistory = new WeakHashMap<>();
}
- protoHistory.put(parentMap, new SoftReference<>(newMap));
+ protoHistory.put(newProto, new SoftReference<>(newMap));
}
/**
@@ -883,8 +883,7 @@
*/
public PropertyMap changeProto(final ScriptObject newProto) {
- final PropertyMap parentMap = newProto == null ? null : newProto.getMap();
- final PropertyMap nextMap = checkProtoHistory(parentMap);
+ final PropertyMap nextMap = checkProtoHistory(newProto);
if (nextMap != null) {
return nextMap;
}
@@ -894,7 +893,7 @@
}
final PropertyMap newMap = new PropertyMap(this);
- addToProtoHistory(parentMap, newMap);
+ addToProtoHistory(newProto, newMap);
return newMap;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062132.js Fri Oct 31 10:06:52 2014 +0100
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010, 2014, 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.
+ */
+
+/**
+ * 8062132: Nashorn incorrectly binds "this" for constructor created by another function
+ *
+ * @test
+ * @run
+ */
+
+function subclass(parentCtor, proto) {
+ function C() {
+ parentCtor.call(this);
+ }
+
+ C.prototype = Object.create(parentCtor.prototype);
+
+ for (var prop in proto) {
+ if (proto.hasOwnProperty(prop)) {
+ C.prototype[prop] = proto[prop];
+ }
+ }
+
+ return C;
+}
+
+var Parent = function() {
+ this.init();
+};
+
+Parent.prototype = {
+ init: null
+};
+
+var Child1 = subclass(Parent, {
+ prop1: 1,
+ init: function() {
+ print('child 1');
+ }
+});
+
+var Child2 = subclass(Parent, {
+ init: function() {
+ print('child 2');
+ }
+});
+
+var Child3 = subclass(Parent, {
+ prop1: 1,
+ init: function() {
+ print('child 3');
+ }
+});
+
+new Child1();
+new Child2();
+new Child3();
+new Child1();
+new Child2();
+new Child3();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062132.js.EXPECTED Fri Oct 31 10:06:52 2014 +0100
@@ -0,0 +1,6 @@
+child 1
+child 2
+child 3
+child 1
+child 2
+child 3