jaroslav@170: /** jaroslav@170: * Back 2 Browser Bytecode Translator jaroslav@170: * Copyright (C) 2012 Jaroslav Tulach jaroslav@170: * jaroslav@170: * This program is free software: you can redistribute it and/or modify jaroslav@170: * it under the terms of the GNU General Public License as published by jaroslav@170: * the Free Software Foundation, version 2 of the License. jaroslav@170: * jaroslav@170: * This program is distributed in the hope that it will be useful, jaroslav@170: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@170: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@170: * GNU General Public License for more details. jaroslav@170: * jaroslav@170: * You should have received a copy of the GNU General Public License jaroslav@170: * along with this program. Look for COPYING file in the top folder. jaroslav@170: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@170: */ jaroslav@170: package org.apidesign.vm4brwsr; jaroslav@170: jaroslav@170: import java.io.ByteArrayInputStream; jaroslav@170: import java.io.IOException; jaroslav@214: import org.apidesign.bck2brwsr.core.JavaScriptBody; jaroslav@170: jaroslav@170: /** jaroslav@170: * jaroslav@170: * @author Jaroslav Tulach jaroslav@170: */ jaroslav@201: class VMLazy extends ByteCodeToJavaScript { jaroslav@277: private final Object loader; jaroslav@214: jaroslav@277: private VMLazy(Object loader, Appendable out) { jaroslav@170: super(out); jaroslav@277: this.loader = loader; jaroslav@170: } jaroslav@170: jaroslav@277: static void init() { jaroslav@277: } jaroslav@277: jaroslav@277: @JavaScriptBody(args={"res", "args" }, body = "return args[0](res.toString());") jaroslav@277: private static native byte[] read(String res, Object[] args); jaroslav@277: jaroslav@277: static Object load(Object loader, String name, Object[] arguments) jaroslav@277: throws IOException, ClassNotFoundException { jaroslav@277: String res = name.replace('.', '/') + ".class"; jaroslav@277: byte[] arr = read(res, arguments); jaroslav@277: if (arr == null) { jaroslav@277: throw new ClassNotFoundException(name); jaroslav@277: } jaroslav@277: String code = toJavaScript(loader, arr); jaroslav@277: return applyCode(loader, name, code); jaroslav@277: } jaroslav@277: jaroslav@277: @JavaScriptBody(args = {"loader", "name", "script" }, body = jaroslav@277: "try {\n" + jaroslav@277: " new Function(script)(loader, name);\n" + jaroslav@277: "} catch (ex) {\n" + jaroslav@277: " throw 'Cannot compile ' + ex + ' script:\\\\n' + script;\n" + jaroslav@277: "}\n" + jaroslav@277: "return vm[name](false);\n" jaroslav@277: ) jaroslav@277: private static native Object applyCode(Object loader, String name, String script); jaroslav@277: jaroslav@277: private static String toJavaScript(Object loader, byte[] is) throws IOException { jaroslav@170: StringBuilder sb = new StringBuilder(); jaroslav@277: sb.append("var loader = arguments[0];\n"); jaroslav@277: sb.append("var vm = loader.vm;\n"); jaroslav@277: new VMLazy(loader, sb).compile(new ByteArrayInputStream(is)); jaroslav@170: return sb.toString().toString(); jaroslav@170: } jaroslav@170: jaroslav@214: @JavaScriptBody(args = { "self", "n" }, jaroslav@214: body= jaroslav@248: "var cls = n.replace__Ljava_lang_String_2CC(n,'/','_').toString();" jaroslav@277: + "var loader = self.fld_loader;" jaroslav@277: + "var vm = loader.vm;" jaroslav@277: + "if (vm[cls]) return false;" jaroslav@277: + "vm[cls] = function() {" jaroslav@277: + " return loader.loadClass(n,cls);" jaroslav@214: + "};" jaroslav@214: + "return true;" jaroslav@214: ) jaroslav@170: @Override jaroslav@170: protected boolean requireReference(String internalClassName) { jaroslav@214: throw new UnsupportedOperationException(); jaroslav@170: } jaroslav@170: jaroslav@170: @Override jaroslav@170: protected void requireScript(String resourcePath) { jaroslav@170: } jaroslav@213: jaroslav@213: @Override jaroslav@277: String assignClass(String className) { jaroslav@277: return "vm[arguments[1]]="; jaroslav@277: } jaroslav@277: jaroslav@277: @Override jaroslav@277: String accessClass(String classOperation) { jaroslav@277: return "vm." + classOperation; jaroslav@213: } jaroslav@170: }