8142924: ES6 symbols created with Symbol.for should deserialize to canonical instances
Reviewed-by: hannesw, lagergren, sundar
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Symbol.java Thu Nov 12 14:14:37 2015 -0800
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Symbol.java Fri Nov 13 16:21:22 2015 +0100
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime;
import java.io.Serializable;
+import jdk.nashorn.internal.objects.NativeSymbol;
/**
* This class represents a unique, non-String Object property key as defined in ECMAScript 6.
@@ -56,4 +57,29 @@
public final String getName() {
return name;
}
+
+ private Object writeReplace() {
+ // If this symbol is a globally registered one, replace it with a
+ // GlobalSymbol in serialized stream.
+ return NativeSymbol.keyFor(null, this) == name ? new GlobalSymbol(name) : this;
+ }
+
+ /**
+ * Represents a globally registered (with NativeSymbol._for) symbol in the
+ * serialized stream. Upon deserialization, it resolves to the globally
+ * registered symbol.
+ */
+ private static class GlobalSymbol implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private final String name;
+
+ GlobalSymbol(final String name) {
+ this.name = name;
+ }
+
+ private Object readResolve() {
+ return NativeSymbol._for(null, name);
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/test/JDK_8142924_Test.java Fri Nov 13 16:21:22 2015 +0100
@@ -0,0 +1,43 @@
+package jdk.nashorn.internal.runtime.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import jdk.nashorn.internal.objects.NativeSymbol;
+import jdk.nashorn.internal.runtime.Symbol;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * @bug 8142924
+ * @summary ES6 symbols created with Symbol.for should deserialize to canonical instances
+ */
+@SuppressWarnings("javadoc")
+public class JDK_8142924_Test {
+ @Test
+ public static void testNonGlobal() throws Exception {
+ final String name = "testNonGlobal";
+ final Symbol symbol1 = (Symbol)NativeSymbol.constructor(false, null, name);
+ final Symbol symbol2 = serializeRoundTrip(symbol1);
+ Assert.assertNotSame(symbol1, symbol2);
+ Assert.assertEquals(symbol2.getName(), name);
+ Assert.assertNotSame(symbol1, NativeSymbol._for(null, name));
+ }
+
+ @Test
+ public static void testGlobal() throws Exception {
+ final String name = "testGlobal";
+ final Symbol symbol1 = (Symbol)NativeSymbol._for(null, name);
+ final Symbol symbol2 = serializeRoundTrip(symbol1);
+ Assert.assertSame(symbol1, symbol2);
+ }
+
+ private static Symbol serializeRoundTrip(final Symbol symbol) throws Exception {
+ final ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ final ObjectOutputStream out = new ObjectOutputStream(bout);
+ out.writeObject(symbol);
+ out.close();
+ return (Symbol) new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray())).readObject();
+ }
+}