1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 09 18:26:23 2012 -0700
1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Oct 09 18:47:42 2012 -0700
1.3 @@ -70,11 +70,12 @@
1.4 * JVM form so String is <code>java/lang/String</code>. Can be <code>null</code>
1.5 * if one is not interested in knowing references
1.6 * @param scripts write only collection with names of resources to read
1.7 + * @return the initialization code for this class, if any. Otherwise <code>null</code>
1.8 *
1.9 * @throws IOException if something goes wrong during read or write or translating
1.10 */
1.11
1.12 - public static void compile(
1.13 + public static String compile(
1.14 InputStream classFile, Appendable out,
1.15 Collection<? super String> references,
1.16 Collection<? super String> scripts
1.17 @@ -88,7 +89,7 @@
1.18 scripts.add(res);
1.19 final AnnotationComponent process = a.getComponent("processByteCode");
1.20 if (process != null && "const=0".equals(process.getValue().toString())) {
1.21 - return;
1.22 + return null;
1.23 }
1.24 }
1.25
1.26 @@ -132,9 +133,12 @@
1.27 for (ClassName superInterface : jc.getInterfaces()) {
1.28 out.append("\n" + className + ".prototype.$instOf_").append(superInterface.getInternalName().replace('/', '_')).append(" = true;");
1.29 }
1.30 +
1.31 + StringBuilder sb = new StringBuilder();
1.32 for (String init : toInitilize) {
1.33 - out.append("\n").append(init).append("();");
1.34 + sb.append("\n").append(init).append("();");
1.35 }
1.36 + return sb.toString();
1.37 }
1.38 private void generateStaticMethod(Method m, List<String> toInitilize) throws IOException {
1.39 if (javaScriptBody(m, true)) {
2.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Tue Oct 09 18:26:23 2012 -0700
2.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Tue Oct 09 18:47:42 2012 -0700
2.3 @@ -7,11 +7,13 @@
2.4 import java.io.Writer;
2.5 import java.net.URL;
2.6 import java.util.Arrays;
2.7 +import java.util.Collections;
2.8 import java.util.Enumeration;
2.9 -import java.util.HashSet;
2.10 +import java.util.HashMap;
2.11 +import java.util.Iterator;
2.12 import java.util.LinkedList;
2.13 import java.util.List;
2.14 -import java.util.Set;
2.15 +import java.util.Map;
2.16
2.17 /** Generator of JavaScript from bytecode of classes on classpath of the VM.
2.18 *
2.19 @@ -36,64 +38,85 @@
2.20 compile(out, Arrays.asList(names));
2.21 }
2.22 static void compile(Appendable out, List<String> names) throws IOException {
2.23 - Set<String> processed = new HashSet<String>();
2.24 - LinkedList<String> toProcess = new LinkedList<String>(names);
2.25 - for (;;) {
2.26 - toProcess.removeAll(processed);
2.27 - if (toProcess.isEmpty()) {
2.28 - break;
2.29 - }
2.30 - String name = toProcess.getFirst();
2.31 - processed.add(name);
2.32 - if (name.startsWith("java/")
2.33 - && !name.equals("java/lang/Object")
2.34 - && !name.equals("java/lang/Class")
2.35 - && !name.equals("java/lang/Number")
2.36 - && !name.equals("java/lang/Integer")
2.37 - && !name.equals("java/lang/Throwable")
2.38 - && !name.equals("java/lang/Exception")
2.39 - && !name.equals("java/lang/RuntimeException")
2.40 - && !name.equals("java/lang/UnsupportedOperationException")
2.41 - && !name.equals("java/lang/String")
2.42 - && !name.equals("java/lang/String$CaseInsensitiveComparator")
2.43 - && !name.equals("java/lang/StringBuilder")
2.44 - && !name.equals("java/lang/AbstractStringBuilder")
2.45 - ) {
2.46 - continue;
2.47 - }
2.48 - InputStream is = loadClass(name);
2.49 - if (is == null) {
2.50 - throw new IOException("Can't find class " + name);
2.51 - }
2.52 - LinkedList<String> scripts = new LinkedList<String>();
2.53 - try {
2.54 - ByteCodeToJavaScript.compile(is, out, toProcess, scripts);
2.55 - } catch (RuntimeException ex) {
2.56 - if (out instanceof CharSequence) {
2.57 - CharSequence seq = (CharSequence)out;
2.58 - int lastBlock = seq.length();
2.59 - while (lastBlock-- >= 0) {
2.60 - if (seq.charAt(lastBlock) == '{') {
2.61 - break;
2.62 + for (String baseClass : names) {
2.63 + Map<String,String> processed = new HashMap<String, String>();
2.64 + LinkedList<String> toProcess = new LinkedList<String>();
2.65 + toProcess.add(baseClass);
2.66 + for (;;) {
2.67 + String name = null;
2.68 + Iterator<String> it = toProcess.iterator();
2.69 + while (it.hasNext() && name == null) {
2.70 + String n = it.next();
2.71 + if (processed.get(n) != null) {
2.72 + continue;
2.73 + }
2.74 + name = n;
2.75 + }
2.76 + if (name == null) {
2.77 + break;
2.78 + }
2.79 + if (name.startsWith("java/")
2.80 + && !name.equals("java/lang/Object")
2.81 + && !name.equals("java/lang/Class")
2.82 + && !name.equals("java/lang/Number")
2.83 + && !name.equals("java/lang/Integer")
2.84 + && !name.equals("java/lang/Throwable")
2.85 + && !name.equals("java/lang/Exception")
2.86 + && !name.equals("java/lang/RuntimeException")
2.87 + && !name.equals("java/lang/UnsupportedOperationException")
2.88 + && !name.equals("java/lang/String")
2.89 + && !name.equals("java/lang/String$CaseInsensitiveComparator")
2.90 + && !name.equals("java/lang/StringBuilder")
2.91 + && !name.equals("java/lang/AbstractStringBuilder")
2.92 + ) {
2.93 + processed.put(name, "");
2.94 + continue;
2.95 + }
2.96 + InputStream is = loadClass(name);
2.97 + if (is == null) {
2.98 + throw new IOException("Can't find class " + name);
2.99 + }
2.100 + LinkedList<String> scripts = new LinkedList<String>();
2.101 + try {
2.102 + String initCode = ByteCodeToJavaScript.compile(is, out, toProcess, scripts);
2.103 + processed.put(name, initCode == null ? "" : initCode);
2.104 + } catch (RuntimeException ex) {
2.105 + if (out instanceof CharSequence) {
2.106 + CharSequence seq = (CharSequence)out;
2.107 + int lastBlock = seq.length();
2.108 + while (lastBlock-- >= 0) {
2.109 + if (seq.charAt(lastBlock) == '{') {
2.110 + break;
2.111 + }
2.112 }
2.113 + throw new IOException("Error while compiling " + name + "\n"
2.114 + + seq.subSequence(lastBlock + 1, seq.length()), ex
2.115 + );
2.116 + } else {
2.117 + throw new IOException("Error while compiling " + name + "\n"
2.118 + + out, ex
2.119 + );
2.120 }
2.121 - throw new IOException("Error while compiling " + name + "\n"
2.122 - + seq.subSequence(lastBlock + 1, seq.length()), ex
2.123 - );
2.124 - } else {
2.125 - throw new IOException("Error while compiling " + name + "\n"
2.126 - + out, ex
2.127 - );
2.128 + }
2.129 + for (String resource : scripts) {
2.130 + InputStream emul = GenJS.class.getResourceAsStream(resource);
2.131 + if (emul == null) {
2.132 + throw new IOException("Can't find " + resource);
2.133 + }
2.134 + readResource(emul, out);
2.135 }
2.136 }
2.137 - for (String resource : scripts) {
2.138 - InputStream emul = GenJS.class.getResourceAsStream(resource);
2.139 - if (emul == null) {
2.140 - throw new IOException("Can't find " + resource);
2.141 +
2.142 + Collections.reverse(toProcess);
2.143 +
2.144 + for (String clazz : toProcess) {
2.145 + String initCode = processed.remove(clazz);
2.146 + if (initCode != null) {
2.147 + out.append(initCode).append("\n");
2.148 }
2.149 - readResource(emul, out);
2.150 }
2.151 }
2.152 +
2.153 }
2.154 private static void readResource(InputStream emul, Appendable out) throws IOException {
2.155 try {
3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Tue Oct 09 18:26:23 2012 -0700
3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Tue Oct 09 18:47:42 2012 -0700
3.3 @@ -100,4 +100,9 @@
3.4 public static String i2s(int i) {
3.5 throw new IllegalStateException();
3.6 }
3.7 +
3.8 + static {
3.9 + // check order of initializers
3.10 + StaticUse.NON_NULL.equals(new Object());
3.11 + }
3.12 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticUse.java Tue Oct 09 18:47:42 2012 -0700
4.3 @@ -0,0 +1,5 @@
4.4 +package org.apidesign.vm4brwsr;
4.5 +
4.6 +public class StaticUse {
4.7 + public static final Object NON_NULL = new Object();
4.8 +}