1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Nov 12 21:05:23 2012 +0100
1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Nov 16 07:36:32 2012 +0100
1.3 @@ -19,9 +19,6 @@
1.4
1.5 import java.io.IOException;
1.6 import java.io.InputStream;
1.7 -import java.util.ArrayList;
1.8 -import java.util.Collection;
1.9 -import java.util.List;
1.10 import org.apidesign.bck2brwsr.core.ExtraJavaScript;
1.11 import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.12 import sun.tools.javap.AnnotationParser;
1.13 @@ -34,63 +31,57 @@
1.14 *
1.15 * @author Jaroslav Tulach <jtulach@netbeans.org>
1.16 */
1.17 -public final class ByteCodeToJavaScript {
1.18 - private final ClassData jc;
1.19 +public abstract class ByteCodeToJavaScript {
1.20 + private ClassData jc;
1.21 private final Appendable out;
1.22 - private final Collection<? super String> references;
1.23
1.24 - private ByteCodeToJavaScript(
1.25 - ClassData jc, Appendable out, Collection<? super String> references
1.26 - ) {
1.27 - this.jc = jc;
1.28 + protected ByteCodeToJavaScript(Appendable out) {
1.29 this.out = out;
1.30 - this.references = references;
1.31 }
1.32 +
1.33 + /* Collects additional required resources.
1.34 + *
1.35 + * @param internalClassName classes that were referenced and should be loaded in order the
1.36 + * generated JavaScript code works properly. The names are in internal
1.37 + * JVM form so String is <code>java/lang/String</code>.
1.38 + */
1.39 + protected abstract boolean requireReference(String internalClassName);
1.40 +
1.41 + /*
1.42 + * @param resourcePath name of resources to read
1.43 + */
1.44 + protected abstract void requireScript(String resourcePath);
1.45
1.46 /**
1.47 * Converts a given class file to a JavaScript version.
1.48 *
1.49 * @param classFile input stream with code of the .class file
1.50 - * @param out a {@link StringBuilder} or similar to generate the output to
1.51 - * @param references a write only collection where the system adds list of
1.52 - * other classes that were referenced and should be loaded in order the
1.53 - * generated JavaScript code works properly. The names are in internal
1.54 - * JVM form so String is <code>java/lang/String</code>. Can be <code>null</code>
1.55 - * if one is not interested in knowing references
1.56 - * @param scripts write only collection with names of resources to read
1.57 * @return the initialization code for this class, if any. Otherwise <code>null</code>
1.58 *
1.59 * @throws IOException if something goes wrong during read or write or translating
1.60 */
1.61
1.62 - public static String compile(
1.63 - InputStream classFile, Appendable out,
1.64 - Collection<? super String> references,
1.65 - Collection<? super String> scripts
1.66 - ) throws IOException {
1.67 - ClassData jc = new ClassData(classFile);
1.68 + public String compile(InputStream classFile) throws IOException {
1.69 + this.jc = new ClassData(classFile);
1.70 byte[] arrData = jc.findAnnotationData(true);
1.71 String[] arr = findAnnotation(arrData, jc, ExtraJavaScript.class.getName(), "resource", "processByteCode");
1.72 if (arr != null) {
1.73 - scripts.add(arr[0]);
1.74 + requireScript(arr[0]);
1.75 if ("0".equals(arr[1])) {
1.76 return null;
1.77 }
1.78 }
1.79 - ByteCodeToJavaScript compiler = new ByteCodeToJavaScript(
1.80 - jc, out, references
1.81 - );
1.82 - List<String> toInitilize = new ArrayList<String>();
1.83 + StringArray toInitilize = new StringArray();
1.84 for (MethodData m : jc.getMethods()) {
1.85 if (m.isStatic()) {
1.86 - compiler.generateStaticMethod(m, toInitilize);
1.87 + generateStaticMethod(m, toInitilize);
1.88 } else {
1.89 - compiler.generateInstanceMethod(m);
1.90 + generateInstanceMethod(m);
1.91 }
1.92 }
1.93 for (FieldData v : jc.getFields()) {
1.94 if (v.isStatic()) {
1.95 - compiler.generateStaticField(v);
1.96 + generateStaticField(v);
1.97 }
1.98 }
1.99
1.100 @@ -119,7 +110,7 @@
1.101 }
1.102 for (MethodData m : jc.getMethods()) {
1.103 if (!m.getName().contains("<init>") && !m.getName().contains("<cinit>")) {
1.104 - compiler.generateMethodReference("\n p.", m);
1.105 + generateMethodReference("\n p.", m);
1.106 }
1.107 }
1.108 out.append("\n p.$instOf_").append(className).append(" = true;");
1.109 @@ -130,12 +121,12 @@
1.110 out.append("\n}");
1.111 out.append("\n").append(className).append("_proto();");
1.112 StringBuilder sb = new StringBuilder();
1.113 - for (String init : toInitilize) {
1.114 + for (String init : toInitilize.toArray()) {
1.115 sb.append("\n").append(init).append("();");
1.116 }
1.117 return sb.toString();
1.118 }
1.119 - private void generateStaticMethod(MethodData m, List<String> toInitilize) throws IOException {
1.120 + private void generateStaticMethod(MethodData m, StringArray toInitilize) throws IOException {
1.121 if (javaScriptBody(m, true)) {
1.122 return;
1.123 }
1.124 @@ -952,10 +943,8 @@
1.125 }
1.126
1.127 private void addReference(String cn) throws IOException {
1.128 - if (references != null) {
1.129 - if (references.add(cn)) {
1.130 - out.append(" /* needs ").append(cn).append(" */");
1.131 - }
1.132 + if (requireReference(cn)) {
1.133 + out.append(" /* needs ").append(cn).append(" */");
1.134 }
1.135 }
1.136