8142924: ES6 symbols created with Symbol.for should deserialize to canonical instances

Reviewed-by: hannesw, lagergren, sundar
This commit is contained in:
Attila Szegedi 2015-11-13 16:21:22 +01:00
parent 196fe549ba
commit e67cae2407
2 changed files with 69 additions and 0 deletions

View File

@ -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 class Symbol implements Serializable {
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);
}
}
}

View File

@ -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();
}
}