# HG changeset patch # User Jaroslav Tulach # Date 1373574961 -7200 # Node ID c3e68a67d46d6c0e2ef9212c6e4f4b17d709a0c1 # Parent c1097ab15f4864006ea741bc8bc65c89996098e5 Recognizes callback to static Java methods diff -r c1097ab15f48 -r c3e68a67d46d rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Jul 11 20:33:19 2013 +0200 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Jul 11 22:36:01 2013 +0200 @@ -1664,7 +1664,8 @@ int next = body.indexOf(".@", pos); if (next == -1) { sb.append(body.substring(pos)); - return sb; + body = sb.toString(); + break; } int ident = next; while (ident > 0) { @@ -1690,23 +1691,63 @@ int paramBeg = body.indexOf('(', sigEnd + 1); sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM()."); - sb.append(mangle(fqn, method, params)); + sb.append(mangle(fqn, method, params, false)); sb.append("(").append(refId); if (body.charAt(paramBeg + 1) != ')') { sb.append(","); } pos = paramBeg + 1; } + sb = null; + pos = 0; + for (;;) { + int next = body.indexOf("@", pos); + if (next == -1) { + if (sb == null) { + return body; + } + sb.append(body.substring(pos)); + return sb; + } + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append(body.substring(pos, next)); + + int sigBeg = body.indexOf('(', next); + int sigEnd = body.indexOf(')', sigBeg); + int colon4 = body.indexOf("::", next); + if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) { + throw new IllegalStateException("Malformed body " + body); + } + String fqn = body.substring(next + 1, colon4); + String method = body.substring(colon4 + 2, sigBeg); + String params = body.substring(sigBeg, sigEnd + 1); + + int paramBeg = body.indexOf('(', sigEnd + 1); + + sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM()."); + sb.append(mangle(fqn, method, params, true)); + sb.append("("); + pos = paramBeg + 1; + } } - private static String mangle(String fqn, String method, String params) { + private static String mangle(String fqn, String method, String params, boolean isStatic) { if (params.startsWith("(")) { params = params.substring(1); } if (params.endsWith(")")) { params = params.substring(0, params.length() - 1); } - return replace(fqn) + "__" + replace(method) + "____Ljava_lang_Object_2L" + - replace(fqn) + "_2" + replace(params); + StringBuilder sb = new StringBuilder(); + final String rfqn = replace(fqn); + sb.append(rfqn).append("__").append(method).append("____Ljava_lang_Object_2"); + if (!isStatic) { + sb.append('L').append(rfqn).append("_2"); + } + sb.append(params); + return sb.toString(); } private static String replace(String orig) { diff -r c1097ab15f48 -r c3e68a67d46d rt/vm/src/test/java/org/apidesign/vm4brwsr/HtmlAnnotations.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/HtmlAnnotations.java Thu Jul 11 20:33:19 2013 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/HtmlAnnotations.java Thu Jul 11 22:36:01 2013 +0200 @@ -47,5 +47,7 @@ @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()()") private static native void callback(Runnable r); - + + @JavaScriptBody(args = { }, javacall = true, body = "return @org.apidesign.vm4brwsr.HtmlAnnotations::callback()();") + private static native int staticCallback(); } diff -r c1097ab15f48 -r c3e68a67d46d rt/vm/src/test/java/org/apidesign/vm4brwsr/HtmlAnnotationsTest.java --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/HtmlAnnotationsTest.java Thu Jul 11 20:33:19 2013 +0200 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/HtmlAnnotationsTest.java Thu Jul 11 22:36:01 2013 +0200 @@ -47,6 +47,13 @@ Double.valueOf(1) ); } + + @Test public void callStaticMethodFromJS() throws Exception { + assertExec("runnable called", HtmlAnnotations.class, + "staticCallback__I", + Double.valueOf(1) + ); + } private static TestVM code;