1.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java Wed Jun 26 18:18:21 2013 +0200
1.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/FnUtils.java Sat Jun 29 22:44:59 2013 +0200
1.3 @@ -29,6 +29,7 @@
1.4 import java.util.Collections;
1.5 import java.util.Enumeration;
1.6 import java.util.List;
1.7 +import java.util.Map;
1.8 import org.apidesign.html.boot.spi.Fn;
1.9 import org.objectweb.asm.Type;
1.10
1.11 @@ -76,9 +77,9 @@
1.12 };
1.13 }
1.14
1.15 - static String callback(String body, ClassLoader loader) {
1.16 + static String callback(String body, ClassLoader loader, String ownName, Map<String,String> ownMethods) {
1.17 try {
1.18 - return callbackImpl(body, loader);
1.19 + return callbackImpl(body, loader, ownName, ownMethods);
1.20 } catch (ClassNotFoundException ex) {
1.21 throw new IllegalStateException("Can't parse " + body, ex);
1.22 } catch (NoSuchMethodException ex) {
1.23 @@ -86,8 +87,9 @@
1.24 }
1.25 }
1.26
1.27 - private static String callbackImpl(String body, ClassLoader loader)
1.28 - throws ClassNotFoundException, NoSuchMethodException {
1.29 + private static String callbackImpl(
1.30 + String body, ClassLoader loader, String ownName, Map<String,String> ownMethods
1.31 + ) throws ClassNotFoundException, NoSuchMethodException {
1.32 StringBuilder sb = new StringBuilder();
1.33 int pos = 0;
1.34 for (;;) {
1.35 @@ -111,21 +113,36 @@
1.36 String method = body.substring(colon4 + 2, sigBeg);
1.37 String params = body.substring(sigBeg, sigEnd + 1);
1.38
1.39 - Class<?> clazz = Class.forName(fqn, false, loader);
1.40 - final Type[] argTps = Type.getArgumentTypes(params);
1.41 - Class<?>[] argCls = new Class<?>[argTps.length];
1.42 - for (int i = 0; i < argCls.length; i++) {
1.43 - argCls[i] = toClass(argTps[i], loader);
1.44 + if (fqn.equals(ownName.replace('/', '.'))) {
1.45 + if (!ownMethods.containsKey(method + params)) {
1.46 + throw new IllegalStateException("Wrong refernece to " + method + params);
1.47 + }
1.48 + sb.append("['").append(method).append("(");
1.49 + final Type[] argTps = Type.getArgumentTypes(params);
1.50 + Class<?>[] argCls = new Class<?>[argTps.length];
1.51 + String sep = "";
1.52 + for (int i = 0; i < argCls.length; i++) {
1.53 + sb.append(sep).append(toClass(argTps[i], loader).getName());
1.54 + sep = ",";
1.55 + }
1.56 + sb.append(")']");
1.57 + } else {
1.58 + Class<?> clazz = Class.forName(fqn, false, loader);
1.59 + final Type[] argTps = Type.getArgumentTypes(params);
1.60 + Class<?>[] argCls = new Class<?>[argTps.length];
1.61 + for (int i = 0; i < argCls.length; i++) {
1.62 + argCls[i] = toClass(argTps[i], loader);
1.63 + }
1.64 + Method m = clazz.getMethod(method, argCls);
1.65 +
1.66 + sb.append("['").append(m.getName()).append("(");
1.67 + String sep = "";
1.68 + for (Class<?> pt : m.getParameterTypes()) {
1.69 + sb.append(sep).append(pt.getName());
1.70 + sep = ",";
1.71 + }
1.72 + sb.append(")']");
1.73 }
1.74 - Method m = clazz.getMethod(method, argCls);
1.75 -
1.76 - sb.append("['").append(m.getName()).append("(");
1.77 - String sep = "";
1.78 - for (Class<?> pt : m.getParameterTypes()) {
1.79 - sb.append(sep).append(pt.getName());
1.80 - sep = ",";
1.81 - }
1.82 - sb.append(")']");
1.83
1.84 pos = sigEnd + 1;
1.85 }
2.1 --- a/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java Wed Jun 26 18:18:21 2013 +0200
2.2 +++ b/boot/src/main/java/org/apidesign/html/boot/impl/JsClassLoader.java Sat Jun 29 22:44:59 2013 +0200
2.3 @@ -27,7 +27,9 @@
2.4 import java.net.URL;
2.5 import java.util.ArrayList;
2.6 import java.util.Enumeration;
2.7 +import java.util.HashMap;
2.8 import java.util.List;
2.9 +import java.util.Map;
2.10 import org.objectweb.asm.AnnotationVisitor;
2.11 import org.objectweb.asm.ClassReader;
2.12 import org.objectweb.asm.ClassVisitor;
2.13 @@ -93,11 +95,11 @@
2.14 is.close();
2.15 is = null;
2.16 ClassReader cr = new ClassReader(arr);
2.17 - FindInClass tst = new FindInClass(null);
2.18 + FindInClass tst = new FindInClass(null, new HashMap<String,String>());
2.19 cr.accept(tst, 0);
2.20 if (tst.found > 0) {
2.21 ClassWriter w = new ClassWriterEx(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
2.22 - FindInClass fic = new FindInClass(w);
2.23 + FindInClass fic = new FindInClass(w, tst.methods);
2.24 cr.accept(fic, 0);
2.25 arr = w.toByteArray();
2.26 }
2.27 @@ -130,9 +132,11 @@
2.28 private final class FindInClass extends ClassVisitor {
2.29 private String name;
2.30 private int found;
2.31 + private final Map<String,String> methods;
2.32
2.33 - public FindInClass(ClassVisitor cv) {
2.34 + public FindInClass(ClassVisitor cv, Map<String,String> methods) {
2.35 super(Opcodes.ASM4, cv);
2.36 + this.methods = methods;
2.37 }
2.38
2.39 @Override
2.40 @@ -152,6 +156,9 @@
2.41
2.42 @Override
2.43 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
2.44 + int end = desc.indexOf(')');
2.45 + methods.put(name + desc.substring(0, end + 1), desc);
2.46 +
2.47 return new FindInMethod(access, name, desc,
2.48 super.visitMethod(access & (~Opcodes.ACC_NATIVE), name, desc, signature, exceptions)
2.49 );
2.50 @@ -402,7 +409,7 @@
2.51 public void visitEnd() {
2.52 if (body != null) {
2.53 generateJSBody(args, javacall ?
2.54 - FnUtils.callback(body, JsClassLoader.this) :
2.55 + FnUtils.callback(body, JsClassLoader.this, FindInClass.this.name, FindInClass.this.methods) :
2.56 body
2.57 );
2.58 }
3.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java Wed Jun 26 18:18:21 2013 +0200
3.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/JsClassLoaderBase.java Sat Jun 29 22:44:59 2013 +0200
3.3 @@ -136,4 +136,15 @@
3.4 throw ex.getTargetException();
3.5 }
3.6 }
3.7 +
3.8 + @Test public void callJavaScriptMethodOnOwnClass() throws Throwable {
3.9 + try {
3.10 + Object thiz = methodClass.newInstance();
3.11 + Method st = methodClass.getMethod("returnYourSelf", methodClass);
3.12 + assertEquals(st.invoke(null, thiz), thiz, "Returns this");
3.13 + } catch (InvocationTargetException ex) {
3.14 + throw ex.getTargetException();
3.15 + }
3.16 +
3.17 + }
3.18 }
3.19 \ No newline at end of file
4.1 --- a/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java Wed Jun 26 18:18:21 2013 +0200
4.2 +++ b/boot/src/test/java/org/apidesign/html/boot/impl/JsMethods.java Sat Jun 29 22:44:59 2013 +0200
4.3 @@ -72,4 +72,7 @@
4.4
4.5 @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
4.6 public static native int useExternalMul(int x, int y);
4.7 +
4.8 + @JavaScriptBody(args = { "m" }, javacall = true, body = "return m.@org.apidesign.html.boot.impl.JsMethods::getThis()()")
4.9 + public static native JsMethods returnYourSelf(JsMethods m);
4.10 }