vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Fri, 07 Dec 2012 06:29:54 +0100
branchlazyvm
changeset 277 e4b9eee9be83
parent 248 vm/src/test/java/org/apidesign/vm4brwsr/VMLazy.java@0bfcb6585290
child 278 ad49b48b7919
permissions -rw-r--r--
Lazy loading is now part of GenJS
jaroslav@170
     1
/**
jaroslav@170
     2
 * Back 2 Browser Bytecode Translator
jaroslav@170
     3
 * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
jaroslav@170
     4
 *
jaroslav@170
     5
 * This program is free software: you can redistribute it and/or modify
jaroslav@170
     6
 * it under the terms of the GNU General Public License as published by
jaroslav@170
     7
 * the Free Software Foundation, version 2 of the License.
jaroslav@170
     8
 *
jaroslav@170
     9
 * This program is distributed in the hope that it will be useful,
jaroslav@170
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jaroslav@170
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
jaroslav@170
    12
 * GNU General Public License for more details.
jaroslav@170
    13
 *
jaroslav@170
    14
 * You should have received a copy of the GNU General Public License
jaroslav@170
    15
 * along with this program. Look for COPYING file in the top folder.
jaroslav@170
    16
 * If not, see http://opensource.org/licenses/GPL-2.0.
jaroslav@170
    17
 */
jaroslav@170
    18
package org.apidesign.vm4brwsr;
jaroslav@170
    19
jaroslav@170
    20
import java.io.ByteArrayInputStream;
jaroslav@170
    21
import java.io.IOException;
jaroslav@214
    22
import org.apidesign.bck2brwsr.core.JavaScriptBody;
jaroslav@170
    23
jaroslav@170
    24
/**
jaroslav@170
    25
 *
jaroslav@170
    26
 * @author Jaroslav Tulach <jtulach@netbeans.org>
jaroslav@170
    27
 */
jaroslav@201
    28
class VMLazy extends ByteCodeToJavaScript {
jaroslav@277
    29
    private final Object loader;
jaroslav@214
    30
    
jaroslav@277
    31
    private VMLazy(Object loader, Appendable out) {
jaroslav@170
    32
        super(out);
jaroslav@277
    33
        this.loader = loader;
jaroslav@170
    34
    }
jaroslav@170
    35
    
jaroslav@277
    36
    static void init() {
jaroslav@277
    37
    }
jaroslav@277
    38
    
jaroslav@277
    39
    @JavaScriptBody(args={"res", "args" }, body = "return args[0](res.toString());")
jaroslav@277
    40
    private static native byte[] read(String res, Object[] args);
jaroslav@277
    41
    
jaroslav@277
    42
    static Object load(Object loader, String name, Object[] arguments) 
jaroslav@277
    43
    throws IOException, ClassNotFoundException {
jaroslav@277
    44
        String res = name.replace('.', '/') + ".class";
jaroslav@277
    45
        byte[] arr = read(res, arguments);
jaroslav@277
    46
        if (arr == null) {
jaroslav@277
    47
            throw new ClassNotFoundException(name);
jaroslav@277
    48
        }
jaroslav@277
    49
        String code = toJavaScript(loader, arr);
jaroslav@277
    50
        return applyCode(loader, name, code);
jaroslav@277
    51
    }
jaroslav@277
    52
    
jaroslav@277
    53
    @JavaScriptBody(args = {"loader", "name", "script" }, body =
jaroslav@277
    54
        "try {\n" +
jaroslav@277
    55
        "  new Function(script)(loader, name);\n" +
jaroslav@277
    56
        "} catch (ex) {\n" +
jaroslav@277
    57
        "  throw 'Cannot compile ' + ex + ' script:\\\\n' + script;\n" +
jaroslav@277
    58
        "}\n" +
jaroslav@277
    59
        "return vm[name](false);\n"
jaroslav@277
    60
    )
jaroslav@277
    61
    private static native Object applyCode(Object loader, String name, String script);
jaroslav@277
    62
    
jaroslav@277
    63
    private static String toJavaScript(Object loader, byte[] is) throws IOException {
jaroslav@170
    64
        StringBuilder sb = new StringBuilder();
jaroslav@277
    65
        sb.append("var loader = arguments[0];\n");
jaroslav@277
    66
        sb.append("var vm = loader.vm;\n");
jaroslav@277
    67
        new VMLazy(loader, sb).compile(new ByteArrayInputStream(is));
jaroslav@170
    68
        return sb.toString().toString();
jaroslav@170
    69
    }
jaroslav@170
    70
jaroslav@214
    71
    @JavaScriptBody(args = { "self", "n" }, 
jaroslav@214
    72
        body=
jaroslav@248
    73
          "var cls = n.replace__Ljava_lang_String_2CC(n,'/','_').toString();"
jaroslav@277
    74
        + "var loader = self.fld_loader;"
jaroslav@277
    75
        + "var vm = loader.vm;"
jaroslav@277
    76
        + "if (vm[cls]) return false;"
jaroslav@277
    77
        + "vm[cls] = function() {"
jaroslav@277
    78
        + "  return loader.loadClass(n,cls);"
jaroslav@214
    79
        + "};"
jaroslav@214
    80
        + "return true;"
jaroslav@214
    81
    )
jaroslav@170
    82
    @Override
jaroslav@170
    83
    protected boolean requireReference(String internalClassName) {
jaroslav@214
    84
        throw new UnsupportedOperationException();
jaroslav@170
    85
    }
jaroslav@170
    86
jaroslav@170
    87
    @Override
jaroslav@170
    88
    protected void requireScript(String resourcePath) {
jaroslav@170
    89
    }
jaroslav@213
    90
jaroslav@213
    91
    @Override
jaroslav@277
    92
    String assignClass(String className) {
jaroslav@277
    93
        return "vm[arguments[1]]=";
jaroslav@277
    94
    }
jaroslav@277
    95
jaroslav@277
    96
    @Override
jaroslav@277
    97
    String accessClass(String classOperation) {
jaroslav@277
    98
        return "vm." + classOperation;
jaroslav@213
    99
    }
jaroslav@170
   100
}