Being able to compile resources into the generated JavaScript file and use them. closure
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 28 Apr 2014 10:59:12 +0200
branchclosure
changeset 1495d5dd07b45f79
parent 1494 3b03a81af4b1
child 1496 d3df935aff70
Being able to compile resources into the generated JavaScript file and use them.
rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java
rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesTest.java
rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java
     1.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Mon Apr 28 08:54:51 2014 +0200
     1.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Mon Apr 28 10:59:12 2014 +0200
     1.3 @@ -253,6 +253,10 @@
     1.4      String[] allClasses() {
     1.5          return classes.addAndNew(rootcls.toArray()).toArray();
     1.6      }
     1.7 +    StringArray allResources() {
     1.8 +        return resources;
     1.9 +    }
    1.10 +
    1.11      
    1.12      StringArray rootClasses() {
    1.13          return rootcls;
     2.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Mon Apr 28 08:54:51 2014 +0200
     2.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Mon Apr 28 10:59:12 2014 +0200
     2.3 @@ -19,6 +19,7 @@
     2.4  
     2.5  import java.io.IOException;
     2.6  import java.io.InputStream;
     2.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     2.8  import org.apidesign.vm4brwsr.ByteCodeParser.ClassData;
     2.9  import org.apidesign.vm4brwsr.ByteCodeParser.FieldData;
    2.10  import org.apidesign.vm4brwsr.ByteCodeParser.MethodData;
    2.11 @@ -79,10 +80,10 @@
    2.12              fixedNames.add(fixedClass.getName().replace('.', '/'));
    2.13          }
    2.14  
    2.15 -        vm.doCompile(fixedNames.addAndNew(both));
    2.16 +        vm.doCompile(fixedNames.addAndNew(both), config.allResources());
    2.17      }
    2.18  
    2.19 -    private void doCompile(StringArray names) throws IOException {
    2.20 +    private void doCompile(StringArray names, StringArray asBinary) throws IOException {
    2.21          generatePrologue();
    2.22          out.append(
    2.23                  "\n  var invoker = function Invoker() {"
    2.24 @@ -97,10 +98,29 @@
    2.25                             + "\n    return invoker;"
    2.26                             + "\n  };");
    2.27          }
    2.28 +        
    2.29 +        for (String r : asBinary.toArray()) {
    2.30 +            out.append("\n  ").append(getExportsObject()).append(".registerResource('");
    2.31 +            out.append(r).append("', '");
    2.32 +            InputStream is = this.resources.get(r);
    2.33 +            byte[] arr = new byte[is.available()];
    2.34 +            int len = is.read(arr);
    2.35 +            if (len != arr.length) {
    2.36 +                throw new IOException("Not read as much as expected for " + r + " expected: " + arr.length + " was: " + len);
    2.37 +            }
    2.38 +            out.append(btoa(arr));
    2.39 +            out.append("');");
    2.40 +        }
    2.41 +        
    2.42          out.append("\n");
    2.43          generateEpilogue();
    2.44      }
    2.45  
    2.46 +    @JavaScriptBody(args = { "arr" }, body = "return btoa(arr);")
    2.47 +    private static String btoa(byte[] arr) {
    2.48 +        return javax.xml.bind.DatatypeConverter.printBase64Binary(arr);
    2.49 +    }
    2.50 +
    2.51      protected abstract void generatePrologue() throws IOException;
    2.52  
    2.53      protected abstract void generateEpilogue() throws IOException;
    2.54 @@ -435,10 +455,19 @@
    2.55                  + "  var extensions = [];\n"
    2.56                  + "  global.bck2brwsr = function() {\n"
    2.57                  + "    var args = Array.prototype.slice.apply(arguments);\n"
    2.58 -                + "    var vm = fillInVMSkeleton({});\n"
    2.59 +                + "    var resources = {};\n"
    2.60 +                + "    function registerResource(n, a64) {\n"
    2.61 +                + "      var str = atob(a64);\n"
    2.62 +                + "      var arr = [];\n"
    2.63 +                + "      for (var i = 0; i < str.length; i++) arr.push(str.charCodeAt(i) & 0xff);\n"
    2.64 +                + "      if (!resources[n]) resources[n] = [arr];\n"
    2.65 +                + "      else resources[n].push(arr);\n"
    2.66 +                + "    }\n"
    2.67 +                + "    var vm = fillInVMSkeleton({ 'registerResource' : registerResource });\n"
    2.68                  + "    for (var i = 0; i < extensions.length; ++i) {\n"
    2.69                  + "      extensions[i](vm);\n"
    2.70                  + "    }\n"
    2.71 +                + "    vm.registerResource = null;\n"
    2.72                  + "    var knownExtensions = extensions.length;\n"
    2.73                  + "    var loader = {};\n"
    2.74                  + "    loader.vm = vm;\n"
    2.75 @@ -451,7 +480,9 @@
    2.76                  + "          load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
    2.77                  + "      } catch (err) {\n"
    2.78                  + "        while (knownExtensions < extensions.length) {\n"
    2.79 +                + "          vm.registerResource = registerResource;\n"
    2.80                  + "          extensions[knownExtensions++](vm);\n"
    2.81 +                + "          vm.registerResource = null;\n"
    2.82                  + "        }\n"
    2.83                  + "        fn = vm[attr];\n"
    2.84                  + "        if (fn) return fn(false);\n"
    2.85 @@ -463,6 +494,7 @@
    2.86                  + "    }\n"
    2.87                  + "    vm.loadClass = loader.loadClass;\n"
    2.88                  + "    vm.loadBytes = function(name) {\n"
    2.89 +                + "      if (resources[name]) return resources[name][0];\n"
    2.90                  + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
    2.91                  + "        loadBytes___3BLjava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
    2.92                  + "    }\n"
     3.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java	Mon Apr 28 08:54:51 2014 +0200
     3.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Resources.java	Mon Apr 28 10:59:12 2014 +0200
     3.3 @@ -35,6 +35,7 @@
     3.4          if (len == -1) {
     3.5              return "No data read!";
     3.6          }
     3.7 -        return new String(arr, 0, len, "UTF-8");
     3.8 +        final Object str = new String(arr, 0, len, "UTF-8");
     3.9 +        return str.toString();
    3.10      }
    3.11  }
     4.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesTest.java	Mon Apr 28 08:54:51 2014 +0200
     4.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ResourcesTest.java	Mon Apr 28 10:59:12 2014 +0200
     4.3 @@ -17,8 +17,7 @@
     4.4   */
     4.5  package org.apidesign.vm4brwsr;
     4.6  
     4.7 -import javax.script.ScriptEngine;
     4.8 -import static org.testng.Assert.*;
     4.9 +import java.io.UnsupportedEncodingException;
    4.10  import org.testng.annotations.AfterClass;
    4.11  import org.testng.annotations.BeforeClass;
    4.12  import org.testng.annotations.Test;
    4.13 @@ -55,4 +54,8 @@
    4.14      ) throws Exception {
    4.15          code.assertExec(msg, clazz, method, ret, args);
    4.16      }
    4.17 +    
    4.18 +    public static String parseBase64Binary(String s) throws UnsupportedEncodingException {
    4.19 +        return new String(javax.xml.bind.DatatypeConverter.parseBase64Binary(s), "UTF-8");
    4.20 +    }
    4.21  }
     5.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Mon Apr 28 08:54:51 2014 +0200
     5.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Mon Apr 28 10:59:12 2014 +0200
     5.3 @@ -169,6 +169,11 @@
     5.4              eng[0] = js;
     5.5          }
     5.6          try {
     5.7 +            js.eval("atob = function(s) { return org.apidesign.vm4brwsr.ResourcesTest.parseBase64Binary(s); }");
     5.8 +            
     5.9 +            Object ahoj = js.eval("atob('QWhvag==')");
    5.10 +            assertEquals(ahoj, "Ahoj", "Verify the atob function behaves properly");
    5.11 +            
    5.12              Object res = js.eval(sb.toString());
    5.13              assertTrue(js instanceof Invocable, "It is invocable object: " + res);
    5.14              return new TestVM((Invocable) js, sb);