diff -r 3ee23267706c -r 8bd4adaf6590 vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
--- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Nov 29 20:19:00 2012 +0100
+++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Dec 03 14:44:49 2012 +0100
@@ -19,7 +19,6 @@
import java.io.IOException;
import java.io.InputStream;
-import org.apidesign.bck2brwsr.core.JavaScriptBody;
import org.apidesign.javap.AnnotationParser;
import org.apidesign.javap.ClassData;
import org.apidesign.javap.FieldData;
@@ -51,6 +50,16 @@
* @param resourcePath name of resources to read
*/
protected abstract void requireScript(String resourcePath);
+
+ /** Allows subclasses to redefine what field a function representing a
+ * class gets assigned. By default it returns the suggested name followed
+ * by " = "
;
+ *
+ * @param className suggested name of the class
+ */
+ protected String assignClass(String className) {
+ return className + " = ";
+ }
/**
* Converts a given class file to a JavaScript version.
@@ -74,71 +83,95 @@
return null;
}
}
+ String[] proto = findAnnotation(arrData, jc,
+ "org.apidesign.bck2brwsr.core.JavaScriptPrototype",
+ "container", "prototype"
+ );
StringArray toInitilize = new StringArray();
- for (MethodData m : jc.getMethods()) {
- if (m.isStatic()) {
- generateStaticMethod(m, toInitilize);
- } else {
- generateInstanceMethod(m);
+ final String className = className(jc);
+ out.append("\n\n").append(assignClass(className));
+ out.append("function CLS() {");
+ out.append("\n if (!CLS.prototype.$instOf_").append(className).append(") {");
+ for (FieldData v : jc.getFields()) {
+ if (v.isStatic()) {
+ out.append("\n CLS.").append(v.getName()).append(initField(v));
}
}
- final String className = className(jc);
- out.append("\nfunction ").append(className);
- out.append("() {");
+ if (proto == null) {
+ String sc = jc.getSuperClassName(); // with _
+ out.append("\n var p = CLS.prototype = ").
+ append(sc.replace('/', '_')).append("(true);");
+ out.append("\n var c = p;");
+ } else {
+ out.append("\n var p = CLS.prototype = ").append(proto[1]).append(";");
+ out.append("\n var c = ").append(proto[0]).append(";");
+ }
+ for (MethodData m : jc.getMethods()) {
+ byte[] onlyArr = m.findAnnotationData(true);
+ String[] only = findAnnotation(onlyArr, jc,
+ "org.apidesign.bck2brwsr.core.JavaScriptOnly",
+ "name", "value"
+ );
+ if (only != null) {
+ if (only[0] != null && only[1] != null) {
+ out.append("\n p.").append(only[0]).append(" = ")
+ .append(only[1]).append(";");
+ }
+ continue;
+ }
+ if (m.isStatic()) {
+ generateStaticMethod("\n c.", m, toInitilize);
+ } else {
+ generateInstanceMethod("\n c.", m);
+ }
+ }
+ out.append("\n c.constructor = CLS;");
+ out.append("\n c.$instOf_").append(className).append(" = true;");
+ for (String superInterface : jc.getSuperInterfaces()) {
+ out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
+ }
+ out.append("\n }");
+ out.append("\n if (arguments.length === 0) {");
+ out.append("\n if (!(this instanceof CLS)) {");
+ out.append("\n return new CLS();");
+ out.append("\n }");
for (FieldData v : jc.getFields()) {
+ byte[] onlyArr = v.findAnnotationData(true);
+ String[] only = findAnnotation(onlyArr, jc,
+ "org.apidesign.bck2brwsr.core.JavaScriptOnly",
+ "name", "value"
+ );
+ if (only != null) {
+ if (only[0] != null && only[1] != null) {
+ out.append("\n p.").append(only[0]).append(" = ")
+ .append(only[1]).append(";");
+ }
+ continue;
+ }
if (!v.isStatic()) {
- out.append("\n this.fld_").
+ out.append("\n this.fld_").
append(v.getName()).append(initField(v));
}
}
- out.append("\n}\n\nfunction ").append(className).append("_proto() {");
- out.append("\n if (").append(className).
- append(".prototype.$instOf_").append(className).append(") {");
- out.append("\n return new ").append(className).append(";");
+ out.append("\n return this;");
out.append("\n }");
- for (FieldData v : jc.getFields()) {
- if (v.isStatic()) {
- generateStaticField(v);
- }
- }
- // ClassName sc = jc.getSuperClass();
- String sc = jc.getSuperClassName(); // with _
- if (sc != null) {
- out.append("\n var p = ").append(className)
- .append(".prototype = ").
- append(sc.replace('/', '_')).append("_proto();");
- } else {
- out.append("\n var p = ").append(className).append(".prototype;");
- }
- for (MethodData m : jc.getMethods()) {
- if (!m.getName().contains("")) {
- generateMethodReference("\n p.", m);
- }
- }
- out.append("\n p.$instOf_").append(className).append(" = true;");
- for (String superInterface : jc.getSuperInterfaces()) {
- out.append("\n p.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
- }
- out.append("\n return new ").append(className).append(";");
+ out.append("\n return arguments[0] ? new CLS() : CLS.prototype;");
out.append("\n}");
- out.append("\n").append(className).append("_proto();");
StringBuilder sb = new StringBuilder();
for (String init : toInitilize.toArray()) {
sb.append("\n").append(init).append("();");
}
return sb.toString();
}
- private void generateStaticMethod(MethodData m, StringArray toInitilize) throws IOException {
- if (javaScriptBody(m, true)) {
+ private void generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
+ if (javaScriptBody(prefix, m, true)) {
return;
}
StringBuilder argsCnt = new StringBuilder();
final String mn = findMethodName(m, argsCnt);
- out.append("\nfunction ").append(
- className(jc)
- ).append('_').append(mn);
+ out.append(prefix).append(mn).append(" = function");
if (mn.equals("classV")) {
- toInitilize.add(className(jc) + '_' + mn);
+ toInitilize.add(className(jc) + "(false)." + mn);
}
out.append('(');
String space = "";
@@ -162,26 +195,18 @@
}
produceCode(m);
} else {
- out.append(" /* no code found for ").append(m.getInternalSig()).append(" */\n");
+ out.append(" throw 'no code found for ").append(m.getInternalSig()).append("';\n");
}
- out.append("}");
+ out.append("};");
}
- private void generateMethodReference(String prefix, MethodData m) throws IOException {
- final String name = findMethodName(m, new StringBuilder());
- out.append(prefix).append(name).append(" = ")
- .append(className(jc))
- .append('_').append(name).append(";");
- }
-
- private void generateInstanceMethod(MethodData m) throws IOException {
- if (javaScriptBody(m, false)) {
+ private void generateInstanceMethod(String prefix, MethodData m) throws IOException {
+ if (javaScriptBody(prefix, m, false)) {
return;
}
StringBuilder argsCnt = new StringBuilder();
- out.append("\nfunction ").append(
- className(jc)
- ).append('_').append(findMethodName(m, argsCnt));
+ final String mn = findMethodName(m, argsCnt);
+ out.append(prefix).append(mn).append(" = function");
out.append("(arg0");
String space = ",";
for (int index = 1, i = 0; i < argsCnt.length(); i++) {
@@ -202,9 +227,9 @@
}
produceCode(m);
} else {
- out.append(" /* no code found for ").append(m.getInternalSig()).append(" */\n");
+ out.append(" throw 'no code found for ").append(m.getInternalSig()).append("';\n");
}
- out.append("}");
+ out.append("};");
}
private void produceCode(MethodData m) throws IOException {
@@ -987,12 +1012,6 @@
}
}
- private void generateStaticField(FieldData v) throws IOException {
- out.append("\n ")
- .append(className(jc))
- .append('.').append(v.getName()).append(initField(v));
- }
-
private String findMethodName(MethodData m, StringBuilder cnt) {
StringBuilder name = new StringBuilder();
if ("".equals(m.getName())) { // NOI18N
@@ -1038,7 +1057,7 @@
final String in = mi[0];
out.append(in.replace('/', '_'));
- out.append(".prototype.");
+ out.append("(false).");
out.append(mn);
out.append('(');
if (numArguments > 0) {
@@ -1113,12 +1132,12 @@
return d.replace('[', 'A');
}
- private boolean javaScriptBody(MethodData m, boolean isStatic) throws IOException {
+ private boolean javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
byte[] arr = m.findAnnotationData(true);
if (arr == null) {
return false;
}
- final String jvmType = "L" + JavaScriptBody.class.getName().replace('.', '/') + ";";
+ final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
class P extends AnnotationParser {
int cnt;
String[] args = new String[30];
@@ -1143,9 +1162,8 @@
return false;
}
StringBuilder cnt = new StringBuilder();
- out.append("\nfunction ").append(className(jc)).append('_').
- append(findMethodName(m, cnt));
- out.append("(");
+ out.append(prefix).append(findMethodName(m, cnt));
+ out.append(" = function(");
String space;
int index;
if (!isStatic) {