In order to support fields of the same name in subclasses we are now prefixing them with name of the class that defines them. To provide convenient way to access them from generated bytecode and also directly from JavaScript, there is a getter/setter function for each field. It starts with _ followed by the field name. If called with a parameter, it sets the field, with a parameter it just returns it.
2 * Back 2 Browser Bytecode Translator
3 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. Look for COPYING file in the top folder.
16 * If not, see http://opensource.org/licenses/GPL-2.0.
18 package org.apidesign.vm4brwsr;
20 import java.io.ByteArrayInputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import org.apidesign.bck2brwsr.core.JavaScriptBody;
27 * @author Jaroslav Tulach <jtulach@netbeans.org>
30 private final Object loader;
31 private final Object[] args;
33 private VMLazy(Object loader, Object[] args) {
41 @JavaScriptBody(args={"l", "res", "args" }, body = ""
43 + "\n return args[0](res.toString());"
45 + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();"
47 private static native byte[] read(Object l, String res, Object[] args);
49 static Object load(Object loader, String name, Object[] arguments)
50 throws IOException, ClassNotFoundException {
51 return new VMLazy(loader, arguments).load(name, false);
54 private Object load(String name, boolean instance)
55 throws IOException, ClassNotFoundException {
56 String res = name.replace('.', '/') + ".class";
57 byte[] arr = read(loader, res, args);
59 throw new ClassNotFoundException(name);
61 // beingDefined(loader, name);
62 StringBuilder out = new StringBuilder();
63 out.append("var loader = arguments[0];\n");
64 out.append("var vm = loader.vm;\n");
65 int prelude = out.length();
66 String initCode = new Gen(this, out).compile(new ByteArrayInputStream(arr));
67 String code = out.toString().toString();
68 // dump("Loading " + name);
70 String under = name.replace('.', '_');
71 Object fn = applyCode(loader, under, code, instance);
73 if (!initCode.isEmpty()) {
74 out.setLength(prelude);
76 code = out.toString().toString();
78 applyCode(loader, null, code, false);
84 // @JavaScriptBody(args = "s", body = "java.lang.System.out.println(s.toString());")
85 static void dump(String s) {
88 /* possibly not needed:
89 @JavaScriptBody(args = {"loader", "n" }, body =
90 "var cls = n.replace__Ljava_lang_String_2CC(n, '.','_').toString();" +
91 "loader.vm[cls] = true;\n"
93 private static native void beingDefined(Object loader, String name);
97 @JavaScriptBody(args = {"loader", "name", "script", "instance" }, body =
99 " new Function(script)(loader, name);\n" +
101 " throw 'Cannot compile ' + name + ' ' + ex + ' line: ' + ex.lineNumber + ' script:\\n' + script;\n" +
103 "return name != null ? vm[name](instance) : null;\n"
105 private static native Object applyCode(Object loader, String name, String script, boolean instance);
108 private static final class Gen extends ByteCodeToJavaScript {
109 private final VMLazy lazy;
111 public Gen(VMLazy vm, Appendable out) {
116 @JavaScriptBody(args = {"n"},
118 "var cls = n.replace__Ljava_lang_String_2CC('/','_').toString();"
119 + "\nvar dot = n.replace__Ljava_lang_String_2CC('/','.').toString();"
120 + "\nvar lazy = this._lazy();"
121 + "\nvar loader = lazy._loader();"
122 + "\nvar vm = loader.vm;"
123 + "\nif (vm[cls]) return false;"
124 + "\nvm[cls] = function() {"
125 + "\n var instance = arguments.length == 0 || arguments[0] === true;"
126 + "\n return lazy.load__Ljava_lang_Object_2Ljava_lang_String_2Z(dot, instance);"
130 protected boolean requireReference(String internalClassName) {
131 throw new UnsupportedOperationException();
135 protected void requireScript(String resourcePath) throws IOException {
136 InputStream is = getClass().getResourceAsStream(resourcePath);
137 StringBuilder sb = new StringBuilder();
145 applyCode(lazy.loader, null, sb.toString(), false);
149 String assignClass(String className) {
150 return "vm[arguments[1]]=";
154 String accessClass(String classOperation) {
155 return "vm." + classOperation;