Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions rhino/src/main/java/org/mozilla/javascript/JavaMembers.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static java.lang.reflect.Modifier.isProtected;
import static java.lang.reflect.Modifier.isPublic;

import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
Expand All @@ -35,7 +36,8 @@
* @see NativeJavaObject
* @see NativeJavaClass
*/
class JavaMembers {
class JavaMembers implements Serializable {
private static final long serialVersionUID = 8260700214130563887L;

private static final boolean STRICT_REFLECTIVE_ACCESS = isModularJava();

Expand Down Expand Up @@ -889,7 +891,9 @@ RuntimeException reportMemberNotFound(String memberName) {
NativeJavaMethod ctors; // we use NativeJavaMethod for ctor overload resolution
}

final class BeanProperty {
final class BeanProperty implements Serializable {
private static final long serialVersionUID = 8260700214130563887L;

BeanProperty(String name) {
this.name = name;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,8 @@ private void writeObject(ObjectOutputStream out) throws IOException {
} else {
out.writeObject(null);
}

out.writeObject(members);
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
Expand All @@ -904,7 +906,7 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
staticType = TypeInfo.NONE;
}

initMembers();
members = (JavaMembers) in.readObject();
}

private static Callable symbol_iterator =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package org.mozilla.javascript.lc.member;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.invoke.MethodType;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
Expand All @@ -22,17 +27,18 @@
/**
* @author ZZZank
*/
public final class ExecutableBox {
public final class ExecutableBox implements Serializable {
private static final long serialVersionUID = 8260700214130563887L;

/**
* Must be either {@link Method} or {@link Constructor}.
*
* <p>Not using {@link java.lang.reflect.Executable} for Android compatibility
*/
private final Member member;
private transient Member member;

private final List<TypeInfo> argTypes;
private final TypeInfo returnType;
private transient List<TypeInfo> argTypes;
private transient TypeInfo returnType;
private final boolean varArgs;

public ExecutableBox(Method method, TypeInfoFactory factory, Class<?> parent) {
Expand Down Expand Up @@ -279,4 +285,64 @@ private static boolean tryToMakeAccessible(AccessibleObject accessible) {
}
return true;
}

private void init(Constructor<?> member, TypeInfoFactory factory, Class<?> parent) {
this.member = member;

var argTypes = factory.createList(member.getGenericParameterTypes());
this.argTypes = argTypes;
this.returnType = TypeInfo.NONE;
}

private void init(Method member, TypeInfoFactory factory, Class<?> parent) {
this.member = member;

var argTypes = factory.createList(member.getGenericParameterTypes());
var returnType = factory.create(member.getGenericReturnType());
var mapping = factory.getConsolidationMapping(parent);
if (mapping.isEmpty()) {
this.argTypes = argTypes;
this.returnType = returnType;
} else {
this.argTypes = TypeInfoFactory.consolidateAll(argTypes, mapping);
this.returnType = returnType.consolidate(mapping);
}
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
boolean isMethod = in.readBoolean();
String name = (String) in.readObject();
Class<?> declaring = (Class<?>) in.readObject();
Class<?>[] parms =
MethodType.fromMethodDescriptorString(
(String) in.readObject(), ExecutableBox.class.getClassLoader())
.parameterArray();

try {
if (isMethod) {
var member = declaring.getMethod(name, parms);
init(member, TypeInfoFactory.GLOBAL, declaring);
} else {
var member = declaring.getConstructor(parms);
init(member, TypeInfoFactory.GLOBAL, declaring);
}
} catch (NoSuchMethodException e) {
throw new IOException("Cannot find member: " + e);
}
}

private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeBoolean(member instanceof Method);
out.writeObject(member.getName());
out.writeObject(member.getDeclaringClass());

var argTypes =
member instanceof Method
? ((Method) member).getParameterTypes()
: ((Constructor<?>) member).getParameterTypes();
// we only care about parameter types, so return type is always void
out.writeObject(MethodType.methodType(void.class, argTypes).toMethodDescriptorString());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package org.mozilla.javascript.lc.member;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import org.mozilla.javascript.lc.type.TypeInfo;
Expand All @@ -8,10 +12,13 @@
/**
* @author ZZZank
*/
public final class NativeJavaField {
private final Field field;
public final class NativeJavaField implements Serializable {

private static final long serialVersionUID = -3440381785576412928L;

private transient Field field;
private final boolean isFinal;
private final TypeInfo type;
private transient TypeInfo type;

public NativeJavaField(Field field, TypeInfoFactory typeFactory) {
this.field = field;
Expand Down Expand Up @@ -39,4 +46,28 @@ public void set(Object javaObject, Object value) throws IllegalAccessException {
}
field.set(javaObject, value);
}

private void init(Field field, TypeInfoFactory factory, Class<?> parent) {
this.field = field;
this.type = factory.create(field.getGenericType());
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
var fieldName = (String) in.readObject();
var declaringClass = (Class<?>) in.readObject();

try {
var field = declaringClass.getField(fieldName);
init(field, TypeInfoFactory.GLOBAL, declaringClass);
} catch (NoSuchFieldException e) {
throw new IOException("Cannot find member: " + e);
}
}

private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(field.getName());
out.writeObject(field.getDeclaringClass());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public void directThrow() {
throw cx.captureContinuation();
}
}

public Double publcField = 0.0;
}

@Before
Expand Down Expand Up @@ -263,13 +265,22 @@ public void continuationsPrototypesAndSerialization()
cx.setInterpretedMode(true); // must use interpreter mode
globalScope.put(
"myObject", globalScope, Context.javaToJS(new MyClass(), globalScope));
var func = (Scriptable) globalScope.get("Function", globalScope);
var fp = func.get("prototype", func);
var myObj = (Scriptable) globalScope.get("myObject", globalScope);
var myFunc = (Scriptable) myObj.get("f", myObj);
var myProto = myFunc.getPrototype();
assertEquals("Thing should be equal", fp, myProto);
}

try (Context cx = Context.enter()) {
cx.setInterpretedMode(true); // must use interpreter mode
cx.evaluateString(
globalScope,
"function f(a) { Number.prototype.blargh = function() {return 'foo';}; var k = myObject.f(a); var t = []; return new Number(8).blargh(); }",
"function f(a) { Number.prototype.blargh = "
+ "function() {return 'foo';}; var k = myObject.f(a); "
+ "var t = []; return new Number(8).blargh(); }; "
+ "var foo = myObject.f;",
"function test source",
1,
null);
Expand Down Expand Up @@ -304,6 +315,15 @@ public void continuationsPrototypesAndSerialization()

Object result = cx.resumeContinuation(continuation, globalScope, 8);
assertEquals("foo", result);

var func = (Scriptable) globalScope.get("Function", globalScope);
var fp = func.get("prototype", func);
var myObj = (Scriptable) globalScope.get("myObject", globalScope);
var myFunc = (Scriptable) myObj.get("f", myObj);
var myProto = myFunc.getPrototype();
var sameFunc = globalScope.get("foo", globalScope);
assertEquals("Prototypes to be equal", fp, myProto);
assertEquals("Functions to be equal", myFunc, sameFunc);
} catch (ContinuationPending e) {
// TODO Auto-generated catch block
e.printStackTrace();
Expand Down