Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve tests and fix comments
Browse files Browse the repository at this point in the history
gbrail committed Jan 26, 2025
1 parent 358b4f1 commit aa11b8b
Showing 4 changed files with 70 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1746,10 +1746,18 @@ public void defineProperty(
slot.setter = setter;
}

/**
* This is a single method interface suitable to be implemented as a lambda. It's used in the
* "defineProperty" method.
*/
public interface LambdaGetterFunction extends Serializable {
Object apply(Scriptable scope);
}

/**
* This is a single method interface suitable to be implemented as a lambda. It's used in the
* "defineProperty" method.
*/
public interface LambdaSetterFunction extends Serializable {
void accept(Scriptable scope, Object value);
}
Original file line number Diff line number Diff line change
@@ -2,4 +2,10 @@

import java.io.Serializable;

/**
* This interface makes it possible to pass a lambda function to the various methods in
* LambdaConstructor and LambdaFunction that require a Callable that is also Serializable. Code that
* works with lambdas will largely "not notice" this interface, but it will make it possible for
* lambda-based classes to work with serialization like older Rhino native classes.
*/
public interface SerializableCallable extends Callable, Serializable {}
Original file line number Diff line number Diff line change
@@ -2,4 +2,8 @@

import java.io.Serializable;

/**
* This interface makes it possible to pass a lambda function to the various methods in
* LambdaConstructor and LambdaFunction that require a Constructable that is also Serializable.
*/
public interface SerializableConstructable extends Constructable, Serializable {}
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
@@ -23,7 +24,6 @@ public class NativeSerializationTest {
@BeforeEach
public void init() {
cx = Context.enter();
// cx.setInterpretedMode(true);
scope = new Global(cx);
}

@@ -33,6 +33,22 @@ public void close() {
}

private static Object[][] getTestCases() {
ArrayList<Object[]> result = new ArrayList<>();
for (Object[] testCase : getBaseTestCases()) {
result.add(addFlag(testCase, true));
result.add(addFlag(testCase, false));
}
return result.toArray(new Object[0][0]);
}

private static Object[] addFlag(Object[] tc, boolean flag) {
Object[] ret = new Object[tc.length + 1];
System.arraycopy(tc, 0, ret, 0, tc.length);
ret[tc.length] = flag;
return ret;
}

private static Object[][] getBaseTestCases() {
return new Object[][] {
{"String", "TESTOBJ = 'testing';", "assertEquals('testing', TESTOBJ);"},
{"Number", "TESTOBJ = Number(123);", "assertEquals(123, TESTOBJ);"},
@@ -42,11 +58,11 @@ private static Object[][] getTestCases() {
"TESTOBJ = Symbol('test');",
"assertEquals('Symbol(test)', TESTOBJ.toString());"
},
/*{
"Symbol Registry",
"TESTOBJ = Symbol.for('test');",
"assertEquals(Symbol.for('test'), TESTOBJ);"
},*/
{
"Date",
"TESTOBJ = new Date(1737920959661);",
"assertEquals(1737920959661, TESTOBJ.valueOf());"
},
{
"Object",
"TESTOBJ = {a: 1, b: 'two', c: {a: 3}};",
@@ -61,22 +77,46 @@ private static Object[][] getTestCases() {
"Set",
"TESTOBJ = new Set();\nTESTOBJ.add('testing');",
"assertTrue(TESTOBJ.has('testing'));"
},
// Don't expect WeakMap and WeakSet to retain values after serialization.
// However, do expect them to serialize without error and work after
// serialization.
{
"WeakMap",
"let key = {};\nTESTOBJ = new WeakMap();\nTESTOBJ.set(key, 123);",
"TESTOBJ.set(key, 456);\nassertEquals(456, TESTOBJ.get(key));"
},
{
"WeakSet",
"let key = {};\nTESTOBJ = new WeakSet();\nTESTOBJ.add(key);",
"TESTOBJ.add(key);\nassertTrue(TESTOBJ.has(key));"
}
};
}

@ParameterizedTest(name = "Sanity Check {0}")
/*
* Test to ensure that each pair of scripts works without serialization.
*/
@ParameterizedTest(name = "Sanity Check {0} interpreted = {3}")
@MethodSource("getTestCases")
public void testWithoutSerialization(String name, String createScript, String testScript) {
public void testWithoutSerialization(
String name, String createScript, String testScript, boolean interpreted) {
cx.setInterpretedMode(interpreted);
cx.evaluateString(scope, "load('testsrc/assert.js');", "init.js", 1, null);
cx.evaluateString(scope, createScript, "create.js", 1, null);
cx.evaluateString(scope, testScript, "test.js", 1, null);
}

@ParameterizedTest(name = "Serialize {0}")
/*
* Test to ensure that each type of object may be serialized and deserialized and end
* up in a sane state.
*/
@ParameterizedTest(name = "Serialize {0} interpreted = {3}")
@MethodSource("getTestCases")
public void testSerialization(String name, String createScript, String testScript)
public void testSerialization(
String name, String createScript, String testScript, boolean interpreted)
throws IOException, ClassNotFoundException {
cx.setInterpretedMode(interpreted);
cx.evaluateString(scope, "load('testsrc/assert.js');", "init.js", 1, null);
cx.evaluateString(scope, createScript, "create.js", 1, null);
cx.evaluateString(scope, testScript, "test.js", 1, null);
@@ -89,6 +129,8 @@ public void testSerialization(String name, String createScript, String testScrip

private Object serializeLoop(Object obj) throws IOException, ClassNotFoundException {
ByteArrayOutputStream outBuf = new ByteArrayOutputStream();
// We need to use ScriptableOutputStream here to ensure that Rhino objects
// are properly serialized, including classloading of generated code.
ScriptableOutputStream out = new ScriptableOutputStream(outBuf, scope);
out.writeObject(obj);
out.close();

0 comments on commit aa11b8b

Please sign in to comment.