# HG changeset patch # User Jaroslav Tulach # Date 1349806318 25200 # Node ID 19497b4312bbe2e867d2986da82b58e7e20e1eb7 # Parent a236a9f137ac2878b6b703a7ae46717e14580b15 Concatenation of string and integer works diff -r a236a9f137ac -r 19497b4312bb core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java Tue Oct 09 11:11:58 2012 -0700 @@ -0,0 +1,38 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.apidesign.bck2brwsr.core; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** Put this method on a method in case it should have a special + * body in the JavaScript. + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.CLASS) +@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR }) +public @interface JavaScriptBody { + /** Names of parameters for the method. + * + * + * + * @return array of the names of parameters for the method + * in JavaScript + */ + public String[] args(); + + /** The actual body of the method in JavaScript. This string will be + * put into generated header (ends with '{') and footer (ends with '}'). + */ + public String body(); +} diff -r a236a9f137ac -r 19497b4312bb emul/src/main/java/java/lang/AbstractStringBuilder.java --- a/emul/src/main/java/java/lang/AbstractStringBuilder.java Mon Oct 08 17:10:27 2012 -0700 +++ b/emul/src/main/java/java/lang/AbstractStringBuilder.java Tue Oct 09 11:11:58 2012 -0700 @@ -25,6 +25,8 @@ package java.lang; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * A mutable sequence of characters. *

@@ -598,6 +600,10 @@ * @param i an {@code int}. * @return a reference to this object. */ + @JavaScriptBody( + args={ "self", "i" }, + body="return java_lang_AbstractStringBuilder_appendLjava_lang_AbstractStringBuilderLjava_lang_String(self,i.toString());" + ) public AbstractStringBuilder append(int i) { if (i == Integer.MIN_VALUE) { append("-2147483648"); diff -r a236a9f137ac -r 19497b4312bb vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Oct 08 17:10:27 2012 -0700 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 09 11:11:58 2012 -0700 @@ -23,8 +23,10 @@ import java.util.Collection; import java.util.List; import org.apidesign.bck2brwsr.core.ExtraJavaScript; +import org.apidesign.bck2brwsr.core.JavaScriptBody; import org.netbeans.modules.classfile.Annotation; import org.netbeans.modules.classfile.AnnotationComponent; +import org.netbeans.modules.classfile.ArrayElementValue; import static org.netbeans.modules.classfile.ByteCodes.*; import org.netbeans.modules.classfile.CPClassInfo; import org.netbeans.modules.classfile.CPEntry; @@ -135,6 +137,9 @@ } } private void generateStaticMethod(Method m, List toInitilize) throws IOException { + if (javaScriptBody(m, true)) { + return; + } final String mn = findMethodName(m); out.append("\nfunction ").append( jc.getName().getInternalName().replace('/', '_') @@ -180,6 +185,9 @@ } private void generateInstanceMethod(Method m) throws IOException { + if (javaScriptBody(m, false)) { + return; + } out.append("\nfunction ").append( jc.getName().getInternalName().replace('/', '_') ).append('_').append(findMethodName(m)); @@ -900,4 +908,45 @@ private String findDescriptor(String d) { return d.replace('[', 'A'); } + + private boolean javaScriptBody(Method m, boolean isStatic) throws IOException { + final ClassName extraAnn = ClassName.getClassName(JavaScriptBody.class.getName().replace('.', '/')); + Annotation a = m.getAnnotation(extraAnn); + if (a != null) { + final ElementValue annVal = a.getComponent("body").getValue(); + String body = ((PrimitiveElementValue) annVal).getValue().getValue().toString(); + + final ArrayElementValue arrVal = (ArrayElementValue) a.getComponent("args").getValue(); + final int len = arrVal.getValues().length; + String[] names = new String[len]; + for (int i = 0; i < len; i++) { + names[i] = ((PrimitiveElementValue) arrVal.getValues()[i]).getValue().getValue().toString(); + } + out.append("\nfunction ").append( + jc.getName().getInternalName().replace('/', '_')).append('_').append(findMethodName(m)); + out.append("("); + String space; + int index; + if (!isStatic) { + out.append(names[0]); + space = ","; + index = 1; + } else { + space = ""; + index = 0; + } + List args = m.getParameters(); + for (int i = 0; i < args.size(); i++) { + out.append(space); + out.append(names[index]); + final String desc = findDescriptor(args.get(i).getDescriptor()); + index++; + } + out.append(") {").append("\n"); + out.append(body); + out.append("\n}\n"); + return true; + } + return false; + } } diff -r a236a9f137ac -r 19497b4312bb vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Mon Oct 08 17:10:27 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Tue Oct 09 11:11:58 2012 -0700 @@ -17,6 +17,8 @@ */ package org.apidesign.vm4brwsr; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + /** * * @author Jaroslav Tulach @@ -91,4 +93,11 @@ cnt++; return cnt; } + + @JavaScriptBody( + args="i", body="return i.toString();" + ) + public static String i2s(int i) { + throw new IllegalStateException(); + } } diff -r a236a9f137ac -r 19497b4312bb vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Mon Oct 08 17:10:27 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Tue Oct 09 11:11:58 2012 -0700 @@ -184,6 +184,15 @@ ); } + @Test public void javaScriptBody() throws Exception { + assertExec( + "JavaScript string", + "org_apidesign_vm4brwsr_StaticMethod_i2sLjava_lang_StringI", + "333", + 333 + ); + } + private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { StringBuilder sb = new StringBuilder(); Invocable i = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod"); diff -r a236a9f137ac -r 19497b4312bb vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Mon Oct 08 17:10:27 2012 -0700 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Tue Oct 09 11:11:58 2012 -0700 @@ -30,9 +30,12 @@ assertExec( "Five executions should generate 5Hello World!", "org_apidesign_vm4brwsr_StringSample_toStringTestLjava_lang_StringI", - "5Hello World!", 5 + "Hello World!5", 5 ); } + @Test public void toStringConcatenationJava() throws Exception { + assertEquals("Hello World!5", StringSample.toStringTest(5)); + } private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception { StringBuilder sb = new StringBuilder();