vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
branchreflection
changeset 249 001389026dbf
parent 237 84ffc347412d
parent 248 0bfcb6585290
child 250 42c2ceb1e160
     1.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Sun Dec 02 14:01:17 2012 +0100
     1.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Tue Dec 04 11:21:10 2012 +0100
     1.3 @@ -82,6 +82,10 @@
     1.4                  return null;
     1.5              }
     1.6          }
     1.7 +        String[] proto = findAnnotation(arrData, jc, 
     1.8 +            "org.apidesign.bck2brwsr.core.JavaScriptPrototype", 
     1.9 +            "container", "prototype"
    1.10 +        );
    1.11          StringArray toInitilize = new StringArray();
    1.12          final String className = className(jc);
    1.13          out.append("\n\n").append(assignClass(className));
    1.14 @@ -92,28 +96,41 @@
    1.15                  out.append("\n  CLS.").append(v.getName()).append(initField(v));
    1.16              }
    1.17          }
    1.18 -        // ClassName sc = jc.getSuperClass();
    1.19 -        String sc = jc.getSuperClassName(); // with _
    1.20 -        if (sc != null) {
    1.21 +        if (proto == null) {
    1.22 +            String sc = jc.getSuperClassName(); // with _
    1.23              out.append("\n    var pp = ").
    1.24                  append(sc.replace('/', '_')).append("(true);");
    1.25              out.append("\n    var p = CLS.prototype = pp;");
    1.26 +            out.append("\n    var c = p;");
    1.27              out.append("\n    var sprcls = pp.constructor.$class;");
    1.28          } else {
    1.29 -            out.append("\n    var p = CLS.prototype;");
    1.30 +            out.append("\n    var p = CLS.prototype = ").append(proto[1]).append(";");
    1.31 +            out.append("\n    var c = ").append(proto[0]).append(";");
    1.32              out.append("\n    var sprcls = null;");
    1.33          }
    1.34          for (MethodData m : jc.getMethods()) {
    1.35 +            byte[] onlyArr = m.findAnnotationData(true);
    1.36 +            String[] only = findAnnotation(onlyArr, jc, 
    1.37 +                "org.apidesign.bck2brwsr.core.JavaScriptOnly", 
    1.38 +                "name", "value"
    1.39 +            );
    1.40 +            if (only != null) {
    1.41 +                if (only[0] != null && only[1] != null) {
    1.42 +                    out.append("\n    p.").append(only[0]).append(" = ")
    1.43 +                        .append(only[1]).append(";");
    1.44 +                }
    1.45 +                continue;
    1.46 +            }
    1.47              if (m.isStatic()) {
    1.48 -                generateStaticMethod("\n    p.", m, toInitilize);
    1.49 +                generateStaticMethod("\n    c.", m, toInitilize);
    1.50              } else {
    1.51 -                generateInstanceMethod("\n    p.", m);
    1.52 +                generateInstanceMethod("\n    c.", m);
    1.53              }
    1.54          }
    1.55 -        out.append("\n    p.constructor = CLS;");
    1.56 -        out.append("\n    p.$instOf_").append(className).append(" = true;");
    1.57 +        out.append("\n    c.constructor = CLS;");
    1.58 +        out.append("\n    c.$instOf_").append(className).append(" = true;");
    1.59          for (String superInterface : jc.getSuperInterfaces()) {
    1.60 -            out.append("\n    p.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
    1.61 +            out.append("\n    c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
    1.62          }
    1.63          out.append("\n    CLS.$class = java_lang_Class(true);");
    1.64          out.append("\n    CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
    1.65 @@ -131,6 +148,18 @@
    1.66          out.append("\n      return new CLS();");
    1.67          out.append("\n    }");
    1.68          for (FieldData v : jc.getFields()) {
    1.69 +            byte[] onlyArr = v.findAnnotationData(true);
    1.70 +            String[] only = findAnnotation(onlyArr, jc, 
    1.71 +                "org.apidesign.bck2brwsr.core.JavaScriptOnly", 
    1.72 +                "name", "value"
    1.73 +            );
    1.74 +            if (only != null) {
    1.75 +                if (only[0] != null && only[1] != null) {
    1.76 +                    out.append("\n    p.").append(only[0]).append(" = ")
    1.77 +                        .append(only[1]).append(";");
    1.78 +                }
    1.79 +                continue;
    1.80 +            }
    1.81              if (!v.isStatic()) {
    1.82                  out.append("\n    this.fld_").
    1.83                      append(v.getName()).append(initField(v));
    1.84 @@ -153,7 +182,7 @@
    1.85          StringBuilder argsCnt = new StringBuilder();
    1.86          final String mn = findMethodName(m, argsCnt);
    1.87          out.append(prefix).append(mn).append(" = function");
    1.88 -        if (mn.equals("classV")) {
    1.89 +        if (mn.equals("class__V")) {
    1.90              toInitilize.add(className(jc) + "(false)." + mn);
    1.91          }
    1.92          out.append('(');
    1.93 @@ -782,6 +811,7 @@
    1.94          int i = 0;
    1.95          Boolean count = null;
    1.96          boolean array = false;
    1.97 +        sig.append("__");
    1.98          int firstPos = sig.length();
    1.99          while (i < descriptor.length()) {
   1.100              char ch = descriptor.charAt(i++);
   1.101 @@ -792,9 +822,6 @@
   1.102                  case ')':
   1.103                      count = false;
   1.104                      continue;
   1.105 -                case 'A':
   1.106 -                    array = true;
   1.107 -                    break;
   1.108                  case 'B': 
   1.109                  case 'C': 
   1.110                  case 'D': 
   1.111 @@ -805,7 +832,7 @@
   1.112                  case 'Z': 
   1.113                      if (count) {
   1.114                          if (array) {
   1.115 -                            sig.append('A');
   1.116 +                            sig.append("_3");
   1.117                          }
   1.118                          sig.append(ch);
   1.119                          if (ch == 'J' || ch == 'D') {
   1.120 @@ -817,7 +844,7 @@
   1.121                          hasReturnType[0] = true;
   1.122                          sig.insert(firstPos, ch);
   1.123                          if (array) {
   1.124 -                            sig.insert(firstPos, 'A');
   1.125 +                            sig.insert(firstPos, "_3");
   1.126                          }
   1.127                      }
   1.128                      array = false;
   1.129 @@ -829,33 +856,47 @@
   1.130                      continue;
   1.131                  case 'L':
   1.132                      int next = descriptor.indexOf(';', i);
   1.133 +                    String realSig = mangleSig(descriptor, i - 1, next + 1);
   1.134                      if (count) {
   1.135                          if (array) {
   1.136 -                            sig.append('A');
   1.137 +                            sig.append("_3");
   1.138                          }
   1.139 -                        sig.append(ch);
   1.140 -                        sig.append(descriptor.substring(i, next).replace('/', '_'));
   1.141 +                        sig.append(realSig);
   1.142                          cnt.append('0');
   1.143                      } else {
   1.144 -                        sig.insert(firstPos, descriptor.substring(i, next).replace('/', '_'));
   1.145 -                        sig.insert(firstPos, ch);
   1.146 +                        sig.insert(firstPos, realSig);
   1.147                          if (array) {
   1.148 -                            sig.insert(firstPos, 'A');
   1.149 +                            sig.insert(firstPos, "_3");
   1.150                          }
   1.151                          hasReturnType[0] = true;
   1.152                      }
   1.153                      i = next + 1;
   1.154                      continue;
   1.155                  case '[':
   1.156 -                    //arrays++;
   1.157 +                    array = true;
   1.158                      continue;
   1.159                  default:
   1.160 -                    break; // invalid character
   1.161 +                    throw new IllegalStateException("Invalid char: " + ch);
   1.162              }
   1.163          }
   1.164      }
   1.165 +    
   1.166 +    private static String mangleSig(String txt, int first, int last) {
   1.167 +        StringBuilder sb = new StringBuilder();
   1.168 +        for (int i = first; i < last; i++) {
   1.169 +            final char ch = txt.charAt(i);
   1.170 +            switch (ch) {
   1.171 +                case '/': sb.append('_'); break;
   1.172 +                case '_': sb.append("_1"); break;
   1.173 +                case ';': sb.append("_2"); break;
   1.174 +                case '[': sb.append("_3"); break;
   1.175 +                default: sb.append(ch); break;
   1.176 +            }
   1.177 +        }
   1.178 +        return sb.toString();
   1.179 +    }
   1.180  
   1.181 -    private String findMethodName(MethodData m, StringBuilder cnt) {
   1.182 +    private static String findMethodName(MethodData m, StringBuilder cnt) {
   1.183          StringBuilder name = new StringBuilder();
   1.184          if ("<init>".equals(m.getName())) { // NOI18N
   1.185              name.append("cons"); // NOI18N
   1.186 @@ -866,11 +907,11 @@
   1.187          } 
   1.188          
   1.189          boolean hasReturn[] = { false };
   1.190 -        countArgs(findDescriptor(m.getInternalSig()), hasReturn, name, cnt);
   1.191 +        countArgs(m.getInternalSig(), hasReturn, name, cnt);
   1.192          return name.toString();
   1.193      }
   1.194  
   1.195 -    private String findMethodName(String[] mi, StringBuilder cnt, boolean[] hasReturn) {
   1.196 +    static String findMethodName(String[] mi, StringBuilder cnt, boolean[] hasReturn) {
   1.197          StringBuilder name = new StringBuilder();
   1.198          String descr = mi[2];//mi.getDescriptor();
   1.199          String nm= mi[1];
   1.200 @@ -879,7 +920,7 @@
   1.201          } else {
   1.202              name.append(nm);
   1.203          }
   1.204 -        countArgs(findDescriptor(descr), hasReturn, name, cnt);
   1.205 +        countArgs(descr, hasReturn, name, cnt);
   1.206          return name.toString();
   1.207      }
   1.208  
   1.209 @@ -983,10 +1024,6 @@
   1.210          return s;
   1.211      }
   1.212  
   1.213 -    private String findDescriptor(String d) {
   1.214 -        return d.replace('[', 'A');
   1.215 -    }
   1.216 -
   1.217      private boolean javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
   1.218          byte[] arr = m.findAnnotationData(true);
   1.219          if (arr == null) {