1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Nov 07 09:24:37 2013 +0100
1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Thu Nov 07 09:41:45 2013 +0100
1.3 @@ -139,7 +139,7 @@
1.4 if (proto == null) {
1.5 String sc = jc.getSuperClassName(); // with _
1.6 out.append("\n var pp = ").
1.7 - append(accessClass(sc.replace('/', '_'))).append("(true);");
1.8 + append(accessClass(mangleClassName(sc))).append("(true);");
1.9 out.append("\n var p = CLS.prototype = pp;");
1.10 out.append("\n var c = p;");
1.11 out.append("\n var sprcls = pp.constructor.$class;");
1.12 @@ -975,7 +975,7 @@
1.13 int indx = readUShortArg(byteCodes, i);
1.14 String ci = jc.getClassName(indx);
1.15 emit(out, "var @1 = new @2;",
1.16 - smapper.pushA(), accessClass(ci.replace('/', '_')));
1.17 + smapper.pushA(), accessClass(mangleClassName(ci)));
1.18 addReference(ci);
1.19 i += 2;
1.20 break;
1.21 @@ -1214,7 +1214,7 @@
1.22 int indx = readUShortArg(byteCodes, i);
1.23 String[] fi = jc.getFieldInfoName(indx);
1.24 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.25 - final String mangleClass = mangleSig(fi[0]);
1.26 + final String mangleClass = mangleClassName(fi[0]);
1.27 final String mangleClassAccess = accessClass(mangleClass);
1.28 emit(out, "var @2 = @4(false)._@3.call(@1);",
1.29 smapper.popA(),
1.30 @@ -1227,7 +1227,7 @@
1.31 int indx = readUShortArg(byteCodes, i);
1.32 String[] fi = jc.getFieldInfoName(indx);
1.33 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.34 - final String mangleClass = mangleSig(fi[0]);
1.35 + final String mangleClass = mangleClassName(fi[0]);
1.36 final String mangleClassAccess = accessClass(mangleClass);
1.37 emit(out, "@4(false)._@3.call(@2, @1);",
1.38 smapper.popT(type),
1.39 @@ -1243,7 +1243,7 @@
1.40 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.41 emit(out, "var @1 = @2(false)._@3();",
1.42 smapper.pushT(type),
1.43 - accessClass(fi[0].replace('/', '_')), fi[1]);
1.44 + accessClass(mangleClassName(fi[0])), fi[1]);
1.45 i += 2;
1.46 addReference(fi[0]);
1.47 break;
1.48 @@ -1253,7 +1253,7 @@
1.49 String[] fi = jc.getFieldInfoName(indx);
1.50 final int type = VarType.fromFieldType(fi[2].charAt(0));
1.51 emit(out, "@1(false)._@2(@3);",
1.52 - accessClass(fi[0].replace('/', '_')), fi[1],
1.53 + accessClass(mangleClassName(fi[0])), fi[1],
1.54 smapper.popT(type));
1.55 i += 2;
1.56 addReference(fi[0]);
1.57 @@ -1435,8 +1435,20 @@
1.58 return mangleSig(sig, 0, sig.length());
1.59 }
1.60
1.61 + private static String mangleMethodName(String name) {
1.62 + StringBuilder sb = new StringBuilder(name.length() * 2);
1.63 + int last = name.length();
1.64 + for (int i = 0; i < last; i++) {
1.65 + final char ch = name.charAt(i);
1.66 + switch (ch) {
1.67 + case '_': sb.append("_1"); break;
1.68 + default: sb.append(ch); break;
1.69 + }
1.70 + }
1.71 + return sb.toString();
1.72 + }
1.73 private static String mangleSig(String txt, int first, int last) {
1.74 - StringBuilder sb = new StringBuilder();
1.75 + StringBuilder sb = new StringBuilder((last - first) * 2);
1.76 for (int i = first; i < last; i++) {
1.77 final char ch = txt.charAt(i);
1.78 switch (ch) {
1.79 @@ -1449,6 +1461,10 @@
1.80 }
1.81 return sb.toString();
1.82 }
1.83 +
1.84 + private static String mangleClassName(String name) {
1.85 + return mangleSig(name);
1.86 + }
1.87
1.88 private static String findMethodName(MethodData m, StringBuilder cnt) {
1.89 StringBuilder name = new StringBuilder();
1.90 @@ -1457,7 +1473,7 @@
1.91 } else if ("<clinit>".equals(m.getName())) { // NOI18N
1.92 name.append("class"); // NOI18N
1.93 } else {
1.94 - name.append(m.getName());
1.95 + name.append(mangleMethodName(m.getName()));
1.96 }
1.97
1.98 countArgs(m.getInternalSig(), new char[1], name, cnt);
1.99 @@ -1471,7 +1487,7 @@
1.100 if ("<init>".equals(nm)) { // NOI18N
1.101 name.append("cons"); // NOI18N
1.102 } else {
1.103 - name.append(nm);
1.104 + name.append(mangleMethodName(nm));
1.105 }
1.106 countArgs(descr, returnType, name, cnt);
1.107 return name.toString();
1.108 @@ -1499,7 +1515,7 @@
1.109 }
1.110
1.111 final String in = mi[0];
1.112 - out.append(accessClass(in.replace('/', '_')));
1.113 + out.append(accessClass(mangleClassName(in)));
1.114 out.append("(false).");
1.115 if (mn.startsWith("cons_")) {
1.116 out.append("constructor.");
1.117 @@ -1585,7 +1601,7 @@
1.118 s = accessClass("java_lang_Class") + "(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('" + classRef[0] + "');";
1.119 } else {
1.120 addReference(classRef[0]);
1.121 - s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
1.122 + s = accessClass(mangleClassName(s)) + "(false).constructor.$class";
1.123 }
1.124 }
1.125 return s;
1.126 @@ -1695,7 +1711,7 @@
1.127 int paramBeg = body.indexOf('(', sigEnd + 1);
1.128
1.129 sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
1.130 - sb.append(mangle(fqn, method, params, false));
1.131 + sb.append(mangleJsCallbacks(fqn, method, params, false));
1.132 sb.append("(").append(refId);
1.133 if (body.charAt(paramBeg + 1) != ')') {
1.134 sb.append(",");
1.135 @@ -1732,12 +1748,13 @@
1.136 int paramBeg = body.indexOf('(', sigEnd + 1);
1.137
1.138 sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
1.139 - sb.append(mangle(fqn, method, params, true));
1.140 + sb.append(mangleJsCallbacks(fqn, method, params, true));
1.141 sb.append("(");
1.142 pos = paramBeg + 1;
1.143 }
1.144 }
1.145 - private static String mangle(String fqn, String method, String params, boolean isStatic) {
1.146 +
1.147 + static String mangleJsCallbacks(String fqn, String method, String params, boolean isStatic) {
1.148 if (params.startsWith("(")) {
1.149 params = params.substring(1);
1.150 }
1.151 @@ -1745,28 +1762,23 @@
1.152 params = params.substring(0, params.length() - 1);
1.153 }
1.154 StringBuilder sb = new StringBuilder();
1.155 - final String rfqn = replace(fqn);
1.156 - final String rm = replace(method);
1.157 - final String rp = replace(params);
1.158 + final String fqnu = fqn.replace('.', '_');
1.159 + final String rfqn = mangleClassName(fqnu);
1.160 + final String rm = mangleMethodName(method);
1.161 + final String rp = mangleSig(params);
1.162 + final String mrp = mangleMethodName(rp);
1.163 sb.append(rfqn).append("$").append(rm).
1.164 - append('$').append(rp).append("__Ljava_lang_Object_2");
1.165 + append('$').append(mrp).append("__Ljava_lang_Object_2");
1.166 if (!isStatic) {
1.167 - sb.append('L').append(rfqn).append("_2");
1.168 + sb.append('L').append(fqnu).append("_2");
1.169 }
1.170 sb.append(rp);
1.171 return sb.toString();
1.172 }
1.173
1.174 - private static String replace(String orig) {
1.175 - return orig.replace("_", "_1").
1.176 - replace(";", "_2").
1.177 - replace("[", "_3").
1.178 - replace('.', '_').replace('/', '_');
1.179 - }
1.180 -
1.181 private static String className(ClassData jc) {
1.182 //return jc.getName().getInternalName().replace('/', '_');
1.183 - return jc.getClassName().replace('/', '_');
1.184 + return mangleClassName(jc.getClassName());
1.185 }
1.186
1.187 private static String[] findAnnotation(
1.188 @@ -1879,7 +1891,7 @@
1.189 final String slashType = attrType.substring(1, attrType.length() - 1);
1.190 requireReference(slashType);
1.191
1.192 - out.append(accessClass(slashType.replace('/', '_')))
1.193 + out.append(accessClass(mangleClassName(slashType)))
1.194 .append("(false).constructor.fld_").append(value);
1.195 }
1.196 };
2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Thu Nov 07 09:24:37 2013 +0100
2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Thu Nov 07 09:41:45 2013 +0100
2.3 @@ -137,13 +137,17 @@
2.4 out.append(
2.5 " return vm;\n"
2.6 + " };\n"
2.7 + + " function mangleClass(name) {\n"
2.8 + + " return name.replace__Ljava_lang_String_2Ljava_lang_CharSequence_2Ljava_lang_CharSequence_2(\n"
2.9 + + " '_', '_1').replace__Ljava_lang_String_2CC('.','_');\n"
2.10 + + " };\n"
2.11 + " global.bck2brwsr = function() {\n"
2.12 + " var args = Array.prototype.slice.apply(arguments);\n"
2.13 + " var vm = fillInVMSkeleton({});\n"
2.14 + " var loader = {};\n"
2.15 + " loader.vm = vm;\n"
2.16 + " loader.loadClass = function(name) {\n"
2.17 - + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
2.18 + + " var attr = mangleClass(name);\n"
2.19 + " var fn = vm[attr];\n"
2.20 + " if (fn) return fn(false);\n"
2.21 + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
2.22 @@ -154,7 +158,7 @@
2.23 + " }\n"
2.24 + " vm.loadClass = loader.loadClass;\n"
2.25 + " vm._reload = function(name, byteCode) {;\n"
2.26 - + " var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
2.27 + + " var attr = mangleClass(name);\n"
2.28 + " delete vm[attr];\n"
2.29 + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
2.30 + " reload__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2_3B(loader, name, args, byteCode);\n"
3.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java Thu Nov 07 09:24:37 2013 +0100
3.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ByteCodeToJavaScriptTest.java Thu Nov 07 09:41:45 2013 +0100
3.3 @@ -52,4 +52,15 @@
3.4 assertTrue(returnType[0] != 'V', "Returns string");
3.5 assertEquals(ret, "toJavaScript__Ljava_lang_String_2_3B");
3.6 }
3.7 +
3.8 + @Test public void mangleJsCallbackToAType() throws Exception {
3.9 + String res = ByteCodeToJavaScript.mangleJsCallbacks(
3.10 + "org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations",
3.11 + "onError", "Ljava/lang/Object;", false
3.12 + );
3.13 + assertEquals(res,
3.14 + "org_1apidesign_1bck2brwsr_1vmtest_1impl_1HtmlAnnotations$onError$Ljava_1lang_1Object_12__Ljava_lang_Object_2Lorg_apidesign_bck2brwsr_vmtest_impl_HtmlAnnotations_2Ljava_lang_Object_2",
3.15 + "Pretty long method name"
3.16 + );
3.17 + }
3.18 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/UnderTest.java Thu Nov 07 09:41:45 2013 +0100
4.3 @@ -0,0 +1,88 @@
4.4 +/**
4.5 + * Back 2 Browser Bytecode Translator
4.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.7 + *
4.8 + * This program is free software: you can redistribute it and/or modify
4.9 + * it under the terms of the GNU General Public License as published by
4.10 + * the Free Software Foundation, version 2 of the License.
4.11 + *
4.12 + * This program is distributed in the hope that it will be useful,
4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.15 + * GNU General Public License for more details.
4.16 + *
4.17 + * You should have received a copy of the GNU General Public License
4.18 + * along with this program. Look for COPYING file in the top folder.
4.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
4.20 + */
4.21 +package org.apidesign.vm4brwsr;
4.22 +
4.23 +import org.testng.annotations.AfterClass;
4.24 +import org.testng.annotations.BeforeClass;
4.25 +import org.testng.annotations.Test;
4.26 +
4.27 +/** Checks behavior of classes and methods with underscore.
4.28 + *
4.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
4.30 + */
4.31 +public class UnderTest {
4.32 + @Test public void one() throws Exception {
4.33 + assertExec(
4.34 + "Should be one",
4.35 + Under_Score.class, "one__I",
4.36 + Double.valueOf(1)
4.37 + );
4.38 + }
4.39 +
4.40 + @Test public void onePlusOne() throws Exception {
4.41 + assertExec(
4.42 + "Should be two",
4.43 + Under_Score.class, "one_1plus_1one__I",
4.44 + Double.valueOf(2)
4.45 + );
4.46 + }
4.47 +
4.48 + @Test public void two() throws Exception {
4.49 + assertExec(
4.50 + "Should be two",
4.51 + Under_Score.class, "two__I",
4.52 + Double.valueOf(2)
4.53 + );
4.54 + }
4.55 +
4.56 + @Test public void staticField() throws Exception {
4.57 + assertExec(
4.58 + "Should be ten",
4.59 + Under_Score.class, "staticField__I",
4.60 + Double.valueOf(10)
4.61 + );
4.62 + }
4.63 +
4.64 + @Test public void instance() throws Exception {
4.65 + assertExec(
4.66 + "Should be five",
4.67 + Under_Score.class, "instance__I",
4.68 + Double.valueOf(5)
4.69 + );
4.70 + }
4.71 +
4.72 +
4.73 + private static TestVM code;
4.74 +
4.75 + @BeforeClass
4.76 + public static void compileTheCode() throws Exception {
4.77 + StringBuilder sb = new StringBuilder();
4.78 + code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/Under_Score");
4.79 + }
4.80 + @AfterClass
4.81 + public static void releaseTheCode() {
4.82 + code = null;
4.83 + }
4.84 +
4.85 + private void assertExec(
4.86 + String msg, Class<?> clazz, String method,
4.87 + Object ret, Object... args
4.88 + ) throws Exception {
4.89 + code.assertExec(msg, clazz, method, ret, args);
4.90 + }
4.91 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Under_Score.java Thu Nov 07 09:41:45 2013 +0100
5.3 @@ -0,0 +1,51 @@
5.4 +/**
5.5 + * Back 2 Browser Bytecode Translator
5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.7 + *
5.8 + * This program is free software: you can redistribute it and/or modify
5.9 + * it under the terms of the GNU General Public License as published by
5.10 + * the Free Software Foundation, version 2 of the License.
5.11 + *
5.12 + * This program is distributed in the hope that it will be useful,
5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.15 + * GNU General Public License for more details.
5.16 + *
5.17 + * You should have received a copy of the GNU General Public License
5.18 + * along with this program. Look for COPYING file in the top folder.
5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
5.20 + */
5.21 +package org.apidesign.vm4brwsr;
5.22 +
5.23 +/**
5.24 + *
5.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
5.26 + */
5.27 +public class Under_Score {
5.28 + public static int under_field = 10;
5.29 + public int instance_field = 5;
5.30 +
5.31 + public static int one() {
5.32 + return 1;
5.33 + }
5.34 +
5.35 + public static int one_plus_one() {
5.36 + return 1 + 1;
5.37 + }
5.38 +
5.39 + public static int two() {
5.40 + return one_plus_one();
5.41 + }
5.42 +
5.43 + public static int staticField() {
5.44 + return under_field;
5.45 + }
5.46 +
5.47 + public static int instance() {
5.48 + return new Under_Score().get_fld();
5.49 + }
5.50 +
5.51 + private int get_fld() {
5.52 + return instance_field;
5.53 + }
5.54 +}