Merge with trunk registers
authorLubomir Nerad <lubomir.nerad@sun.com>
Fri, 14 Dec 2012 11:15:37 +0100
branchregisters
changeset 31715cbc8cb2163
parent 310 ec7d8bc17725
parent 316 8da329789435
child 318 5876fdbbca11
child 319 83f638b13242
Merge with trunk
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java
vm/src/main/java/org/apidesign/vm4brwsr/Main.java
vm/src/test/java/org/apidesign/vm4brwsr/VMLazy.java
     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 +}