1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/benchmarks/matrix-multiplication/jsTestDriver.conf Fri Dec 14 11:15:37 2012 +0100
1.3 @@ -0,0 +1,5 @@
1.4 +server: http://localhost:9876
1.5 +
1.6 +load:
1.7 + - target/classes/org/apidesign/benchmark/matrixmul/*.js
1.8 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/benchmarks/matrix-multiplication/nbactions.xml Fri Dec 14 11:15:37 2012 +0100
2.3 @@ -0,0 +1,29 @@
2.4 +<?xml version="1.0" encoding="UTF-8"?>
2.5 +<!--
2.6 +
2.7 + Back 2 Browser Bytecode Translator
2.8 + Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.9 +
2.10 + This program is free software: you can redistribute it and/or modify
2.11 + it under the terms of the GNU General Public License as published by
2.12 + the Free Software Foundation, version 2 of the License.
2.13 +
2.14 + This program is distributed in the hope that it will be useful,
2.15 + but WITHOUT ANY WARRANTY; without even the implied warranty of
2.16 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.17 + GNU General Public License for more details.
2.18 +
2.19 + You should have received a copy of the GNU General Public License
2.20 + along with this program. Look for COPYING file in the top folder.
2.21 + If not, see http://opensource.org/licenses/GPL-2.0.
2.22 +
2.23 +-->
2.24 +<actions>
2.25 + <action>
2.26 + <actionName>run</actionName>
2.27 + <goals>
2.28 + <goal>process-classes</goal>
2.29 + <goal>org.codehaus.mojo:exec-maven-plugin:1.2.1:exec</goal>
2.30 + </goals>
2.31 + </action>
2.32 +</actions>
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/benchmarks/matrix-multiplication/pom.xml Fri Dec 14 11:15:37 2012 +0100
3.3 @@ -0,0 +1,111 @@
3.4 +<?xml version="1.0"?>
3.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3.6 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3.7 + <modelVersion>4.0.0</modelVersion>
3.8 +
3.9 + <groupId>org.apidesign.bck2brwsr</groupId>
3.10 + <artifactId>matrix.multiplication</artifactId>
3.11 + <version>0.3-SNAPSHOT</version>
3.12 + <packaging>jar</packaging>
3.13 +
3.14 + <name>Matrix multiplication</name>
3.15 +
3.16 + <properties>
3.17 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3.18 + </properties>
3.19 +
3.20 + <build>
3.21 + <plugins>
3.22 + <plugin>
3.23 + <groupId>org.apache.maven.plugins</groupId>
3.24 + <artifactId>maven-compiler-plugin</artifactId>
3.25 + <version>2.3.2</version>
3.26 + <configuration>
3.27 + <source>1.7</source>
3.28 + <target>1.7</target>
3.29 + </configuration>
3.30 + </plugin>
3.31 +
3.32 + <plugin>
3.33 + <groupId>org.apidesign.bck2brwsr</groupId>
3.34 + <artifactId>mojo</artifactId>
3.35 + <version>0.3-SNAPSHOT</version>
3.36 + <executions>
3.37 + <execution>
3.38 + <goals>
3.39 + <goal>j2js</goal>
3.40 + </goals>
3.41 + </execution>
3.42 + </executions>
3.43 + </plugin>
3.44 +
3.45 + </plugins>
3.46 + </build>
3.47 +
3.48 + <profiles>
3.49 + <profile>
3.50 + <id>run-benchmarks</id>
3.51 + <activation>
3.52 + <property><name>bck2brwsr.runBenchmarks.browsers</name></property>
3.53 + </activation>
3.54 +
3.55 + <build>
3.56 + <plugins>
3.57 +
3.58 + <plugin>
3.59 + <groupId>com.googlecode.jstd-maven-plugin</groupId>
3.60 + <artifactId>jstd-maven-plugin</artifactId>
3.61 + <version>1.3.2.5</version>
3.62 + <configuration>
3.63 + <port>9876</port>
3.64 + <browser>${bck2brwsr.runBenchmarks.browsers}</browser>
3.65 + <browserTimeout>720</browserTimeout>
3.66 + <tests>all</tests>
3.67 + <config>jsTestDriver.conf</config>
3.68 + <reset>true</reset>
3.69 + <testOutput>${basedir}/target/testOutput</testOutput>
3.70 + <!-- runnerMode>DEBUG</runnerMode -->
3.71 + </configuration>
3.72 + <executions>
3.73 + <execution>
3.74 + <id>run-tests</id>
3.75 + <goals>
3.76 + <goal>test</goal>
3.77 + </goals>
3.78 + </execution>
3.79 + </executions>
3.80 + </plugin>
3.81 +
3.82 + </plugins>
3.83 + </build>
3.84 + </profile>
3.85 + </profiles>
3.86 +
3.87 + <dependencies>
3.88 + <dependency>
3.89 + <groupId>org.apidesign.bck2brwsr</groupId>
3.90 + <artifactId>emul</artifactId>
3.91 + <version>0.3-SNAPSHOT</version>
3.92 + </dependency>
3.93 + <dependency>
3.94 + <groupId>com.googlecode.jstd-maven-plugin</groupId>
3.95 + <artifactId>jstd-maven-plugin</artifactId>
3.96 + <version>1.3.2.5</version>
3.97 + <scope>test</scope>
3.98 + </dependency>
3.99 + </dependencies>
3.100 +
3.101 + <repositories>
3.102 + <repository>
3.103 + <id>jstd-maven-plugin google code repo</id>
3.104 + <url>http://jstd-maven-plugin.googlecode.com/svn/maven2</url>
3.105 + </repository>
3.106 + </repositories>
3.107 + <pluginRepositories>
3.108 + <pluginRepository>
3.109 + <id>jstd-maven-plugin google code repo</id>
3.110 + <url>http://jstd-maven-plugin.googlecode.com/svn/maven2</url>
3.111 + </pluginRepository>
3.112 + </pluginRepositories>
3.113 +
3.114 +</project>
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Main.java Fri Dec 14 11:15:37 2012 +0100
4.3 @@ -0,0 +1,42 @@
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.benchmark.matrixmul;
4.22 +
4.23 +public class Main {
4.24 +
4.25 + public static final int ITERATION_COUNT = 100000;
4.26 +
4.27 + public static void main(String[] args) {
4.28 + Matrix m1 = new Matrix(5);
4.29 + Matrix m2 = new Matrix(5);
4.30 +
4.31 + m1.generateData();
4.32 + m2.generateData();
4.33 +
4.34 + //m1.printOn(System.out);
4.35 + //System.out.println("x");
4.36 + //m2.printOn(System.out);
4.37 +
4.38 + for (int i = 0; i < ITERATION_COUNT; i++) {
4.39 + m1.multiply(m2);
4.40 + }
4.41 +
4.42 + //System.out.println("=");
4.43 + //m1.printOn(System.out);
4.44 + }
4.45 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Matrix.java Fri Dec 14 11:15:37 2012 +0100
5.3 @@ -0,0 +1,81 @@
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.benchmark.matrixmul;
5.22 +
5.23 +//import java.io.PrintStream;
5.24 +//import java.util.Random;
5.25 +
5.26 +public class Matrix {
5.27 +
5.28 + private final int rank;
5.29 + private float data[][];
5.30 +
5.31 + public Matrix(int r) {
5.32 + rank = r;
5.33 + data = new float[r][r];
5.34 + }
5.35 +
5.36 + public void setElement(int i, int j, float value) {
5.37 + data[i][j] = value;
5.38 + }
5.39 + public float getElement(int i, int j) {
5.40 + return data[i][j];
5.41 + }
5.42 +
5.43 + public void generateData() {
5.44 + //final Random rand = new Random();
5.45 + //final int x = 10;
5.46 + for (int i = 0; i < rank; i++) {
5.47 + for (int j = 0; j < rank; j++) {
5.48 + data[i][j] = i + j;
5.49 + }
5.50 + }
5.51 + }
5.52 +
5.53 + public Matrix multiply(Matrix m) {
5.54 + if (rank != m.rank) {
5.55 + throw new IllegalArgumentException("Rank doesn't match");
5.56 + }
5.57 +
5.58 + final float res[][] = new float[rank][rank];
5.59 + for (int i = 0; i < rank; i++) {
5.60 + for (int j = 0; j < rank; j++) {
5.61 + float ij = 0;
5.62 + for (int q = 0; q < rank; q++) {
5.63 + ij += data[i][q] * m.data[q][j];
5.64 + }
5.65 + res[i][j] = ij;
5.66 + }
5.67 + }
5.68 + data = res;
5.69 +
5.70 + return this;
5.71 + }
5.72 +
5.73 + /*
5.74 + public void printOn(PrintStream s) {
5.75 + for (int i = 0; i < rank; i++) {
5.76 + for (int j = 0; j < rank; j++) {
5.77 + s.printf("%f ", data[i][j]);
5.78 + }
5.79 + s.println();
5.80 + }
5.81 + }
5.82 + */
5.83 +
5.84 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/benchmarks/matrix-multiplication/src/main/resources/org/apidesign/benchmark/matrixmul/multiplication-test.js Fri Dec 14 11:15:37 2012 +0100
6.3 @@ -0,0 +1,25 @@
6.4 +/*
6.5 + * Back 2 Browser Bytecode Translator
6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
6.7 + *
6.8 + * This program is free software: you can redistribute it and/or modify
6.9 + * it under the terms of the GNU General Public License as published by
6.10 + * the Free Software Foundation, version 2 of the License.
6.11 + *
6.12 + * This program is distributed in the hope that it will be useful,
6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.15 + * GNU General Public License for more details.
6.16 + *
6.17 + * You should have received a copy of the GNU General Public License
6.18 + * along with this program. Look for COPYING file in the top folder.
6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
6.20 + */
6.21 +MatrixTest = TestCase("MatrixTest");
6.22 +
6.23 +
6.24 +MatrixTest.prototype.testMultiplication = function() {
6.25 + var vm = new bck2brwsr();
6.26 + var x = vm.loadClass("org.apidesign.benchmark.matrixmul.Main");
6.27 + x.main__V_3Ljava_lang_String_2(null);
6.28 +};
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/benchmarks/pom.xml Fri Dec 14 11:15:37 2012 +0100
7.3 @@ -0,0 +1,17 @@
7.4 +<?xml version="1.0" encoding="UTF-8"?>
7.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
7.6 + <modelVersion>4.0.0</modelVersion>
7.7 + <parent>
7.8 + <artifactId>bck2brwsr</artifactId>
7.9 + <groupId>org.apidesign</groupId>
7.10 + <version>0.3-SNAPSHOT</version>
7.11 + </parent>
7.12 + <groupId>org.apidesign.bck2brwsr</groupId>
7.13 + <artifactId>benchmarks</artifactId>
7.14 + <version>0.3-SNAPSHOT</version>
7.15 + <packaging>pom</packaging>
7.16 + <name>Performance benchmarks</name>
7.17 + <modules>
7.18 + <module>matrix-multiplication</module>
7.19 + </modules>
7.20 +</project>
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/benchmarks/run-firefox.sh Fri Dec 14 11:15:37 2012 +0100
8.3 @@ -0,0 +1,20 @@
8.4 +#!/bin/bash
8.5 +#
8.6 +# Back 2 Browser Bytecode Translator
8.7 +# Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
8.8 +#
8.9 +# This program is free software: you can redistribute it and/or modify
8.10 +# it under the terms of the GNU General Public License as published by
8.11 +# the Free Software Foundation, version 2 of the License.
8.12 +#
8.13 +# This program is distributed in the hope that it will be useful,
8.14 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
8.15 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.16 +# GNU General Public License for more details.
8.17 +#
8.18 +# You should have received a copy of the GNU General Public License
8.19 +# along with this program. Look for COPYING file in the top folder.
8.20 +# If not, see http://opensource.org/licenses/GPL-2.0.
8.21 +#
8.22 +
8.23 +/usr/bin/firefox --display=`echo $DISPLAY` "$@"
9.1 --- a/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java Wed Dec 12 14:07:53 2012 +0100
9.2 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java Fri Dec 14 11:15:37 2012 +0100
9.3 @@ -29,10 +29,13 @@
9.4 @Target({ ElementType.TYPE })
9.5 public @interface JavaScriptPrototype {
9.6 /** Expression that identifies the function where all methods
9.7 - * should be added into.
9.8 + * should be added into. If this attribute is unspecified
9.9 + * all methods are added to the same object specified by
9.10 + * {@link #prototype()}.
9.11 + *
9.12 * @return name of function to contain methods found in given class
9.13 */
9.14 - String container();
9.15 + String container() default "";
9.16 /** Expression that defines the way to construct prototype for this
9.17 * class.
9.18 * @return expression to construct prototype
10.1 --- a/emul/src/main/java/java/lang/String.java Wed Dec 12 14:07:53 2012 +0100
10.2 +++ b/emul/src/main/java/java/lang/String.java Fri Dec 14 11:15:37 2012 +0100
10.3 @@ -1426,7 +1426,7 @@
10.4 */
10.5 @JavaScriptBody(args = { "self", "find", "from" }, body=
10.6 "find = find.toString();\n" +
10.7 - "return self.toString().substring(from, find.length) === find;\n"
10.8 + "return self.toString().substring(from, from + find.length) === find;\n"
10.9 )
10.10 public boolean startsWith(String prefix, int toffset) {
10.11 char ta[] = toCharArray();
11.1 --- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Wed Dec 12 14:07:53 2012 +0100
11.2 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Fri Dec 14 11:15:37 2012 +0100
11.3 @@ -1,5 +1,5 @@
11.4 // initialize methods on String constants
11.5 -java_lang_String(false);
11.6 +vm.java_lang_String(false);
11.7
11.8 // we need initialized arrays
11.9 Array.prototype.fillNulls = function() {
12.1 --- a/javap/src/main/java/org/apidesign/javap/ClassData.java Wed Dec 12 14:07:53 2012 +0100
12.2 +++ b/javap/src/main/java/org/apidesign/javap/ClassData.java Fri Dec 14 11:15:37 2012 +0100
12.3 @@ -554,14 +554,14 @@
12.4 return in.toString();
12.5 }
12.6 case CONSTANT_CLASS:
12.7 - String jn = javaName(getClassName(cpx));
12.8 + String jn = getClassName(cpx);
12.9 if (textual) {
12.10 if (refs != null) {
12.11 refs[0] = jn;
12.12 }
12.13 - return jn.replace('/', '_') + "(false).constructor.$class";
12.14 + return jn;
12.15 }
12.16 - return jn;
12.17 + return javaName(jn);
12.18 case CONSTANT_STRING:
12.19 String sv = stringValue(((CPX)x).cpx, textual);
12.20 if (textual) {
13.1 --- a/javap/src/main/java/org/apidesign/javap/Hashtable.java Wed Dec 12 14:07:53 2012 +0100
13.2 +++ b/javap/src/main/java/org/apidesign/javap/Hashtable.java Fri Dec 14 11:15:37 2012 +0100
13.3 @@ -4,6 +4,8 @@
13.4 */
13.5 package org.apidesign.javap;
13.6
13.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
13.8 +
13.9 /** A JavaScript optimized replacement for Hashtable.
13.10 *
13.11 * @author Jaroslav Tulach <jtulach@netbeans.org>
13.12 @@ -23,6 +25,9 @@
13.13 Hashtable() {
13.14 }
13.15
13.16 + @JavaScriptBody(args = { "self", "key", "val" }, body =
13.17 + "self[key] = val;"
13.18 + )
13.19 synchronized void put(Object key, Object val) {
13.20 int[] where = { -1, -1 };
13.21 Object found = get(key, where);
13.22 @@ -56,6 +61,9 @@
13.23 }
13.24 }
13.25
13.26 + @JavaScriptBody(args = {"self", "key" }, body =
13.27 + "return self[key];"
13.28 + )
13.29 Object get(Object key) {
13.30 return get(key, null);
13.31 }
14.1 --- a/javap/src/main/java/org/apidesign/javap/Vector.java Wed Dec 12 14:07:53 2012 +0100
14.2 +++ b/javap/src/main/java/org/apidesign/javap/Vector.java Fri Dec 14 11:15:37 2012 +0100
14.3 @@ -4,10 +4,14 @@
14.4 */
14.5 package org.apidesign.javap;
14.6
14.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
14.8 +import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
14.9 +
14.10 /** A JavaScript ready replacement for java.util.Vector
14.11 *
14.12 * @author Jaroslav Tulach <jtulach@netbeans.org>
14.13 */
14.14 +@JavaScriptPrototype(prototype = "new Array" )
14.15 final class Vector {
14.16 private Object[] arr;
14.17
14.18 @@ -15,22 +19,31 @@
14.19 }
14.20
14.21 Vector(int i) {
14.22 - this();
14.23 }
14.24
14.25 void add(Object objectType) {
14.26 addElement(objectType);
14.27 }
14.28 + @JavaScriptBody(args = { "self", "obj" }, body =
14.29 + "self.push(obj);"
14.30 + )
14.31 void addElement(Object obj) {
14.32 final int s = size();
14.33 setSize(s + 1);
14.34 setElementAt(obj, s);
14.35 }
14.36
14.37 + @JavaScriptBody(args = { "self" }, body =
14.38 + "return self.length;"
14.39 + )
14.40 int size() {
14.41 return arr == null ? 0 : arr.length;
14.42 }
14.43
14.44 + @JavaScriptBody(args = { "self", "newArr" }, body =
14.45 + "for (var i = 0; i < self.length; i++) {\n"
14.46 + + " newArr[i] = self[i];\n"
14.47 + + "}\n")
14.48 void copyInto(Object[] newArr) {
14.49 if (arr == null) {
14.50 return;
14.51 @@ -41,16 +54,22 @@
14.52 }
14.53 }
14.54
14.55 + @JavaScriptBody(args = { "self", "index" }, body =
14.56 + "return self[index];"
14.57 + )
14.58 Object elementAt(int index) {
14.59 return arr[index];
14.60 }
14.61
14.62 - void setSize(int len) {
14.63 + private void setSize(int len) {
14.64 Object[] newArr = new Object[len];
14.65 copyInto(newArr);
14.66 arr = newArr;
14.67 }
14.68
14.69 + @JavaScriptBody(args = { "self", "val", "index" }, body =
14.70 + "self[index] = val;"
14.71 + )
14.72 void setElementAt(Object val, int index) {
14.73 arr[index] = val;
14.74 }
15.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Wed Dec 12 14:07:53 2012 +0100
15.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java Fri Dec 14 11:15:37 2012 +0100
15.3 @@ -19,12 +19,12 @@
15.4
15.5 import java.io.IOException;
15.6 import java.io.InputStream;
15.7 -import java.lang.reflect.Method;
15.8 import java.util.Set;
15.9 import javax.script.Invocable;
15.10 import javax.script.ScriptEngine;
15.11 import javax.script.ScriptEngineManager;
15.12 import javax.script.ScriptException;
15.13 +import org.apidesign.vm4brwsr.Bck2Brwsr;
15.14 import org.testng.annotations.Test;
15.15 import static org.testng.Assert.*;
15.16
15.17 @@ -125,15 +125,7 @@
15.18 if (sb == null) {
15.19 sb = new StringBuilder();
15.20 }
15.21 - try {
15.22 - Method m;
15.23 - Class<?> genJS = Class.forName("org.apidesign.vm4brwsr.GenJS");
15.24 - m = genJS.getDeclaredMethod("compile", Appendable.class, String[].class);
15.25 - m.setAccessible(true);
15.26 - m.invoke(null, sb, names);
15.27 - } catch (Exception exception) {
15.28 - throw new IOException(exception);
15.29 - }
15.30 + Bck2Brwsr.generate(sb, ProcessPageTest.class.getClassLoader(), names);
15.31 ScriptEngineManager sem = new ScriptEngineManager();
15.32 ScriptEngine js = sem.getEngineByExtension("js");
15.33 try {
16.1 --- a/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java Wed Dec 12 14:07:53 2012 +0100
16.2 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java Fri Dec 14 11:15:37 2012 +0100
16.3 @@ -70,6 +70,10 @@
16.4 private static void setValue(double v) {
16.5 StringBuilder sb = new StringBuilder();
16.6 sb.append(v);
16.7 + if (sb.toString().endsWith(".0")) {
16.8 + final int l = sb.length();
16.9 + sb.delete(l - 2, l);
16.10 + }
16.11 Calculator.DISPLAY.setValue(sb.toString());
16.12 }
16.13
17.1 --- a/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java Wed Dec 12 14:07:53 2012 +0100
17.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Bck2BrswrMojo.java Fri Dec 14 11:15:37 2012 +0100
17.3 @@ -21,7 +21,7 @@
17.4
17.5 import java.io.File;
17.6 import java.io.FileWriter;
17.7 -import java.lang.reflect.Method;
17.8 +import java.io.IOException;
17.9 import java.net.MalformedURLException;
17.10 import java.net.URL;
17.11 import java.net.URLClassLoader;
17.12 @@ -34,6 +34,7 @@
17.13 import org.apache.maven.plugins.annotations.Mojo;
17.14 import org.apache.maven.plugins.annotations.Parameter;
17.15 import org.apache.maven.project.MavenProject;
17.16 +import org.apidesign.vm4brwsr.Bck2Brwsr;
17.17
17.18 /** Compiles classes into JavaScript. */
17.19 @Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
17.20 @@ -72,14 +73,10 @@
17.21
17.22 try {
17.23 URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
17.24 -
17.25 - Class<?> c = Class.forName("org.apidesign.vm4brwsr.GenJS");
17.26 - Method m = c.getDeclaredMethod("compile", ClassLoader.class, Appendable.class, String[].class);
17.27 - m.setAccessible(true);
17.28 FileWriter w = new FileWriter(javascript);
17.29 - m.invoke(null, url, w, arr.toArray(new String[0]));
17.30 + Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
17.31 w.close();
17.32 - } catch (Exception ex) {
17.33 + } catch (IOException ex) {
17.34 throw new MojoExecutionException("Can't compile", ex);
17.35 }
17.36 }
18.1 --- a/pom.xml Wed Dec 12 14:07:53 2012 +0100
18.2 +++ b/pom.xml Fri Dec 14 11:15:37 2012 +0100
18.3 @@ -13,6 +13,7 @@
18.4 <module>mojo</module>
18.5 <module>javaquery</module>
18.6 <module>javap</module>
18.7 + <module>benchmarks</module>
18.8 </modules>
18.9 <licenses>
18.10 <license>
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java Fri Dec 14 11:15:37 2012 +0100
19.3 @@ -0,0 +1,106 @@
19.4 +/**
19.5 + * Back 2 Browser Bytecode Translator
19.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
19.7 + *
19.8 + * This program is free software: you can redistribute it and/or modify
19.9 + * it under the terms of the GNU General Public License as published by
19.10 + * the Free Software Foundation, version 2 of the License.
19.11 + *
19.12 + * This program is distributed in the hope that it will be useful,
19.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
19.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19.15 + * GNU General Public License for more details.
19.16 + *
19.17 + * You should have received a copy of the GNU General Public License
19.18 + * along with this program. Look for COPYING file in the top folder.
19.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
19.20 + */
19.21 +package org.apidesign.vm4brwsr;
19.22 +
19.23 +import java.io.IOException;
19.24 +import java.io.InputStream;
19.25 +import java.net.URL;
19.26 +import java.util.Enumeration;
19.27 +
19.28 +/** Build your own virtual machine! Use methods in this class to generate
19.29 + * a skeleton JVM in JavaScript that contains pre-compiled classes of your
19.30 + * choice. The generated script defines one JavaScript method that can
19.31 + * be used to bootstrap and load the virtual machine: <pre>
19.32 + * var vm = bck2brwsr();
19.33 + * var main = vm.loadClass('org.your.pkg.Main');
19.34 + * main.main__V_3Ljava_lang_String_2(null);
19.35 + * </pre>
19.36 + * In case one wants to initialize the virtual machine with ability to
19.37 + * load classes lazily when needed, one can provide a loader function to
19.38 + * when creating the virtual machine: <pre>
19.39 + * var vm = bck2brwsr(function(resource) {
19.40 + * return null; // byte[] for the resource
19.41 + * });
19.42 + * </pre>
19.43 + * In this scenario, when a request for a unknown class is made, the loader
19.44 + * function is asked for its byte code and the system dynamically transforms
19.45 + * it to JavaScript.
19.46 + *
19.47 + * @author Jaroslav Tulach <jtulach@netbeans.org>
19.48 + */
19.49 +public final class Bck2Brwsr {
19.50 + private Bck2Brwsr() {
19.51 + }
19.52 +
19.53 + /** Generates virtual machine from bytes served by a <code>resources</code>
19.54 + * provider.
19.55 + *
19.56 + * @param out the output to write the generated JavaScript to
19.57 + * @param resources provider of class files to use
19.58 + * @param classes additional classes to include in the generated script
19.59 + * @throws IOException I/O exception can be thrown when something goes wrong
19.60 + */
19.61 + public static void generate(Appendable out, Resources resources, String... classes) throws IOException {
19.62 + StringArray arr = StringArray.asList(classes);
19.63 + arr.add(VM.class.getName().replace('.', '/'));
19.64 + VM.compile(resources, out, arr);
19.65 + }
19.66 +
19.67 + /** Generates virtual machine from bytes served by a class loader.
19.68 + *
19.69 + * @param out the output to write the generated JavaScript to
19.70 + * @param loader class loader to load needed classes from
19.71 + * @param classes additional classes to include in the generated script
19.72 + * @throws IOException I/O exception can be thrown when something goes wrong
19.73 + */
19.74 + public static void generate(Appendable out, final ClassLoader loader, String... classes) throws IOException {
19.75 + class R implements Resources {
19.76 + @Override
19.77 + public InputStream get(String name) throws IOException {
19.78 + Enumeration<URL> en = loader.getResources(name);
19.79 + URL u = null;
19.80 + while (en.hasMoreElements()) {
19.81 + u = en.nextElement();
19.82 + }
19.83 + if (u == null) {
19.84 + throw new IOException("Can't find " + name);
19.85 + }
19.86 + return u.openStream();
19.87 + }
19.88 + }
19.89 + generate(out, new R(), classes);
19.90 + }
19.91 +
19.92 + /** Provider of resources (classes and other files). The
19.93 + * {@link #generate(java.lang.Appendable, org.apidesign.vm4brwsr.Bck2Brwsr.Resources, java.lang.String[])
19.94 + * generator method} will call back here for all classes needed during
19.95 + * translation to JavaScript.
19.96 + */
19.97 + public interface Resources {
19.98 + /** Loads given resource (class or other file like image). The
19.99 + * resource name to load bytes for the {@link String} class
19.100 + * would be <code>"java/lang/String.class"</code>.
19.101 + *
19.102 + * @param resource path to resource to load
19.103 + * @return the input stream for the resource
19.104 + * @throws IOException can be thrown if the loading fails on some error
19.105 + * or the file cannot be found
19.106 + */
19.107 + public InputStream get(String resource) throws IOException;
19.108 + }
19.109 +}
20.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Dec 12 14:07:53 2012 +0100
20.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Fri Dec 14 11:15:37 2012 +0100
20.3 @@ -19,6 +19,7 @@
20.4
20.5 import java.io.IOException;
20.6 import java.io.InputStream;
20.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
20.8 import org.apidesign.javap.AnnotationParser;
20.9 import org.apidesign.javap.ClassData;
20.10 import org.apidesign.javap.FieldData;
20.11 @@ -30,7 +31,7 @@
20.12 *
20.13 * @author Jaroslav Tulach <jtulach@netbeans.org>
20.14 */
20.15 -public abstract class ByteCodeToJavaScript {
20.16 +abstract class ByteCodeToJavaScript {
20.17 private ClassData jc;
20.18 final Appendable out;
20.19
20.20 @@ -57,9 +58,12 @@
20.21 *
20.22 * @param className suggested name of the class
20.23 */
20.24 - protected String assignClass(String className) {
20.25 + /* protected */ String assignClass(String className) {
20.26 return className + " = ";
20.27 }
20.28 + /* protected */ String accessClass(String classOperation) {
20.29 + return classOperation;
20.30 + }
20.31
20.32 /**
20.33 * Converts a given class file to a JavaScript version.
20.34 @@ -100,12 +104,15 @@
20.35 if (proto == null) {
20.36 String sc = jc.getSuperClassName(); // with _
20.37 out.append("\n var pp = ").
20.38 - append(sc.replace('/', '_')).append("(true);");
20.39 + append(accessClass(sc.replace('/', '_'))).append("(true);");
20.40 out.append("\n var p = CLS.prototype = pp;");
20.41 out.append("\n var c = p;");
20.42 out.append("\n var sprcls = pp.constructor.$class;");
20.43 } else {
20.44 out.append("\n var p = CLS.prototype = ").append(proto[1]).append(";");
20.45 + if (proto[0] == null) {
20.46 + proto[0] = "p";
20.47 + }
20.48 out.append("\n var c = ").append(proto[0]).append(";");
20.49 out.append("\n var sprcls = null;");
20.50 }
20.51 @@ -140,7 +147,8 @@
20.52 for (String superInterface : jc.getSuperInterfaces()) {
20.53 out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
20.54 }
20.55 - out.append("\n CLS.$class = java_lang_Class(true);");
20.56 + out.append("\n CLS.$class = ");
20.57 + out.append(accessClass("java_lang_Class(true);"));
20.58 out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
20.59 out.append("\n CLS.$class.superclass = sprcls;");
20.60 out.append("\n CLS.$class.cnstr = CLS;");
20.61 @@ -190,7 +198,7 @@
20.62 }
20.63 final String mn = findMethodName(m, new StringBuilder());
20.64 if (mn.equals("class__V")) {
20.65 - toInitilize.add(className(jc) + "(false)." + mn);
20.66 + toInitilize.add(accessClass(className(jc)) + "(false)." + mn);
20.67 }
20.68 generateMethod(prefix, mn, m);
20.69 return mn;
20.70 @@ -849,7 +857,7 @@
20.71 int indx = readIntArg(byteCodes, i);
20.72 String ci = jc.getClassName(indx);
20.73 emit(out, "@1 = new @2;",
20.74 - smapper.pushA(), ci.replace('/', '_'));
20.75 + smapper.pushA(), accessClass(ci.replace('/', '_')));
20.76 addReference(ci);
20.77 i += 2;
20.78 break;
20.79 @@ -1017,7 +1025,8 @@
20.80 String[] fi = jc.getFieldInfoName(indx);
20.81 final int type = VarType.fromFieldType(fi[2].charAt(0));
20.82 emit(out, "@1 = @2.@3;",
20.83 - smapper.pushT(type), fi[0].replace('/', '_'), fi[1]);
20.84 + smapper.pushT(type),
20.85 + accessClass(fi[0].replace('/', '_')), fi[1]);
20.86 i += 2;
20.87 addReference(fi[0]);
20.88 break;
20.89 @@ -1036,7 +1045,8 @@
20.90 String[] fi = jc.getFieldInfoName(indx);
20.91 final int type = VarType.fromFieldType(fi[2].charAt(0));
20.92 emit(out, "@1.@2 = @3;",
20.93 - fi[0].replace('/', '_'), fi[1], smapper.popT(type));
20.94 + accessClass(fi[0].replace('/', '_')), fi[1],
20.95 + smapper.popT(type));
20.96 i += 2;
20.97 addReference(fi[0]);
20.98 break;
20.99 @@ -1047,7 +1057,8 @@
20.100 if (!type.startsWith("[")) {
20.101 // no way to check arrays right now
20.102 // XXX proper exception
20.103 - emit(out, "if (@1.$instOf_@2 != 1) throw {};",
20.104 + emit(out,
20.105 + "if (@1 !== null && !@1.$instOf_@2) throw {};",
20.106 smapper.getA(0), type.replace('/', '_'));
20.107 }
20.108 i += 2;
20.109 @@ -1057,7 +1068,8 @@
20.110 int indx = readIntArg(byteCodes, i);
20.111 final String type = jc.getClassName(indx);
20.112 emit(out, "@2 = @1.$instOf_@3 ? 1 : 0;",
20.113 - smapper.popA(), smapper.pushI(), type.replace('/', '_'));
20.114 + smapper.popA(), smapper.pushI(),
20.115 + type.replace('/', '_'));
20.116 i += 2;
20.117 break;
20.118 }
20.119 @@ -1265,7 +1277,7 @@
20.120 }
20.121
20.122 final String in = mi[0];
20.123 - out.append(in.replace('/', '_'));
20.124 + out.append(accessClass(in.replace('/', '_')));
20.125 out.append("(false).");
20.126 out.append(mn);
20.127 out.append('(');
20.128 @@ -1339,6 +1351,7 @@
20.129 String s = jc.stringValue(entryIndex, classRef);
20.130 if (classRef[0] != null) {
20.131 addReference(classRef[0]);
20.132 + s = accessClass(s.replace('/', '_')) + "(false).constructor.$class";
20.133 }
20.134 return s;
20.135 }
20.136 @@ -1383,8 +1396,7 @@
20.137 String space;
20.138 int index;
20.139 if (!isStatic) {
20.140 - out.append(p.args[0]);
20.141 - space = ",";
20.142 + space = outputArg(out, p.args, 0);
20.143 index = 1;
20.144 } else {
20.145 space = "";
20.146 @@ -1392,9 +1404,8 @@
20.147 }
20.148 for (int i = 0; i < cnt.length(); i++) {
20.149 out.append(space);
20.150 - out.append(p.args[index]);
20.151 + space = outputArg(out, p.args, index);
20.152 index++;
20.153 - space = ",";
20.154 }
20.155 out.append(") {").append("\n");
20.156 out.append(p.body);
20.157 @@ -1487,6 +1498,18 @@
20.158 ap.parse(data, cd);
20.159 }
20.160
20.161 + private static String outputArg(Appendable out, String[] args, int indx) throws IOException {
20.162 + final String name = args[indx];
20.163 + if (name == null) {
20.164 + return "";
20.165 + }
20.166 + if (name.contains(",")) {
20.167 + throw new IOException("Wrong parameter with ',': " + name);
20.168 + }
20.169 + out.append(name);
20.170 + return ",";
20.171 + }
20.172 +
20.173 private static void emit(final Appendable out,
20.174 final String format,
20.175 final CharSequence... params) throws IOException {
20.176 @@ -1511,5 +1534,4 @@
20.177
20.178 out.append(format, processed, length);
20.179 }
20.180 -
20.181 }
21.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Wed Dec 12 14:07:53 2012 +0100
21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
21.3 @@ -1,198 +0,0 @@
21.4 -/**
21.5 - * Back 2 Browser Bytecode Translator
21.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
21.7 - *
21.8 - * This program is free software: you can redistribute it and/or modify
21.9 - * it under the terms of the GNU General Public License as published by
21.10 - * the Free Software Foundation, version 2 of the License.
21.11 - *
21.12 - * This program is distributed in the hope that it will be useful,
21.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
21.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21.15 - * GNU General Public License for more details.
21.16 - *
21.17 - * You should have received a copy of the GNU General Public License
21.18 - * along with this program. Look for COPYING file in the top folder.
21.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
21.20 - */
21.21 -package org.apidesign.vm4brwsr;
21.22 -
21.23 -import java.io.IOException;
21.24 -import java.io.InputStream;
21.25 -import java.net.URL;
21.26 -import java.util.Enumeration;
21.27 -
21.28 -/** Generator of JavaScript from bytecode of classes on classpath of the VM.
21.29 - *
21.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
21.31 - */
21.32 -class GenJS extends ByteCodeToJavaScript {
21.33 - public GenJS(Appendable out) {
21.34 - super(out);
21.35 - }
21.36 -
21.37 - static void compile(Appendable out, String... names) throws IOException {
21.38 - compile(out, StringArray.asList(names));
21.39 - }
21.40 - static void compile(ClassLoader l, Appendable out, String... names) throws IOException {
21.41 - compile(l, out, StringArray.asList(names));
21.42 - }
21.43 - static void compile(Appendable out, StringArray names) throws IOException {
21.44 - compile(GenJS.class.getClassLoader(), out, names);
21.45 - }
21.46 - static void compile(ClassLoader l, Appendable out, StringArray names) throws IOException {
21.47 - new GenJS(out).doCompile(l, names);
21.48 - }
21.49 - protected void doCompile(ClassLoader l, StringArray names) throws IOException {
21.50 - StringArray processed = new StringArray();
21.51 - StringArray initCode = new StringArray();
21.52 - for (String baseClass : names.toArray()) {
21.53 - references.add(baseClass);
21.54 - for (;;) {
21.55 - String name = null;
21.56 - for (String n : references.toArray()) {
21.57 - if (processed.contains(n)) {
21.58 - continue;
21.59 - }
21.60 - name = n;
21.61 - }
21.62 - if (name == null) {
21.63 - break;
21.64 - }
21.65 - InputStream is = loadClass(l, name);
21.66 - if (is == null) {
21.67 - throw new IOException("Can't find class " + name);
21.68 - }
21.69 - try {
21.70 - String ic = compile(is);
21.71 - processed.add(name);
21.72 - initCode.add(ic == null ? "" : ic);
21.73 - } catch (RuntimeException ex) {
21.74 - if (out instanceof CharSequence) {
21.75 - CharSequence seq = (CharSequence)out;
21.76 - int lastBlock = seq.length();
21.77 - while (lastBlock-- > 0) {
21.78 - if (seq.charAt(lastBlock) == '{') {
21.79 - break;
21.80 - }
21.81 - }
21.82 - throw new IOException("Error while compiling " + name + "\n"
21.83 - + seq.subSequence(lastBlock + 1, seq.length()), ex
21.84 - );
21.85 - } else {
21.86 - throw new IOException("Error while compiling " + name + "\n"
21.87 - + out, ex
21.88 - );
21.89 - }
21.90 - }
21.91 - }
21.92 -
21.93 - for (String resource : scripts.toArray()) {
21.94 - while (resource.startsWith("/")) {
21.95 - resource = resource.substring(1);
21.96 - }
21.97 - InputStream emul = l.getResourceAsStream(resource);
21.98 - if (emul == null) {
21.99 - throw new IOException("Can't find " + resource);
21.100 - }
21.101 - readResource(emul, out);
21.102 - }
21.103 - scripts = new StringArray();
21.104 -
21.105 - StringArray toInit = StringArray.asList(references.toArray());
21.106 - toInit.reverse();
21.107 -
21.108 - for (String ic : toInit.toArray()) {
21.109 - int indx = processed.indexOf(ic);
21.110 - if (indx >= 0) {
21.111 - out.append(initCode.toArray()[indx]).append("\n");
21.112 - initCode.toArray()[indx] = "";
21.113 - }
21.114 - }
21.115 -
21.116 - }
21.117 - }
21.118 - private static void readResource(InputStream emul, Appendable out) throws IOException {
21.119 - try {
21.120 - int state = 0;
21.121 - for (;;) {
21.122 - int ch = emul.read();
21.123 - if (ch == -1) {
21.124 - break;
21.125 - }
21.126 - if (ch < 0 || ch > 255) {
21.127 - throw new IOException("Invalid char in emulation " + ch);
21.128 - }
21.129 - switch (state) {
21.130 - case 0:
21.131 - if (ch == '/') {
21.132 - state = 1;
21.133 - } else {
21.134 - out.append((char)ch);
21.135 - }
21.136 - break;
21.137 - case 1:
21.138 - if (ch == '*') {
21.139 - state = 2;
21.140 - } else {
21.141 - out.append('/').append((char)ch);
21.142 - state = 0;
21.143 - }
21.144 - break;
21.145 - case 2:
21.146 - if (ch == '*') {
21.147 - state = 3;
21.148 - }
21.149 - break;
21.150 - case 3:
21.151 - if (ch == '/') {
21.152 - state = 0;
21.153 - } else {
21.154 - state = 2;
21.155 - }
21.156 - break;
21.157 - }
21.158 - }
21.159 - } finally {
21.160 - emul.close();
21.161 - }
21.162 - }
21.163 -
21.164 - private static InputStream loadClass(ClassLoader l, String name) throws IOException {
21.165 - Enumeration<URL> en = l.getResources(name + ".class");
21.166 - URL u = null;
21.167 - while (en.hasMoreElements()) {
21.168 - u = en.nextElement();
21.169 - }
21.170 - if (u == null) {
21.171 - throw new IOException("Can't find " + name);
21.172 - }
21.173 - if (u.toExternalForm().contains("rt.jar!")) {
21.174 - throw new IOException("No emulation for " + u);
21.175 - }
21.176 - return u.openStream();
21.177 - }
21.178 -
21.179 - static String toString(String name) throws IOException {
21.180 - StringBuilder sb = new StringBuilder();
21.181 - compile(sb, name);
21.182 - return sb.toString().toString();
21.183 - }
21.184 -
21.185 - private StringArray scripts = new StringArray();
21.186 - private StringArray references = new StringArray();
21.187 -
21.188 - @Override
21.189 - protected boolean requireReference(String cn) {
21.190 - if (references.contains(cn)) {
21.191 - return false;
21.192 - }
21.193 - references.add(cn);
21.194 - return true;
21.195 - }
21.196 -
21.197 - @Override
21.198 - protected void requireScript(String resourcePath) {
21.199 - scripts.add(resourcePath);
21.200 - }
21.201 -}
22.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Wed Dec 12 14:07:53 2012 +0100
22.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Main.java Fri Dec 14 11:15:37 2012 +0100
22.3 @@ -32,6 +32,7 @@
22.4
22.5 public static void main(String... args) throws IOException {
22.6 if (args.length < 2) {
22.7 + System.err.println("Bck2Brwsr Translator from Java(tm) to JavaScript, (c) Jaroslav Tulach 2012");
22.8 System.err.println("Usage: java -cp ... -jar ... <file_to_generate_js_code_to> java/lang/Class org/your/App ...");
22.9 return;
22.10 }
22.11 @@ -40,7 +41,8 @@
22.12 StringArray classes = StringArray.asList(args);
22.13 classes.delete(0);
22.14 try {
22.15 - GenJS.compile(w, classes);
22.16 + Bck2Brwsr.generate(w, Main.class.getClassLoader(),
22.17 + classes.toArray());
22.18 } finally {
22.19 w.close();
22.20 }
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java Fri Dec 14 11:15:37 2012 +0100
23.3 @@ -0,0 +1,208 @@
23.4 +/**
23.5 + * Back 2 Browser Bytecode Translator
23.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
23.7 + *
23.8 + * This program is free software: you can redistribute it and/or modify
23.9 + * it under the terms of the GNU General Public License as published by
23.10 + * the Free Software Foundation, version 2 of the License.
23.11 + *
23.12 + * This program is distributed in the hope that it will be useful,
23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23.15 + * GNU General Public License for more details.
23.16 + *
23.17 + * You should have received a copy of the GNU General Public License
23.18 + * along with this program. Look for COPYING file in the top folder.
23.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
23.20 + */
23.21 +package org.apidesign.vm4brwsr;
23.22 +
23.23 +import java.io.IOException;
23.24 +import java.io.InputStream;
23.25 +
23.26 +/** Generator of JavaScript from bytecode of classes on classpath of the VM.
23.27 + *
23.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
23.29 + */
23.30 +class VM extends ByteCodeToJavaScript {
23.31 + public VM(Appendable out) {
23.32 + super(out);
23.33 + }
23.34 +
23.35 + static {
23.36 + // uses VMLazy to load dynamic classes
23.37 + VMLazy.init();
23.38 + }
23.39 +
23.40 + static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
23.41 + new VM(out).doCompile(l, names);
23.42 + }
23.43 + protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
23.44 + out.append("(function VM(global) {");
23.45 + out.append("\n var vm = {};");
23.46 + StringArray processed = new StringArray();
23.47 + StringArray initCode = new StringArray();
23.48 + for (String baseClass : names.toArray()) {
23.49 + references.add(baseClass);
23.50 + for (;;) {
23.51 + String name = null;
23.52 + for (String n : references.toArray()) {
23.53 + if (processed.contains(n)) {
23.54 + continue;
23.55 + }
23.56 + name = n;
23.57 + }
23.58 + if (name == null) {
23.59 + break;
23.60 + }
23.61 + InputStream is = loadClass(l, name);
23.62 + if (is == null) {
23.63 + throw new IOException("Can't find class " + name);
23.64 + }
23.65 + try {
23.66 + String ic = compile(is);
23.67 + processed.add(name);
23.68 + initCode.add(ic == null ? "" : ic);
23.69 + } catch (RuntimeException ex) {
23.70 + if (out instanceof CharSequence) {
23.71 + CharSequence seq = (CharSequence)out;
23.72 + int lastBlock = seq.length();
23.73 + while (lastBlock-- > 0) {
23.74 + if (seq.charAt(lastBlock) == '{') {
23.75 + break;
23.76 + }
23.77 + }
23.78 + throw new IOException("Error while compiling " + name + "\n"
23.79 + + seq.subSequence(lastBlock + 1, seq.length()), ex
23.80 + );
23.81 + } else {
23.82 + throw new IOException("Error while compiling " + name + "\n"
23.83 + + out, ex
23.84 + );
23.85 + }
23.86 + }
23.87 + }
23.88 +
23.89 + for (String resource : scripts.toArray()) {
23.90 + while (resource.startsWith("/")) {
23.91 + resource = resource.substring(1);
23.92 + }
23.93 + InputStream emul = l.get(resource);
23.94 + if (emul == null) {
23.95 + throw new IOException("Can't find " + resource);
23.96 + }
23.97 + readResource(emul, out);
23.98 + }
23.99 + scripts = new StringArray();
23.100 +
23.101 + StringArray toInit = StringArray.asList(references.toArray());
23.102 + toInit.reverse();
23.103 +
23.104 + for (String ic : toInit.toArray()) {
23.105 + int indx = processed.indexOf(ic);
23.106 + if (indx >= 0) {
23.107 + out.append(initCode.toArray()[indx]).append("\n");
23.108 + initCode.toArray()[indx] = "";
23.109 + }
23.110 + }
23.111 + }
23.112 + out.append(
23.113 + " global.bck2brwsr = function() {\n"
23.114 + + " var args = arguments;\n"
23.115 + + " var loader = {};\n"
23.116 + + " loader.vm = vm;\n"
23.117 + + " loader.loadClass = function(name) {\n"
23.118 + + " var attr = name.replace__Ljava_lang_String_2CC(name, '.','_');\n"
23.119 + + " var fn = vm[attr];\n"
23.120 + + " if (fn) return fn(false);\n"
23.121 + + " if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
23.122 + + " return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
23.123 + + " load___3Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
23.124 + + " }\n"
23.125 + + " return loader;\n"
23.126 + + " };\n");
23.127 + out.append("}(this));");
23.128 + }
23.129 + private static void readResource(InputStream emul, Appendable out) throws IOException {
23.130 + try {
23.131 + int state = 0;
23.132 + for (;;) {
23.133 + int ch = emul.read();
23.134 + if (ch == -1) {
23.135 + break;
23.136 + }
23.137 + if (ch < 0 || ch > 255) {
23.138 + throw new IOException("Invalid char in emulation " + ch);
23.139 + }
23.140 + switch (state) {
23.141 + case 0:
23.142 + if (ch == '/') {
23.143 + state = 1;
23.144 + } else {
23.145 + out.append((char)ch);
23.146 + }
23.147 + break;
23.148 + case 1:
23.149 + if (ch == '*') {
23.150 + state = 2;
23.151 + } else {
23.152 + out.append('/').append((char)ch);
23.153 + state = 0;
23.154 + }
23.155 + break;
23.156 + case 2:
23.157 + if (ch == '*') {
23.158 + state = 3;
23.159 + }
23.160 + break;
23.161 + case 3:
23.162 + if (ch == '/') {
23.163 + state = 0;
23.164 + } else {
23.165 + state = 2;
23.166 + }
23.167 + break;
23.168 + }
23.169 + }
23.170 + } finally {
23.171 + emul.close();
23.172 + }
23.173 + }
23.174 +
23.175 + private static InputStream loadClass(Bck2Brwsr.Resources l, String name) throws IOException {
23.176 + return l.get(name + ".class"); // NOI18N
23.177 + }
23.178 +
23.179 + static String toString(String name) throws IOException {
23.180 + StringBuilder sb = new StringBuilder();
23.181 +// compile(sb, name);
23.182 + return sb.toString().toString();
23.183 + }
23.184 +
23.185 + private StringArray scripts = new StringArray();
23.186 + private StringArray references = new StringArray();
23.187 +
23.188 + @Override
23.189 + protected boolean requireReference(String cn) {
23.190 + if (references.contains(cn)) {
23.191 + return false;
23.192 + }
23.193 + references.add(cn);
23.194 + return true;
23.195 + }
23.196 +
23.197 + @Override
23.198 + protected void requireScript(String resourcePath) {
23.199 + scripts.add(resourcePath);
23.200 + }
23.201 +
23.202 + @Override
23.203 + String assignClass(String className) {
23.204 + return "vm." + className + " = ";
23.205 + }
23.206 +
23.207 + @Override
23.208 + String accessClass(String className) {
23.209 + return "vm." + className;
23.210 + }
23.211 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java Fri Dec 14 11:15:37 2012 +0100
24.3 @@ -0,0 +1,129 @@
24.4 +/**
24.5 + * Back 2 Browser Bytecode Translator
24.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
24.7 + *
24.8 + * This program is free software: you can redistribute it and/or modify
24.9 + * it under the terms of the GNU General Public License as published by
24.10 + * the Free Software Foundation, version 2 of the License.
24.11 + *
24.12 + * This program is distributed in the hope that it will be useful,
24.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
24.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24.15 + * GNU General Public License for more details.
24.16 + *
24.17 + * You should have received a copy of the GNU General Public License
24.18 + * along with this program. Look for COPYING file in the top folder.
24.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
24.20 + */
24.21 +package org.apidesign.vm4brwsr;
24.22 +
24.23 +import java.io.ByteArrayInputStream;
24.24 +import java.io.IOException;
24.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
24.26 +
24.27 +/**
24.28 + *
24.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
24.30 + */
24.31 +final class VMLazy {
24.32 + private final Object loader;
24.33 + private final Object[] args;
24.34 +
24.35 + private VMLazy(Object loader, Object[] args) {
24.36 + this.loader = loader;
24.37 + this.args = args;
24.38 + }
24.39 +
24.40 + static void init() {
24.41 + }
24.42 +
24.43 + @JavaScriptBody(args={"l", "res", "args" }, body = ""
24.44 + + "\ntry {"
24.45 + + "\n return args[0](res.toString());"
24.46 + + "\n} catch (x) {"
24.47 + + "\n throw Object.getOwnPropertyNames(l.vm).toString() + x.toString();"
24.48 + + "\n}")
24.49 + private static native byte[] read(Object l, String res, Object[] args);
24.50 +
24.51 + static Object load(Object loader, String name, Object[] arguments)
24.52 + throws IOException, ClassNotFoundException {
24.53 + return new VMLazy(loader, arguments).load(name);
24.54 + }
24.55 +
24.56 + private Object load(String name)
24.57 + throws IOException, ClassNotFoundException {
24.58 + String res = name.replace('.', '/') + ".class";
24.59 + byte[] arr = read(loader, res, args);
24.60 + if (arr == null) {
24.61 + throw new ClassNotFoundException(name);
24.62 + }
24.63 +// beingDefined(loader, name);
24.64 + StringBuilder out = new StringBuilder();
24.65 + out.append("var loader = arguments[0];\n");
24.66 + out.append("var vm = loader.vm;\n");
24.67 + new Gen(this, out).compile(new ByteArrayInputStream(arr));
24.68 + String code = out.toString().toString();
24.69 + String under = name.replace('.', '_');
24.70 + return applyCode(loader, under, code);
24.71 + }
24.72 +
24.73 +/* possibly not needed:
24.74 + @JavaScriptBody(args = {"loader", "n" }, body =
24.75 + "var cls = n.replace__Ljava_lang_String_2CC(n, '.','_').toString();" +
24.76 + "loader.vm[cls] = true;\n"
24.77 + )
24.78 + private static native void beingDefined(Object loader, String name);
24.79 +*/
24.80 +
24.81 +
24.82 + @JavaScriptBody(args = {"loader", "name", "script" }, body =
24.83 + "try {\n" +
24.84 + " new Function(script)(loader, name);\n" +
24.85 + "} catch (ex) {\n" +
24.86 + " throw 'Cannot compile ' + ex + ' line: ' + ex.lineNumber + ' script:\\n' + script;\n" +
24.87 + "}\n" +
24.88 + "return vm[name](false);\n"
24.89 + )
24.90 + private static native Object applyCode(Object loader, String name, String script);
24.91 +
24.92 +
24.93 + private static final class Gen extends ByteCodeToJavaScript {
24.94 + private final VMLazy lazy;
24.95 +
24.96 + public Gen(VMLazy vm, Appendable out) {
24.97 + super(out);
24.98 + this.lazy = vm;
24.99 + }
24.100 +
24.101 + @JavaScriptBody(args = {"self", "n"},
24.102 + body =
24.103 + "var cls = n.replace__Ljava_lang_String_2CC(n, '/','_').toString();"
24.104 + + "\nvar dot = n.replace__Ljava_lang_String_2CC(n,'/','.').toString();"
24.105 + + "\nvar lazy = self.fld_lazy;"
24.106 + + "\nvar loader = lazy.fld_loader;"
24.107 + + "\nvar vm = loader.vm;"
24.108 + + "\nif (vm[cls]) return false;"
24.109 + + "\nvm[cls] = function() {"
24.110 + + "\n return lazy.load__Ljava_lang_Object_2Ljava_lang_String_2(lazy, dot);"
24.111 + + "\n};"
24.112 + + "\nreturn true;")
24.113 + @Override
24.114 + protected boolean requireReference(String internalClassName) {
24.115 + throw new UnsupportedOperationException();
24.116 + }
24.117 +
24.118 + @Override
24.119 + protected void requireScript(String resourcePath) {
24.120 + }
24.121 +
24.122 + @Override
24.123 + String assignClass(String className) {
24.124 + return "vm[arguments[1]]=";
24.125 + }
24.126 +
24.127 + @Override
24.128 + String accessClass(String classOperation) {
24.129 + return "vm." + classOperation;
24.130 + }
24.131 + }
24.132 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java Fri Dec 14 11:15:37 2012 +0100
25.3 @@ -0,0 +1,58 @@
25.4 +/**
25.5 + * Back 2 Browser Bytecode Translator
25.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
25.7 + *
25.8 + * This program is free software: you can redistribute it and/or modify
25.9 + * it under the terms of the GNU General Public License as published by
25.10 + * the Free Software Foundation, version 2 of the License.
25.11 + *
25.12 + * This program is distributed in the hope that it will be useful,
25.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
25.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25.15 + * GNU General Public License for more details.
25.16 + *
25.17 + * You should have received a copy of the GNU General Public License
25.18 + * along with this program. Look for COPYING file in the top folder.
25.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
25.20 + */
25.21 +package org.apidesign.vm4brwsr;
25.22 +
25.23 +import java.io.IOException;
25.24 +import java.io.InputStream;
25.25 +import java.util.Set;
25.26 +import java.util.TreeSet;
25.27 +
25.28 +/**
25.29 + *
25.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
25.31 + */
25.32 +public final class BytesLoader {
25.33 + private static Set<String> requested = new TreeSet<String>();
25.34 +
25.35 + public byte[] get(String name) throws IOException {
25.36 + if (!requested.add(name)) {
25.37 + throw new IllegalStateException("Requested for second time: " + name);
25.38 + }
25.39 + InputStream is = BytesLoader.class.getClassLoader().getResourceAsStream(name);
25.40 + if (is == null) {
25.41 + throw new IOException("Can't find " + name);
25.42 + }
25.43 + byte[] arr = new byte[is.available()];
25.44 + int len = is.read(arr);
25.45 + if (len != arr.length) {
25.46 + throw new IOException("Read only " + len + " wanting " + arr.length);
25.47 + }
25.48 + /*
25.49 + System.err.print("loader['" + name + "'] = [");
25.50 + for (int i = 0; i < arr.length; i++) {
25.51 + if (i > 0) {
25.52 + System.err.print(", ");
25.53 + }
25.54 + System.err.print(arr[i]);
25.55 + }
25.56 + System.err.println("]");
25.57 + */
25.58 + return arr;
25.59 + }
25.60 +
25.61 +}
26.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Wed Dec 12 14:07:53 2012 +0100
26.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Fri Dec 14 11:15:37 2012 +0100
26.3 @@ -110,6 +110,12 @@
26.4 "java.io.IOException", false, null
26.5 );
26.6 }
26.7 + @Test public void jsClassParam() throws Exception {
26.8 + assertExec("Calls the nameOfIO()", Classes.class,
26.9 + "nameOfIO__Ljava_lang_String_2",
26.10 + "java.io.IOException"
26.11 + );
26.12 + }
26.13
26.14 private static CharSequence codeSeq;
26.15 private static Invocable code;
27.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Wed Dec 12 14:07:53 2012 +0100
27.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Fri Dec 14 11:15:37 2012 +0100
27.3 @@ -30,6 +30,14 @@
27.4 @ClassesMarker(number = 10)
27.5 @ClassesNamer(name = "my text")
27.6 public class Classes {
27.7 + public static String nameOfIO() {
27.8 + return nameFor(IOException.class);
27.9 + }
27.10 +
27.11 + private static String nameFor(Class<?> c) {
27.12 + return c.getName();
27.13 + }
27.14 +
27.15 public static boolean equalsClassesOfExceptions() {
27.16 return MalformedURLException.class.getSuperclass() == IOException.class;
27.17 }
28.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java Wed Dec 12 14:07:53 2012 +0100
28.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java Fri Dec 14 11:15:37 2012 +0100
28.3 @@ -18,7 +18,10 @@
28.4 package org.apidesign.vm4brwsr;
28.5
28.6 import java.lang.reflect.Method;
28.7 +import java.util.Map;
28.8 +import java.util.WeakHashMap;
28.9 import javax.script.Invocable;
28.10 +import javax.script.ScriptContext;
28.11 import javax.script.ScriptEngine;
28.12 import javax.script.ScriptEngineManager;
28.13 import org.testng.Assert;
28.14 @@ -73,7 +76,7 @@
28.15 if (v1 instanceof Number) {
28.16 v1 = ((Number)v1).doubleValue();
28.17 }
28.18 - Assert.assertEquals(v1, v2, "Comparing results");
28.19 + Assert.assertEquals(v2, v1, "Comparing results");
28.20 }
28.21
28.22 @Override
28.23 @@ -85,52 +88,49 @@
28.24 private final Method m;
28.25 private final boolean js;
28.26 Object value;
28.27 - private static Invocable code;
28.28 - private static CharSequence codeSeq;
28.29 + private Invocable code;
28.30 + private CharSequence codeSeq;
28.31 + private static final Map<Class,Object[]> compiled = new WeakHashMap<Class,Object[]>();
28.32
28.33 private Run(Method m, boolean js) {
28.34 this.m = m;
28.35 this.js = js;
28.36 }
28.37
28.38 - private static void compileTheCode(Class<?> clazz) throws Exception {
28.39 - if (code != null) {
28.40 + private void compileTheCode(Class<?> clazz) throws Exception {
28.41 + final Object[] data = compiled.get(clazz);
28.42 + if (data != null) {
28.43 + code = (Invocable) data[0];
28.44 + codeSeq = (CharSequence) data[1];
28.45 return;
28.46 }
28.47 StringBuilder sb = new StringBuilder();
28.48 - class SkipMe extends GenJS {
28.49 -
28.50 - public SkipMe(Appendable out) {
28.51 - super(out);
28.52 - }
28.53 -
28.54 - @Override
28.55 - protected boolean requireReference(String cn) {
28.56 - if (cn.contains("CompareVMs")) {
28.57 - return true;
28.58 - }
28.59 - return super.requireReference(cn);
28.60 - }
28.61 - }
28.62 - SkipMe sm = new SkipMe(sb);
28.63 - sm.doCompile(CompareVMs.class.getClassLoader(), StringArray.asList(
28.64 - clazz.getName().replace('.', '/')));
28.65 + Bck2Brwsr.generate(sb, CompareVMs.class.getClassLoader());
28.66
28.67 ScriptEngineManager sem = new ScriptEngineManager();
28.68 ScriptEngine js = sem.getEngineByExtension("js");
28.69 + js.getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
28.70 +
28.71 + sb.append("\nfunction initVM() {"
28.72 + + "\n return bck2brwsr("
28.73 + + "\n function(name) { return loader.get(name);}"
28.74 + + "\n );"
28.75 + + "\n};");
28.76
28.77 Object res = js.eval(sb.toString());
28.78 Assert.assertTrue(js instanceof Invocable, "It is invocable object: " + res);
28.79 code = (Invocable) js;
28.80 codeSeq = sb;
28.81 + compiled.put(clazz, new Object[] { code, codeSeq });
28.82 }
28.83
28.84 @Test(groups = "run") public void executeCode() throws Throwable {
28.85 if (js) {
28.86 try {
28.87 compileTheCode(m.getDeclaringClass());
28.88 - Object inst = code.invokeFunction(m.getDeclaringClass().getName().replace('.', '_'), false);
28.89 - value = code.invokeMethod(inst, m.getName() + "__I");
28.90 + Object vm = code.invokeFunction("initVM");
28.91 + Object inst = code.invokeMethod(vm, "loadClass", m.getDeclaringClass().getName());
28.92 + value = code.invokeMethod(inst, m.getName() + "__" + computeSignature(m));
28.93 } catch (Exception ex) {
28.94 throw new AssertionError(StaticMethodTest.dumpJS(codeSeq)).initCause(ex);
28.95 }
28.96 @@ -142,5 +142,56 @@
28.97 public String getTestName() {
28.98 return m.getName() + (js ? "[JavaScript]" : "[Java]");
28.99 }
28.100 +
28.101 + private static String computeSignature(Method m) {
28.102 + StringBuilder sb = new StringBuilder();
28.103 + appendType(sb, m.getReturnType());
28.104 + for (Class<?> c : m.getParameterTypes()) {
28.105 + appendType(sb, c);
28.106 + }
28.107 + return sb.toString();
28.108 + }
28.109 +
28.110 + private static void appendType(StringBuilder sb, Class<?> t) {
28.111 + if (t == null) {
28.112 + sb.append('V');
28.113 + return;
28.114 + }
28.115 + if (t.isPrimitive()) {
28.116 + int ch = -1;
28.117 + if (t == int.class) {
28.118 + ch = 'I';
28.119 + }
28.120 + if (t == short.class) {
28.121 + ch = 'S';
28.122 + }
28.123 + if (t == byte.class) {
28.124 + ch = 'B';
28.125 + }
28.126 + if (t == boolean.class) {
28.127 + ch = 'Z';
28.128 + }
28.129 + if (t == long.class) {
28.130 + ch = 'J';
28.131 + }
28.132 + if (t == float.class) {
28.133 + ch = 'F';
28.134 + }
28.135 + if (t == double.class) {
28.136 + ch = 'D';
28.137 + }
28.138 + assert ch != -1 : "Unknown primitive type " + t;
28.139 + sb.append((char)ch);
28.140 + return;
28.141 + }
28.142 + if (t.isArray()) {
28.143 + sb.append("_3");
28.144 + appendType(sb, t.getComponentType());
28.145 + return;
28.146 + }
28.147 + sb.append('L');
28.148 + sb.append(t.getName().replace('.', '_'));
28.149 + sb.append("_2");
28.150 + }
28.151 }
28.152 }
29.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Wed Dec 12 14:07:53 2012 +0100
29.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java Fri Dec 14 11:15:37 2012 +0100
29.3 @@ -161,7 +161,8 @@
29.4
29.5 Object ret = null;
29.6 try {
29.7 - ret = code.invokeFunction(clazz.getName().replace('.', '_'), true);
29.8 + ret = code.invokeFunction("bck2brwsr");
29.9 + ret = code.invokeMethod(ret, "loadClass", clazz.getName());
29.10 ret = code.invokeMethod(ret, method, args);
29.11 } catch (ScriptException ex) {
29.12 fail("Execution failed in\n" + StaticMethodTest.dumpJS(codeSeq), ex);
30.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Wed Dec 12 14:07:53 2012 +0100
30.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethod.java Fri Dec 14 11:15:37 2012 +0100
30.3 @@ -106,6 +106,11 @@
30.4 throw new IllegalStateException();
30.5 }
30.6
30.7 + public static String castNull(boolean n) {
30.8 + Object value = n ? null : "Ahoj";
30.9 + return (String)value;
30.10 + }
30.11 +
30.12 public static String swtch(int what) {
30.13 switch (what) {
30.14 case 0: return "Jarda";
31.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Wed Dec 12 14:07:53 2012 +0100
31.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java Fri Dec 14 11:15:37 2012 +0100
31.3 @@ -20,6 +20,9 @@
31.4 import java.io.File;
31.5 import java.io.FileWriter;
31.6 import java.io.IOException;
31.7 +import java.io.InputStream;
31.8 +import java.net.URL;
31.9 +import java.util.Enumeration;
31.10 import javax.script.Invocable;
31.11 import javax.script.ScriptEngine;
31.12 import javax.script.ScriptEngineManager;
31.13 @@ -238,6 +241,13 @@
31.14 );
31.15 }
31.16
31.17 + @Test public void checkNullCast() throws Exception {
31.18 + assertExec("Null can be cast to any type",
31.19 + StaticMethod.class, "castNull__Ljava_lang_String_2Z",
31.20 + null, true
31.21 + );
31.22 + }
31.23 +
31.24 private static CharSequence codeSeq;
31.25 private static Invocable code;
31.26
31.27 @@ -262,7 +272,8 @@
31.28 ) throws Exception {
31.29 Object ret = null;
31.30 try {
31.31 - ret = toRun.invokeFunction(clazz.getName().replace('.', '_'), true);
31.32 + ret = toRun.invokeFunction("bck2brwsr");
31.33 + ret = toRun.invokeMethod(ret, "loadClass", clazz.getName());
31.34 ret = toRun.invokeMethod(ret, method, args);
31.35 } catch (ScriptException ex) {
31.36 fail("Execution failed in\n" + dumpJS(theCode), ex);
31.37 @@ -288,7 +299,7 @@
31.38 if (sb == null) {
31.39 sb = new StringBuilder();
31.40 }
31.41 - GenJS.compile(sb, names);
31.42 + Bck2Brwsr.generate(sb, new EmulationResources(), names);
31.43 ScriptEngineManager sem = new ScriptEngineManager();
31.44 ScriptEngine js = sem.getEngineByExtension("js");
31.45 if (eng != null) {
31.46 @@ -313,4 +324,21 @@
31.47 w.close();
31.48 return new StringBuilder(f.getPath());
31.49 }
31.50 + private static class EmulationResources implements Bck2Brwsr.Resources {
31.51 + @Override
31.52 + public InputStream get(String name) throws IOException {
31.53 + Enumeration<URL> en = StaticMethodTest.class.getClassLoader().getResources(name);
31.54 + URL u = null;
31.55 + while (en.hasMoreElements()) {
31.56 + u = en.nextElement();
31.57 + }
31.58 + if (u == null) {
31.59 + throw new IOException("Can't find " + name);
31.60 + }
31.61 + if (u.toExternalForm().contains("rt.jar!")) {
31.62 + throw new IOException("No emulation for " + u);
31.63 + }
31.64 + return u.openStream();
31.65 + }
31.66 + }
31.67 }
32.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazy.java Wed Dec 12 14:07:53 2012 +0100
32.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
32.3 @@ -1,68 +0,0 @@
32.4 -/**
32.5 - * Back 2 Browser Bytecode Translator
32.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
32.7 - *
32.8 - * This program is free software: you can redistribute it and/or modify
32.9 - * it under the terms of the GNU General Public License as published by
32.10 - * the Free Software Foundation, version 2 of the License.
32.11 - *
32.12 - * This program is distributed in the hope that it will be useful,
32.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
32.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32.15 - * GNU General Public License for more details.
32.16 - *
32.17 - * You should have received a copy of the GNU General Public License
32.18 - * along with this program. Look for COPYING file in the top folder.
32.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
32.20 - */
32.21 -package org.apidesign.vm4brwsr;
32.22 -
32.23 -import java.io.ByteArrayInputStream;
32.24 -import java.io.IOException;
32.25 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
32.26 -
32.27 -/**
32.28 - *
32.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
32.30 - */
32.31 -class VMLazy extends ByteCodeToJavaScript {
32.32 - private final Object vm;
32.33 - private final Object global;
32.34 -
32.35 - private VMLazy(Object global, Object vm, Appendable out) {
32.36 - super(out);
32.37 - this.vm = vm;
32.38 - this.global = global;
32.39 - }
32.40 -
32.41 - static String toJavaScript(Object global, Object vm, byte[] is) throws IOException {
32.42 - StringBuilder sb = new StringBuilder();
32.43 - new VMLazy(global, vm, sb).compile(new ByteArrayInputStream(is));
32.44 - return sb.toString().toString();
32.45 - }
32.46 -
32.47 - @JavaScriptBody(args = { "self", "n" },
32.48 - body=
32.49 - "var cls = n.replace__Ljava_lang_String_2CC(n,'/','_').toString();"
32.50 - + "var glb = self.fld_global;"
32.51 - + "var vm = self.fld_vm;"
32.52 - + "if (glb[cls]) return false;"
32.53 - + "glb[cls] = function() {"
32.54 - + " return vm.loadClass(n,cls);"
32.55 - + "};"
32.56 - + "return true;"
32.57 - )
32.58 - @Override
32.59 - protected boolean requireReference(String internalClassName) {
32.60 - throw new UnsupportedOperationException();
32.61 - }
32.62 -
32.63 - @Override
32.64 - protected void requireScript(String resourcePath) {
32.65 - }
32.66 -
32.67 - @Override
32.68 - protected String assignClass(String className) {
32.69 - return "arguments[0][arguments[1]]=";
32.70 - }
32.71 -}
33.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Wed Dec 12 14:07:53 2012 +0100
33.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java Fri Dec 14 11:15:37 2012 +0100
33.3 @@ -17,8 +17,6 @@
33.4 */
33.5 package org.apidesign.vm4brwsr;
33.6
33.7 -import java.io.IOException;
33.8 -import java.io.InputStream;
33.9 import javax.script.Invocable;
33.10 import javax.script.ScriptContext;
33.11 import javax.script.ScriptEngine;
33.12 @@ -40,50 +38,32 @@
33.13 @BeforeClass
33.14 public void compileTheCode() throws Exception {
33.15 StringBuilder sb = new StringBuilder();
33.16 -
33.17 - sb.append("\nfunction test(clazz, as, method) {");
33.18 - sb.append("\n var l = new lazyVM(this);");
33.19 - sb.append("\n var c = l.loadClass(clazz, as);");
33.20 + sb.append("\nvar data = {};");
33.21 + sb.append("\nfunction test(clazz, method) {");
33.22 + sb.append("\n if (!data.bck2brwsr) data.bck2brwsr = bck2brwsr(function(name) { return loader.get(name); });");
33.23 + sb.append("\n var c = data.bck2brwsr.loadClass(clazz);");
33.24 sb.append("\n return c[method]();");
33.25 sb.append("\n}");
33.26
33.27
33.28 - sb.append("\nfunction lazyVM(global) {");
33.29 - sb.append("\n var self = this;");
33.30 - sb.append("\n var glb = global;");
33.31 - sb.append("\n lazyVM.prototype.loadClass = function(res, name) {");
33.32 - sb.append("\n var script = org_apidesign_vm4brwsr_VMLazy(true)."
33.33 - + "toJavaScript__Ljava_lang_String_2Ljava_lang_Object_2Ljava_lang_Object_2_3B("
33.34 - + " glb, self,"
33.35 - + " loader.get(res + '.class')"
33.36 - + ");");
33.37 - sb.append("\n try {");
33.38 - sb.append("\n new Function(script)(glb, name);");
33.39 - sb.append("\n } catch (ex) {");
33.40 - sb.append("\n throw 'Cannot compile ' + res + ' error: ' + ex + ' script:\\n' + script;");
33.41 - sb.append("\n };");
33.42 - sb.append("\n return glb[name](true);");
33.43 - sb.append("\n };");
33.44 - sb.append("\n");
33.45 - sb.append("\n}\n");
33.46 -
33.47 +
33.48 ScriptEngine[] arr = { null };
33.49 code = StaticMethodTest.compileClass(sb, arr,
33.50 - "org/apidesign/vm4brwsr/VMLazy"
33.51 + "org/apidesign/vm4brwsr/VM"
33.52 );
33.53 - arr[0].getContext().setAttribute("loader", new FindBytes(), ScriptContext.ENGINE_SCOPE);
33.54 + arr[0].getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
33.55 codeSeq = sb;
33.56 }
33.57
33.58 @Test public void invokeStaticMethod() throws Exception {
33.59 assertExec("Trying to get -1", "test", Double.valueOf(-1),
33.60 - "org/apidesign/vm4brwsr/StaticMethod", "org_apidesign_vm4brwsr_StaticMethod", "minusOne__I"
33.61 + StaticMethod.class.getName(), "minusOne__I"
33.62 );
33.63 }
33.64
33.65 @Test public void loadDependantClass() throws Exception {
33.66 - assertExec("Trying to get zero", "test", Double.valueOf(0),
33.67 - "org/apidesign/vm4brwsr/InstanceSub", "org_apidesign_vm4brwsr_InstanceSub", "recallDbl__D"
33.68 + assertExec("Expecting zero", "test", Double.valueOf(0),
33.69 + InstanceSub.class.getName(), "recallDbl__D"
33.70 );
33.71 }
33.72
33.73 @@ -104,29 +84,4 @@
33.74 }
33.75 assertEquals(ret, expRes, msg + "was: " + ret + "\n" + StaticMethodTest.dumpJS(codeSeq));
33.76 }
33.77 -
33.78 - public static final class FindBytes {
33.79 - public byte[] get(String name) throws IOException {
33.80 - InputStream is = VMLazyTest.class.getClassLoader().getResourceAsStream(name);
33.81 - if (is == null) {
33.82 - throw new IOException("Can't find " + name);
33.83 - }
33.84 - byte[] arr = new byte[is.available()];
33.85 - int len = is.read(arr);
33.86 - if (len != arr.length) {
33.87 - throw new IOException("Read only " + len + " wanting " + arr.length);
33.88 - }
33.89 - /*
33.90 - System.err.print("loader['" + name + "'] = [");
33.91 - for (int i = 0; i < arr.length; i++) {
33.92 - if (i > 0) {
33.93 - System.err.print(", ");
33.94 - }
33.95 - System.err.print(arr[i]);
33.96 - }
33.97 - System.err.println("]");
33.98 - */
33.99 - return arr;
33.100 - }
33.101 - }
33.102 }
34.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Wed Dec 12 14:07:53 2012 +0100
34.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java Fri Dec 14 11:15:37 2012 +0100
34.3 @@ -35,13 +35,43 @@
34.4 private static CharSequence codeSeq;
34.5 private static Invocable code;
34.6
34.7 - @Test public void compareTheGeneratedCode() throws Exception {
34.8 - byte[] arr = readClass("/org/apidesign/vm4brwsr/Array.class");
34.9 + @Test public void compareGeneratedCodeForArrayClass() throws Exception {
34.10 + compareCode("/org/apidesign/vm4brwsr/Array.class");
34.11 + }
34.12 +
34.13 + @Test public void compareGeneratedCodeForClassesClass() throws Exception {
34.14 + compareCode("/org/apidesign/vm4brwsr/Classes.class");
34.15 + }
34.16 +
34.17 + @BeforeClass
34.18 + public void compileTheCode() throws Exception {
34.19 + StringBuilder sb = new StringBuilder();
34.20 + code = StaticMethodTest.compileClass(sb,
34.21 + "org/apidesign/vm4brwsr/VMinVM"
34.22 + );
34.23 + codeSeq = sb;
34.24 + }
34.25 +
34.26 + private static byte[] readClass(String res) throws IOException {
34.27 + InputStream is1 = VMinVMTest.class.getResourceAsStream(res);
34.28 + assertNotNull(is1, "Stream found");
34.29 + byte[] arr = new byte[is1.available()];
34.30 + int len = is1.read(arr);
34.31 + is1.close();
34.32 + if (len != arr.length) {
34.33 + throw new IOException("Wrong len " + len + " for arr: " + arr.length);
34.34 + }
34.35 + return arr;
34.36 + }
34.37 +
34.38 + private void compareCode(final String nm) throws Exception, IOException {
34.39 + byte[] arr = readClass(nm);
34.40 String ret1 = VMinVM.toJavaScript(arr);
34.41
34.42 Object ret;
34.43 try {
34.44 - ret = code.invokeFunction(VMinVM.class.getName().replace('.', '_'), true);
34.45 + ret = code.invokeFunction("bck2brwsr");
34.46 + ret = code.invokeMethod(ret, "loadClass", VMinVM.class.getName());
34.47 ret = code.invokeMethod(ret, "toJavaScript__Ljava_lang_String_2_3B", arr);
34.48 } catch (Exception ex) {
34.49 File f = File.createTempFile("execution", ".js");
34.50 @@ -64,27 +94,14 @@
34.51
34.52 assertTrue(ret instanceof String, "It is string: " + ret);
34.53
34.54 - assertEquals((String)ret, ret1.toString(), "The code is the same");
34.55 - }
34.56 -
34.57 - @BeforeClass
34.58 - public void compileTheCode() throws Exception {
34.59 - StringBuilder sb = new StringBuilder();
34.60 - code = StaticMethodTest.compileClass(sb,
34.61 - "org/apidesign/vm4brwsr/VMinVM"
34.62 - );
34.63 - codeSeq = sb;
34.64 - }
34.65 -
34.66 - private static byte[] readClass(String res) throws IOException {
34.67 - InputStream is1 = VMinVMTest.class.getResourceAsStream(res);
34.68 - assertNotNull(is1, "Stream found");
34.69 - byte[] arr = new byte[is1.available()];
34.70 - int len = is1.read(arr);
34.71 - is1.close();
34.72 - if (len != arr.length) {
34.73 - throw new IOException("Wrong len " + len + " for arr: " + arr.length);
34.74 + if (!ret1.toString().equals(ret)) {
34.75 + StringBuilder msg = new StringBuilder("Difference found between ");
34.76 + msg.append(StaticMethodTest.dumpJS(ret1));
34.77 + msg.append(" ");
34.78 + msg.append(StaticMethodTest.dumpJS((CharSequence) ret));
34.79 + msg.append(" compiled by ");
34.80 + msg.append(StaticMethodTest.dumpJS(codeSeq));
34.81 + fail(msg.toString());
34.82 }
34.83 - return arr;
34.84 }
34.85 }
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareStringsTest.java Fri Dec 14 11:15:37 2012 +0100
35.3 @@ -0,0 +1,43 @@
35.4 +/**
35.5 + * Back 2 Browser Bytecode Translator
35.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
35.7 + *
35.8 + * This program is free software: you can redistribute it and/or modify
35.9 + * it under the terms of the GNU General Public License as published by
35.10 + * the Free Software Foundation, version 2 of the License.
35.11 + *
35.12 + * This program is distributed in the hope that it will be useful,
35.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
35.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35.15 + * GNU General Public License for more details.
35.16 + *
35.17 + * You should have received a copy of the GNU General Public License
35.18 + * along with this program. Look for COPYING file in the top folder.
35.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
35.20 + */
35.21 +package org.apidesign.vm4brwsr.tck;
35.22 +
35.23 +import org.apidesign.vm4brwsr.Compare;
35.24 +import org.apidesign.vm4brwsr.CompareVMs;
35.25 +import org.testng.annotations.Factory;
35.26 +
35.27 +/**
35.28 + *
35.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
35.30 + */
35.31 +public class CompareStringsTest {
35.32 + @Compare public String deleteLastTwoCharacters() {
35.33 + StringBuilder sb = new StringBuilder();
35.34 + sb.append("453.0");
35.35 + if (sb.toString().endsWith(".0")) {
35.36 + final int l = sb.length();
35.37 + sb.delete(l - 2, l);
35.38 + }
35.39 + return sb.toString().toString();
35.40 + }
35.41 +
35.42 + @Factory
35.43 + public static Object[] create() {
35.44 + return CompareVMs.create(CompareStringsTest.class);
35.45 + }
35.46 +}