1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java Tue Oct 09 11:11:58 2012 -0700
1.3 @@ -0,0 +1,38 @@
1.4 +/*
1.5 + * To change this template, choose Tools | Templates
1.6 + * and open the template in the editor.
1.7 + */
1.8 +package org.apidesign.bck2brwsr.core;
1.9 +
1.10 +import java.lang.annotation.ElementType;
1.11 +import java.lang.annotation.Retention;
1.12 +import java.lang.annotation.RetentionPolicy;
1.13 +import java.lang.annotation.Target;
1.14 +
1.15 +/** Put this method on a method in case it should have a special
1.16 + * body in the <em>JavaScript</em>.
1.17 + *
1.18 + * @author Jaroslav Tulach <jtulach@netbeans.org>
1.19 + */
1.20 +@Retention(RetentionPolicy.CLASS)
1.21 +@Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
1.22 +public @interface JavaScriptBody {
1.23 + /** Names of parameters for the method.
1.24 + *
1.25 + * <!--
1.26 + * If not specified
1.27 + * it will be <code>arg0, arg1, arg2</code>. In case of
1.28 + * instance methods, the <code>arg0</code> is reference
1.29 + * to <code>this</code>.
1.30 + * -->
1.31 + *
1.32 + * @return array of the names of parameters for the method
1.33 + * in JavaScript
1.34 + */
1.35 + public String[] args();
1.36 +
1.37 + /** The actual body of the method in JavaScript. This string will be
1.38 + * put into generated header (ends with '{') and footer (ends with '}').
1.39 + */
1.40 + public String body();
1.41 +}
2.1 --- a/emul/src/main/java/java/lang/AbstractStringBuilder.java Mon Oct 08 17:10:27 2012 -0700
2.2 +++ b/emul/src/main/java/java/lang/AbstractStringBuilder.java Tue Oct 09 11:11:58 2012 -0700
2.3 @@ -25,6 +25,8 @@
2.4
2.5 package java.lang;
2.6
2.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
2.8 +
2.9 /**
2.10 * A mutable sequence of characters.
2.11 * <p>
2.12 @@ -598,6 +600,10 @@
2.13 * @param i an {@code int}.
2.14 * @return a reference to this object.
2.15 */
2.16 + @JavaScriptBody(
2.17 + args={ "self", "i" },
2.18 + body="return java_lang_AbstractStringBuilder_appendLjava_lang_AbstractStringBuilderLjava_lang_String(self,i.toString());"
2.19 + )
2.20 public AbstractStringBuilder append(int i) {
2.21 if (i == Integer.MIN_VALUE) {
2.22 append("-2147483648");
3.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Oct 08 17:10:27 2012 -0700
3.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 09 11:11:58 2012 -0700
3.3 @@ -23,8 +23,10 @@
3.4 import java.util.Collection;
3.5 import java.util.List;
3.6 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
3.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
3.8 import org.netbeans.modules.classfile.Annotation;
3.9 import org.netbeans.modules.classfile.AnnotationComponent;
3.10 +import org.netbeans.modules.classfile.ArrayElementValue;
3.11 import static org.netbeans.modules.classfile.ByteCodes.*;
3.12 import org.netbeans.modules.classfile.CPClassInfo;
3.13 import org.netbeans.modules.classfile.CPEntry;
3.14 @@ -135,6 +137,9 @@
3.15 }
3.16 }
3.17 private void generateStaticMethod(Method m, List<String> toInitilize) throws IOException {
3.18 + if (javaScriptBody(m, true)) {
3.19 + return;
3.20 + }
3.21 final String mn = findMethodName(m);
3.22 out.append("\nfunction ").append(
3.23 jc.getName().getInternalName().replace('/', '_')
3.24 @@ -180,6 +185,9 @@
3.25 }
3.26
3.27 private void generateInstanceMethod(Method m) throws IOException {
3.28 + if (javaScriptBody(m, false)) {
3.29 + return;
3.30 + }
3.31 out.append("\nfunction ").append(
3.32 jc.getName().getInternalName().replace('/', '_')
3.33 ).append('_').append(findMethodName(m));
3.34 @@ -900,4 +908,45 @@
3.35 private String findDescriptor(String d) {
3.36 return d.replace('[', 'A');
3.37 }
3.38 +
3.39 + private boolean javaScriptBody(Method m, boolean isStatic) throws IOException {
3.40 + final ClassName extraAnn = ClassName.getClassName(JavaScriptBody.class.getName().replace('.', '/'));
3.41 + Annotation a = m.getAnnotation(extraAnn);
3.42 + if (a != null) {
3.43 + final ElementValue annVal = a.getComponent("body").getValue();
3.44 + String body = ((PrimitiveElementValue) annVal).getValue().getValue().toString();
3.45 +
3.46 + final ArrayElementValue arrVal = (ArrayElementValue) a.getComponent("args").getValue();
3.47 + final int len = arrVal.getValues().length;
3.48 + String[] names = new String[len];
3.49 + for (int i = 0; i < len; i++) {
3.50 + names[i] = ((PrimitiveElementValue) arrVal.getValues()[i]).getValue().getValue().toString();
3.51 + }
3.52 + out.append("\nfunction ").append(
3.53 + jc.getName().getInternalName().replace('/', '_')).append('_').append(findMethodName(m));
3.54 + out.append("(");
3.55 + String space;
3.56 + int index;
3.57 + if (!isStatic) {
3.58 + out.append(names[0]);
3.59 + space = ",";
3.60 + index = 1;
3.61 + } else {
3.62 + space = "";
3.63 + index = 0;
3.64 + }
3.65 + List<Parameter> args = m.getParameters();
3.66 + for (int i = 0; i < args.size(); i++) {
3.67 + out.append(space);
3.68 + out.append(names[index]);
3.69 + final String desc = findDescriptor(args.get(i).getDescriptor());
3.70 + index++;
3.71 + }
3.72 + out.append(") {").append("\n");
3.73 + out.append(body);
3.74 + out.append("\n}\n");
3.75 + return true;
3.76 + }
3.77 + return false;
3.78 + }
3.79 }
4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Mon Oct 08 17:10:27 2012 -0700
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Tue Oct 09 11:11:58 2012 -0700
4.3 @@ -17,6 +17,8 @@
4.4 */
4.5 package org.apidesign.vm4brwsr;
4.6
4.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
4.8 +
4.9 /**
4.10 *
4.11 * @author Jaroslav Tulach <jtulach@netbeans.org>
4.12 @@ -91,4 +93,11 @@
4.13 cnt++;
4.14 return cnt;
4.15 }
4.16 +
4.17 + @JavaScriptBody(
4.18 + args="i", body="return i.toString();"
4.19 + )
4.20 + public static String i2s(int i) {
4.21 + throw new IllegalStateException();
4.22 + }
4.23 }
5.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Mon Oct 08 17:10:27 2012 -0700
5.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Tue Oct 09 11:11:58 2012 -0700
5.3 @@ -184,6 +184,15 @@
5.4 );
5.5 }
5.6
5.7 + @Test public void javaScriptBody() throws Exception {
5.8 + assertExec(
5.9 + "JavaScript string",
5.10 + "org_apidesign_vm4brwsr_StaticMethod_i2sLjava_lang_StringI",
5.11 + "333",
5.12 + 333
5.13 + );
5.14 + }
5.15 +
5.16 private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
5.17 StringBuilder sb = new StringBuilder();
5.18 Invocable i = compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
6.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Mon Oct 08 17:10:27 2012 -0700
6.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java Tue Oct 09 11:11:58 2012 -0700
6.3 @@ -30,9 +30,12 @@
6.4 assertExec(
6.5 "Five executions should generate 5Hello World!",
6.6 "org_apidesign_vm4brwsr_StringSample_toStringTestLjava_lang_StringI",
6.7 - "5Hello World!", 5
6.8 + "Hello World!5", 5
6.9 );
6.10 }
6.11 + @Test public void toStringConcatenationJava() throws Exception {
6.12 + assertEquals("Hello World!5", StringSample.toStringTest(5));
6.13 + }
6.14
6.15 private static void assertExec(String msg, String methodName, Object expRes, Object... args) throws Exception {
6.16 StringBuilder sb = new StringBuilder();