1.1 --- a/emul/src/main/java/java/lang/reflect/Method.java Mon Jan 07 18:40:20 2013 +0100
1.2 +++ b/emul/src/main/java/java/lang/reflect/Method.java Tue Jan 08 16:01:25 2013 +0100
1.3 @@ -26,6 +26,7 @@
1.4 package java.lang.reflect;
1.5
1.6 import java.lang.annotation.Annotation;
1.7 +import java.util.Enumeration;
1.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.9 import org.apidesign.bck2brwsr.emul.AnnotationImpl;
1.10 import org.apidesign.bck2brwsr.emul.MethodImpl;
1.11 @@ -140,24 +141,7 @@
1.12 * @return the return type for the method this object represents
1.13 */
1.14 public Class<?> getReturnType() {
1.15 - switch (sig.charAt(0)) {
1.16 - case 'I': return Integer.TYPE;
1.17 - case 'J': return Long.TYPE;
1.18 - case 'D': return Double.TYPE;
1.19 - case 'F': return Float.TYPE;
1.20 - case 'B': return Byte.TYPE;
1.21 - case 'Z': return Boolean.TYPE;
1.22 - case 'S': return Short.TYPE;
1.23 - case 'V': return Void.TYPE;
1.24 - case 'L': try {
1.25 - int up = sig.indexOf("_2");
1.26 - String type = sig.substring(1, up);
1.27 - return Class.forName(type);
1.28 - } catch (ClassNotFoundException ex) {
1.29 - // should not happen
1.30 - }
1.31 - }
1.32 - throw new UnsupportedOperationException(sig);
1.33 + return MethodImpl.signatureParser(sig).nextElement();
1.34 }
1.35
1.36 /**
1.37 @@ -199,8 +183,13 @@
1.38 * represents
1.39 */
1.40 public Class<?>[] getParameterTypes() {
1.41 - throw new UnsupportedOperationException();
1.42 - //return (Class<?>[]) parameterTypes.clone();
1.43 + Class[] arr = new Class[MethodImpl.signatureElements(sig) - 1];
1.44 + Enumeration<Class> en = MethodImpl.signatureParser(sig);
1.45 + en.nextElement(); // return type
1.46 + for (int i = 0; i < arr.length; i++) {
1.47 + arr[i] = en.nextElement();
1.48 + }
1.49 + return arr;
1.50 }
1.51
1.52 /**
1.53 @@ -512,21 +501,41 @@
1.54 throws IllegalAccessException, IllegalArgumentException,
1.55 InvocationTargetException
1.56 {
1.57 - if ((getModifiers() & Modifier.STATIC) == 0 && obj == null) {
1.58 + final boolean isStatic = (getModifiers() & Modifier.STATIC) == 0;
1.59 + if (isStatic && obj == null) {
1.60 throw new NullPointerException();
1.61 }
1.62 - Object res = invoke0(this, obj, args);
1.63 + Class[] types = getParameterTypes();
1.64 + if (types.length != args.length) {
1.65 + throw new IllegalArgumentException("Types len " + types.length + " args: " + args.length);
1.66 + } else {
1.67 + args = args.clone();
1.68 + for (int i = 0; i < types.length; i++) {
1.69 + Class c = types[i];
1.70 + if (c.isPrimitive()) {
1.71 + args[i] = toPrimitive(c, args[i]);
1.72 + }
1.73 + }
1.74 + }
1.75 + Object res = invoke0(isStatic, this, obj, args);
1.76 if (getReturnType().isPrimitive()) {
1.77 res = fromPrimitive(getReturnType(), res);
1.78 }
1.79 return res;
1.80 }
1.81
1.82 - @JavaScriptBody(args = { "method", "self", "args" }, body =
1.83 - "if (args.length > 0) throw 'unsupported now';"
1.84 - + "return method.fld_data(self);"
1.85 + @JavaScriptBody(args = { "st", "method", "self", "args" }, body =
1.86 + "var p;\n"
1.87 + + "if (st) {\n"
1.88 + + " p = new Array(1);\n"
1.89 + + " p[0] = self;\n"
1.90 + + " p = p.concat(args);\n"
1.91 + + "} else {\n"
1.92 + + " p = args;\n"
1.93 + + "}\n"
1.94 + + "return method.fld_data.apply(self, p);\n"
1.95 )
1.96 - private static native Object invoke0(Method m, Object self, Object[] args);
1.97 + private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
1.98
1.99 private static Object fromPrimitive(Class<?> type, Object o) {
1.100 if (type == Integer.TYPE) {
1.101 @@ -560,6 +569,39 @@
1.102 body = "return cls.cnstr(false)[m](o);"
1.103 )
1.104 private static native Integer fromRaw(Class<?> cls, String m, Object o);
1.105 +
1.106 + private static Object toPrimitive(Class<?> type, Object o) {
1.107 + if (type == Integer.TYPE) {
1.108 + return toRaw("intValue__I", o);
1.109 + }
1.110 + if (type == Long.TYPE) {
1.111 + return toRaw("longValue__J", o);
1.112 + }
1.113 + if (type == Double.TYPE) {
1.114 + return toRaw("doubleValue__D", o);
1.115 + }
1.116 + if (type == Float.TYPE) {
1.117 + return toRaw("floatValue__F", o);
1.118 + }
1.119 + if (type == Byte.TYPE) {
1.120 + return toRaw("byteValue__B", o);
1.121 + }
1.122 + if (type == Boolean.TYPE) {
1.123 + return toRaw("booleanValue__Z", o);
1.124 + }
1.125 + if (type == Short.TYPE) {
1.126 + return toRaw("shortValue__S", o);
1.127 + }
1.128 + if (type.getName().equals("void")) {
1.129 + return o;
1.130 + }
1.131 + throw new IllegalStateException("Can't convert " + o);
1.132 + }
1.133 +
1.134 + @JavaScriptBody(args = { "m", "o" },
1.135 + body = "return o[m](o);"
1.136 + )
1.137 + private static native Object toRaw(String m, Object o);
1.138
1.139 /**
1.140 * Returns {@code true} if this method is a bridge
2.1 --- a/emul/src/main/java/org/apidesign/bck2brwsr/emul/MethodImpl.java Mon Jan 07 18:40:20 2013 +0100
2.2 +++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/MethodImpl.java Tue Jan 08 16:01:25 2013 +0100
2.3 @@ -25,6 +25,7 @@
2.4 package org.apidesign.bck2brwsr.emul;
2.5
2.6 import java.lang.reflect.Method;
2.7 +import java.util.Enumeration;
2.8 import org.apidesign.bck2brwsr.core.JavaScriptBody;
2.9
2.10 /** Utilities to work on methods.
2.11 @@ -96,5 +97,56 @@
2.12 }
2.13 return arr;
2.14 }
2.15 +
2.16 + public static int signatureElements(String sig) {
2.17 + Enumeration<Class> en = signatureParser(sig);
2.18 + int cnt = 0;
2.19 + while (en.hasMoreElements()) {
2.20 + en.nextElement();
2.21 + cnt++;
2.22 + }
2.23 + return cnt;
2.24 + }
2.25
2.26 + public static Enumeration<Class> signatureParser(final String sig) {
2.27 + class E implements Enumeration<Class> {
2.28 + int pos;
2.29 +
2.30 + public boolean hasMoreElements() {
2.31 + return pos < sig.length();
2.32 + }
2.33 +
2.34 + public Class nextElement() {
2.35 + switch (sig.charAt(pos++)) {
2.36 + case 'I':
2.37 + return Integer.TYPE;
2.38 + case 'J':
2.39 + return Long.TYPE;
2.40 + case 'D':
2.41 + return Double.TYPE;
2.42 + case 'F':
2.43 + return Float.TYPE;
2.44 + case 'B':
2.45 + return Byte.TYPE;
2.46 + case 'Z':
2.47 + return Boolean.TYPE;
2.48 + case 'S':
2.49 + return Short.TYPE;
2.50 + case 'V':
2.51 + return Void.TYPE;
2.52 + case 'L':
2.53 + try {
2.54 + int up = sig.indexOf("_2");
2.55 + String type = sig.substring(1, up);
2.56 + pos = up + 2;
2.57 + return Class.forName(type);
2.58 + } catch (ClassNotFoundException ex) {
2.59 + // should not happen
2.60 + }
2.61 + }
2.62 + throw new UnsupportedOperationException(sig + " at " + pos);
2.63 + }
2.64 + }
2.65 + return new E();
2.66 + }
2.67 }
3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Mon Jan 07 18:40:20 2013 +0100
3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Tue Jan 08 16:01:25 2013 +0100
3.3 @@ -102,6 +102,11 @@
3.4 "java.io.IOException", true, "name"
3.5 );
3.6 }
3.7 + @Test public void jsInvokeParamMethod() throws Exception {
3.8 + assertExec("sums two numbers via reflection", Classes.class,
3.9 + "reflectiveSum__III", Double.valueOf(5), 2, 3
3.10 + );
3.11 + }
3.12 @Test public void javaFindMethod() throws Exception {
3.13 assertEquals(Classes.reflectiveMethodCall(false, "name"), "java.io.IOException", "Calls the name() method via reflection");
3.14 }
4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Mon Jan 07 18:40:20 2013 +0100
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Tue Jan 08 16:01:25 2013 +0100
4.3 @@ -146,4 +146,9 @@
4.4 }
4.5 return find.invoke(null);
4.6 }
4.7 +
4.8 + public static int reflectiveSum(int a, int b) throws Exception {
4.9 + Method m = StaticMethod.class.getMethod("sum", int.class, int.class);
4.10 + return (int) m.invoke(null, a, b);
4.11 + }
4.12 }
5.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Mon Jan 07 18:40:20 2013 +0100
5.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java Tue Jan 08 16:01:25 2013 +0100
5.3 @@ -77,6 +77,16 @@
5.4 }
5.5 }
5.6
5.7 + @Compare public String paramTypes() throws Exception {
5.8 + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
5.9 + final Class[] pt = plus.getParameterTypes();
5.10 + return pt[0].getName();
5.11 + }
5.12 + @Compare public int methodWithArgs() throws Exception {
5.13 + Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
5.14 + return (Integer)plus.invoke(null, 2, 3);
5.15 + }
5.16 +
5.17 @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;")
5.18 private static String[] sort(String[] arr, int len) {
5.19 List<String> list = Arrays.asList(arr).subList(0, len);
6.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Mon Jan 07 18:40:20 2013 +0100
6.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java Tue Jan 08 16:01:25 2013 +0100
6.3 @@ -24,4 +24,8 @@
6.4
6.5 public void instanceMethod() {
6.6 }
6.7 +
6.8 + public static int plus(int a, int b) {
6.9 + return a + b;
6.10 + }
6.11 }