Merge with trunk registers
authorLubomir Nerad <lubomir.nerad@oracle.com>
Fri, 18 Jan 2013 14:27:22 +0100
branchregisters
changeset 47395b68e21a53f
parent 472 1a73c6e08cc5
parent 459 a2871a3fd4c5
child 474 859cc3a0b8f0
Merge with trunk
benchmarks/matrix-multiplication/jsTestDriver.conf
benchmarks/matrix-multiplication/nbactions.xml
benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Main.java
benchmarks/matrix-multiplication/src/main/resources/org/apidesign/benchmark/matrixmul/multiplication-test.js
benchmarks/run-firefox.sh
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java
vm/src/test/java/org/apidesign/vm4brwsr/Compare.java
vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java
vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareHashTest.java
vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareStringsTest.java
     1.1 --- a/benchmarks/matrix-multiplication/jsTestDriver.conf	Fri Jan 18 14:23:18 2013 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,5 +0,0 @@
     1.4 -server: http://localhost:9876
     1.5 -
     1.6 -load:
     1.7 -  - target/classes/org/apidesign/benchmark/matrixmul/*.js
     1.8 -
     2.1 --- a/benchmarks/matrix-multiplication/nbactions.xml	Fri Jan 18 14:23:18 2013 +0100
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,29 +0,0 @@
     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 --- a/benchmarks/matrix-multiplication/pom.xml	Fri Jan 18 14:23:18 2013 +0100
     3.2 +++ b/benchmarks/matrix-multiplication/pom.xml	Fri Jan 18 14:27:22 2013 +0100
     3.3 @@ -25,62 +25,9 @@
     3.4                 <target>1.7</target>
     3.5              </configuration>
     3.6            </plugin>
     3.7 -          
     3.8 -          <plugin>
     3.9 -              <groupId>org.apidesign.bck2brwsr</groupId>
    3.10 -              <artifactId>mojo</artifactId>
    3.11 -              <version>0.3-SNAPSHOT</version>
    3.12 -              <executions>
    3.13 -                  <execution>
    3.14 -                      <goals>
    3.15 -                          <goal>j2js</goal>
    3.16 -                      </goals>
    3.17 -                  </execution>
    3.18 -              </executions>
    3.19 -          </plugin>
    3.20 -          
    3.21        </plugins>
    3.22    </build>
    3.23    
    3.24 -  <profiles>
    3.25 -    <profile>
    3.26 -      <id>run-benchmarks</id>
    3.27 -      <activation>
    3.28 -        <property><name>bck2brwsr.runBenchmarks.browsers</name></property>
    3.29 -      </activation>
    3.30 -
    3.31 -      <build>
    3.32 -        <plugins>
    3.33 -
    3.34 -          <plugin>
    3.35 -            <groupId>com.googlecode.jstd-maven-plugin</groupId>
    3.36 -            <artifactId>jstd-maven-plugin</artifactId>
    3.37 -            <version>1.3.2.5</version>
    3.38 -            <configuration>
    3.39 -                <port>9876</port>
    3.40 -                <browser>${bck2brwsr.runBenchmarks.browsers}</browser>
    3.41 -                <browserTimeout>720</browserTimeout>
    3.42 -                <tests>all</tests>
    3.43 -                <config>jsTestDriver.conf</config>
    3.44 -                <reset>true</reset>
    3.45 -                <testOutput>${basedir}/target/testOutput</testOutput>
    3.46 -                <!-- runnerMode>DEBUG</runnerMode -->
    3.47 -            </configuration>
    3.48 -            <executions>
    3.49 -                <execution>
    3.50 -                    <id>run-tests</id>
    3.51 -                    <goals>
    3.52 -                        <goal>test</goal>
    3.53 -                    </goals>
    3.54 -                </execution>
    3.55 -            </executions>
    3.56 -          </plugin>
    3.57 -
    3.58 -        </plugins>
    3.59 -      </build>
    3.60 -    </profile>
    3.61 -  </profiles>
    3.62 -
    3.63    <dependencies>
    3.64      <dependency>
    3.65        <groupId>org.apidesign.bck2brwsr</groupId>
    3.66 @@ -88,24 +35,22 @@
    3.67        <version>0.3-SNAPSHOT</version>
    3.68      </dependency>
    3.69      <dependency>
    3.70 -        <groupId>com.googlecode.jstd-maven-plugin</groupId>
    3.71 -        <artifactId>jstd-maven-plugin</artifactId>
    3.72 -        <version>1.3.2.5</version>
    3.73 -        <scope>test</scope>
    3.74 +      <groupId>org.testng</groupId>
    3.75 +      <artifactId>testng</artifactId>
    3.76 +      <version>6.5.2</version>
    3.77 +      <scope>test</scope>
    3.78 +      <exclusions>
    3.79 +        <exclusion>
    3.80 +          <artifactId>junit</artifactId>
    3.81 +          <groupId>junit</groupId>
    3.82 +        </exclusion>
    3.83 +      </exclusions>
    3.84 +    </dependency>
    3.85 +    <dependency>
    3.86 +      <groupId>org.apidesign.bck2brwsr</groupId>
    3.87 +      <artifactId>vmtest</artifactId>
    3.88 +      <version>0.3-SNAPSHOT</version>
    3.89 +      <scope>test</scope>
    3.90      </dependency>
    3.91    </dependencies>
    3.92 -  
    3.93 -  <repositories>
    3.94 -        <repository>
    3.95 -            <id>jstd-maven-plugin google code repo</id>
    3.96 -            <url>http://jstd-maven-plugin.googlecode.com/svn/maven2</url>
    3.97 -        </repository>
    3.98 -  </repositories>
    3.99 -  <pluginRepositories>
   3.100 -        <pluginRepository>
   3.101 -            <id>jstd-maven-plugin google code repo</id>
   3.102 -            <url>http://jstd-maven-plugin.googlecode.com/svn/maven2</url>
   3.103 -        </pluginRepository>
   3.104 -  </pluginRepositories>
   3.105 -  
   3.106  </project>
     4.1 --- a/benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Main.java	Fri Jan 18 14:23:18 2013 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,42 +0,0 @@
     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 --- a/benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Matrix.java	Fri Jan 18 14:23:18 2013 +0100
     5.2 +++ b/benchmarks/matrix-multiplication/src/main/java/org/apidesign/benchmark/matrixmul/Matrix.java	Fri Jan 18 14:27:22 2013 +0100
     5.3 @@ -17,17 +17,20 @@
     5.4   */
     5.5  package org.apidesign.benchmark.matrixmul;
     5.6  
     5.7 -//import java.io.PrintStream;
     5.8 -//import java.util.Random;
     5.9 +import java.io.IOException;
    5.10 +import java.util.Arrays;
    5.11  
    5.12  public class Matrix {
    5.13 -
    5.14      private final int rank;
    5.15 -    private float data[][];
    5.16 +    private final float data[][];
    5.17      
    5.18      public Matrix(int r) {
    5.19 -        rank = r;
    5.20 -        data = new float[r][r];
    5.21 +        this(r, new float[r][r]);
    5.22 +    }
    5.23 +    
    5.24 +    private Matrix(int r, float[][] data) {
    5.25 +        this.rank = r;
    5.26 +        this.data = data;
    5.27      }
    5.28      
    5.29      public void setElement(int i, int j, float value) {
    5.30 @@ -62,20 +65,44 @@
    5.31                  res[i][j] = ij;
    5.32              }
    5.33          }
    5.34 -        data = res;
    5.35 -        
    5.36 -        return this;
    5.37 +        return new Matrix(rank, res);
    5.38      }
    5.39      
    5.40 -    /*
    5.41 -    public void printOn(PrintStream s) {
    5.42 +    public void printOn(Appendable s) throws IOException {
    5.43          for (int i = 0; i < rank; i++) {
    5.44 +            String sep = "";
    5.45              for (int j = 0; j < rank; j++) {
    5.46 -                s.printf("%f ", data[i][j]);
    5.47 +                s.append(sep + data[i][j]);
    5.48 +                sep = " ";
    5.49              }
    5.50 -            s.println();
    5.51 +            s.append("\n");
    5.52          }
    5.53      }
    5.54 -    */
    5.55 -    
    5.56 +
    5.57 +    @Override
    5.58 +    public boolean equals(Object obj) {
    5.59 +        if (obj instanceof Matrix) {
    5.60 +            Matrix snd = (Matrix)obj;
    5.61 +            if (snd.rank != rank) {
    5.62 +                return false;
    5.63 +            }
    5.64 +            for (int i = 0; i < rank; i++) {
    5.65 +                for (int j = 0; j < rank; j++) {
    5.66 +                    if (data[i][j] != snd.data[i][j]) {
    5.67 +                        return false;
    5.68 +                    }
    5.69 +                }
    5.70 +            }
    5.71 +            return true;
    5.72 +        }
    5.73 +        return false;
    5.74 +    }
    5.75 +
    5.76 +    @Override
    5.77 +    public int hashCode() {
    5.78 +        int hash = 3;
    5.79 +        hash = 97 * hash + this.rank;
    5.80 +        hash = 97 * hash + Arrays.deepHashCode(this.data);
    5.81 +        return hash;
    5.82 +    }
    5.83  }
     6.1 --- a/benchmarks/matrix-multiplication/src/main/resources/org/apidesign/benchmark/matrixmul/multiplication-test.js	Fri Jan 18 14:23:18 2013 +0100
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,25 +0,0 @@
     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/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java	Fri Jan 18 14:27:22 2013 +0100
     7.3 @@ -0,0 +1,61 @@
     7.4 +/**
     7.5 + * Back 2 Browser Bytecode Translator
     7.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.7 + *
     7.8 + * This program is free software: you can redistribute it and/or modify
     7.9 + * it under the terms of the GNU General Public License as published by
    7.10 + * the Free Software Foundation, version 2 of the License.
    7.11 + *
    7.12 + * This program is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 + * GNU General Public License for more details.
    7.16 + *
    7.17 + * You should have received a copy of the GNU General Public License
    7.18 + * along with this program. Look for COPYING file in the top folder.
    7.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    7.20 + */
    7.21 +package org.apidesign.benchmark.matrixmul;
    7.22 +
    7.23 +import java.io.IOException;
    7.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
    7.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    7.26 +import org.testng.annotations.Factory;
    7.27 +
    7.28 +/**
    7.29 + *
    7.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    7.31 + */
    7.32 +public class MatrixTest {
    7.33 +    public static final int ITERATION_COUNT = 10;
    7.34 +    
    7.35 +    public MatrixTest() {
    7.36 +    }
    7.37 +
    7.38 +    @Compare public String tenThousandIterations() throws IOException {
    7.39 +    
    7.40 +        Matrix m1 = new Matrix(5);
    7.41 +        Matrix m2 = new Matrix(5);
    7.42 +        
    7.43 +        m1.generateData();
    7.44 +        m2.generateData();
    7.45 +        
    7.46 +        Matrix res = null;
    7.47 +        for (int i = 0; i < ITERATION_COUNT; i++) {
    7.48 +            Matrix m = m1.multiply(m2);
    7.49 +            if (res != null && !res.equals(m)) {
    7.50 +                return "different";
    7.51 +            }
    7.52 +            res = m;
    7.53 +        }
    7.54 +        
    7.55 +        StringBuilder sb = new StringBuilder();
    7.56 +        res.printOn(sb);
    7.57 +        return sb.toString();
    7.58 +    }
    7.59 +    
    7.60 +    @Factory
    7.61 +    public static Object[] create() {
    7.62 +        return VMTest.create(MatrixTest.class);
    7.63 +    }
    7.64 +}
     8.1 --- a/benchmarks/run-firefox.sh	Fri Jan 18 14:23:18 2013 +0100
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,20 +0,0 @@
     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/pom.xml	Fri Jan 18 14:23:18 2013 +0100
     9.2 +++ b/core/pom.xml	Fri Jan 18 14:27:22 2013 +0100
     9.3 @@ -19,8 +19,8 @@
     9.4                  <artifactId>maven-compiler-plugin</artifactId>
     9.5                  <version>2.3.2</version>
     9.6                  <configuration>
     9.7 -                    <source>1.6</source>
     9.8 -                    <target>1.6</target>
     9.9 +                    <source>1.7</source>
    9.10 +                    <target>1.7</target>
    9.11                  </configuration>
    9.12              </plugin>
    9.13          </plugins>
    9.14 @@ -35,6 +35,10 @@
    9.15        <version>3.8.1</version>
    9.16        <scope>test</scope>
    9.17      </dependency>
    9.18 +    <dependency>
    9.19 +      <groupId>org.netbeans.api</groupId>
    9.20 +      <artifactId>org-openide-util-lookup</artifactId>
    9.21 +    </dependency>
    9.22    </dependencies>
    9.23      <description>Contains esential annotations for associating JavaScript code with
    9.24  methods and classes.</description>
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/core/src/main/java/org/apidesign/bck2brwsr/core/impl/JavaScriptProcesor.java	Fri Jan 18 14:27:22 2013 +0100
    10.3 @@ -0,0 +1,92 @@
    10.4 +/**
    10.5 + * Back 2 Browser Bytecode Translator
    10.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    10.7 + *
    10.8 + * This program is free software: you can redistribute it and/or modify
    10.9 + * it under the terms of the GNU General Public License as published by
   10.10 + * the Free Software Foundation, version 2 of the License.
   10.11 + *
   10.12 + * This program is distributed in the hope that it will be useful,
   10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 + * GNU General Public License for more details.
   10.16 + *
   10.17 + * You should have received a copy of the GNU General Public License
   10.18 + * along with this program. Look for COPYING file in the top folder.
   10.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   10.20 + */
   10.21 +package org.apidesign.bck2brwsr.core.impl;
   10.22 +
   10.23 +import java.util.Collections;
   10.24 +import java.util.HashSet;
   10.25 +import java.util.List;
   10.26 +import java.util.Set;
   10.27 +import javax.annotation.processing.AbstractProcessor;
   10.28 +import javax.annotation.processing.Completion;
   10.29 +import javax.annotation.processing.Completions;
   10.30 +import javax.annotation.processing.Processor;
   10.31 +import javax.annotation.processing.RoundEnvironment;
   10.32 +import javax.lang.model.element.AnnotationMirror;
   10.33 +import javax.lang.model.element.Element;
   10.34 +import javax.lang.model.element.ElementKind;
   10.35 +import javax.lang.model.element.ExecutableElement;
   10.36 +import javax.lang.model.element.Modifier;
   10.37 +import javax.lang.model.element.TypeElement;
   10.38 +import javax.lang.model.element.VariableElement;
   10.39 +import javax.tools.Diagnostic;
   10.40 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   10.41 +import org.openide.util.lookup.ServiceProvider;
   10.42 +
   10.43 +/**
   10.44 + *
   10.45 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.46 + */
   10.47 +@ServiceProvider(service = Processor.class)
   10.48 +public final class JavaScriptProcesor extends AbstractProcessor {
   10.49 +    @Override
   10.50 +    public Set<String> getSupportedAnnotationTypes() {
   10.51 +        Set<String> set = new HashSet<>();
   10.52 +        set.add(JavaScriptBody.class.getName());
   10.53 +        return set;
   10.54 +    }
   10.55 +    
   10.56 +    @Override
   10.57 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   10.58 +        for (Element e : roundEnv.getElementsAnnotatedWith(JavaScriptBody.class)) {
   10.59 +            if (e.getKind() != ElementKind.METHOD && e.getKind() != ElementKind.CONSTRUCTOR) {
   10.60 +                continue;
   10.61 +            }
   10.62 +            ExecutableElement ee = (ExecutableElement)e;
   10.63 +            List<? extends VariableElement> params = ee.getParameters();
   10.64 +            
   10.65 +            JavaScriptBody jsb = e.getAnnotation(JavaScriptBody.class);
   10.66 +            String[] arr = jsb.args();
   10.67 +            if (params.size() != arr.length) {
   10.68 +                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Number of args arguments does not match real arguments!", e);
   10.69 +            }
   10.70 +        }
   10.71 +        return true;
   10.72 +    }
   10.73 +
   10.74 +    @Override
   10.75 +    public Iterable<? extends Completion> getCompletions(Element e, 
   10.76 +        AnnotationMirror annotation, ExecutableElement member, String userText
   10.77 +    ) {
   10.78 +        StringBuilder sb = new StringBuilder();
   10.79 +        if (e.getKind() == ElementKind.METHOD && member.getSimpleName().contentEquals("args")) {
   10.80 +            ExecutableElement ee = (ExecutableElement) e;
   10.81 +            String sep = "";
   10.82 +            sb.append("{ ");
   10.83 +            for (VariableElement ve : ee.getParameters()) {
   10.84 +                sb.append(sep).append('"').append(ve.getSimpleName())
   10.85 +                    .append('"');
   10.86 +                sep = ", ";
   10.87 +            }
   10.88 +            sb.append(" }");
   10.89 +            return Collections.nCopies(1, Completions.of(sb.toString()));
   10.90 +        }
   10.91 +        return null;
   10.92 +    }
   10.93 +
   10.94 +    
   10.95 +}
    11.1 --- a/emul/src/main/java/java/lang/AbstractStringBuilder.java	Fri Jan 18 14:23:18 2013 +0100
    11.2 +++ b/emul/src/main/java/java/lang/AbstractStringBuilder.java	Fri Jan 18 14:27:22 2013 +0100
    11.3 @@ -1271,8 +1271,7 @@
    11.4       *            <code>null</code>.
    11.5       */
    11.6      public int indexOf(String str, int fromIndex) {
    11.7 -        return String.indexOf(value, 0, count,
    11.8 -                              str.toCharArray(), 0, str.length(), fromIndex);
    11.9 +        return toString().indexOf(str, fromIndex);
   11.10      }
   11.11  
   11.12      /**
    12.1 --- a/emul/src/main/java/java/lang/Character.java	Fri Jan 18 14:23:18 2013 +0100
    12.2 +++ b/emul/src/main/java/java/lang/Character.java	Fri Jan 18 14:27:22 2013 +0100
    12.3 @@ -25,6 +25,8 @@
    12.4  
    12.5  package java.lang;
    12.6  
    12.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    12.8 +
    12.9  /**
   12.10   * The {@code Character} class wraps a value of the primitive
   12.11   * type {@code char} in an object. An object of type
   12.12 @@ -1525,7 +1527,7 @@
   12.13       * @see     Character#getType(char)
   12.14       */
   12.15      public static boolean isLowerCase(char ch) {
   12.16 -        throw new UnsupportedOperationException();
   12.17 +        return ch == toLowerCase(ch);
   12.18      }
   12.19  
   12.20      /**
   12.21 @@ -1560,7 +1562,7 @@
   12.22       * @since   1.0
   12.23       */
   12.24      public static boolean isUpperCase(char ch) {
   12.25 -        throw new UnsupportedOperationException();
   12.26 +        return ch == toUpperCase(ch);
   12.27      }
   12.28  
   12.29      /**
   12.30 @@ -1676,7 +1678,7 @@
   12.31       * @see     Character#getType(char)
   12.32       */
   12.33      public static boolean isDigit(char ch) {
   12.34 -        return isDigit((int)ch);
   12.35 +        return String.valueOf(ch).matches("\\d");
   12.36      }
   12.37  
   12.38      /**
   12.39 @@ -1710,8 +1712,11 @@
   12.40       * @since   1.5
   12.41       */
   12.42      public static boolean isDigit(int codePoint) {
   12.43 -        return getType(codePoint) == Character.DECIMAL_DIGIT_NUMBER;
   12.44 +        return fromCodeChars(codePoint).matches("\\d");
   12.45      }
   12.46 +    
   12.47 +    @JavaScriptBody(args = "c", body = "return String.fromCharCode(c);")
   12.48 +    private native static String fromCodeChars(int codePoint);
   12.49  
   12.50      /**
   12.51       * Determines if a character is defined in Unicode.
   12.52 @@ -1802,7 +1807,7 @@
   12.53       * @see     Character#isUpperCase(char)
   12.54       */
   12.55      public static boolean isLetter(char ch) {
   12.56 -        return isLetter((int)ch);
   12.57 +        return String.valueOf(ch).matches("\\w") && !isDigit(ch);
   12.58      }
   12.59  
   12.60      /**
   12.61 @@ -1835,12 +1840,7 @@
   12.62       * @since   1.5
   12.63       */
   12.64      public static boolean isLetter(int codePoint) {
   12.65 -        return ((((1 << Character.UPPERCASE_LETTER) |
   12.66 -            (1 << Character.LOWERCASE_LETTER) |
   12.67 -            (1 << Character.TITLECASE_LETTER) |
   12.68 -            (1 << Character.MODIFIER_LETTER) |
   12.69 -            (1 << Character.OTHER_LETTER)) >> getType(codePoint)) & 1)
   12.70 -            != 0;
   12.71 +        return fromCodeChars(codePoint).matches("\\w") && !isDigit(codePoint);
   12.72      }
   12.73  
   12.74      /**
   12.75 @@ -1868,7 +1868,7 @@
   12.76       * @since   1.0.2
   12.77       */
   12.78      public static boolean isLetterOrDigit(char ch) {
   12.79 -        return isLetterOrDigit((int)ch);
   12.80 +        return String.valueOf(ch).matches("\\w");
   12.81      }
   12.82  
   12.83      /**
   12.84 @@ -1889,13 +1889,7 @@
   12.85       * @since   1.5
   12.86       */
   12.87      public static boolean isLetterOrDigit(int codePoint) {
   12.88 -        return ((((1 << Character.UPPERCASE_LETTER) |
   12.89 -            (1 << Character.LOWERCASE_LETTER) |
   12.90 -            (1 << Character.TITLECASE_LETTER) |
   12.91 -            (1 << Character.MODIFIER_LETTER) |
   12.92 -            (1 << Character.OTHER_LETTER) |
   12.93 -            (1 << Character.DECIMAL_DIGIT_NUMBER)) >> getType(codePoint)) & 1)
   12.94 -            != 0;
   12.95 +        return fromCodeChars(codePoint).matches("\\w");
   12.96      }
   12.97      
   12.98      static int getType(int x) {
   12.99 @@ -1930,7 +1924,7 @@
  12.100       * @see     String#toLowerCase()
  12.101       */
  12.102      public static char toLowerCase(char ch) {
  12.103 -        throw new UnsupportedOperationException();
  12.104 +        return String.valueOf(ch).toLowerCase().charAt(0);
  12.105      }
  12.106  
  12.107      /**
  12.108 @@ -1961,7 +1955,7 @@
  12.109       * @see     String#toUpperCase()
  12.110       */
  12.111      public static char toUpperCase(char ch) {
  12.112 -        throw new UnsupportedOperationException();
  12.113 +        return String.valueOf(ch).toUpperCase().charAt(0);
  12.114      }
  12.115  
  12.116      /**
    13.1 --- a/emul/src/main/java/java/lang/Class.java	Fri Jan 18 14:23:18 2013 +0100
    13.2 +++ b/emul/src/main/java/java/lang/Class.java	Fri Jan 18 14:27:22 2013 +0100
    13.3 @@ -25,6 +25,7 @@
    13.4  
    13.5  package java.lang;
    13.6  
    13.7 +import java.io.ByteArrayInputStream;
    13.8  import org.apidesign.bck2brwsr.emul.AnnotationImpl;
    13.9  import java.io.InputStream;
   13.10  import java.lang.annotation.Annotation;
   13.11 @@ -32,6 +33,7 @@
   13.12  import java.lang.reflect.Method;
   13.13  import java.lang.reflect.TypeVariable;
   13.14  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   13.15 +import org.apidesign.bck2brwsr.emul.MethodImpl;
   13.16  
   13.17  /**
   13.18   * Instances of the class {@code Class} represent classes and
   13.19 @@ -143,9 +145,31 @@
   13.20       * @exception ClassNotFoundException if the class cannot be located
   13.21       */
   13.22      public static Class<?> forName(String className)
   13.23 -                throws ClassNotFoundException {
   13.24 -        throw new UnsupportedOperationException();
   13.25 +    throws ClassNotFoundException {
   13.26 +        if (className.startsWith("[")) {
   13.27 +            Class<?> arrType = defineArray(className);
   13.28 +            Class<?> c = arrType;
   13.29 +            while (c != null && c.isArray()) {
   13.30 +                c = c.getComponentType0(); // verify component type is sane
   13.31 +            }
   13.32 +            return arrType;
   13.33 +        }
   13.34 +        Class<?> c = loadCls(className, className.replace('.', '_'));
   13.35 +        if (c == null) {
   13.36 +            throw new ClassNotFoundException(className);
   13.37 +        }
   13.38 +        return c;
   13.39      }
   13.40 +    
   13.41 +    @JavaScriptBody(args = {"n", "c" }, body =
   13.42 +        "if (vm[c]) return vm[c].$class;\n"
   13.43 +      + "if (vm.loadClass) {\n"
   13.44 +      + "  vm.loadClass(n);\n"
   13.45 +      + "  if (vm[c]) return vm[c].$class;\n"
   13.46 +      + "}\n"
   13.47 +      + "return null;"
   13.48 +    )
   13.49 +    private static native Class<?> loadCls(String n, String c);
   13.50  
   13.51  
   13.52      /**
   13.53 @@ -195,15 +219,32 @@
   13.54       *             </ul>
   13.55       *
   13.56       */
   13.57 -    @JavaScriptBody(args = "self", body =
   13.58 -          "var inst = self.cnstr();"
   13.59 -        + "inst.cons__V(inst);"
   13.60 -        + "return inst;"
   13.61 +    @JavaScriptBody(args = { "self", "illegal" }, body =
   13.62 +          "\nvar c = self.cnstr;"
   13.63 +        + "\nif (c['cons__V']) {"
   13.64 +        + "\n  if ((c.cons__V.access & 0x1) != 0) {"
   13.65 +        + "\n    var inst = c();"
   13.66 +        + "\n    c.cons__V.call(inst);"
   13.67 +        + "\n    return inst;"
   13.68 +        + "\n  }"
   13.69 +        + "\n  return illegal;"
   13.70 +        + "\n}"
   13.71 +        + "\nreturn null;"
   13.72      )
   13.73 +    private static native Object newInstance0(Class<?> self, Object illegal);
   13.74 +    
   13.75      public T newInstance()
   13.76          throws InstantiationException, IllegalAccessException
   13.77      {
   13.78 -        throw new UnsupportedOperationException();
   13.79 +        Object illegal = new Object();
   13.80 +        Object inst = newInstance0(this, illegal);
   13.81 +        if (inst == null) {
   13.82 +            throw new InstantiationException(getName());
   13.83 +        }
   13.84 +        if (inst == illegal) {
   13.85 +            throw new IllegalAccessException();
   13.86 +        }
   13.87 +        return (T)inst;
   13.88      }
   13.89  
   13.90      /**
   13.91 @@ -236,7 +277,15 @@
   13.92       *
   13.93       * @since JDK1.1
   13.94       */
   13.95 -    public native boolean isInstance(Object obj);
   13.96 +    public boolean isInstance(Object obj) {
   13.97 +        String prop = "$instOf_" + getName().replace('.', '_');
   13.98 +        return hasProperty(obj, prop);
   13.99 +    }
  13.100 +    
  13.101 +    @JavaScriptBody(args = { "who", "prop" }, body = 
  13.102 +        "if (who[prop]) return true; else return false;"
  13.103 +    )
  13.104 +    private static native boolean hasProperty(Object who, String prop);
  13.105  
  13.106  
  13.107      /**
  13.108 @@ -273,7 +322,12 @@
  13.109       * @return  {@code true} if this object represents an interface;
  13.110       *          {@code false} otherwise.
  13.111       */
  13.112 -    public native boolean isInterface();
  13.113 +    public boolean isInterface() {
  13.114 +        return (getAccess() & 0x200) != 0;
  13.115 +    }
  13.116 +    
  13.117 +    @JavaScriptBody(args = {}, body = "return this.access;")
  13.118 +    private native int getAccess();
  13.119  
  13.120  
  13.121      /**
  13.122 @@ -284,7 +338,7 @@
  13.123       * @since   JDK1.1
  13.124       */
  13.125      public boolean isArray() {
  13.126 -        return false;
  13.127 +        return hasProperty(this, "array"); // NOI18N
  13.128      }
  13.129  
  13.130  
  13.131 @@ -316,6 +370,10 @@
  13.132       * @see     java.lang.Void#TYPE
  13.133       * @since JDK1.1
  13.134       */
  13.135 +    @JavaScriptBody(args = {}, body = 
  13.136 +           "if (this.primitive) return true;"
  13.137 +        + "else return false;"
  13.138 +    )
  13.139      public native boolean isPrimitive();
  13.140  
  13.141      /**
  13.142 @@ -397,7 +455,7 @@
  13.143          return jvmName().replace('/', '.');
  13.144      }
  13.145  
  13.146 -    @JavaScriptBody(args = "self", body = "return self.jvmName;")
  13.147 +    @JavaScriptBody(args = {}, body = "return this.jvmName;")
  13.148      private native String jvmName();
  13.149  
  13.150      
  13.151 @@ -431,7 +489,7 @@
  13.152       *
  13.153       * @return the superclass of the class represented by this object.
  13.154       */
  13.155 -    @JavaScriptBody(args = "self", body = "return self.superclass;")
  13.156 +    @JavaScriptBody(args = {}, body = "return this.superclass;")
  13.157      public native Class<? super T> getSuperclass();
  13.158  
  13.159      /**
  13.160 @@ -617,7 +675,7 @@
  13.161       * @since JDK1.1
  13.162       */
  13.163      public Method[] getMethods() throws SecurityException {
  13.164 -        return Method.findMethods(this);
  13.165 +        return MethodImpl.findMethods(this, 0x01);
  13.166      }
  13.167  
  13.168      /**
  13.169 @@ -747,10 +805,18 @@
  13.170       * @since JDK1.1
  13.171       */
  13.172      public Method getMethod(String name, Class<?>... parameterTypes)
  13.173 -        throws SecurityException {
  13.174 -        Method m = Method.findMethod(this, name, parameterTypes);
  13.175 +        throws SecurityException, NoSuchMethodException {
  13.176 +        Method m = MethodImpl.findMethod(this, name, parameterTypes);
  13.177          if (m == null) {
  13.178 -            throw new SecurityException(); // XXX: NoSuchMethodException
  13.179 +            StringBuilder sb = new StringBuilder();
  13.180 +            sb.append(getName()).append('.').append(name).append('(');
  13.181 +            String sep = "";
  13.182 +            for (int i = 0; i < parameterTypes.length; i++) {
  13.183 +                sb.append(sep).append(parameterTypes[i].getName());
  13.184 +                sep = ", ";
  13.185 +            }
  13.186 +            sb.append(')');
  13.187 +            throw new NoSuchMethodException(sb.toString());
  13.188          }
  13.189          return m;
  13.190      }
  13.191 @@ -832,13 +898,14 @@
  13.192       */
  13.193       public InputStream getResourceAsStream(String name) {
  13.194          name = resolveName(name);
  13.195 -        ClassLoader cl = getClassLoader0();
  13.196 -        if (cl==null) {
  13.197 -            // A system class.
  13.198 -            return ClassLoader.getSystemResourceAsStream(name);
  13.199 -        }
  13.200 -        return cl.getResourceAsStream(name);
  13.201 -    }
  13.202 +        byte[] arr = getResourceAsStream0(name);
  13.203 +        return arr == null ? null : new ByteArrayInputStream(arr);
  13.204 +     }
  13.205 +     
  13.206 +     @JavaScriptBody(args = "name", body = 
  13.207 +         "return (vm.loadBytes) ? vm.loadBytes(name) : null;"
  13.208 +     )
  13.209 +     private static native byte[] getResourceAsStream0(String name);
  13.210  
  13.211      /**
  13.212       * Finds a resource with a given name.  The rules for searching resources
  13.213 @@ -876,7 +943,7 @@
  13.214       */
  13.215      public java.net.URL getResource(String name) {
  13.216          name = resolveName(name);
  13.217 -        ClassLoader cl = getClassLoader0();
  13.218 +        ClassLoader cl = null;
  13.219          if (cl==null) {
  13.220              // A system class.
  13.221              return ClassLoader.getSystemResource(name);
  13.222 @@ -940,9 +1007,6 @@
  13.223          throw new SecurityException();
  13.224      }
  13.225      
  13.226 -    // Package-private to allow ClassLoader access
  13.227 -    native ClassLoader getClassLoader0();    
  13.228 -
  13.229      /**
  13.230       * Returns the {@code Class} representing the component type of an
  13.231       * array.  If this class does not represent an array class this method
  13.232 @@ -954,9 +1018,59 @@
  13.233       * @since JDK1.1
  13.234       */
  13.235      public Class<?> getComponentType() {
  13.236 +        if (isArray()) {
  13.237 +            try {
  13.238 +                return getComponentType0();
  13.239 +            } catch (ClassNotFoundException cnfe) {
  13.240 +                throw new IllegalStateException(cnfe);
  13.241 +            }
  13.242 +        }
  13.243          return null;
  13.244      }
  13.245  
  13.246 +    private Class<?> getComponentType0() throws ClassNotFoundException {
  13.247 +        String n = getName().substring(1);
  13.248 +        switch (n.charAt(0)) {
  13.249 +            case 'L': 
  13.250 +                n = n.substring(1, n.length() - 1);
  13.251 +                return Class.forName(n);
  13.252 +            case 'I':
  13.253 +                return Integer.TYPE;
  13.254 +            case 'J':
  13.255 +                return Long.TYPE;
  13.256 +            case 'D':
  13.257 +                return Double.TYPE;
  13.258 +            case 'F':
  13.259 +                return Float.TYPE;
  13.260 +            case 'B':
  13.261 +                return Byte.TYPE;
  13.262 +            case 'Z':
  13.263 +                return Boolean.TYPE;
  13.264 +            case 'S':
  13.265 +                return Short.TYPE;
  13.266 +            case 'V':
  13.267 +                return Void.TYPE;
  13.268 +            case 'C':
  13.269 +                return Character.TYPE;
  13.270 +            case '[':
  13.271 +                return defineArray(n);
  13.272 +            default:
  13.273 +                throw new ClassNotFoundException("Unknown component type of " + getName());
  13.274 +        }
  13.275 +    }
  13.276 +    
  13.277 +    @JavaScriptBody(args = { "sig" }, body = 
  13.278 +        "var c = Array[sig];\n" +
  13.279 +        "if (c) return c;\n" +
  13.280 +        "c = vm.java_lang_Class(true);\n" +
  13.281 +        "c.jvmName = sig;\n" +
  13.282 +        "c.superclass = vm.java_lang_Object(false).$class;\n" +
  13.283 +        "c.array = true;\n" +
  13.284 +        "Array[sig] = c;\n" +
  13.285 +        "return c;"
  13.286 +    )
  13.287 +    private static native Class<?> defineArray(String sig);
  13.288 +    
  13.289      /**
  13.290       * Returns true if and only if this class was declared as an enum in the
  13.291       * source code.
  13.292 @@ -1022,10 +1136,10 @@
  13.293              throw new ClassCastException(this.toString());
  13.294      }
  13.295  
  13.296 -    @JavaScriptBody(args = { "self", "ac" }, 
  13.297 +    @JavaScriptBody(args = { "ac" }, 
  13.298          body = 
  13.299 -          "if (self.anno) {"
  13.300 -        + "  return self.anno['L' + ac.jvmName + ';'];"
  13.301 +          "if (this.anno) {"
  13.302 +        + "  return this.anno['L' + ac.jvmName + ';'];"
  13.303          + "} else return null;"
  13.304      )
  13.305      private Object getAnnotationData(Class<?> annotationClass) {
  13.306 @@ -1044,8 +1158,8 @@
  13.307       * @throws NullPointerException {@inheritDoc}
  13.308       * @since 1.5
  13.309       */
  13.310 -    @JavaScriptBody(args = { "self", "ac" }, 
  13.311 -        body = "if (self.anno && self.anno['L' + ac.jvmName + ';']) { return true; }"
  13.312 +    @JavaScriptBody(args = { "ac" }, 
  13.313 +        body = "if (this.anno && this.anno['L' + ac.jvmName + ';']) { return true; }"
  13.314          + "else return false;"
  13.315      )
  13.316      public boolean isAnnotationPresent(
  13.317 @@ -1056,7 +1170,7 @@
  13.318          return getAnnotation(annotationClass) != null;
  13.319      }
  13.320  
  13.321 -    @JavaScriptBody(args = "self", body = "return self.anno;")
  13.322 +    @JavaScriptBody(args = {}, body = "return this.anno;")
  13.323      private Object getAnnotationData() {
  13.324          throw new UnsupportedOperationException();
  13.325      }
  13.326 @@ -1076,10 +1190,13 @@
  13.327          throw new UnsupportedOperationException();
  13.328      }
  13.329  
  13.330 -    static Class getPrimitiveClass(String type) {
  13.331 -        // XXX
  13.332 -        return Object.class;
  13.333 -    }
  13.334 +    @JavaScriptBody(args = "type", body = ""
  13.335 +        + "var c = vm.java_lang_Class(true);"
  13.336 +        + "c.jvmName = type;"
  13.337 +        + "c.primitive = true;"
  13.338 +        + "return c;"
  13.339 +    )
  13.340 +    native static Class getPrimitiveClass(String type);
  13.341  
  13.342      public boolean desiredAssertionStatus() {
  13.343          return false;
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/emul/src/main/java/java/lang/NoSuchMethodException.java	Fri Jan 18 14:27:22 2013 +0100
    14.3 @@ -0,0 +1,53 @@
    14.4 +/*
    14.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
    14.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.7 + *
    14.8 + * This code is free software; you can redistribute it and/or modify it
    14.9 + * under the terms of the GNU General Public License version 2 only, as
   14.10 + * published by the Free Software Foundation.  Oracle designates this
   14.11 + * particular file as subject to the "Classpath" exception as provided
   14.12 + * by Oracle in the LICENSE file that accompanied this code.
   14.13 + *
   14.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.17 + * version 2 for more details (a copy is included in the LICENSE file that
   14.18 + * accompanied this code).
   14.19 + *
   14.20 + * You should have received a copy of the GNU General Public License version
   14.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.23 + *
   14.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.25 + * or visit www.oracle.com if you need additional information or have any
   14.26 + * questions.
   14.27 + */
   14.28 +
   14.29 +package java.lang;
   14.30 +
   14.31 +/**
   14.32 + * Thrown when a particular method cannot be found.
   14.33 + *
   14.34 + * @author     unascribed
   14.35 + * @since      JDK1.0
   14.36 + */
   14.37 +public
   14.38 +class NoSuchMethodException extends ReflectiveOperationException {
   14.39 +    private static final long serialVersionUID = 5034388446362600923L;
   14.40 +
   14.41 +    /**
   14.42 +     * Constructs a <code>NoSuchMethodException</code> without a detail message.
   14.43 +     */
   14.44 +    public NoSuchMethodException() {
   14.45 +        super();
   14.46 +    }
   14.47 +
   14.48 +    /**
   14.49 +     * Constructs a <code>NoSuchMethodException</code> with a detail message.
   14.50 +     *
   14.51 +     * @param      s   the detail message.
   14.52 +     */
   14.53 +    public NoSuchMethodException(String s) {
   14.54 +        super(s);
   14.55 +    }
   14.56 +}
    15.1 --- a/emul/src/main/java/java/lang/Number.java	Fri Jan 18 14:23:18 2013 +0100
    15.2 +++ b/emul/src/main/java/java/lang/Number.java	Fri Jan 18 14:27:22 2013 +0100
    15.3 @@ -25,6 +25,8 @@
    15.4  
    15.5  package java.lang;
    15.6  
    15.7 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
    15.8 +
    15.9  /**
   15.10   * The abstract class <code>Number</code> is the superclass of classes
   15.11   * <code>BigDecimal</code>, <code>BigInteger</code>,
   15.12 @@ -46,6 +48,10 @@
   15.13   * @see     java.lang.Short
   15.14   * @since   JDK1.0
   15.15   */
   15.16 +@ExtraJavaScript(
   15.17 +    resource="/org/apidesign/vm4brwsr/emul/java_lang_Number.js",
   15.18 +    processByteCode=true
   15.19 +)
   15.20  public abstract class Number implements java.io.Serializable {
   15.21      /**
   15.22       * Returns the value of the specified number as an <code>int</code>.
    16.1 --- a/emul/src/main/java/java/lang/Object.java	Fri Jan 18 14:23:18 2013 +0100
    16.2 +++ b/emul/src/main/java/java/lang/Object.java	Fri Jan 18 14:27:22 2013 +0100
    16.3 @@ -66,7 +66,7 @@
    16.4       * @see    Class Literals, section 15.8.2 of
    16.5       *         <cite>The Java&trade; Language Specification</cite>.
    16.6       */
    16.7 -    @JavaScriptBody(args="self", body="return self.constructor.$class;")
    16.8 +    @JavaScriptBody(args={}, body="return this.constructor.$class;")
    16.9      public final native Class<?> getClass();
   16.10  
   16.11      /**
   16.12 @@ -104,8 +104,16 @@
   16.13       * @see     java.lang.Object#equals(java.lang.Object)
   16.14       * @see     java.lang.System#identityHashCode
   16.15       */
   16.16 +    @JavaScriptBody(args = {}, body = 
   16.17 +        "if (this.$hashCode) return this.$hashCode;\n"
   16.18 +        + "var h = this.computeHashCode__I();\n"
   16.19 +        + "return this.$hashCode = h & h;"
   16.20 +    )
   16.21      public native int hashCode();
   16.22  
   16.23 +    @JavaScriptBody(args = {}, body = "Math.random() * Math.pow(2, 32);")
   16.24 +    native int computeHashCode();
   16.25 +    
   16.26      /**
   16.27       * Indicates whether some other object is "equal to" this one.
   16.28       * <p>
   16.29 @@ -216,7 +224,28 @@
   16.30       *               be cloned.
   16.31       * @see java.lang.Cloneable
   16.32       */
   16.33 -    protected native Object clone() throws CloneNotSupportedException;
   16.34 +    protected Object clone() throws CloneNotSupportedException {
   16.35 +        Object ret = clone(this);
   16.36 +        if (ret == null) {
   16.37 +            throw new CloneNotSupportedException(getClass().getName());
   16.38 +        }
   16.39 +        return ret;
   16.40 +    }
   16.41 +
   16.42 +    @JavaScriptBody(args = "self", body = 
   16.43 +          "\nif (!self.$instOf_java_lang_Cloneable) {"
   16.44 +        + "\n  return null;"
   16.45 +        + "\n} else {"
   16.46 +        + "\n  var clone = self.constructor(true);"
   16.47 +        + "\n  var props = Object.getOwnPropertyNames(self);"
   16.48 +        + "\n  for (var i = 0; i < props.length; i++) {"
   16.49 +        + "\n    var p = props[i];"
   16.50 +        + "\n    clone[p] = self[p];"
   16.51 +        + "\n  };"
   16.52 +        + "\n  return clone;"
   16.53 +        + "\n}"
   16.54 +    )
   16.55 +    private static native Object clone(Object self) throws CloneNotSupportedException;
   16.56  
   16.57      /**
   16.58       * Returns a string representation of the object. In general, the
    17.1 --- a/emul/src/main/java/java/lang/String.java	Fri Jan 18 14:23:18 2013 +0100
    17.2 +++ b/emul/src/main/java/java/lang/String.java	Fri Jan 18 14:27:22 2013 +0100
    17.3 @@ -108,10 +108,6 @@
    17.4  public final class String
    17.5      implements java.io.Serializable, Comparable<String>, CharSequence
    17.6  {
    17.7 -    @JavaScriptOnly
    17.8 -    /** Cache the hash code for the string */
    17.9 -    private int hash; // Default to 0
   17.10 -    
   17.11      /** real string to delegate to */
   17.12      private Object r;
   17.13  
   17.14 @@ -173,11 +169,11 @@
   17.15       * @param  value
   17.16       *         The initial value of the string
   17.17       */
   17.18 -    @JavaScriptBody(args = { "self", "charArr" }, body=
   17.19 +    @JavaScriptBody(args = { "charArr" }, body=
   17.20          "for (var i = 0; i < charArr.length; i++) {\n"
   17.21        + "  if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n"
   17.22        + "}\n"
   17.23 -      + "self.fld_r = charArr.join('');\n"
   17.24 +      + "this.fld_r = charArr.join('');\n"
   17.25      )
   17.26      public String(char value[]) {
   17.27      }
   17.28 @@ -203,12 +199,12 @@
   17.29       *          If the {@code offset} and {@code count} arguments index
   17.30       *          characters outside the bounds of the {@code value} array
   17.31       */
   17.32 -    @JavaScriptBody(args = { "self", "charArr", "off", "cnt" }, body =
   17.33 +    @JavaScriptBody(args = { "charArr", "off", "cnt" }, body =
   17.34          "var up = off + cnt;\n" +
   17.35          "for (var i = off; i < up; i++) {\n" +
   17.36          "  if (typeof charArr[i] === 'number') charArr[i] = String.fromCharCode(charArr[i]);\n" +
   17.37          "}\n" +
   17.38 -        "self.fld_r = charArr.slice(off, up).join(\"\");\n"
   17.39 +        "this.fld_r = charArr.slice(off, up).join(\"\");\n"
   17.40      )
   17.41      public String(char value[], int offset, int count) {
   17.42      }
   17.43 @@ -622,7 +618,7 @@
   17.44       * @return  the length of the sequence of characters represented by this
   17.45       *          object.
   17.46       */
   17.47 -    @JavaScriptBody(args = "self", body = "return self.toString().length;")
   17.48 +    @JavaScriptBody(args = {}, body = "return this.toString().length;")
   17.49      public int length() {
   17.50          throw new UnsupportedOperationException();
   17.51      }
   17.52 @@ -635,7 +631,7 @@
   17.53       *
   17.54       * @since 1.6
   17.55       */
   17.56 -    @JavaScriptBody(args = "self", body="return self.toString().length === 0;")
   17.57 +    @JavaScriptBody(args = {}, body="return this.toString().length === 0;")
   17.58      public boolean isEmpty() {
   17.59          return length() == 0;
   17.60      }
   17.61 @@ -658,8 +654,8 @@
   17.62       *             argument is negative or not less than the length of this
   17.63       *             string.
   17.64       */
   17.65 -    @JavaScriptBody(args = { "self", "index" }, 
   17.66 -        body = "return self.toString().charCodeAt(index);"
   17.67 +    @JavaScriptBody(args = { "index" }, 
   17.68 +        body = "return this.toString().charCodeAt(index);"
   17.69      )
   17.70      public char charAt(int index) {
   17.71          throw new UnsupportedOperationException();
   17.72 @@ -784,8 +780,8 @@
   17.73       * Copy characters from this string into dst starting at dstBegin.
   17.74       * This method doesn't perform any range checking.
   17.75       */
   17.76 -    @JavaScriptBody(args = { "self", "arr", "to" }, body = 
   17.77 -        "var s = self.toString();\n" +
   17.78 +    @JavaScriptBody(args = { "arr", "to" }, body = 
   17.79 +        "var s = this.toString();\n" +
   17.80          "for (var i = 0; i < s.length; i++) {\n" +
   17.81          "   arr[to++] = s[i];\n" +
   17.82          "}"
   17.83 @@ -824,8 +820,8 @@
   17.84       *            <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
   17.85       *                <code>dst.length</code></ul>
   17.86       */
   17.87 -    @JavaScriptBody(args = { "self", "beg", "end", "arr", "dst" }, body=
   17.88 -        "var s = self.toString();\n" +
   17.89 +    @JavaScriptBody(args = { "beg", "end", "arr", "dst" }, body=
   17.90 +        "var s = this.toString();\n" +
   17.91          "while (beg < end) {\n" +
   17.92          "  arr[dst++] = s[beg++];\n" +
   17.93          "}\n"
   17.94 @@ -997,9 +993,9 @@
   17.95       * @see  #compareTo(String)
   17.96       * @see  #equalsIgnoreCase(String)
   17.97       */
   17.98 -    @JavaScriptBody(args = { "self", "obj" }, body = 
   17.99 +    @JavaScriptBody(args = { "obj" }, body = 
  17.100          "return obj.$instOf_java_lang_String && "
  17.101 -        + "self.toString() === obj.toString();"
  17.102 +        + "this.toString() === obj.toString();"
  17.103      )
  17.104      public boolean equals(Object anObject) {
  17.105          if (this == anObject) {
  17.106 @@ -1424,9 +1420,9 @@
  17.107       *          this.substring(toffset).startsWith(prefix)
  17.108       *          </pre>
  17.109       */
  17.110 -    @JavaScriptBody(args = { "self", "find", "from" }, body=
  17.111 +    @JavaScriptBody(args = { "find", "from" }, body=
  17.112          "find = find.toString();\n" +
  17.113 -        "return self.toString().substring(from, from + find.length) === find;\n"
  17.114 +        "return this.toString().substring(from, from + find.length) === find;\n"
  17.115      )
  17.116      public boolean startsWith(String prefix, int toffset) {
  17.117          char ta[] = toCharArray();
  17.118 @@ -1491,26 +1487,18 @@
  17.119       *
  17.120       * @return  a hash code value for this object.
  17.121       */
  17.122 -    @JavaScriptBody(args = "self", body = 
  17.123 -        "var h = 0;\n" +
  17.124 -        "var s = self.toString();\n" +
  17.125 -        "for (var i = 0; i < s.length; i++) {\n" +
  17.126 -        "  var high = (h >> 16) & 0xffff, low = h & 0xffff;\n" +
  17.127 -        "  h = (((((31 * high) & 0xffff) << 16) >>> 0) + (31 * low) + s.charCodeAt(i)) & 0xffffffff;\n" +
  17.128 -        "}\n" +
  17.129 -        "return h;\n"
  17.130 -    )
  17.131      public int hashCode() {
  17.132 -        int h = hash;
  17.133 +        return super.hashCode();
  17.134 +    }
  17.135 +    int computeHashCode() {
  17.136 +        int h = 0;
  17.137          if (h == 0 && length() > 0) {
  17.138              int off = offset();
  17.139 -            char val[] = toCharArray();
  17.140              int len = length();
  17.141  
  17.142              for (int i = 0; i < len; i++) {
  17.143 -                h = 31*h + val[off++];
  17.144 +                h = 31*h + charAt(off++);
  17.145              }
  17.146 -            hash = h;
  17.147          }
  17.148          return h;
  17.149      }
  17.150 @@ -1582,9 +1570,9 @@
  17.151       *          than or equal to <code>fromIndex</code>, or <code>-1</code>
  17.152       *          if the character does not occur.
  17.153       */
  17.154 -    @JavaScriptBody(args = { "self", "ch", "from" }, body = 
  17.155 +    @JavaScriptBody(args = { "ch", "from" }, body = 
  17.156          "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
  17.157 -        "return self.toString().indexOf(ch, from);\n"
  17.158 +        "return this.toString().indexOf(ch, from);\n"
  17.159      )
  17.160      public int indexOf(int ch, int fromIndex) {
  17.161          if (fromIndex < 0) {
  17.162 @@ -1691,9 +1679,9 @@
  17.163       *          than or equal to <code>fromIndex</code>, or <code>-1</code>
  17.164       *          if the character does not occur before that point.
  17.165       */
  17.166 -    @JavaScriptBody(args = { "self", "ch", "from" }, body = 
  17.167 +    @JavaScriptBody(args = { "ch", "from" }, body = 
  17.168          "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" +
  17.169 -        "return self.toString().lastIndexOf(ch, from);"
  17.170 +        "return this.toString().lastIndexOf(ch, from);"
  17.171      )
  17.172      public int lastIndexOf(int ch, int fromIndex) {
  17.173          if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
  17.174 @@ -1766,63 +1754,10 @@
  17.175       *          starting at the specified index,
  17.176       *          or {@code -1} if there is no such occurrence.
  17.177       */
  17.178 -    @JavaScriptBody(args = { "self", "str", "fromIndex" }, body =
  17.179 -        "return self.toString().indexOf(str.toString(), fromIndex);"
  17.180 +    @JavaScriptBody(args = { "str", "fromIndex" }, body =
  17.181 +        "return this.toString().indexOf(str.toString(), fromIndex);"
  17.182      )
  17.183 -    public int indexOf(String str, int fromIndex) {
  17.184 -        return indexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex);
  17.185 -    }
  17.186 -
  17.187 -    /**
  17.188 -     * Code shared by String and StringBuffer to do searches. The
  17.189 -     * source is the character array being searched, and the target
  17.190 -     * is the string being searched for.
  17.191 -     *
  17.192 -     * @param   source       the characters being searched.
  17.193 -     * @param   sourceOffset offset of the source string.
  17.194 -     * @param   sourceCount  count of the source string.
  17.195 -     * @param   target       the characters being searched for.
  17.196 -     * @param   targetOffset offset of the target string.
  17.197 -     * @param   targetCount  count of the target string.
  17.198 -     * @param   fromIndex    the index to begin searching from.
  17.199 -     */
  17.200 -    static int indexOf(char[] source, int sourceOffset, int sourceCount,
  17.201 -                       char[] target, int targetOffset, int targetCount,
  17.202 -                       int fromIndex) {
  17.203 -        if (fromIndex >= sourceCount) {
  17.204 -            return (targetCount == 0 ? sourceCount : -1);
  17.205 -        }
  17.206 -        if (fromIndex < 0) {
  17.207 -            fromIndex = 0;
  17.208 -        }
  17.209 -        if (targetCount == 0) {
  17.210 -            return fromIndex;
  17.211 -        }
  17.212 -
  17.213 -        char first  = target[targetOffset];
  17.214 -        int max = sourceOffset + (sourceCount - targetCount);
  17.215 -
  17.216 -        for (int i = sourceOffset + fromIndex; i <= max; i++) {
  17.217 -            /* Look for first character. */
  17.218 -            if (source[i] != first) {
  17.219 -                while (++i <= max && source[i] != first);
  17.220 -            }
  17.221 -
  17.222 -            /* Found first character, now look at the rest of v2 */
  17.223 -            if (i <= max) {
  17.224 -                int j = i + 1;
  17.225 -                int end = j + targetCount - 1;
  17.226 -                for (int k = targetOffset + 1; j < end && source[j] ==
  17.227 -                         target[k]; j++, k++);
  17.228 -
  17.229 -                if (j == end) {
  17.230 -                    /* Found whole string. */
  17.231 -                    return i - sourceOffset;
  17.232 -                }
  17.233 -            }
  17.234 -        }
  17.235 -        return -1;
  17.236 -    }
  17.237 +    public native int indexOf(String str, int fromIndex);
  17.238  
  17.239      /**
  17.240       * Returns the index within this string of the last occurrence of the
  17.241 @@ -1859,8 +1794,8 @@
  17.242       *          searching backward from the specified index,
  17.243       *          or {@code -1} if there is no such occurrence.
  17.244       */
  17.245 -    @JavaScriptBody(args = { "self", "s", "from" }, body = 
  17.246 -        "return self.toString().lastIndexOf(s.toString(), from);"
  17.247 +    @JavaScriptBody(args = { "s", "from" }, body = 
  17.248 +        "return this.toString().lastIndexOf(s.toString(), from);"
  17.249      )
  17.250      public int lastIndexOf(String str, int fromIndex) {
  17.251          return lastIndexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex);
  17.252 @@ -1968,8 +1903,8 @@
  17.253       *             <code>beginIndex</code> is larger than
  17.254       *             <code>endIndex</code>.
  17.255       */
  17.256 -    @JavaScriptBody(args = { "self", "beginIndex", "endIndex" }, body = 
  17.257 -        "return self.toString().substring(beginIndex, endIndex);"
  17.258 +    @JavaScriptBody(args = { "beginIndex", "endIndex" }, body = 
  17.259 +        "return this.toString().substring(beginIndex, endIndex);"
  17.260      )
  17.261      public String substring(int beginIndex, int endIndex) {
  17.262          if (beginIndex < 0) {
  17.263 @@ -2077,10 +2012,10 @@
  17.264       * @return  a string derived from this string by replacing every
  17.265       *          occurrence of <code>oldChar</code> with <code>newChar</code>.
  17.266       */
  17.267 -    @JavaScriptBody(args = { "self", "arg1", "arg2" }, body =
  17.268 +    @JavaScriptBody(args = { "arg1", "arg2" }, body =
  17.269          "if (typeof arg1 === 'number') arg1 = String.fromCharCode(arg1);\n" +
  17.270          "if (typeof arg2 === 'number') arg2 = String.fromCharCode(arg2);\n" +
  17.271 -        "var s = self.toString();\n" +
  17.272 +        "var s = this.toString();\n" +
  17.273          "for (;;) {\n" +
  17.274          "  var ret = s.replace(arg1, arg2);\n" +
  17.275          "  if (ret === s) {\n" +
  17.276 @@ -2143,6 +2078,12 @@
  17.277       * @since 1.4
  17.278       * @spec JSR-51
  17.279       */
  17.280 +    @JavaScriptBody(args = { "regex" }, body = 
  17.281 +          "var self = this.toString();\n"
  17.282 +        + "var re = new RegExp(regex.toString());\n"
  17.283 +        + "var r = re.exec(self);\n"
  17.284 +        + "return r != null && r.length > 0 && self.length == r[0].length;"
  17.285 +    )
  17.286      public boolean matches(String regex) {
  17.287          throw new UnsupportedOperationException();
  17.288      }
  17.289 @@ -2555,6 +2496,7 @@
  17.290       * @return  the <code>String</code>, converted to lowercase.
  17.291       * @see     java.lang.String#toLowerCase(Locale)
  17.292       */
  17.293 +    @JavaScriptBody(args = {}, body = "return this.toLowerCase();")
  17.294      public String toLowerCase() {
  17.295          throw new UnsupportedOperationException("Should be supported but without connection to locale");
  17.296      }
  17.297 @@ -2720,6 +2662,7 @@
  17.298       * @return  the <code>String</code>, converted to uppercase.
  17.299       * @see     java.lang.String#toUpperCase(Locale)
  17.300       */
  17.301 +    @JavaScriptBody(args = {}, body = "return this.toUpperCase();")
  17.302      public String toUpperCase() {
  17.303          throw new UnsupportedOperationException();
  17.304      }
  17.305 @@ -2775,7 +2718,7 @@
  17.306       *
  17.307       * @return  the string itself.
  17.308       */
  17.309 -    @JavaScriptBody(args = "self", body = "return self.toString();")
  17.310 +    @JavaScriptBody(args = {}, body = "return this.toString();")
  17.311      public String toString() {
  17.312          return this;
  17.313      }
  17.314 @@ -2787,7 +2730,6 @@
  17.315       *          of this string and whose contents are initialized to contain
  17.316       *          the character sequence represented by this string.
  17.317       */
  17.318 -    @JavaScriptBody(args = "self", body = "return self.toString().split('');")
  17.319      public char[] toCharArray() {
  17.320          char result[] = new char[length()];
  17.321          getChars(0, length(), result, 0);
    18.1 --- a/emul/src/main/java/java/lang/StringBuffer.java	Fri Jan 18 14:23:18 2013 +0100
    18.2 +++ b/emul/src/main/java/java/lang/StringBuffer.java	Fri Jan 18 14:27:22 2013 +0100
    18.3 @@ -527,8 +527,7 @@
    18.4       * @since      1.4
    18.5       */
    18.6      public synchronized int indexOf(String str, int fromIndex) {
    18.7 -        return String.indexOf(value, 0, count,
    18.8 -                              str.toCharArray(), 0, str.length(), fromIndex);
    18.9 +        return super.indexOf(str, fromIndex);
   18.10      }
   18.11  
   18.12      /**
    19.1 --- a/emul/src/main/java/java/lang/StringBuilder.java	Fri Jan 18 14:23:18 2013 +0100
    19.2 +++ b/emul/src/main/java/java/lang/StringBuilder.java	Fri Jan 18 14:27:22 2013 +0100
    19.3 @@ -376,8 +376,7 @@
    19.4       * @throws NullPointerException {@inheritDoc}
    19.5       */
    19.6      public int indexOf(String str, int fromIndex) {
    19.7 -        return String.indexOf(value, 0, count,
    19.8 -                              str.toCharArray(), 0, str.length(), fromIndex);
    19.9 +        return super.indexOf(str, fromIndex);
   19.10      }
   19.11  
   19.12      /**
    20.1 --- a/emul/src/main/java/java/lang/Throwable.java	Fri Jan 18 14:23:18 2013 +0100
    20.2 +++ b/emul/src/main/java/java/lang/Throwable.java	Fri Jan 18 14:27:22 2013 +0100
    20.3 @@ -783,7 +783,7 @@
    20.4          return this;
    20.5      }
    20.6  
    20.7 -    @JavaScriptBody(args = { "self", "dummy" }, body = "")
    20.8 +    @JavaScriptBody(args = { "dummy" }, body = "")
    20.9      private native Throwable fillInStackTrace(int dummy);
   20.10  
   20.11      /**
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/emul/src/main/java/java/lang/Void.java	Fri Jan 18 14:27:22 2013 +0100
    21.3 @@ -0,0 +1,49 @@
    21.4 +/*
    21.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    21.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 + *
    21.8 + * This code is free software; you can redistribute it and/or modify it
    21.9 + * under the terms of the GNU General Public License version 2 only, as
   21.10 + * published by the Free Software Foundation.  Oracle designates this
   21.11 + * particular file as subject to the "Classpath" exception as provided
   21.12 + * by Oracle in the LICENSE file that accompanied this code.
   21.13 + *
   21.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   21.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.17 + * version 2 for more details (a copy is included in the LICENSE file that
   21.18 + * accompanied this code).
   21.19 + *
   21.20 + * You should have received a copy of the GNU General Public License version
   21.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   21.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.23 + *
   21.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.25 + * or visit www.oracle.com if you need additional information or have any
   21.26 + * questions.
   21.27 + */
   21.28 +
   21.29 +package java.lang;
   21.30 +
   21.31 +/**
   21.32 + * The {@code Void} class is an uninstantiable placeholder class to hold a
   21.33 + * reference to the {@code Class} object representing the Java keyword
   21.34 + * void.
   21.35 + *
   21.36 + * @author  unascribed
   21.37 + * @since   JDK1.1
   21.38 + */
   21.39 +public final
   21.40 +class Void {
   21.41 +
   21.42 +    /**
   21.43 +     * The {@code Class} object representing the pseudo-type corresponding to
   21.44 +     * the keyword {@code void}.
   21.45 +     */
   21.46 +    public static final Class<Void> TYPE = Class.getPrimitiveClass("void");
   21.47 +
   21.48 +    /*
   21.49 +     * The Void class cannot be instantiated.
   21.50 +     */
   21.51 +    private Void() {}
   21.52 +}
    22.1 --- a/emul/src/main/java/java/lang/reflect/Method.java	Fri Jan 18 14:23:18 2013 +0100
    22.2 +++ b/emul/src/main/java/java/lang/reflect/Method.java	Fri Jan 18 14:27:22 2013 +0100
    22.3 @@ -26,8 +26,10 @@
    22.4  package java.lang.reflect;
    22.5  
    22.6  import java.lang.annotation.Annotation;
    22.7 +import java.util.Enumeration;
    22.8  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    22.9  import org.apidesign.bck2brwsr.emul.AnnotationImpl;
   22.10 +import org.apidesign.bck2brwsr.emul.MethodImpl;
   22.11  
   22.12  /**
   22.13   * A {@code Method} provides information about, and access to, a single method
   22.14 @@ -56,7 +58,6 @@
   22.15      private final String name;
   22.16      private final Object data;
   22.17      private final String sig;
   22.18 -    private int modifiers;
   22.19  
   22.20     // Generics infrastructure
   22.21  
   22.22 @@ -108,9 +109,12 @@
   22.23       * @see Modifier
   22.24       */
   22.25      public int getModifiers() {
   22.26 -        return modifiers;
   22.27 +        return getAccess(data);
   22.28      }
   22.29 -
   22.30 +    
   22.31 +    @JavaScriptBody(args = "self", body = "return self.access;")
   22.32 +    private static native int getAccess(Object self);
   22.33 +    
   22.34      /**
   22.35       * Returns an array of {@code TypeVariable} objects that represent the
   22.36       * type variables declared by the generic declaration represented by this
   22.37 @@ -137,7 +141,7 @@
   22.38       * @return the return type for the method this object represents
   22.39       */
   22.40      public Class<?> getReturnType() {
   22.41 -        throw new UnsupportedOperationException();
   22.42 +        return MethodImpl.signatureParser(sig).nextElement();
   22.43      }
   22.44  
   22.45      /**
   22.46 @@ -179,8 +183,13 @@
   22.47       * represents
   22.48       */
   22.49      public Class<?>[] getParameterTypes() {
   22.50 -        throw new UnsupportedOperationException();
   22.51 -        //return (Class<?>[]) parameterTypes.clone();
   22.52 +        Class[] arr = new Class[MethodImpl.signatureElements(sig) - 1];
   22.53 +        Enumeration<Class> en = MethodImpl.signatureParser(sig);
   22.54 +        en.nextElement(); // return type
   22.55 +        for (int i = 0; i < arr.length; i++) {
   22.56 +            arr[i] = en.nextElement();
   22.57 +        }
   22.58 +        return arr;
   22.59      }
   22.60  
   22.61      /**
   22.62 @@ -311,14 +320,14 @@
   22.63              sb.append(Field.getTypeName(getReturnType())).append(' ');
   22.64              sb.append(Field.getTypeName(getDeclaringClass())).append('.');
   22.65              sb.append(getName()).append('(');
   22.66 -            /*
   22.67 -            Class<?>[] params = parameterTypes; // avoid clone
   22.68 +            Class<?>[] params = getParameterTypes(); // avoid clone
   22.69              for (int j = 0; j < params.length; j++) {
   22.70                  sb.append(Field.getTypeName(params[j]));
   22.71                  if (j < (params.length - 1))
   22.72                      sb.append(',');
   22.73              }
   22.74              sb.append(')');
   22.75 +            /*
   22.76              Class<?>[] exceptions = exceptionTypes; // avoid clone
   22.77              if (exceptions.length > 0) {
   22.78                  sb.append(" throws ");
   22.79 @@ -488,17 +497,118 @@
   22.80       * @exception ExceptionInInitializerError if the initialization
   22.81       * provoked by this method fails.
   22.82       */
   22.83 -    @JavaScriptBody(args = { "method", "self", "args" }, body =
   22.84 -          "if (args.length > 0) throw 'unsupported now';"
   22.85 -        + "return method.fld_data(self);"
   22.86 -    )
   22.87      public Object invoke(Object obj, Object... args)
   22.88          throws IllegalAccessException, IllegalArgumentException,
   22.89             InvocationTargetException
   22.90      {
   22.91 -        throw new UnsupportedOperationException();
   22.92 +        final boolean isStatic = (getModifiers() & Modifier.STATIC) == 0;
   22.93 +        if (isStatic && obj == null) {
   22.94 +            throw new NullPointerException();
   22.95 +        }
   22.96 +        Class[] types = getParameterTypes();
   22.97 +        if (types.length != args.length) {
   22.98 +            throw new IllegalArgumentException("Types len " + types.length + " args: " + args.length);
   22.99 +        } else {
  22.100 +            args = args.clone();
  22.101 +            for (int i = 0; i < types.length; i++) {
  22.102 +                Class c = types[i];
  22.103 +                if (c.isPrimitive()) {
  22.104 +                    args[i] = toPrimitive(c, args[i]);
  22.105 +                }
  22.106 +            }
  22.107 +        }
  22.108 +        Object res = invoke0(isStatic, this, obj, args);
  22.109 +        if (getReturnType().isPrimitive()) {
  22.110 +            res = fromPrimitive(getReturnType(), res);
  22.111 +        }
  22.112 +        return res;
  22.113      }
  22.114 +    
  22.115 +    @JavaScriptBody(args = { "st", "method", "self", "args" }, body =
  22.116 +          "var p;\n"
  22.117 +        + "if (st) {\n"
  22.118 +        + "  p = new Array(1);\n"
  22.119 +        + "  p[0] = self;\n"
  22.120 +        + "  p = p.concat(args);\n"
  22.121 +        + "} else {\n"
  22.122 +        + "  p = args;\n"
  22.123 +        + "}\n"
  22.124 +        + "return method.fld_data.apply(self, p);\n"
  22.125 +    )
  22.126 +    private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
  22.127  
  22.128 +    private static Object fromPrimitive(Class<?> type, Object o) {
  22.129 +        if (type == Integer.TYPE) {
  22.130 +            return fromRaw(Integer.class, "valueOf__Ljava_lang_Integer_2I", o);
  22.131 +        }
  22.132 +        if (type == Long.TYPE) {
  22.133 +            return fromRaw(Long.class, "valueOf__Ljava_lang_Long_2J", o);
  22.134 +        }
  22.135 +        if (type == Double.TYPE) {
  22.136 +            return fromRaw(Double.class, "valueOf__Ljava_lang_Double_2D", o);
  22.137 +        }
  22.138 +        if (type == Float.TYPE) {
  22.139 +            return fromRaw(Float.class, "valueOf__Ljava_lang_Float_2F", o);
  22.140 +        }
  22.141 +        if (type == Byte.TYPE) {
  22.142 +            return fromRaw(Byte.class, "valueOf__Ljava_lang_Byte_2B", o);
  22.143 +        }
  22.144 +        if (type == Boolean.TYPE) {
  22.145 +            return fromRaw(Boolean.class, "valueOf__Ljava_lang_Boolean_2Z", o);
  22.146 +        }
  22.147 +        if (type == Short.TYPE) {
  22.148 +            return fromRaw(Short.class, "valueOf__Ljava_lang_Short_2S", o);
  22.149 +        }
  22.150 +        if (type == Character.TYPE) {
  22.151 +            return fromRaw(Character.class, "valueOf__Ljava_lang_Character_2C", o);
  22.152 +        }
  22.153 +        if (type.getName().equals("void")) {
  22.154 +            return null;
  22.155 +        }
  22.156 +        throw new IllegalStateException("Can't convert " + o);
  22.157 +    }
  22.158 +    
  22.159 +    @JavaScriptBody(args = { "cls", "m", "o" }, 
  22.160 +        body = "return cls.cnstr(false)[m](o);"
  22.161 +    )
  22.162 +    private static native Integer fromRaw(Class<?> cls, String m, Object o);
  22.163 +
  22.164 +    private static Object toPrimitive(Class<?> type, Object o) {
  22.165 +        if (type == Integer.TYPE) {
  22.166 +            return toRaw("intValue__I", o);
  22.167 +        }
  22.168 +        if (type == Long.TYPE) {
  22.169 +            return toRaw("longValue__J", o);
  22.170 +        }
  22.171 +        if (type == Double.TYPE) {
  22.172 +            return toRaw("doubleValue__D", o);
  22.173 +        }
  22.174 +        if (type == Float.TYPE) {
  22.175 +            return toRaw("floatValue__F", o);
  22.176 +        }
  22.177 +        if (type == Byte.TYPE) {
  22.178 +            return toRaw("byteValue__B", o);
  22.179 +        }
  22.180 +        if (type == Boolean.TYPE) {
  22.181 +            return toRaw("booleanValue__Z", o);
  22.182 +        }
  22.183 +        if (type == Short.TYPE) {
  22.184 +            return toRaw("shortValue__S", o);
  22.185 +        }
  22.186 +        if (type == Character.TYPE) {
  22.187 +            return toRaw("charValue__C", o);
  22.188 +        }
  22.189 +        if (type.getName().equals("void")) {
  22.190 +            return o;
  22.191 +        }
  22.192 +        throw new IllegalStateException("Can't convert " + o);
  22.193 +    }
  22.194 +    
  22.195 +    @JavaScriptBody(args = { "m", "o" }, 
  22.196 +        body = "return o[m](o);"
  22.197 +    )
  22.198 +    private static native Object toRaw(String m, Object o);
  22.199 +    
  22.200      /**
  22.201       * Returns {@code true} if this method is a bridge
  22.202       * method; returns {@code false} otherwise.
  22.203 @@ -536,10 +646,10 @@
  22.204          return Modifier.isSynthetic(getModifiers());
  22.205      }
  22.206  
  22.207 -    @JavaScriptBody(args = { "self", "ac" }, 
  22.208 +    @JavaScriptBody(args = { "ac" }, 
  22.209          body = 
  22.210 -          "if (self.fld_data.anno) {"
  22.211 -        + "  return self.fld_data.anno['L' + ac.jvmName + ';'];"
  22.212 +          "if (this.fld_data.anno) {"
  22.213 +        + "  return this.fld_data.anno['L' + ac.jvmName + ';'];"
  22.214          + "} else return null;"
  22.215      )
  22.216      private Object getAnnotationData(Class<?> annotationClass) {
  22.217 @@ -599,57 +709,12 @@
  22.218      public Annotation[][] getParameterAnnotations() {
  22.219          throw new UnsupportedOperationException();
  22.220      }
  22.221 -    
  22.222 -    //
  22.223 -    // bck2brwsr implementation
  22.224 -    //
  22.225  
  22.226 -    @JavaScriptBody(args = { "clazz", "prefix" },
  22.227 -        body = ""
  22.228 -        + "var c = clazz.cnstr.prototype;"
  22.229 -        + "var arr = new Array();\n"
  22.230 -        + "for (m in c) {\n"
  22.231 -        + "  if (m.indexOf(prefix) === 0) {\n"
  22.232 -        + "     arr.push(m);\n"
  22.233 -        + "     arr.push(c[m]);\n"
  22.234 -        + "  }"
  22.235 -        + "}\n"
  22.236 -        + "return arr;"
  22.237 -    )
  22.238 -    private static native Object[] findMethodData(
  22.239 -        Class<?> clazz, String prefix
  22.240 -    );
  22.241 -
  22.242 -    // XXX should not be public
  22.243 -    public static Method findMethod(
  22.244 -        Class<?> clazz, String name, Class<?>... parameterTypes
  22.245 -    ) {
  22.246 -        Object[] data = findMethodData(clazz, name + "__");
  22.247 -        if (data.length == 0) {
  22.248 -            return null;
  22.249 -        }
  22.250 -        String sig = ((String)data[0]).substring(name.length() + 2);
  22.251 -        return new Method(clazz, name, data[1], sig);
  22.252 -    }
  22.253 -    
  22.254 -    public static Method[] findMethods(Class<?> clazz) {
  22.255 -        Object[] namesAndData = findMethodData(clazz, "");
  22.256 -        int cnt = 0;
  22.257 -        for (int i = 0; i < namesAndData.length; i += 2) {
  22.258 -            String sig = (String) namesAndData[i];
  22.259 -            Object data = namesAndData[i + 1];
  22.260 -            int middle = sig.indexOf("__");
  22.261 -            if (middle == -1) {
  22.262 -                continue;
  22.263 +    static {
  22.264 +        MethodImpl.INSTANCE = new MethodImpl() {
  22.265 +            protected Method create(Class<?> declaringClass, String name, Object data, String sig) {
  22.266 +                return new Method(declaringClass, name, data, sig);
  22.267              }
  22.268 -            String name = sig.substring(0, middle);
  22.269 -            sig = sig.substring(middle + 2);
  22.270 -            namesAndData[cnt++] = new Method(clazz, name, data, sig);
  22.271 -        }
  22.272 -        Method[] arr = new Method[cnt];
  22.273 -        for (int i = 0; i < cnt; i++) {
  22.274 -            arr[i] = (Method)namesAndData[i];
  22.275 -        }
  22.276 -        return arr;
  22.277 +        };
  22.278      }
  22.279  }
    23.1 --- a/emul/src/main/java/java/net/URL.java	Fri Jan 18 14:23:18 2013 +0100
    23.2 +++ b/emul/src/main/java/java/net/URL.java	Fri Jan 18 14:27:22 2013 +0100
    23.3 @@ -27,6 +27,7 @@
    23.4  
    23.5  import java.io.IOException;
    23.6  import java.io.InputStream;
    23.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    23.8  
    23.9  /**
   23.10   * Class <code>URL</code> represents a Uniform Resource
   23.11 @@ -196,6 +197,17 @@
   23.12       */
   23.13      private String ref;
   23.14  
   23.15 +    /**
   23.16 +     * The host's IP address, used in equals and hashCode.
   23.17 +     * Computed on demand. An uninitialized or unknown hostAddress is null.
   23.18 +     */
   23.19 +    transient Object hostAddress;
   23.20 +
   23.21 +    /**
   23.22 +     * The URLStreamHandler for this URL.
   23.23 +     */
   23.24 +    transient URLStreamHandler handler;
   23.25 +
   23.26      /* Our hash code.
   23.27       * @serial
   23.28       */
   23.29 @@ -308,8 +320,47 @@
   23.30          this(protocol, host, -1, file);
   23.31      }
   23.32  
   23.33 -    private URL(String protocol, String host, int port, String file,
   23.34 -               Object handler) throws MalformedURLException {
   23.35 +    /**
   23.36 +     * Creates a <code>URL</code> object from the specified
   23.37 +     * <code>protocol</code>, <code>host</code>, <code>port</code>
   23.38 +     * number, <code>file</code>, and <code>handler</code>. Specifying
   23.39 +     * a <code>port</code> number of <code>-1</code> indicates that
   23.40 +     * the URL should use the default port for the protocol. Specifying
   23.41 +     * a <code>handler</code> of <code>null</code> indicates that the URL
   23.42 +     * should use a default stream handler for the protocol, as outlined
   23.43 +     * for:
   23.44 +     *     java.net.URL#URL(java.lang.String, java.lang.String, int,
   23.45 +     *                      java.lang.String)
   23.46 +     *
   23.47 +     * <p>If the handler is not null and there is a security manager,
   23.48 +     * the security manager's <code>checkPermission</code>
   23.49 +     * method is called with a
   23.50 +     * <code>NetPermission("specifyStreamHandler")</code> permission.
   23.51 +     * This may result in a SecurityException.
   23.52 +     *
   23.53 +     * No validation of the inputs is performed by this constructor.
   23.54 +     *
   23.55 +     * @param      protocol   the name of the protocol to use.
   23.56 +     * @param      host       the name of the host.
   23.57 +     * @param      port       the port number on the host.
   23.58 +     * @param      file       the file on the host
   23.59 +     * @param      handler    the stream handler for the URL.
   23.60 +     * @exception  MalformedURLException  if an unknown protocol is specified.
   23.61 +     * @exception  SecurityException
   23.62 +     *        if a security manager exists and its
   23.63 +     *        <code>checkPermission</code> method doesn't allow
   23.64 +     *        specifying a stream handler explicitly.
   23.65 +     * @see        java.lang.System#getProperty(java.lang.String)
   23.66 +     * @see        java.net.URL#setURLStreamHandlerFactory(
   23.67 +     *                  java.net.URLStreamHandlerFactory)
   23.68 +     * @see        java.net.URLStreamHandler
   23.69 +     * @see        java.net.URLStreamHandlerFactory#createURLStreamHandler(
   23.70 +     *                  java.lang.String)
   23.71 +     * @see        SecurityManager#checkPermission
   23.72 +     * @see        java.net.NetPermission
   23.73 +     */
   23.74 +    public URL(String protocol, String host, int port, String file,
   23.75 +               URLStreamHandler handler) throws MalformedURLException {
   23.76          if (handler != null) {
   23.77              throw new SecurityException();
   23.78          }
   23.79 @@ -348,10 +399,11 @@
   23.80  
   23.81          // Note: we don't do validation of the URL here. Too risky to change
   23.82          // right now, but worth considering for future reference. -br
   23.83 -//        if (handler == null &&
   23.84 -//            (handler = getURLStreamHandler(protocol)) == null) {
   23.85 -//            throw new MalformedURLException("unknown protocol: " + protocol);
   23.86 -//        }
   23.87 +        if (handler == null &&
   23.88 +            (handler = getURLStreamHandler(protocol)) == null) {
   23.89 +            throw new MalformedURLException("unknown protocol: " + protocol);
   23.90 +        }
   23.91 +        this.handler = handler;
   23.92      }
   23.93  
   23.94      /**
   23.95 @@ -441,7 +493,7 @@
   23.96       * @see        java.net.URLStreamHandler#parseURL(java.net.URL,
   23.97       *                  java.lang.String, int, int)
   23.98       */
   23.99 -    private URL(URL context, String spec, Object handler)
  23.100 +    public URL(URL context, String spec, URLStreamHandler handler)
  23.101          throws MalformedURLException
  23.102      {
  23.103          String original = spec;
  23.104 @@ -494,9 +546,9 @@
  23.105                              newProtocol.equalsIgnoreCase(context.protocol))) {
  23.106                  // inherit the protocol handler from the context
  23.107                  // if not specified to the constructor
  23.108 -//                if (handler == null) {
  23.109 -//                    handler = context.handler;
  23.110 -//                }
  23.111 +                if (handler == null) {
  23.112 +                    handler = context.handler;
  23.113 +                }
  23.114  
  23.115                  // If the context is a hierarchical URL scheme and the spec
  23.116                  // contains a matching scheme then maintain backwards
  23.117 @@ -523,15 +575,15 @@
  23.118  
  23.119              // Get the protocol handler if not specified or the protocol
  23.120              // of the context could not be used
  23.121 -//            if (handler == null &&
  23.122 -//                (handler = getURLStreamHandler(protocol)) == null) {
  23.123 -//                throw new MalformedURLException("unknown protocol: "+protocol);
  23.124 -//            }
  23.125 -
  23.126 -//            this.handler = handler;
  23.127 +            if (handler == null &&
  23.128 +                (handler = getURLStreamHandler(protocol)) == null) {
  23.129 +                throw new MalformedURLException("unknown protocol: "+protocol);
  23.130 +            }
  23.131 +            this.handler = handler;
  23.132  
  23.133              i = spec.indexOf('#', start);
  23.134              if (i >= 0) {
  23.135 +//thrw(protocol + " hnd: " + handler.getClass().getName() + " i: " + i);
  23.136                  ref = spec.substring(i + 1, limit);
  23.137                  limit = i;
  23.138              }
  23.139 @@ -547,7 +599,7 @@
  23.140                  }
  23.141              }
  23.142  
  23.143 -//            handler.parseURL(this, spec, start, limit);
  23.144 +            handler.parseURL(this, spec, start, limit);
  23.145  
  23.146          } catch(MalformedURLException e) {
  23.147              throw e;
  23.148 @@ -557,7 +609,7 @@
  23.149              throw exception;
  23.150          }
  23.151      }
  23.152 -
  23.153 +    
  23.154      /*
  23.155       * Returns true if specified string is a valid protocol name.
  23.156       */
  23.157 @@ -601,6 +653,7 @@
  23.158              /* This is very important. We must recompute this after the
  23.159               * URL has been changed. */
  23.160              hashCode = -1;
  23.161 +            hostAddress = null;
  23.162              int q = file.lastIndexOf('?');
  23.163              if (q != -1) {
  23.164                  query = file.substring(q+1);
  23.165 @@ -639,6 +692,7 @@
  23.166              /* This is very important. We must recompute this after the
  23.167               * URL has been changed. */
  23.168              hashCode = -1;
  23.169 +            hostAddress = null;
  23.170              this.query = query;
  23.171              this.authority = authority;
  23.172          }
  23.173 @@ -697,6 +751,19 @@
  23.174      }
  23.175  
  23.176      /**
  23.177 +     * Gets the default port number of the protocol associated
  23.178 +     * with this <code>URL</code>. If the URL scheme or the URLStreamHandler
  23.179 +     * for the URL do not define a default port number,
  23.180 +     * then -1 is returned.
  23.181 +     *
  23.182 +     * @return  the port number
  23.183 +     * @since 1.4
  23.184 +     */
  23.185 +    public int getDefaultPort() {
  23.186 +        return handler.getDefaultPort();
  23.187 +    }
  23.188 +
  23.189 +    /**
  23.190       * Gets the protocol name of this <code>URL</code>.
  23.191       *
  23.192       * @return  the protocol of this <code>URL</code>.
  23.193 @@ -773,8 +840,7 @@
  23.194              return false;
  23.195          URL u2 = (URL)obj;
  23.196  
  23.197 -     //   return handler.equals(this, u2);
  23.198 -        return u2 == this;
  23.199 +        return handler.equals(this, u2);
  23.200      }
  23.201  
  23.202      /**
  23.203 @@ -789,7 +855,7 @@
  23.204          if (hashCode != -1)
  23.205              return hashCode;
  23.206  
  23.207 -     //   hashCode = handler.hashCode(this);
  23.208 +        hashCode = handler.hashCode(this);
  23.209          return hashCode;
  23.210      }
  23.211  
  23.212 @@ -805,8 +871,7 @@
  23.213       *          <code>false</code> otherwise.
  23.214       */
  23.215      public boolean sameFile(URL other) {
  23.216 -//        return handler.sameFile(this, other);
  23.217 -        throw new UnsupportedOperationException();
  23.218 +        return handler.sameFile(this, other);
  23.219      }
  23.220  
  23.221      /**
  23.222 @@ -834,8 +899,7 @@
  23.223       * @see     java.net.URLStreamHandler#toExternalForm(java.net.URL)
  23.224       */
  23.225      public String toExternalForm() {
  23.226 -        throw new UnsupportedOperationException();
  23.227 -//        return handler.toExternalForm(this);
  23.228 +        return handler.toExternalForm(this);
  23.229      }
  23.230  
  23.231      /**
  23.232 @@ -901,9 +965,16 @@
  23.233       * @see        java.net.URLConnection#getContent()
  23.234       */
  23.235      public final Object getContent() throws java.io.IOException {
  23.236 -        throw new IOException();
  23.237 -//        return openConnection().getContent();
  23.238 +        return loadText(toExternalForm());
  23.239      }
  23.240 +    
  23.241 +    @JavaScriptBody(args = "url", body = ""
  23.242 +        + "var request = new XMLHttpRequest();\n"
  23.243 +        + "request.open('GET', url, false);\n"
  23.244 +        + "request.send();\n"
  23.245 +        + "return request.responseText;\n"
  23.246 +    )
  23.247 +    private static native String loadText(String url) throws IOException;
  23.248  
  23.249      /**
  23.250       * Gets the contents of this URL. This method is a shorthand for:
  23.251 @@ -921,10 +992,18 @@
  23.252       */
  23.253      public final Object getContent(Class[] classes)
  23.254      throws java.io.IOException {
  23.255 -        throw new IOException();
  23.256 -//        return openConnection().getContent(classes);
  23.257 +        for (Class<?> c : classes) {
  23.258 +            if (c == String.class) {
  23.259 +                return getContent();
  23.260 +            }
  23.261 +        }
  23.262 +        return null;
  23.263      }
  23.264  
  23.265 +    static URLStreamHandler getURLStreamHandler(String protocol) {
  23.266 +        URLStreamHandler universal = new URLStreamHandler() {};
  23.267 +        return universal;
  23.268 +    }
  23.269  
  23.270  }
  23.271  
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/emul/src/main/java/java/net/URLStreamHandler.java	Fri Jan 18 14:27:22 2013 +0100
    24.3 @@ -0,0 +1,568 @@
    24.4 +/*
    24.5 + * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
    24.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    24.7 + *
    24.8 + * This code is free software; you can redistribute it and/or modify it
    24.9 + * under the terms of the GNU General Public License version 2 only, as
   24.10 + * published by the Free Software Foundation.  Oracle designates this
   24.11 + * particular file as subject to the "Classpath" exception as provided
   24.12 + * by Oracle in the LICENSE file that accompanied this code.
   24.13 + *
   24.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   24.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   24.17 + * version 2 for more details (a copy is included in the LICENSE file that
   24.18 + * accompanied this code).
   24.19 + *
   24.20 + * You should have received a copy of the GNU General Public License version
   24.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   24.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   24.23 + *
   24.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   24.25 + * or visit www.oracle.com if you need additional information or have any
   24.26 + * questions.
   24.27 + */
   24.28 +
   24.29 +package java.net;
   24.30 +
   24.31 +
   24.32 +/**
   24.33 + * The abstract class <code>URLStreamHandler</code> is the common
   24.34 + * superclass for all stream protocol handlers. A stream protocol
   24.35 + * handler knows how to make a connection for a particular protocol
   24.36 + * type, such as <code>http</code>, <code>ftp</code>, or
   24.37 + * <code>gopher</code>.
   24.38 + * <p>
   24.39 + * In most cases, an instance of a <code>URLStreamHandler</code>
   24.40 + * subclass is not created directly by an application. Rather, the
   24.41 + * first time a protocol name is encountered when constructing a
   24.42 + * <code>URL</code>, the appropriate stream protocol handler is
   24.43 + * automatically loaded.
   24.44 + *
   24.45 + * @author  James Gosling
   24.46 + * @see     java.net.URL#URL(java.lang.String, java.lang.String, int, java.lang.String)
   24.47 + * @since   JDK1.0
   24.48 + */
   24.49 +public abstract class URLStreamHandler {
   24.50 +    /**
   24.51 +     * Opens a connection to the object referenced by the
   24.52 +     * <code>URL</code> argument.
   24.53 +     * This method should be overridden by a subclass.
   24.54 +     *
   24.55 +     * <p>If for the handler's protocol (such as HTTP or JAR), there
   24.56 +     * exists a public, specialized URLConnection subclass belonging
   24.57 +     * to one of the following packages or one of their subpackages:
   24.58 +     * java.lang, java.io, java.util, java.net, the connection
   24.59 +     * returned will be of that subclass. For example, for HTTP an
   24.60 +     * HttpURLConnection will be returned, and for JAR a
   24.61 +     * JarURLConnection will be returned.
   24.62 +     *
   24.63 +     * @param      u   the URL that this connects to.
   24.64 +     * @return     a <code>URLConnection</code> object for the <code>URL</code>.
   24.65 +     * @exception  IOException  if an I/O error occurs while opening the
   24.66 +     *               connection.
   24.67 +     */
   24.68 +//    abstract protected URLConnection openConnection(URL u) throws IOException;
   24.69 +
   24.70 +    /**
   24.71 +     * Same as openConnection(URL), except that the connection will be
   24.72 +     * made through the specified proxy; Protocol handlers that do not
   24.73 +     * support proxying will ignore the proxy parameter and make a
   24.74 +     * normal connection.
   24.75 +     *
   24.76 +     * Calling this method preempts the system's default ProxySelector
   24.77 +     * settings.
   24.78 +     *
   24.79 +     * @param      u   the URL that this connects to.
   24.80 +     * @param      p   the proxy through which the connection will be made.
   24.81 +     *                 If direct connection is desired, Proxy.NO_PROXY
   24.82 +     *                 should be specified.
   24.83 +     * @return     a <code>URLConnection</code> object for the <code>URL</code>.
   24.84 +     * @exception  IOException  if an I/O error occurs while opening the
   24.85 +     *               connection.
   24.86 +     * @exception  IllegalArgumentException if either u or p is null,
   24.87 +     *               or p has the wrong type.
   24.88 +     * @exception  UnsupportedOperationException if the subclass that
   24.89 +     *               implements the protocol doesn't support this method.
   24.90 +     * @since      1.5
   24.91 +     */
   24.92 +//    protected URLConnection openConnection(URL u, Proxy p) throws IOException {
   24.93 +//        throw new UnsupportedOperationException("Method not implemented.");
   24.94 +//    }
   24.95 +
   24.96 +    /**
   24.97 +     * Parses the string representation of a <code>URL</code> into a
   24.98 +     * <code>URL</code> object.
   24.99 +     * <p>
  24.100 +     * If there is any inherited context, then it has already been
  24.101 +     * copied into the <code>URL</code> argument.
  24.102 +     * <p>
  24.103 +     * The <code>parseURL</code> method of <code>URLStreamHandler</code>
  24.104 +     * parses the string representation as if it were an
  24.105 +     * <code>http</code> specification. Most URL protocol families have a
  24.106 +     * similar parsing. A stream protocol handler for a protocol that has
  24.107 +     * a different syntax must override this routine.
  24.108 +     *
  24.109 +     * @param   u       the <code>URL</code> to receive the result of parsing
  24.110 +     *                  the spec.
  24.111 +     * @param   spec    the <code>String</code> representing the URL that
  24.112 +     *                  must be parsed.
  24.113 +     * @param   start   the character index at which to begin parsing. This is
  24.114 +     *                  just past the '<code>:</code>' (if there is one) that
  24.115 +     *                  specifies the determination of the protocol name.
  24.116 +     * @param   limit   the character position to stop parsing at. This is the
  24.117 +     *                  end of the string or the position of the
  24.118 +     *                  "<code>#</code>" character, if present. All information
  24.119 +     *                  after the sharp sign indicates an anchor.
  24.120 +     */
  24.121 +    protected void parseURL(URL u, String spec, int start, int limit) {
  24.122 +        // These fields may receive context content if this was relative URL
  24.123 +        String protocol = u.getProtocol();
  24.124 +        String authority = u.getAuthority();
  24.125 +        String userInfo = u.getUserInfo();
  24.126 +        String host = u.getHost();
  24.127 +        int port = u.getPort();
  24.128 +        String path = u.getPath();
  24.129 +        String query = u.getQuery();
  24.130 +
  24.131 +        // This field has already been parsed
  24.132 +        String ref = u.getRef();
  24.133 +
  24.134 +        boolean isRelPath = false;
  24.135 +        boolean queryOnly = false;
  24.136 +
  24.137 +// FIX: should not assume query if opaque
  24.138 +        // Strip off the query part
  24.139 +        if (start < limit) {
  24.140 +            int queryStart = spec.indexOf('?');
  24.141 +            queryOnly = queryStart == start;
  24.142 +            if ((queryStart != -1) && (queryStart < limit)) {
  24.143 +                query = spec.substring(queryStart+1, limit);
  24.144 +                if (limit > queryStart)
  24.145 +                    limit = queryStart;
  24.146 +                spec = spec.substring(0, queryStart);
  24.147 +            }
  24.148 +        }
  24.149 +
  24.150 +        int i = 0;
  24.151 +        // Parse the authority part if any
  24.152 +        boolean isUNCName = (start <= limit - 4) &&
  24.153 +                        (spec.charAt(start) == '/') &&
  24.154 +                        (spec.charAt(start + 1) == '/') &&
  24.155 +                        (spec.charAt(start + 2) == '/') &&
  24.156 +                        (spec.charAt(start + 3) == '/');
  24.157 +        if (!isUNCName && (start <= limit - 2) && (spec.charAt(start) == '/') &&
  24.158 +            (spec.charAt(start + 1) == '/')) {
  24.159 +            start += 2;
  24.160 +            i = spec.indexOf('/', start);
  24.161 +            if (i < 0) {
  24.162 +                i = spec.indexOf('?', start);
  24.163 +                if (i < 0)
  24.164 +                    i = limit;
  24.165 +            }
  24.166 +
  24.167 +            host = authority = spec.substring(start, i);
  24.168 +
  24.169 +            int ind = authority.indexOf('@');
  24.170 +            if (ind != -1) {
  24.171 +                userInfo = authority.substring(0, ind);
  24.172 +                host = authority.substring(ind+1);
  24.173 +            } else {
  24.174 +                userInfo = null;
  24.175 +            }
  24.176 +            if (host != null) {
  24.177 +                // If the host is surrounded by [ and ] then its an IPv6
  24.178 +                // literal address as specified in RFC2732
  24.179 +                if (host.length()>0 && (host.charAt(0) == '[')) {
  24.180 +                    if ((ind = host.indexOf(']')) > 2) {
  24.181 +
  24.182 +                        String nhost = host ;
  24.183 +                        host = nhost.substring(0,ind+1);
  24.184 +//                        if (!IPAddressUtil.
  24.185 +//                            isIPv6LiteralAddress(host.substring(1, ind))) {
  24.186 +//                            throw new IllegalArgumentException(
  24.187 +//                                "Invalid host: "+ host);
  24.188 +//                        }
  24.189 +
  24.190 +                        port = -1 ;
  24.191 +                        if (nhost.length() > ind+1) {
  24.192 +                            if (nhost.charAt(ind+1) == ':') {
  24.193 +                                ++ind ;
  24.194 +                                // port can be null according to RFC2396
  24.195 +                                if (nhost.length() > (ind + 1)) {
  24.196 +                                    port = Integer.parseInt(nhost.substring(ind+1));
  24.197 +                                }
  24.198 +                            } else {
  24.199 +                                throw new IllegalArgumentException(
  24.200 +                                    "Invalid authority field: " + authority);
  24.201 +                            }
  24.202 +                        }
  24.203 +                    } else {
  24.204 +                        throw new IllegalArgumentException(
  24.205 +                            "Invalid authority field: " + authority);
  24.206 +                    }
  24.207 +                } else {
  24.208 +                    ind = host.indexOf(':');
  24.209 +                    port = -1;
  24.210 +                    if (ind >= 0) {
  24.211 +                        // port can be null according to RFC2396
  24.212 +                        if (host.length() > (ind + 1)) {
  24.213 +                            port = Integer.parseInt(host.substring(ind + 1));
  24.214 +                        }
  24.215 +                        host = host.substring(0, ind);
  24.216 +                    }
  24.217 +                }
  24.218 +            } else {
  24.219 +                host = "";
  24.220 +            }
  24.221 +            if (port < -1)
  24.222 +                throw new IllegalArgumentException("Invalid port number :" +
  24.223 +                                                   port);
  24.224 +            start = i;
  24.225 +            // If the authority is defined then the path is defined by the
  24.226 +            // spec only; See RFC 2396 Section 5.2.4.
  24.227 +            if (authority != null && authority.length() > 0)
  24.228 +                path = "";
  24.229 +        }
  24.230 +
  24.231 +        if (host == null) {
  24.232 +            host = "";
  24.233 +        }
  24.234 +
  24.235 +        // Parse the file path if any
  24.236 +        if (start < limit) {
  24.237 +            if (spec.charAt(start) == '/') {
  24.238 +                path = spec.substring(start, limit);
  24.239 +            } else if (path != null && path.length() > 0) {
  24.240 +                isRelPath = true;
  24.241 +                int ind = path.lastIndexOf('/');
  24.242 +                String seperator = "";
  24.243 +                if (ind == -1 && authority != null)
  24.244 +                    seperator = "/";
  24.245 +                path = path.substring(0, ind + 1) + seperator +
  24.246 +                         spec.substring(start, limit);
  24.247 +
  24.248 +            } else {
  24.249 +                String seperator = (authority != null) ? "/" : "";
  24.250 +                path = seperator + spec.substring(start, limit);
  24.251 +            }
  24.252 +        } else if (queryOnly && path != null) {
  24.253 +            int ind = path.lastIndexOf('/');
  24.254 +            if (ind < 0)
  24.255 +                ind = 0;
  24.256 +            path = path.substring(0, ind) + "/";
  24.257 +        }
  24.258 +        if (path == null)
  24.259 +            path = "";
  24.260 +
  24.261 +        if (isRelPath) {
  24.262 +            // Remove embedded /./
  24.263 +            while ((i = path.indexOf("/./")) >= 0) {
  24.264 +                path = path.substring(0, i) + path.substring(i + 2);
  24.265 +            }
  24.266 +            // Remove embedded /../ if possible
  24.267 +            i = 0;
  24.268 +            while ((i = path.indexOf("/../", i)) >= 0) {
  24.269 +                /*
  24.270 +                 * A "/../" will cancel the previous segment and itself,
  24.271 +                 * unless that segment is a "/../" itself
  24.272 +                 * i.e. "/a/b/../c" becomes "/a/c"
  24.273 +                 * but "/../../a" should stay unchanged
  24.274 +                 */
  24.275 +                if (i > 0 && (limit = path.lastIndexOf('/', i - 1)) >= 0 &&
  24.276 +                    (path.indexOf("/../", limit) != 0)) {
  24.277 +                    path = path.substring(0, limit) + path.substring(i + 3);
  24.278 +                    i = 0;
  24.279 +                } else {
  24.280 +                    i = i + 3;
  24.281 +                }
  24.282 +            }
  24.283 +            // Remove trailing .. if possible
  24.284 +            while (path.endsWith("/..")) {
  24.285 +                i = path.indexOf("/..");
  24.286 +                if ((limit = path.lastIndexOf('/', i - 1)) >= 0) {
  24.287 +                    path = path.substring(0, limit+1);
  24.288 +                } else {
  24.289 +                    break;
  24.290 +                }
  24.291 +            }
  24.292 +            // Remove starting .
  24.293 +            if (path.startsWith("./") && path.length() > 2)
  24.294 +                path = path.substring(2);
  24.295 +
  24.296 +            // Remove trailing .
  24.297 +            if (path.endsWith("/."))
  24.298 +                path = path.substring(0, path.length() -1);
  24.299 +        }
  24.300 +
  24.301 +        setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
  24.302 +    }
  24.303 +
  24.304 +    /**
  24.305 +     * Returns the default port for a URL parsed by this handler. This method
  24.306 +     * is meant to be overidden by handlers with default port numbers.
  24.307 +     * @return the default port for a <code>URL</code> parsed by this handler.
  24.308 +     * @since 1.3
  24.309 +     */
  24.310 +    protected int getDefaultPort() {
  24.311 +        return -1;
  24.312 +    }
  24.313 +
  24.314 +    /**
  24.315 +     * Provides the default equals calculation. May be overidden by handlers
  24.316 +     * for other protocols that have different requirements for equals().
  24.317 +     * This method requires that none of its arguments is null. This is
  24.318 +     * guaranteed by the fact that it is only called by java.net.URL class.
  24.319 +     * @param u1 a URL object
  24.320 +     * @param u2 a URL object
  24.321 +     * @return <tt>true</tt> if the two urls are
  24.322 +     * considered equal, ie. they refer to the same
  24.323 +     * fragment in the same file.
  24.324 +     * @since 1.3
  24.325 +     */
  24.326 +    protected boolean equals(URL u1, URL u2) {
  24.327 +        String ref1 = u1.getRef();
  24.328 +        String ref2 = u2.getRef();
  24.329 +        return (ref1 == ref2 || (ref1 != null && ref1.equals(ref2))) &&
  24.330 +               sameFile(u1, u2);
  24.331 +    }
  24.332 +
  24.333 +    /**
  24.334 +     * Provides the default hash calculation. May be overidden by handlers for
  24.335 +     * other protocols that have different requirements for hashCode
  24.336 +     * calculation.
  24.337 +     * @param u a URL object
  24.338 +     * @return an <tt>int</tt> suitable for hash table indexing
  24.339 +     * @since 1.3
  24.340 +     */
  24.341 +    protected int hashCode(URL u) {
  24.342 +        int h = 0;
  24.343 +
  24.344 +        // Generate the protocol part.
  24.345 +        String protocol = u.getProtocol();
  24.346 +        if (protocol != null)
  24.347 +            h += protocol.hashCode();
  24.348 +
  24.349 +        // Generate the host part.
  24.350 +        Object addr = getHostAddress(u);
  24.351 +        if (addr != null) {
  24.352 +            h += addr.hashCode();
  24.353 +        } else {
  24.354 +            String host = u.getHost();
  24.355 +            if (host != null)
  24.356 +                h += host.toLowerCase().hashCode();
  24.357 +        }
  24.358 +
  24.359 +        // Generate the file part.
  24.360 +        String file = u.getFile();
  24.361 +        if (file != null)
  24.362 +            h += file.hashCode();
  24.363 +
  24.364 +        // Generate the port part.
  24.365 +        if (u.getPort() == -1)
  24.366 +            h += getDefaultPort();
  24.367 +        else
  24.368 +            h += u.getPort();
  24.369 +
  24.370 +        // Generate the ref part.
  24.371 +        String ref = u.getRef();
  24.372 +        if (ref != null)
  24.373 +            h += ref.hashCode();
  24.374 +
  24.375 +        return h;
  24.376 +    }
  24.377 +
  24.378 +    /**
  24.379 +     * Compare two urls to see whether they refer to the same file,
  24.380 +     * i.e., having the same protocol, host, port, and path.
  24.381 +     * This method requires that none of its arguments is null. This is
  24.382 +     * guaranteed by the fact that it is only called indirectly
  24.383 +     * by java.net.URL class.
  24.384 +     * @param u1 a URL object
  24.385 +     * @param u2 a URL object
  24.386 +     * @return true if u1 and u2 refer to the same file
  24.387 +     * @since 1.3
  24.388 +     */
  24.389 +    protected boolean sameFile(URL u1, URL u2) {
  24.390 +        // Compare the protocols.
  24.391 +        if (!((u1.getProtocol() == u2.getProtocol()) ||
  24.392 +              (u1.getProtocol() != null &&
  24.393 +               u1.getProtocol().equalsIgnoreCase(u2.getProtocol()))))
  24.394 +            return false;
  24.395 +
  24.396 +        // Compare the files.
  24.397 +        if (!(u1.getFile() == u2.getFile() ||
  24.398 +              (u1.getFile() != null && u1.getFile().equals(u2.getFile()))))
  24.399 +            return false;
  24.400 +
  24.401 +        // Compare the ports.
  24.402 +        int port1, port2;
  24.403 +        port1 = (u1.getPort() != -1) ? u1.getPort() : u1.handler.getDefaultPort();
  24.404 +        port2 = (u2.getPort() != -1) ? u2.getPort() : u2.handler.getDefaultPort();
  24.405 +        if (port1 != port2)
  24.406 +            return false;
  24.407 +
  24.408 +        // Compare the hosts.
  24.409 +        if (!hostsEqual(u1, u2))
  24.410 +            return false;
  24.411 +
  24.412 +        return true;
  24.413 +    }
  24.414 +
  24.415 +    /**
  24.416 +     * Get the IP address of our host. An empty host field or a DNS failure
  24.417 +     * will result in a null return.
  24.418 +     *
  24.419 +     * @param u a URL object
  24.420 +     * @return an <code>InetAddress</code> representing the host
  24.421 +     * IP address.
  24.422 +     * @since 1.3
  24.423 +     */
  24.424 +    private synchronized Object getHostAddress(URL u) {
  24.425 +        return u.hostAddress;
  24.426 +    }
  24.427 +
  24.428 +    /**
  24.429 +     * Compares the host components of two URLs.
  24.430 +     * @param u1 the URL of the first host to compare
  24.431 +     * @param u2 the URL of the second host to compare
  24.432 +     * @return  <tt>true</tt> if and only if they
  24.433 +     * are equal, <tt>false</tt> otherwise.
  24.434 +     * @since 1.3
  24.435 +     */
  24.436 +    protected boolean hostsEqual(URL u1, URL u2) {
  24.437 +        Object a1 = getHostAddress(u1);
  24.438 +        Object a2 = getHostAddress(u2);
  24.439 +        // if we have internet address for both, compare them
  24.440 +        if (a1 != null && a2 != null) {
  24.441 +            return a1.equals(a2);
  24.442 +        // else, if both have host names, compare them
  24.443 +        } else if (u1.getHost() != null && u2.getHost() != null)
  24.444 +            return u1.getHost().equalsIgnoreCase(u2.getHost());
  24.445 +         else
  24.446 +            return u1.getHost() == null && u2.getHost() == null;
  24.447 +    }
  24.448 +
  24.449 +    /**
  24.450 +     * Converts a <code>URL</code> of a specific protocol to a
  24.451 +     * <code>String</code>.
  24.452 +     *
  24.453 +     * @param   u   the URL.
  24.454 +     * @return  a string representation of the <code>URL</code> argument.
  24.455 +     */
  24.456 +    protected String toExternalForm(URL u) {
  24.457 +
  24.458 +        // pre-compute length of StringBuffer
  24.459 +        int len = u.getProtocol().length() + 1;
  24.460 +        if (u.getAuthority() != null && u.getAuthority().length() > 0)
  24.461 +            len += 2 + u.getAuthority().length();
  24.462 +        if (u.getPath() != null) {
  24.463 +            len += u.getPath().length();
  24.464 +        }
  24.465 +        if (u.getQuery() != null) {
  24.466 +            len += 1 + u.getQuery().length();
  24.467 +        }
  24.468 +        if (u.getRef() != null)
  24.469 +            len += 1 + u.getRef().length();
  24.470 +
  24.471 +        StringBuffer result = new StringBuffer(len);
  24.472 +        result.append(u.getProtocol());
  24.473 +        result.append(":");
  24.474 +        if (u.getAuthority() != null && u.getAuthority().length() > 0) {
  24.475 +            result.append("//");
  24.476 +            result.append(u.getAuthority());
  24.477 +        }
  24.478 +        if (u.getPath() != null) {
  24.479 +            result.append(u.getPath());
  24.480 +        }
  24.481 +        if (u.getQuery() != null) {
  24.482 +            result.append('?');
  24.483 +            result.append(u.getQuery());
  24.484 +        }
  24.485 +        if (u.getRef() != null) {
  24.486 +            result.append("#");
  24.487 +            result.append(u.getRef());
  24.488 +        }
  24.489 +        return result.toString();
  24.490 +    }
  24.491 +
  24.492 +    /**
  24.493 +     * Sets the fields of the <code>URL</code> argument to the indicated values.
  24.494 +     * Only classes derived from URLStreamHandler are supposed to be able
  24.495 +     * to call the set method on a URL.
  24.496 +     *
  24.497 +     * @param   u         the URL to modify.
  24.498 +     * @param   protocol  the protocol name.
  24.499 +     * @param   host      the remote host value for the URL.
  24.500 +     * @param   port      the port on the remote machine.
  24.501 +     * @param   authority the authority part for the URL.
  24.502 +     * @param   userInfo the userInfo part of the URL.
  24.503 +     * @param   path      the path component of the URL.
  24.504 +     * @param   query     the query part for the URL.
  24.505 +     * @param   ref       the reference.
  24.506 +     * @exception       SecurityException       if the protocol handler of the URL is
  24.507 +     *                                  different from this one
  24.508 +     * @see     java.net.URL#set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String)
  24.509 +     * @since 1.3
  24.510 +     */
  24.511 +       protected void setURL(URL u, String protocol, String host, int port,
  24.512 +                             String authority, String userInfo, String path,
  24.513 +                             String query, String ref) {
  24.514 +        if (this != u.handler) {
  24.515 +            throw new SecurityException("handler for url different from " +
  24.516 +                                        "this handler");
  24.517 +        }
  24.518 +        // ensure that no one can reset the protocol on a given URL.
  24.519 +        u.set(u.getProtocol(), host, port, authority, userInfo, path, query, ref);
  24.520 +    }
  24.521 +
  24.522 +    /**
  24.523 +     * Sets the fields of the <code>URL</code> argument to the indicated values.
  24.524 +     * Only classes derived from URLStreamHandler are supposed to be able
  24.525 +     * to call the set method on a URL.
  24.526 +     *
  24.527 +     * @param   u         the URL to modify.
  24.528 +     * @param   protocol  the protocol name. This value is ignored since 1.2.
  24.529 +     * @param   host      the remote host value for the URL.
  24.530 +     * @param   port      the port on the remote machine.
  24.531 +     * @param   file      the file.
  24.532 +     * @param   ref       the reference.
  24.533 +     * @exception       SecurityException       if the protocol handler of the URL is
  24.534 +     *                                  different from this one
  24.535 +     * @deprecated Use setURL(URL, String, String, int, String, String, String,
  24.536 +     *             String);
  24.537 +     */
  24.538 +    @Deprecated
  24.539 +    protected void setURL(URL u, String protocol, String host, int port,
  24.540 +                          String file, String ref) {
  24.541 +        /*
  24.542 +         * Only old URL handlers call this, so assume that the host
  24.543 +         * field might contain "user:passwd@host". Fix as necessary.
  24.544 +         */
  24.545 +        String authority = null;
  24.546 +        String userInfo = null;
  24.547 +        if (host != null && host.length() != 0) {
  24.548 +            authority = (port == -1) ? host : host + ":" + port;
  24.549 +            int at = host.lastIndexOf('@');
  24.550 +            if (at != -1) {
  24.551 +                userInfo = host.substring(0, at);
  24.552 +                host = host.substring(at+1);
  24.553 +            }
  24.554 +        }
  24.555 +
  24.556 +        /*
  24.557 +         * Assume file might contain query part. Fix as necessary.
  24.558 +         */
  24.559 +        String path = null;
  24.560 +        String query = null;
  24.561 +        if (file != null) {
  24.562 +            int q = file.lastIndexOf('?');
  24.563 +            if (q != -1) {
  24.564 +                query = file.substring(q+1);
  24.565 +                path = file.substring(0, q);
  24.566 +            } else
  24.567 +                path = file;
  24.568 +        }
  24.569 +        setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
  24.570 +    }
  24.571 +}
    25.1 --- a/emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java	Fri Jan 18 14:23:18 2013 +0100
    25.2 +++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java	Fri Jan 18 14:27:22 2013 +0100
    25.3 @@ -1,6 +1,19 @@
    25.4 -/*
    25.5 - * To change this template, choose Tools | Templates
    25.6 - * and open the template in the editor.
    25.7 +/**
    25.8 + * Back 2 Browser Bytecode Translator
    25.9 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   25.10 + *
   25.11 + * This program is free software: you can redistribute it and/or modify
   25.12 + * it under the terms of the GNU General Public License as published by
   25.13 + * the Free Software Foundation, version 2 of the License.
   25.14 + *
   25.15 + * This program is distributed in the hope that it will be useful,
   25.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   25.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   25.18 + * GNU General Public License for more details.
   25.19 + *
   25.20 + * You should have received a copy of the GNU General Public License
   25.21 + * along with this program. Look for COPYING file in the top folder.
   25.22 + * If not, see http://opensource.org/licenses/GPL-2.0.
   25.23   */
   25.24  package org.apidesign.bck2brwsr.emul;
   25.25  
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/MethodImpl.java	Fri Jan 18 14:27:22 2013 +0100
    26.3 @@ -0,0 +1,164 @@
    26.4 +/*
    26.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    26.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.7 + *
    26.8 + * This code is free software; you can redistribute it and/or modify it
    26.9 + * under the terms of the GNU General Public License version 2 only, as
   26.10 + * published by the Free Software Foundation.  Oracle designates this
   26.11 + * particular file as subject to the "Classpath" exception as provided
   26.12 + * by Oracle in the LICENSE file that accompanied this code.
   26.13 + *
   26.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   26.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   26.17 + * version 2 for more details (a copy is included in the LICENSE file that
   26.18 + * accompanied this code).
   26.19 + *
   26.20 + * You should have received a copy of the GNU General Public License version
   26.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   26.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   26.23 + *
   26.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   26.25 + * or visit www.oracle.com if you need additional information or have any
   26.26 + * questions.
   26.27 + */
   26.28 +package org.apidesign.bck2brwsr.emul;
   26.29 +
   26.30 +import java.lang.reflect.Method;
   26.31 +import java.util.Enumeration;
   26.32 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   26.33 +
   26.34 +/** Utilities to work on methods.
   26.35 + *
   26.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   26.37 + */
   26.38 +public abstract class MethodImpl {
   26.39 +    public static MethodImpl INSTANCE;
   26.40 +    static {
   26.41 +        try {
   26.42 +            Class.forName(Method.class.getName());
   26.43 +        } catch (ClassNotFoundException ex) {
   26.44 +            throw new IllegalStateException(ex);
   26.45 +        }
   26.46 +    }
   26.47 +    
   26.48 +    protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
   26.49 +    
   26.50 +    
   26.51 +    //
   26.52 +    // bck2brwsr implementation
   26.53 +    //
   26.54 +
   26.55 +    @JavaScriptBody(args = {"clazz", "prefix"},
   26.56 +        body = ""
   26.57 +        + "var c = clazz.cnstr.prototype;"
   26.58 +        + "var arr = new Array();\n"
   26.59 +        + "for (m in c) {\n"
   26.60 +        + "  if (m.indexOf(prefix) === 0) {\n"
   26.61 +        + "     arr.push(m);\n"
   26.62 +        + "     arr.push(c[m]);\n"
   26.63 +        + "  }"
   26.64 +        + "}\n"
   26.65 +        + "return arr;")
   26.66 +    private static native Object[] findMethodData(
   26.67 +        Class<?> clazz, String prefix);
   26.68 +
   26.69 +    public static Method findMethod(
   26.70 +        Class<?> clazz, String name, Class<?>... parameterTypes) {
   26.71 +        Object[] data = findMethodData(clazz, name + "__");
   26.72 +        BIG: for (int i = 0; i < data.length; i += 2) {
   26.73 +            String sig = ((String) data[0]).substring(name.length() + 2);
   26.74 +            Method tmp = INSTANCE.create(clazz, name, data[1], sig);
   26.75 +            Class<?>[] tmpParms = tmp.getParameterTypes();
   26.76 +            if (parameterTypes.length != tmpParms.length) {
   26.77 +                continue;
   26.78 +            }
   26.79 +            for (int j = 0; j < tmpParms.length; j++) {
   26.80 +                if (!parameterTypes[j].equals(tmpParms[j])) {
   26.81 +                    continue BIG;
   26.82 +                }
   26.83 +            }
   26.84 +            return tmp;
   26.85 +        }
   26.86 +        return null;
   26.87 +    }
   26.88 +
   26.89 +    public static Method[] findMethods(Class<?> clazz, int mask) {
   26.90 +        Object[] namesAndData = findMethodData(clazz, "");
   26.91 +        int cnt = 0;
   26.92 +        for (int i = 0; i < namesAndData.length; i += 2) {
   26.93 +            String sig = (String) namesAndData[i];
   26.94 +            Object data = namesAndData[i + 1];
   26.95 +            int middle = sig.indexOf("__");
   26.96 +            if (middle == -1) {
   26.97 +                continue;
   26.98 +            }
   26.99 +            String name = sig.substring(0, middle);
  26.100 +            sig = sig.substring(middle + 2);
  26.101 +            final Method m = INSTANCE.create(clazz, name, data, sig);
  26.102 +            if ((m.getModifiers() & mask) == 0) {
  26.103 +                continue;
  26.104 +            }
  26.105 +            namesAndData[cnt++] = m;
  26.106 +        }
  26.107 +        Method[] arr = new Method[cnt];
  26.108 +        for (int i = 0; i < cnt; i++) {
  26.109 +            arr[i] = (Method) namesAndData[i];
  26.110 +        }
  26.111 +        return arr;
  26.112 +    }
  26.113 +
  26.114 +    public static int signatureElements(String sig) {
  26.115 +        Enumeration<Class> en = signatureParser(sig);
  26.116 +        int cnt = 0;
  26.117 +        while (en.hasMoreElements()) {
  26.118 +            en.nextElement();
  26.119 +            cnt++;
  26.120 +        }
  26.121 +        return cnt;
  26.122 +    }
  26.123 +    
  26.124 +    public static Enumeration<Class> signatureParser(final String sig) {
  26.125 +        class E implements Enumeration<Class> {
  26.126 +            int pos;
  26.127 +            
  26.128 +            public boolean hasMoreElements() {
  26.129 +                return pos < sig.length();
  26.130 +            }
  26.131 +
  26.132 +            public Class nextElement() {
  26.133 +                switch (sig.charAt(pos++)) {
  26.134 +                    case 'I':
  26.135 +                        return Integer.TYPE;
  26.136 +                    case 'J':
  26.137 +                        return Long.TYPE;
  26.138 +                    case 'D':
  26.139 +                        return Double.TYPE;
  26.140 +                    case 'F':
  26.141 +                        return Float.TYPE;
  26.142 +                    case 'B':
  26.143 +                        return Byte.TYPE;
  26.144 +                    case 'Z':
  26.145 +                        return Boolean.TYPE;
  26.146 +                    case 'S':
  26.147 +                        return Short.TYPE;
  26.148 +                    case 'V':
  26.149 +                        return Void.TYPE;
  26.150 +                    case 'C':
  26.151 +                        return Character.TYPE;
  26.152 +                    case 'L':
  26.153 +                        try {
  26.154 +                            int up = sig.indexOf("_2");
  26.155 +                            String type = sig.substring(1, up);
  26.156 +                            pos = up + 2;
  26.157 +                            return Class.forName(type);
  26.158 +                        } catch (ClassNotFoundException ex) {
  26.159 +                            // should not happen
  26.160 +                        }
  26.161 +                }
  26.162 +                throw new UnsupportedOperationException(sig + " at " + pos);
  26.163 +            }
  26.164 +        }
  26.165 +        return new E();
  26.166 +    }
  26.167 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_Number.js	Fri Jan 18 14:27:22 2013 +0100
    27.3 @@ -0,0 +1,9 @@
    27.4 +// empty line needed here
    27.5 +Number.prototype.add32 = function(x) { return (this + x) | 0; };
    27.6 +Number.prototype.sub32 = function(x) { return (this - x) | 0; };
    27.7 +Number.prototype.mul32 = function(x) { 
    27.8 +    return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
    27.9 +};
   27.10 +
   27.11 +Number.prototype.toInt8 = function()  { return (this << 24) >> 24; };
   27.12 +Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
   27.13 \ No newline at end of file
    28.1 --- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js	Fri Jan 18 14:23:18 2013 +0100
    28.2 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js	Fri Jan 18 14:27:22 2013 +0100
    28.3 @@ -2,8 +2,30 @@
    28.4  vm.java_lang_String(false);
    28.5  
    28.6  // we need initialized arrays
    28.7 -Array.prototype.fillNulls = function() {
    28.8 -  for(var i = 0; i < this.length; i++) this[i] = null;
    28.9 +Array.prototype.initWith = function(sig, value) {
   28.10 +  for(var i = 0; i < this.length; i++) this[i] = value;
   28.11 +  this.jvmName = sig;
   28.12    return this;
   28.13  };
   28.14 -
   28.15 +Array.prototype.at = function(indx, value) {
   28.16 +  if (indx < 0 || indx > this.length) {
   28.17 +      var e = vm.java_lang_ArrayIndexOutOfBoundsException(true);
   28.18 +      e.constructor.cons__VLjava_lang_String_2.call(e, indx.toString());
   28.19 +      throw e;
   28.20 +  }
   28.21 +  if (arguments.length === 2) {
   28.22 +      this[indx] = value;
   28.23 +  }
   28.24 +  return this[indx];
   28.25 +};
   28.26 +Array.prototype.getClass__Ljava_lang_Class_2 = function() {
   28.27 +  return vm.java_lang_Class(false).defineArray__Ljava_lang_Class_2Ljava_lang_String_2(this.jvmName);
   28.28 +};
   28.29 +Array.prototype.clone__Ljava_lang_Object_2 = function() {
   28.30 +  var s = this.length;
   28.31 +  var ret = new Array(s);
   28.32 +  for (var i = 0; i < s; i++) {
   28.33 +      ret[i] = this[i];
   28.34 +  }
   28.35 +  return ret;
   28.36 +};
    29.1 --- a/javap/src/main/java/org/apidesign/javap/ClassData.java	Fri Jan 18 14:23:18 2013 +0100
    29.2 +++ b/javap/src/main/java/org/apidesign/javap/ClassData.java	Fri Jan 18 14:27:22 2013 +0100
    29.3 @@ -326,6 +326,10 @@
    29.4              return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
    29.5          }
    29.6      }
    29.7 +    
    29.8 +    public int getAccessFlags() {
    29.9 +        return access;
   29.10 +    }
   29.11  
   29.12      /**
   29.13       * Returns true if it is a class
    30.1 --- a/javap/src/main/java/org/apidesign/javap/Hashtable.java	Fri Jan 18 14:23:18 2013 +0100
    30.2 +++ b/javap/src/main/java/org/apidesign/javap/Hashtable.java	Fri Jan 18 14:27:22 2013 +0100
    30.3 @@ -1,11 +1,22 @@
    30.4 -/*
    30.5 - * To change this template, choose Tools | Templates
    30.6 - * and open the template in the editor.
    30.7 +/**
    30.8 + * Back 2 Browser Bytecode Translator
    30.9 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   30.10 + *
   30.11 + * This program is free software: you can redistribute it and/or modify
   30.12 + * it under the terms of the GNU General Public License as published by
   30.13 + * the Free Software Foundation, version 2 of the License.
   30.14 + *
   30.15 + * This program is distributed in the hope that it will be useful,
   30.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.18 + * GNU General Public License for more details.
   30.19 + *
   30.20 + * You should have received a copy of the GNU General Public License
   30.21 + * along with this program. Look for COPYING file in the top folder.
   30.22 + * If not, see http://opensource.org/licenses/GPL-2.0.
   30.23   */
   30.24  package org.apidesign.javap;
   30.25  
   30.26 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
   30.27 -
   30.28  /** A JavaScript optimized replacement for Hashtable.
   30.29   *
   30.30   * @author Jaroslav Tulach <jtulach@netbeans.org>
   30.31 @@ -25,9 +36,6 @@
   30.32      Hashtable() {
   30.33      }
   30.34  
   30.35 -    @JavaScriptBody(args = { "self", "key", "val" }, body = 
   30.36 -        "self[key] = val;"
   30.37 -    )
   30.38      synchronized void put(Object key, Object val) {
   30.39          int[] where = { -1, -1 };
   30.40          Object found = get(key, where);
   30.41 @@ -61,9 +69,6 @@
   30.42          }
   30.43      }
   30.44  
   30.45 -    @JavaScriptBody(args = {"self", "key" }, body = 
   30.46 -        "return self[key];"
   30.47 -    )
   30.48      Object get(Object key) {
   30.49          return get(key, null);
   30.50      }
    31.1 --- a/javap/src/main/java/org/apidesign/javap/MethodData.java	Fri Jan 18 14:23:18 2013 +0100
    31.2 +++ b/javap/src/main/java/org/apidesign/javap/MethodData.java	Fri Jan 18 14:27:22 2013 +0100
    31.3 @@ -25,9 +25,9 @@
    31.4  
    31.5  package org.apidesign.javap;
    31.6  
    31.7 -import java.io.*;
    31.8 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
    31.9  
   31.10 +import java.io.DataInputStream;
   31.11 +import java.io.IOException;
   31.12  import static org.apidesign.javap.RuntimeConstants.*;
   31.13  
   31.14  /**
   31.15 @@ -235,22 +235,8 @@
   31.16      /**
   31.17       * Return access of the method.
   31.18       */
   31.19 -    public String[] getAccess(){
   31.20 -
   31.21 -        Vector v = new Vector();
   31.22 -        if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
   31.23 -        if ((access & ACC_PRIVATE)   !=0) v.addElement("private");
   31.24 -        if ((access & ACC_PROTECTED)   !=0) v.addElement("protected");
   31.25 -        if ((access & ACC_STATIC)   !=0) v.addElement("static");
   31.26 -        if ((access & ACC_FINAL)    !=0) v.addElement("final");
   31.27 -        if ((access & ACC_SYNCHRONIZED) !=0) v.addElement("synchronized");
   31.28 -        if ((access & ACC_NATIVE) !=0) v.addElement("native");
   31.29 -        if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
   31.30 -        if ((access & ACC_STRICT) !=0) v.addElement("strictfp");
   31.31 -
   31.32 -        String[] accflags = new String[v.size()];
   31.33 -        v.copyInto(accflags);
   31.34 -        return accflags;
   31.35 +    public int getAccess(){
   31.36 +        return access;
   31.37      }
   31.38  
   31.39      /**
   31.40 @@ -357,10 +343,10 @@
   31.41      /**
   31.42       * Return exception table in code attributre.
   31.43       */
   31.44 -    public Vector getexception_table(){
   31.45 -        return exception_table;
   31.46 +    public TrapDataIterator getTrapDataIterator(){
   31.47 +        return new TrapDataIterator(exception_table);
   31.48      }
   31.49 -
   31.50 +    
   31.51  
   31.52      /**
   31.53       * Return method attributes.
   31.54 @@ -401,4 +387,8 @@
   31.55          attrs.copyInto(arr);
   31.56          return ClassData.findAttr(n, arr);
   31.57      }
   31.58 +
   31.59 +    public boolean isConstructor() {
   31.60 +        return "<init>".equals(getName());
   31.61 +    }
   31.62  }
    32.1 --- a/javap/src/main/java/org/apidesign/javap/TrapData.java	Fri Jan 18 14:23:18 2013 +0100
    32.2 +++ b/javap/src/main/java/org/apidesign/javap/TrapData.java	Fri Jan 18 14:27:22 2013 +0100
    32.3 @@ -26,7 +26,6 @@
    32.4  
    32.5  package org.apidesign.javap;
    32.6  
    32.7 -import java.util.*;
    32.8  import java.io.*;
    32.9  
   32.10  /**
   32.11 @@ -34,15 +33,18 @@
   32.12   *
   32.13   * @author  Sucheta Dambalkar (Adopted code from jdis)
   32.14   */
   32.15 -class TrapData {
   32.16 -    short start_pc, end_pc, handler_pc, catch_cpx;
   32.17 -  int num;
   32.18 +public final class TrapData {
   32.19 +  public final short start_pc;
   32.20 +  public final short end_pc;
   32.21 +  public final short handler_pc;
   32.22 +  public final short catch_cpx;
   32.23 +  final int num;
   32.24  
   32.25  
   32.26      /**
   32.27       * Read and store exception table data in code attribute.
   32.28       */
   32.29 -    public TrapData(DataInputStream in, int num) throws IOException {
   32.30 +    TrapData(DataInputStream in, int num) throws IOException {
   32.31          this.num=num;
   32.32          start_pc = in.readShort();
   32.33          end_pc=in.readShort();
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/javap/src/main/java/org/apidesign/javap/TrapDataIterator.java	Fri Jan 18 14:27:22 2013 +0100
    33.3 @@ -0,0 +1,114 @@
    33.4 +/**
    33.5 + * Back 2 Browser Bytecode Translator
    33.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    33.7 + *
    33.8 + * This program is free software: you can redistribute it and/or modify
    33.9 + * it under the terms of the GNU General Public License as published by
   33.10 + * the Free Software Foundation, version 2 of the License.
   33.11 + *
   33.12 + * This program is distributed in the hope that it will be useful,
   33.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.15 + * GNU General Public License for more details.
   33.16 + *
   33.17 + * You should have received a copy of the GNU General Public License
   33.18 + * along with this program. Look for COPYING file in the top folder.
   33.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   33.20 + */
   33.21 +package org.apidesign.javap;
   33.22 +
   33.23 +/**
   33.24 + *
   33.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   33.26 + */
   33.27 +public final class TrapDataIterator {
   33.28 +    private final Hashtable exStart = new Hashtable();
   33.29 +    private final Hashtable exStop = new Hashtable();
   33.30 +    private TrapData[] current = new TrapData[10];
   33.31 +    private int currentCount;
   33.32 +    
   33.33 +    TrapDataIterator(Vector exceptionTable) {
   33.34 +        for (int i=0 ; i < exceptionTable.size(); i++) {
   33.35 +            final TrapData td = (TrapData)exceptionTable.elementAt(i);
   33.36 +            put(exStart, td.start_pc, td);
   33.37 +            put(exStop, td.end_pc, td);
   33.38 +        }
   33.39 +    }
   33.40 +    
   33.41 +    private static void put(Hashtable h, short key, TrapData td) {
   33.42 +        Short s = Short.valueOf((short)key);
   33.43 +        Vector v = (Vector) h.get(s);
   33.44 +        if (v == null) {
   33.45 +            v = new Vector(1);
   33.46 +            h.put(s, v);
   33.47 +        }
   33.48 +        v.add(td);
   33.49 +    }
   33.50 +    
   33.51 +    private boolean processAll(Hashtable h, Short key, boolean add) {
   33.52 +        boolean change = false;
   33.53 +        Vector v = (Vector)h.get(key);
   33.54 +        if (v != null) {
   33.55 +            int s = v.size();
   33.56 +            for (int i = 0; i < s; i++) {
   33.57 +                TrapData td = (TrapData)v.elementAt(i);
   33.58 +                if (add) {
   33.59 +                    add(td);
   33.60 +                    change = true;
   33.61 +                } else {
   33.62 +                    remove(td);
   33.63 +                    change = true;
   33.64 +                }
   33.65 +            }
   33.66 +        }
   33.67 +        return change;
   33.68 +    }
   33.69 +    
   33.70 +    public boolean advanceTo(int i) {
   33.71 +        Short s = Short.valueOf((short)i);
   33.72 +        boolean ch1 = processAll(exStart, s, true);
   33.73 +        boolean ch2 = processAll(exStop, s, false);
   33.74 +        return ch1 || ch2;
   33.75 +    }
   33.76 +
   33.77 +    public boolean useTry() {
   33.78 +        return currentCount > 0;
   33.79 +    }
   33.80 +
   33.81 +    public TrapData[] current() {
   33.82 +        TrapData[] copy = new TrapData[currentCount];
   33.83 +        for (int i = 0; i < currentCount; i++) {
   33.84 +            copy[i] = current[i];
   33.85 +        }
   33.86 +        return copy;
   33.87 +    }
   33.88 +
   33.89 +    private void add(TrapData e) {
   33.90 +        if (currentCount == current.length) {
   33.91 +            TrapData[] data = new TrapData[currentCount * 2];
   33.92 +            for (int i = 0; i < currentCount; i++) {
   33.93 +                data[i] = current[i];
   33.94 +            }
   33.95 +            current = data;
   33.96 +        }
   33.97 +        current[currentCount++] = e;
   33.98 +    }
   33.99 +
  33.100 +    private void remove(TrapData e) {
  33.101 +        if (currentCount == 0) {
  33.102 +            return;
  33.103 +        }
  33.104 +        int from = 0;
  33.105 +        while (from < currentCount) {
  33.106 +            if (e == current[from++]) {
  33.107 +                break;
  33.108 +            }
  33.109 +        }
  33.110 +        while (from < currentCount) {
  33.111 +            current[from - 1] = current[from];
  33.112 +            current[from] = null;
  33.113 +            from++;
  33.114 +        }
  33.115 +        currentCount--;
  33.116 +    }
  33.117 +}
    34.1 --- a/javap/src/main/java/org/apidesign/javap/Vector.java	Fri Jan 18 14:23:18 2013 +0100
    34.2 +++ b/javap/src/main/java/org/apidesign/javap/Vector.java	Fri Jan 18 14:27:22 2013 +0100
    34.3 @@ -1,6 +1,19 @@
    34.4 -/*
    34.5 - * To change this template, choose Tools | Templates
    34.6 - * and open the template in the editor.
    34.7 +/**
    34.8 + * Back 2 Browser Bytecode Translator
    34.9 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   34.10 + *
   34.11 + * This program is free software: you can redistribute it and/or modify
   34.12 + * it under the terms of the GNU General Public License as published by
   34.13 + * the Free Software Foundation, version 2 of the License.
   34.14 + *
   34.15 + * This program is distributed in the hope that it will be useful,
   34.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   34.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   34.18 + * GNU General Public License for more details.
   34.19 + *
   34.20 + * You should have received a copy of the GNU General Public License
   34.21 + * along with this program. Look for COPYING file in the top folder.
   34.22 + * If not, see http://opensource.org/licenses/GPL-2.0.
   34.23   */
   34.24  package org.apidesign.javap;
   34.25  
   34.26 @@ -24,8 +37,8 @@
   34.27      void add(Object objectType) {
   34.28          addElement(objectType);
   34.29      }
   34.30 -    @JavaScriptBody(args = { "self", "obj" }, body = 
   34.31 -        "self.push(obj);"
   34.32 +    @JavaScriptBody(args = { "obj" }, body = 
   34.33 +        "this.push(obj);"
   34.34      )
   34.35      void addElement(Object obj) {
   34.36          final int s = size();
   34.37 @@ -33,16 +46,16 @@
   34.38          setElementAt(obj, s);
   34.39      }
   34.40  
   34.41 -    @JavaScriptBody(args = { "self" }, body = 
   34.42 -        "return self.length;"
   34.43 +    @JavaScriptBody(args = { }, body = 
   34.44 +        "return this.length;"
   34.45      )
   34.46      int size() {
   34.47          return arr == null ? 0 : arr.length;
   34.48      }
   34.49  
   34.50 -    @JavaScriptBody(args = { "self", "newArr" }, body =
   34.51 -        "for (var i = 0; i < self.length; i++) {\n"
   34.52 -      + "  newArr[i] = self[i];\n"
   34.53 +    @JavaScriptBody(args = { "newArr" }, body =
   34.54 +        "for (var i = 0; i < this.length; i++) {\n"
   34.55 +      + "  newArr[i] = this[i];\n"
   34.56        + "}\n")
   34.57      void copyInto(Object[] newArr) {
   34.58          if (arr == null) {
   34.59 @@ -54,8 +67,8 @@
   34.60          }
   34.61      }
   34.62  
   34.63 -    @JavaScriptBody(args = { "self", "index" }, body =
   34.64 -        "return self[index];"
   34.65 +    @JavaScriptBody(args = { "index" }, body =
   34.66 +        "return this[index];"
   34.67      )
   34.68      Object elementAt(int index) {
   34.69          return arr[index];
   34.70 @@ -67,8 +80,8 @@
   34.71          arr = newArr;
   34.72      }
   34.73  
   34.74 -    @JavaScriptBody(args = { "self", "val", "index" }, body = 
   34.75 -        "self[index] = val;"
   34.76 +    @JavaScriptBody(args = { "val", "index" }, body = 
   34.77 +        "this[index] = val;"
   34.78      )
   34.79      void setElementAt(Object val, int index) {
   34.80          arr[index] = val;
    35.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Fri Jan 18 14:23:18 2013 +0100
    35.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Fri Jan 18 14:27:22 2013 +0100
    35.3 @@ -43,7 +43,7 @@
    35.4  import javax.tools.Diagnostic;
    35.5  import javax.tools.FileObject;
    35.6  import javax.tools.StandardLocation;
    35.7 -import org.apidesign.bck2brwsr.htmlpage.api.OnClick;
    35.8 +import org.apidesign.bck2brwsr.htmlpage.api.On;
    35.9  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   35.10  import org.openide.util.lookup.ServiceProvider;
   35.11  
   35.12 @@ -55,7 +55,7 @@
   35.13  @ServiceProvider(service=Processor.class)
   35.14  @SupportedAnnotationTypes({
   35.15      "org.apidesign.bck2brwsr.htmlpage.api.Page",
   35.16 -    "org.apidesign.bck2brwsr.htmlpage.api.OnClick"
   35.17 +    "org.apidesign.bck2brwsr.htmlpage.api.On"
   35.18  })
   35.19  public final class PageProcessor extends AbstractProcessor {
   35.20      @Override
   35.21 @@ -146,11 +146,11 @@
   35.22              }
   35.23              TypeElement type = (TypeElement)clazz;
   35.24              for (Element method : clazz.getEnclosedElements()) {
   35.25 -                OnClick oc = method.getAnnotation(OnClick.class);
   35.26 +                On oc = method.getAnnotation(On.class);
   35.27                  if (oc != null) {
   35.28                      for (String id : oc.id()) {
   35.29                          if (pp.tagNameForId(id) == null) {
   35.30 -                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + oc.id() + " does not exist in the HTML page. Found only " + pp.ids(), method);
   35.31 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
   35.32                              return false;
   35.33                          }
   35.34                          ExecutableElement ee = (ExecutableElement)method;
   35.35 @@ -159,21 +159,21 @@
   35.36                              hasParam = false;
   35.37                          } else {
   35.38                              if (ee.getParameters().size() != 1 || ee.getParameters().get(0).asType() != stringType) {
   35.39 -                                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClick method should either have no arguments or one String argument", ee);
   35.40 +                                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method should either have no arguments or one String argument", ee);
   35.41                                  return false;
   35.42                              }
   35.43                              hasParam = true;
   35.44                          }
   35.45                          if (!ee.getModifiers().contains(Modifier.STATIC)) {
   35.46 -                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClick method has to be static", ee);
   35.47 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee);
   35.48                              return false;
   35.49                          }
   35.50                          if (ee.getModifiers().contains(Modifier.PRIVATE)) {
   35.51 -                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@OnClick method can't be private", ee);
   35.52 +                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method can't be private", ee);
   35.53                              return false;
   35.54                          }
   35.55 -                        w.append("  ").append(cnstnt(id)).
   35.56 -                            append(".addOnClick(new Runnable() { public void run() {\n");
   35.57 +                        w.append("  OnEvent." + oc.event()).append(".of(").append(cnstnt(id)).
   35.58 +                            append(").perform(new Runnable() { public void run() {\n");
   35.59                          w.append("    ").append(type.getSimpleName().toString()).
   35.60                              append('.').append(ee.getSimpleName()).append("(");
   35.61                          if (hasParam) {
    36.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java	Fri Jan 18 14:23:18 2013 +0100
    36.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java	Fri Jan 18 14:27:22 2013 +0100
    36.3 @@ -37,29 +37,45 @@
    36.4          body="var e = window.document.getElementById(el.fld_id);\n"
    36.5             + "e[property] = value;\n"
    36.6      )
    36.7 -    static void setAttribute(Element el, String property, Object value) {
    36.8 -        throw new UnsupportedOperationException("Needs JavaScript!");
    36.9 -    }
   36.10 +    static native void setAttribute(Element el, String property, Object value);
   36.11  
   36.12      @JavaScriptBody(
   36.13          args={"el", "property"},
   36.14          body="var e = window.document.getElementById(el.fld_id);\n"
   36.15             + "return e[property];\n"
   36.16      )
   36.17 -    static Object getAttribute(Element el, String property) {
   36.18 -        throw new UnsupportedOperationException("Needs JavaScript!");
   36.19 -    }
   36.20 +    static native Object getAttribute(Element el, String property);
   36.21      
   36.22      /** Executes given runnable when user performs a "click" on the given
   36.23       * element.
   36.24       * @param r the runnable to execute, never null
   36.25       */
   36.26      @JavaScriptBody(
   36.27 -        args={"el", "r"},
   36.28 -        body="var e = window.document.getElementById(el.fld_id);\n"
   36.29 -           + "e.onclick = function() { r.run__V(); };\n"
   36.30 +        args={ "ev", "r" },
   36.31 +        body="var e = window.document.getElementById(this.fld_id);\n"
   36.32 +           + "e[ev.fld_id] = function() { r.run__V(); };\n"
   36.33      )
   36.34 -    public final void addOnClick(Runnable r) {
   36.35 -        throw new UnsupportedOperationException("Needs JavaScript!");
   36.36 +    final native void on(OnEvent ev, Runnable r);
   36.37 +
   36.38 +    /** Shows alert message dialog in a browser.
   36.39 +     * @param msg the message to show
   36.40 +     */
   36.41 +    @JavaScriptBody(args = "msg", body = "alert(msg);")
   36.42 +    public static native void alert(String msg);
   36.43 +
   36.44 +    /** Generic way to query any attribute of this element.
   36.45 +     * @param property name of the attribute
   36.46 +     */
   36.47 +    public final Object getAttribute(String property) {
   36.48 +        return getAttribute(this, property);
   36.49 +    }
   36.50 +    
   36.51 +    /** Generic way to change an attribute of this element.
   36.52 +     * 
   36.53 +     * @param property name of the attribute
   36.54 +     * @param value value to associate with the attribute
   36.55 +     */
   36.56 +    public final void setAttribute(String property, Object value) {
   36.57 +        setAttribute(this, property, value);
   36.58      }
   36.59  }
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/On.java	Fri Jan 18 14:27:22 2013 +0100
    37.3 @@ -0,0 +1,35 @@
    37.4 +/**
    37.5 + * Back 2 Browser Bytecode Translator
    37.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    37.7 + *
    37.8 + * This program is free software: you can redistribute it and/or modify
    37.9 + * it under the terms of the GNU General Public License as published by
   37.10 + * the Free Software Foundation, version 2 of the License.
   37.11 + *
   37.12 + * This program is distributed in the hope that it will be useful,
   37.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.15 + * GNU General Public License for more details.
   37.16 + *
   37.17 + * You should have received a copy of the GNU General Public License
   37.18 + * along with this program. Look for COPYING file in the top folder.
   37.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   37.20 + */
   37.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   37.22 +
   37.23 +import java.lang.annotation.ElementType;
   37.24 +import java.lang.annotation.Retention;
   37.25 +import java.lang.annotation.RetentionPolicy;
   37.26 +import java.lang.annotation.Target;
   37.27 +
   37.28 +/** Adds an onClick handler to an element identified by given <em>id</em>.
   37.29 + * Apply on a <code>public static void</code> method with no arguments.
   37.30 + *
   37.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   37.32 + */
   37.33 +@Retention(RetentionPolicy.SOURCE)
   37.34 +@Target(ElementType.METHOD)
   37.35 +public @interface On {
   37.36 +    OnEvent event();
   37.37 +    String[] id();
   37.38 +}
    38.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnClick.java	Fri Jan 18 14:23:18 2013 +0100
    38.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.3 @@ -1,34 +0,0 @@
    38.4 -/**
    38.5 - * Back 2 Browser Bytecode Translator
    38.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    38.7 - *
    38.8 - * This program is free software: you can redistribute it and/or modify
    38.9 - * it under the terms of the GNU General Public License as published by
   38.10 - * the Free Software Foundation, version 2 of the License.
   38.11 - *
   38.12 - * This program is distributed in the hope that it will be useful,
   38.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   38.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   38.15 - * GNU General Public License for more details.
   38.16 - *
   38.17 - * You should have received a copy of the GNU General Public License
   38.18 - * along with this program. Look for COPYING file in the top folder.
   38.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   38.20 - */
   38.21 -package org.apidesign.bck2brwsr.htmlpage.api;
   38.22 -
   38.23 -import java.lang.annotation.ElementType;
   38.24 -import java.lang.annotation.Retention;
   38.25 -import java.lang.annotation.RetentionPolicy;
   38.26 -import java.lang.annotation.Target;
   38.27 -
   38.28 -/** Adds an onClick handler to an element identified by given <em>id</em>.
   38.29 - * Apply on a <code>public static void</code> method with no arguments.
   38.30 - *
   38.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   38.32 - */
   38.33 -@Retention(RetentionPolicy.SOURCE)
   38.34 -@Target(ElementType.METHOD)
   38.35 -public @interface OnClick {
   38.36 -    String[] id();
   38.37 -}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java	Fri Jan 18 14:27:22 2013 +0100
    39.3 @@ -0,0 +1,43 @@
    39.4 +/**
    39.5 + * Back 2 Browser Bytecode Translator
    39.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    39.7 + *
    39.8 + * This program is free software: you can redistribute it and/or modify
    39.9 + * it under the terms of the GNU General Public License as published by
   39.10 + * the Free Software Foundation, version 2 of the License.
   39.11 + *
   39.12 + * This program is distributed in the hope that it will be useful,
   39.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.15 + * GNU General Public License for more details.
   39.16 + *
   39.17 + * You should have received a copy of the GNU General Public License
   39.18 + * along with this program. Look for COPYING file in the top folder.
   39.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   39.20 + */
   39.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   39.22 +
   39.23 +/** Controller created via {@link OnEvent#of(org.apidesign.bck2brwsr.htmlpage.api.Element[])}.
   39.24 + *
   39.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   39.26 + */
   39.27 +public final class OnController {
   39.28 +    private final Element[] arr;
   39.29 +    private final OnEvent event;
   39.30 +    
   39.31 +    OnController(OnEvent event, Element[] arr) {
   39.32 +        this.event = event;
   39.33 +        this.arr = arr;
   39.34 +    }
   39.35 +    
   39.36 +    /** Registers a runnable to be performed on associated {@link OnEvent} 
   39.37 +     * and {@link Element}.
   39.38 +     * 
   39.39 +     * @see OnEvent#of
   39.40 +     */
   39.41 +    public void perform(Runnable r) {
   39.42 +        for (Element e : arr) {
   39.43 +            e.on(event, r);
   39.44 +        }
   39.45 +    }
   39.46 +}
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java	Fri Jan 18 14:27:22 2013 +0100
    40.3 @@ -0,0 +1,95 @@
    40.4 +/**
    40.5 + * Back 2 Browser Bytecode Translator
    40.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    40.7 + *
    40.8 + * This program is free software: you can redistribute it and/or modify
    40.9 + * it under the terms of the GNU General Public License as published by
   40.10 + * the Free Software Foundation, version 2 of the License.
   40.11 + *
   40.12 + * This program is distributed in the hope that it will be useful,
   40.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   40.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40.15 + * GNU General Public License for more details.
   40.16 + *
   40.17 + * You should have received a copy of the GNU General Public License
   40.18 + * along with this program. Look for COPYING file in the top folder.
   40.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   40.20 + */
   40.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   40.22 +
   40.23 +/** Type of events to use in connection with {@link On} annotation.
   40.24 + *
   40.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   40.26 + */
   40.27 +public enum OnEvent {
   40.28 +    ABORT("onabort"),
   40.29 +    BLUR("onblur"),
   40.30 +    CAN_PLAY("oncanplay"),
   40.31 +    CAN_PLAY_THROUGH("oncanplaythrough"),
   40.32 +    CLICK("onclick"),
   40.33 +    CONTEXT_MENU("oncontextmenu"),
   40.34 +    DBL_CLICK("ondblclick"),
   40.35 +    DRAG("ondrag"),
   40.36 +    DRAG_END("ondragend"),
   40.37 +    DRAG_ENTER("ondragenter"),
   40.38 +    DRAG_LEAVE("ondragleave"),
   40.39 +    DRAG_OVER("ondragover"),
   40.40 +    DRAG_START("ondragstart"),
   40.41 +    DROP("ondrop"),
   40.42 +    DURATION_CHANGE("ondurationchange"),
   40.43 +    EMPTIED("onemptied"),
   40.44 +    ENDED("onended"),
   40.45 +    ERROR("onerror"),
   40.46 +    FOCUS("onfocus"),
   40.47 +    FORM_CHANGE("onformchange"),
   40.48 +    FORM_INPUT("onforminput"),
   40.49 +    INPUT("oninput"),
   40.50 +    INVALID("oninvalid"),
   40.51 +    KEY_DOWN("onkeydown"),
   40.52 +    KEY_PRESS("onkeypress"),
   40.53 +    KEY_UP("onkeyup"),
   40.54 +    LOAD("onload"),
   40.55 +    LOADED_DATA("onloadeddata"),
   40.56 +    LOADED_META_DATA("onloadedmetadata"),
   40.57 +    LOAD_START("onloadstart"),
   40.58 +    MOUSE_DOWN("onmousedown"),
   40.59 +    MOUSE_MOVE("onmousemove"),
   40.60 +    MOUSE_OUT("onmouseout"),
   40.61 +    MOUSE_OVER("onmouseover"),
   40.62 +    MOUSE_UP("onmouseup"),
   40.63 +    MOUSE_WHEEL("onmousewheel"),
   40.64 +    PAUSE("onpause"),
   40.65 +    PLAY("onplay"),
   40.66 +    PLAYING("onplaying"),
   40.67 +    PROGRESS("onprogress"),
   40.68 +    RATE_CHANGE("onratechange"),
   40.69 +    READY_STATE_CHANGE("onreadystatechange"),
   40.70 +    SCROLL("onscroll"),
   40.71 +    SEEKED("onseeked"),
   40.72 +    SEEKING("onseeking"),
   40.73 +    SELECT("onselect"),
   40.74 +    SHOW("onshow"),
   40.75 +    STALLED("onstalled"),
   40.76 +    SUBMIT("onsubmit"),
   40.77 +    SUSPEND("onsuspend"),
   40.78 +    TIME_UPDATE("ontimeupdate"),
   40.79 +    VOLUME_CHANGE("onvolumechange"),
   40.80 +    WAITING("onwaiting");
   40.81 +    
   40.82 +    final String id;
   40.83 +    
   40.84 +    private OnEvent(String id) {
   40.85 +        this.id = id;
   40.86 +    }
   40.87 +    
   40.88 +    /** What should happen when this even happen on one
   40.89 +     * of associated elements. Continue by calling {@link OnController#perform(java.lang.Runnable)}
   40.90 +     * method.
   40.91 +     * 
   40.92 +     * @param elmnts one or more elements
   40.93 +     * @return controller with <code>perform</code> method.
   40.94 +     */
   40.95 +    public OnController of(Element... elmnts) {
   40.96 +        return new OnController(this, elmnts);
   40.97 +    }
   40.98 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Timer.java	Fri Jan 18 14:27:22 2013 +0100
    41.3 @@ -0,0 +1,59 @@
    41.4 +/**
    41.5 + * Back 2 Browser Bytecode Translator
    41.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    41.7 + *
    41.8 + * This program is free software: you can redistribute it and/or modify
    41.9 + * it under the terms of the GNU General Public License as published by
   41.10 + * the Free Software Foundation, version 2 of the License.
   41.11 + *
   41.12 + * This program is distributed in the hope that it will be useful,
   41.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   41.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   41.15 + * GNU General Public License for more details.
   41.16 + *
   41.17 + * You should have received a copy of the GNU General Public License
   41.18 + * along with this program. Look for COPYING file in the top folder.
   41.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   41.20 + */
   41.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   41.22 +
   41.23 +import java.io.Closeable;
   41.24 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   41.25 +
   41.26 +/**
   41.27 + *
   41.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   41.29 + */
   41.30 +public class Timer implements Closeable {
   41.31 +    private final Object t;
   41.32 +    
   41.33 +    private Timer(Object t) {
   41.34 +        this.t = t;
   41.35 +    }
   41.36 +    
   41.37 +    /** Creates a timer that invokes provided runnable on a fixed interval
   41.38 +     * 
   41.39 +     * @param r the runnable to execute
   41.40 +     * @param time milliseconds to invoke the timer periodically
   41.41 +     */
   41.42 +    public static Timer create(Runnable r, int time) {
   41.43 +        return new Timer(interval(r, time));
   41.44 +    }
   41.45 +    
   41.46 +    @JavaScriptBody(args = { "r", "time" }, body = 
   41.47 +        "return window.setInterval(function() { r.run__V(); }, time);"
   41.48 +    )
   41.49 +    private static native Object interval(Runnable r, int time);
   41.50 +
   41.51 +    @JavaScriptBody(args = { "self" }, body = 
   41.52 +        "window.clearInterval(self);"
   41.53 +    )
   41.54 +    private static native void close(Object self);
   41.55 +    
   41.56 +    /** Cancels this timer.
   41.57 +     */
   41.58 +    @Override
   41.59 +    public void close() {
   41.60 +        close(t);
   41.61 +    }
   41.62 +}
    42.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java	Fri Jan 18 14:23:18 2013 +0100
    42.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java	Fri Jan 18 14:27:22 2013 +0100
    42.3 @@ -17,7 +17,8 @@
    42.4   */
    42.5  package org.apidesign.bck2brwsr.htmlpage;
    42.6  
    42.7 -import org.apidesign.bck2brwsr.htmlpage.api.OnClick;
    42.8 +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
    42.9 +import org.apidesign.bck2brwsr.htmlpage.api.On;
   42.10  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   42.11  
   42.12  /** Trivial demo for the bck2brwsr project. First of all start
   42.13 @@ -42,12 +43,12 @@
   42.14   */
   42.15  @Page(xhtml="TestPage.html")
   42.16  public class PageController {
   42.17 -    @OnClick(id="pg.button")
   42.18 +    @On(event = CLICK, id="pg.button")
   42.19      static void updateTitle() {
   42.20          TestPage.PG_TITLE.setText("You want this window to be named " + TestPage.PG_TEXT.getValue());
   42.21      }
   42.22      
   42.23 -    @OnClick(id={ "pg.title", "pg.text" })
   42.24 +    @On(event = CLICK, id={ "pg.title", "pg.text" })
   42.25      static void click(String id) {
   42.26          if (!id.equals("pg.title")) {
   42.27              throw new IllegalStateException();
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/javaquery/demo-calculator-dynamic/nbactions.xml	Fri Jan 18 14:27:22 2013 +0100
    43.3 @@ -0,0 +1,29 @@
    43.4 +<?xml version="1.0" encoding="UTF-8"?>
    43.5 +<!--
    43.6 +
    43.7 +    Back 2 Browser Bytecode Translator
    43.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    43.9 +
   43.10 +    This program is free software: you can redistribute it and/or modify
   43.11 +    it under the terms of the GNU General Public License as published by
   43.12 +    the Free Software Foundation, version 2 of the License.
   43.13 +
   43.14 +    This program is distributed in the hope that it will be useful,
   43.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   43.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   43.17 +    GNU General Public License for more details.
   43.18 +
   43.19 +    You should have received a copy of the GNU General Public License
   43.20 +    along with this program. Look for COPYING file in the top folder.
   43.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   43.22 +
   43.23 +-->
   43.24 +<actions>
   43.25 +        <action>
   43.26 +            <actionName>run</actionName>
   43.27 +            <goals>
   43.28 +                <goal>process-classes</goal>
   43.29 +                <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
   43.30 +            </goals>
   43.31 +        </action>
   43.32 +    </actions>
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    44.3 @@ -0,0 +1,58 @@
    44.4 +<?xml version="1.0"?>
    44.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    44.6 +  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    44.7 +  <modelVersion>4.0.0</modelVersion>
    44.8 +
    44.9 +  <groupId>org.apidesign.bck2brwsr</groupId>
   44.10 +  <artifactId>demo.calculator</artifactId>
   44.11 +  <version>0.3-SNAPSHOT</version>
   44.12 +  <packaging>jar</packaging>
   44.13 +
   44.14 +  <name>JavaQuery Demo - Calculator</name>
   44.15 +  <url>http://maven.apache.org</url>
   44.16 +
   44.17 +  <properties>
   44.18 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   44.19 +  </properties>
   44.20 +  <build>
   44.21 +      <plugins>
   44.22 +            <plugin>
   44.23 +                <groupId>org.apidesign.bck2brwsr</groupId>
   44.24 +                <artifactId>mojo</artifactId>
   44.25 +                <version>0.3-SNAPSHOT</version>
   44.26 +                <executions>
   44.27 +                    <execution>
   44.28 +                        <goals>
   44.29 +                            <goal>brwsr</goal>
   44.30 +                        </goals>
   44.31 +                    </execution>
   44.32 +                </executions>
   44.33 +                <configuration>
   44.34 +                    <startpage>org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml</startpage>
   44.35 +                </configuration>
   44.36 +            </plugin>
   44.37 +         <plugin>
   44.38 +            <groupId>org.apache.maven.plugins</groupId>
   44.39 +            <artifactId>maven-compiler-plugin</artifactId>
   44.40 +            <version>2.3.2</version>
   44.41 +            <configuration>
   44.42 +               <source>1.7</source>
   44.43 +               <target>1.7</target>
   44.44 +            </configuration>
   44.45 +         </plugin>
   44.46 +      </plugins>
   44.47 +  </build>
   44.48 +
   44.49 +  <dependencies>
   44.50 +    <dependency>
   44.51 +      <groupId>org.apidesign.bck2brwsr</groupId>
   44.52 +      <artifactId>emul</artifactId>
   44.53 +      <version>0.3-SNAPSHOT</version>
   44.54 +    </dependency>
   44.55 +    <dependency>
   44.56 +      <groupId>org.apidesign.bck2brwsr</groupId>
   44.57 +      <artifactId>javaquery.api</artifactId>
   44.58 +      <version>0.3-SNAPSHOT</version>
   44.59 +    </dependency>
   44.60 +  </dependencies>
   44.61 +</project>
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java	Fri Jan 18 14:27:22 2013 +0100
    45.3 @@ -0,0 +1,89 @@
    45.4 +/**
    45.5 + * Back 2 Browser Bytecode Translator
    45.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    45.7 + *
    45.8 + * This program is free software: you can redistribute it and/or modify
    45.9 + * it under the terms of the GNU General Public License as published by
   45.10 + * the Free Software Foundation, version 2 of the License.
   45.11 + *
   45.12 + * This program is distributed in the hope that it will be useful,
   45.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   45.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   45.15 + * GNU General Public License for more details.
   45.16 + *
   45.17 + * You should have received a copy of the GNU General Public License
   45.18 + * along with this program. Look for COPYING file in the top folder.
   45.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   45.20 + */
   45.21 +package org.apidesign.bck2brwsr.mavenhtml;
   45.22 +
   45.23 +import org.apidesign.bck2brwsr.htmlpage.api.On;
   45.24 +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
   45.25 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
   45.26 +
   45.27 +/** HTML5 & Java demo showing the power of 
   45.28 + * <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
   45.29 + * as well as other goodies.
   45.30 + * 
   45.31 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   45.32 + */
   45.33 +@Page(xhtml="Calculator.xhtml")
   45.34 +public class App {
   45.35 +    private static double memory;
   45.36 +    private static String operation;
   45.37 +    
   45.38 +    @On(event = CLICK, id="clear")
   45.39 +    static void clear() {
   45.40 +        memory = 0;
   45.41 +        operation = null;
   45.42 +        Calculator.DISPLAY.setValue("0");
   45.43 +    }
   45.44 +    
   45.45 +    @On(event = CLICK, id= { "plus", "minus", "mul", "div" })
   45.46 +    static void applyOp(String op) {
   45.47 +        memory = getValue();
   45.48 +        operation = op;
   45.49 +        Calculator.DISPLAY.setValue("0");
   45.50 +    }
   45.51 +    
   45.52 +    @On(event = CLICK, id="result")
   45.53 +    static void computeTheValue() {
   45.54 +        switch (operation) {
   45.55 +            case "plus": setValue(memory + getValue()); break;
   45.56 +            case "minus": setValue(memory - getValue()); break;
   45.57 +            case "mul": setValue(memory * getValue()); break;
   45.58 +            case "div": setValue(memory / getValue()); break;
   45.59 +            default: throw new IllegalStateException(operation);
   45.60 +        }
   45.61 +    }
   45.62 +    
   45.63 +    @On(event = CLICK, id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) 
   45.64 +    static void addDigit(String digit) {
   45.65 +        digit = digit.substring(1);
   45.66 +        String v = Calculator.DISPLAY.getValue();
   45.67 +        if (getValue() == 0.0) {
   45.68 +            Calculator.DISPLAY.setValue(digit);
   45.69 +        } else {
   45.70 +            Calculator.DISPLAY.setValue(v + digit);
   45.71 +        }
   45.72 +    }
   45.73 +    
   45.74 +    private static void setValue(double v) {
   45.75 +        StringBuilder sb = new StringBuilder();
   45.76 +        sb.append(v);
   45.77 +        if (sb.toString().endsWith(".0")) {
   45.78 +            final int l = sb.length();
   45.79 +            sb.delete(l - 2, l);
   45.80 +        }
   45.81 +        Calculator.DISPLAY.setValue(sb.toString());
   45.82 +    }
   45.83 +
   45.84 +    private static double getValue() {
   45.85 +        try {
   45.86 +            return Double.parseDouble(Calculator.DISPLAY.getValue());
   45.87 +        } catch (NumberFormatException ex) {
   45.88 +            Calculator.DISPLAY.setValue("err");
   45.89 +            return 0.0;
   45.90 +        }
   45.91 +    }
   45.92 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/mavenhtml/Calculator.xhtml	Fri Jan 18 14:27:22 2013 +0100
    46.3 @@ -0,0 +1,158 @@
    46.4 +<?xml version="1.0" encoding="UTF-8"?>
    46.5 +<!--
    46.6 +
    46.7 +    Back 2 Browser Bytecode Translator
    46.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    46.9 +
   46.10 +    This program is free software: you can redistribute it and/or modify
   46.11 +    it under the terms of the GNU General Public License as published by
   46.12 +    the Free Software Foundation, version 2 of the License.
   46.13 +
   46.14 +    This program is distributed in the hope that it will be useful,
   46.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   46.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   46.17 +    GNU General Public License for more details.
   46.18 +
   46.19 +    You should have received a copy of the GNU General Public License
   46.20 +    along with this program. Look for COPYING file in the top folder.
   46.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   46.22 +
   46.23 +-->
   46.24 +<!DOCTYPE html>
   46.25 +<html xmlns="http://www.w3.org/1999/xhtml">
   46.26 +    <head>
   46.27 +        <title>Simple Calculator in HTML5 and Java</title>
   46.28 +
   46.29 +        <style type="text/css">
   46.30 +        body {color: #ffffff; background-color: #121e31; font-family: Monospaced}
   46.31 +        pre {color: #ffffff; background-color: #121e31; font-family: Monospaced}
   46.32 +        table {color: #ffffff; background-color: #121e31; font-family: Monospaced}
   46.33 +        .string {color: #e2ce00}
   46.34 +        a {color: #e2ce00}
   46.35 +        .ST1 {color: #0000cc; font-family: Monospaced; font-weight: bold}
   46.36 +        .ST0 {color: #0000ff}
   46.37 +        .comment {color: #428bdd}
   46.38 +        .keyword-directive {color: #f8bb00}
   46.39 +        .tag {color: #f8bb00}
   46.40 +        .ST0 {color: #628fb5; background-color: #1b3450}
   46.41 +        .sgml-comment {color: #808080}
   46.42 +        .value {color: #99006b}
   46.43 +        .argument {color: #007c00}
   46.44 +        .sgml-declaration {color: #bf9221}
   46.45 +        </style>    
   46.46 +        </head>
   46.47 +    <body>
   46.48 +        <h1>Java and HTML5 - Together at Last!</h1>
   46.49 +        <table border="0" cellspacing="2">
   46.50 +            <tbody>
   46.51 +                <tr>
   46.52 +                    <td colspan="4"><input id="display" value="0" 
   46.53 +                            style="text-align: right"/>
   46.54 +                </td>
   46.55 +                </tr>
   46.56 +                <tr>
   46.57 +                    <td><button id="n1">1</button></td>
   46.58 +                    <td><button id="n2">2</button></td>
   46.59 +                    <td><button id="n3">3</button></td>
   46.60 +                    <td><button id="plus">+</button></td>
   46.61 +                </tr>
   46.62 +                <tr>
   46.63 +                    <td><button id="n4">4</button></td>
   46.64 +                    <td><button id="n5">5</button></td>
   46.65 +                    <td><button id="n6">6</button></td>
   46.66 +                    <td><button id="minus">-</button></td>
   46.67 +                </tr>
   46.68 +                <tr>
   46.69 +                    <td><button id="n7">7</button></td>
   46.70 +                    <td><button id="n8">8</button></td>
   46.71 +                    <td><button id="n9">9</button></td>
   46.72 +                    <td><button id="mul">*</button></td>
   46.73 +                </tr>
   46.74 +                <tr>
   46.75 +                    <td><button id="clear">C</button></td>
   46.76 +                    <td><button id="n0">0</button></td>
   46.77 +                    <td><button id="result">=</button></td>
   46.78 +                    <td><button id="div">/</button></td>
   46.79 +                </tr>
   46.80 +            </tbody>
   46.81 +        </table>
   46.82 +
   46.83 +        <script src="/bck2brwsr.js"></script>
   46.84 +        <script src="/vm.js"></script>
   46.85 +        <script type="text/javascript">
   46.86 +            vm.loadClass('org.apidesign.bck2brwsr.mavenhtml.Calculator');
   46.87 +        </script>
   46.88 +        
   46.89 +        <hr/>
   46.90 +    <pre>
   46.91 +    <span class="keyword-directive">package</span> org.apidesign.bck2brwsr.mavenhtml;
   46.92 +
   46.93 +    <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.OnClick;
   46.94 +    <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.Page;
   46.95 +
   46.96 +    <span class="comment">/**</span> <span class="comment">HTML5</span><span class="comment"> &amp; </span><span class="comment">Java</span> <span class="comment">demo</span> <span class="comment">showing</span> <span class="comment">the</span> <span class="comment">power</span> <span class="comment">of</span> <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
   46.97 +    <span class="comment"> * </span><span class="comment">as</span> <span class="comment">well</span> <span class="comment">as</span> <span class="comment">other</span> <span class="comment">goodies</span><span class="comment">, including type-safe association between</span>
   46.98 +    <span class="comment"> * </span><span class="comment">an XHTML page and Java.</span>
   46.99 +    <span class="comment"> * </span>
  46.100 +    <span class="comment"> * </span><span class="ST1">@author</span> <span class="comment">Jaroslav</span> <span class="comment">Tulach</span> <span class="ST0">&lt;jaroslav.tulach@apidesign.org&gt;</span>
  46.101 +     <span class="comment">*/</span>
  46.102 +    @Page(xhtml=<span class="string">&quot;</span><span class="string">Calculator.xhtml</span><span class="string">&quot;</span>)
  46.103 +    <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> App {
  46.104 +        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> memory;
  46.105 +        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> String operation;
  46.106 +
  46.107 +        @OnClick(id=<span class="string">&quot;</span><span class="string">clear</span><span class="string">&quot;</span>)
  46.108 +        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> clear() {
  46.109 +            memory = <span class="number">0</span>;
  46.110 +            operation = <span class="keyword-directive">null</span>;
  46.111 +            Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
  46.112 +        }
  46.113 +
  46.114 +        @OnClick(id= { <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span> })
  46.115 +        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> applyOp(String op) {
  46.116 +            memory = getValue();
  46.117 +            operation = op;
  46.118 +            Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
  46.119 +        }
  46.120 +
  46.121 +        @OnClick(id=<span class="string">&quot;</span><span class="string">result</span><span class="string">&quot;</span>)
  46.122 +        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> computeTheValue() {
  46.123 +            <span class="keyword-directive">switch</span> (operation) {
  46.124 +                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
  46.125 +                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
  46.126 +                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
  46.127 +                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span>: setValue(memory / getValue()); <span class="keyword-directive">break</span>;
  46.128 +                <span class="keyword-directive">default</span>: <span class="keyword-directive">throw</span> <span class="keyword-directive">new</span> IllegalStateException(operation);
  46.129 +            }
  46.130 +        }
  46.131 +
  46.132 +        @OnClick(id={<span class="string">&quot;</span><span class="string">n0</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n1</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n2</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n3</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n4</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n5</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n6</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n7</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n8</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n9</span><span class="string">&quot;</span>}) 
  46.133 +        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> addDigit(String digit) {
  46.134 +            digit = digit.substring(<span class="number">1</span>);
  46.135 +            String v = Calculator.DISPLAY.getValue();
  46.136 +            <span class="keyword-directive">if</span> (getValue() == <span class="number">0.0</span>) {
  46.137 +                Calculator.DISPLAY.setValue(digit);
  46.138 +            } <span class="keyword-directive">else</span> {
  46.139 +                Calculator.DISPLAY.setValue(v + digit);
  46.140 +            }
  46.141 +        }
  46.142 +
  46.143 +        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> setValue(<span class="keyword-directive">double</span> v) {
  46.144 +            StringBuilder sb = <span class="keyword-directive">new</span> StringBuilder();
  46.145 +            sb.append(v);
  46.146 +            Calculator.DISPLAY.setValue(sb.toString());
  46.147 +        }
  46.148 +
  46.149 +        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> getValue() {
  46.150 +            <span class="keyword-directive">try</span> {
  46.151 +                <span class="keyword-directive">return</span> Double.parseDouble(Calculator.DISPLAY.getValue());
  46.152 +            } <span class="keyword-directive">catch</span> (NumberFormatException ex) {
  46.153 +                Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">err</span><span class="string">&quot;</span>);
  46.154 +                <span class="keyword-directive">return</span> <span class="number">0.0</span>;
  46.155 +            }
  46.156 +        }
  46.157 +    }
  46.158 +
  46.159 +    </pre>
  46.160 +    </body>
  46.161 +</html>
    47.1 --- a/javaquery/demo-calculator/pom.xml	Fri Jan 18 14:23:18 2013 +0100
    47.2 +++ b/javaquery/demo-calculator/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    47.3 @@ -4,11 +4,11 @@
    47.4    <modelVersion>4.0.0</modelVersion>
    47.5  
    47.6    <groupId>org.apidesign.bck2brwsr</groupId>
    47.7 -  <artifactId>demo.calculator</artifactId>
    47.8 +  <artifactId>demo.static.calculator</artifactId>
    47.9    <version>0.3-SNAPSHOT</version>
   47.10    <packaging>jar</packaging>
   47.11  
   47.12 -  <name>JavaQuery Demo - Calculator</name>
   47.13 +  <name>JavaQuery Demo - Calculator - Static Compilation</name>
   47.14    <url>http://maven.apache.org</url>
   47.15  
   47.16    <properties>
    48.1 --- a/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java	Fri Jan 18 14:23:18 2013 +0100
    48.2 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/mavenhtml/App.java	Fri Jan 18 14:27:22 2013 +0100
    48.3 @@ -17,7 +17,8 @@
    48.4   */
    48.5  package org.apidesign.bck2brwsr.mavenhtml;
    48.6  
    48.7 -import org.apidesign.bck2brwsr.htmlpage.api.OnClick;
    48.8 +import org.apidesign.bck2brwsr.htmlpage.api.On;
    48.9 +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
   48.10  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   48.11  
   48.12  /** HTML5 & Java demo showing the power of 
   48.13 @@ -31,21 +32,21 @@
   48.14      private static double memory;
   48.15      private static String operation;
   48.16      
   48.17 -    @OnClick(id="clear")
   48.18 +    @On(event = CLICK, id="clear")
   48.19      static void clear() {
   48.20          memory = 0;
   48.21          operation = null;
   48.22          Calculator.DISPLAY.setValue("0");
   48.23      }
   48.24      
   48.25 -    @OnClick(id= { "plus", "minus", "mul", "div" })
   48.26 +    @On(event = CLICK, id= { "plus", "minus", "mul", "div" })
   48.27      static void applyOp(String op) {
   48.28          memory = getValue();
   48.29          operation = op;
   48.30          Calculator.DISPLAY.setValue("0");
   48.31      }
   48.32      
   48.33 -    @OnClick(id="result")
   48.34 +    @On(event = CLICK, id="result")
   48.35      static void computeTheValue() {
   48.36          switch (operation) {
   48.37              case "plus": setValue(memory + getValue()); break;
   48.38 @@ -56,7 +57,7 @@
   48.39          }
   48.40      }
   48.41      
   48.42 -    @OnClick(id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) 
   48.43 +    @On(event = CLICK, id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) 
   48.44      static void addDigit(String digit) {
   48.45          digit = digit.substring(1);
   48.46          String v = Calculator.DISPLAY.getValue();
    49.1 --- a/javaquery/pom.xml	Fri Jan 18 14:23:18 2013 +0100
    49.2 +++ b/javaquery/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    49.3 @@ -14,5 +14,6 @@
    49.4      <modules>
    49.5          <module>api</module>
    49.6          <module>demo-calculator</module>
    49.7 +        <module>demo-calculator-dynamic</module>
    49.8      </modules>
    49.9  </project>
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/launcher/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    50.3 @@ -0,0 +1,49 @@
    50.4 +<?xml version="1.0"?>
    50.5 +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    50.6 +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    50.7 +  <modelVersion>4.0.0</modelVersion>
    50.8 +  <parent>
    50.9 +    <groupId>org.apidesign</groupId>
   50.10 +    <artifactId>bck2brwsr</artifactId>
   50.11 +    <version>0.3-SNAPSHOT</version>
   50.12 +  </parent>
   50.13 +  <groupId>org.apidesign.bck2brwsr</groupId>
   50.14 +  <artifactId>launcher</artifactId>
   50.15 +  <version>0.3-SNAPSHOT</version>
   50.16 +  <name>Bck2Brwsr Launcher</name>
   50.17 +  <url>http://maven.apache.org</url>
   50.18 +    <build>
   50.19 +        <plugins>
   50.20 +            <plugin>
   50.21 +                <groupId>org.apache.maven.plugins</groupId>
   50.22 +                <artifactId>maven-compiler-plugin</artifactId>
   50.23 +                <version>2.3.2</version>
   50.24 +                <configuration>
   50.25 +                    <source>1.7</source>
   50.26 +                    <target>1.7</target>
   50.27 +                </configuration>
   50.28 +            </plugin>
   50.29 +        </plugins>
   50.30 +    </build>
   50.31 +    <properties>
   50.32 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   50.33 +  </properties>
   50.34 +  <dependencies>
   50.35 +    <dependency>
   50.36 +      <groupId>junit</groupId>
   50.37 +      <artifactId>junit</artifactId>
   50.38 +      <version>3.8.1</version>
   50.39 +      <scope>test</scope>
   50.40 +    </dependency>
   50.41 +    <dependency>
   50.42 +      <groupId>org.glassfish.grizzly</groupId>
   50.43 +      <artifactId>grizzly-http-server</artifactId>
   50.44 +      <version>2.2.19</version>
   50.45 +    </dependency>
   50.46 +    <dependency>
   50.47 +      <groupId>${project.groupId}</groupId>
   50.48 +      <artifactId>vm4brwsr</artifactId>
   50.49 +      <version>${project.version}</version>
   50.50 +    </dependency>
   50.51 +  </dependencies>
   50.52 +</project>
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Fri Jan 18 14:27:22 2013 +0100
    51.3 @@ -0,0 +1,455 @@
    51.4 +/**
    51.5 + * Back 2 Browser Bytecode Translator
    51.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    51.7 + *
    51.8 + * This program is free software: you can redistribute it and/or modify
    51.9 + * it under the terms of the GNU General Public License as published by
   51.10 + * the Free Software Foundation, version 2 of the License.
   51.11 + *
   51.12 + * This program is distributed in the hope that it will be useful,
   51.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   51.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   51.15 + * GNU General Public License for more details.
   51.16 + *
   51.17 + * You should have received a copy of the GNU General Public License
   51.18 + * along with this program. Look for COPYING file in the top folder.
   51.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   51.20 + */
   51.21 +package org.apidesign.bck2brwsr.launcher;
   51.22 +
   51.23 +import java.io.Closeable;
   51.24 +import java.io.File;
   51.25 +import java.io.IOException;
   51.26 +import java.io.InputStream;
   51.27 +import java.io.InterruptedIOException;
   51.28 +import java.io.OutputStream;
   51.29 +import java.io.Writer;
   51.30 +import java.net.URI;
   51.31 +import java.net.URISyntaxException;
   51.32 +import java.net.URL;
   51.33 +import java.util.ArrayList;
   51.34 +import java.util.Arrays;
   51.35 +import java.util.Enumeration;
   51.36 +import java.util.LinkedHashSet;
   51.37 +import java.util.List;
   51.38 +import java.util.Set;
   51.39 +import java.util.concurrent.BlockingQueue;
   51.40 +import java.util.concurrent.CountDownLatch;
   51.41 +import java.util.concurrent.LinkedBlockingQueue;
   51.42 +import java.util.concurrent.TimeUnit;
   51.43 +import java.util.logging.Level;
   51.44 +import java.util.logging.Logger;
   51.45 +import org.apidesign.vm4brwsr.Bck2Brwsr;
   51.46 +import org.glassfish.grizzly.PortRange;
   51.47 +import org.glassfish.grizzly.http.server.HttpHandler;
   51.48 +import org.glassfish.grizzly.http.server.HttpServer;
   51.49 +import org.glassfish.grizzly.http.server.NetworkListener;
   51.50 +import org.glassfish.grizzly.http.server.Request;
   51.51 +import org.glassfish.grizzly.http.server.Response;
   51.52 +import org.glassfish.grizzly.http.server.ServerConfiguration;
   51.53 +
   51.54 +/**
   51.55 + * Lightweight server to launch Bck2Brwsr applications and tests.
   51.56 + * Supports execution in native browser as well as Java's internal 
   51.57 + * execution engine.
   51.58 + */
   51.59 +final class Bck2BrwsrLauncher extends Launcher implements Closeable {
   51.60 +    private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
   51.61 +    private static final MethodInvocation END = new MethodInvocation(null, null);
   51.62 +    private Set<ClassLoader> loaders = new LinkedHashSet<>();
   51.63 +    private BlockingQueue<MethodInvocation> methods = new LinkedBlockingQueue<>();
   51.64 +    private long timeOut;
   51.65 +    private final Res resources = new Res();
   51.66 +    private final String cmd;
   51.67 +    private Object[] brwsr;
   51.68 +    private HttpServer server;
   51.69 +    private CountDownLatch wait;
   51.70 +
   51.71 +    public Bck2BrwsrLauncher(String cmd) {
   51.72 +        this.cmd = cmd;
   51.73 +    }
   51.74 +    
   51.75 +    @Override
   51.76 +    public MethodInvocation addMethod(Class<?> clazz, String method) throws IOException {
   51.77 +        loaders.add(clazz.getClassLoader());
   51.78 +        MethodInvocation c = new MethodInvocation(clazz.getName(), method);
   51.79 +        methods.add(c);
   51.80 +        try {
   51.81 +            c.await(timeOut);
   51.82 +        } catch (InterruptedException ex) {
   51.83 +            throw new IOException(ex);
   51.84 +        }
   51.85 +        return c;
   51.86 +    }
   51.87 +    
   51.88 +    public void setTimeout(long ms) {
   51.89 +        timeOut = ms;
   51.90 +    }
   51.91 +    
   51.92 +    public void addClassLoader(ClassLoader url) {
   51.93 +        this.loaders.add(url);
   51.94 +    }
   51.95 +
   51.96 +    public void showURL(String startpage) throws IOException {
   51.97 +        if (!startpage.startsWith("/")) {
   51.98 +            startpage = "/" + startpage;
   51.99 +        }
  51.100 +        HttpServer s = initServer();
  51.101 +        s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
  51.102 +        try {
  51.103 +            launchServerAndBrwsr(s, startpage);
  51.104 +        } catch (URISyntaxException | InterruptedException ex) {
  51.105 +            throw new IOException(ex);
  51.106 +        }
  51.107 +    }
  51.108 +
  51.109 +    @Override
  51.110 +    public void initialize() throws IOException {
  51.111 +        try {
  51.112 +            executeInBrowser();
  51.113 +        } catch (InterruptedException ex) {
  51.114 +            final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
  51.115 +            iio.initCause(ex);
  51.116 +            throw iio;
  51.117 +        } catch (Exception ex) {
  51.118 +            if (ex instanceof IOException) {
  51.119 +                throw (IOException)ex;
  51.120 +            }
  51.121 +            if (ex instanceof RuntimeException) {
  51.122 +                throw (RuntimeException)ex;
  51.123 +            }
  51.124 +            throw new IOException(ex);
  51.125 +        }
  51.126 +    }
  51.127 +    
  51.128 +    private HttpServer initServer() {
  51.129 +        HttpServer s = HttpServer.createSimpleServer(".", new PortRange(8080, 65535));
  51.130 +
  51.131 +        final ServerConfiguration conf = s.getServerConfiguration();
  51.132 +        conf.addHttpHandler(new Page(resources, 
  51.133 +            "org/apidesign/bck2brwsr/launcher/console.xhtml",
  51.134 +            "org.apidesign.bck2brwsr.launcher.Console", "welcome", "false"
  51.135 +        ), "/console");
  51.136 +        conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
  51.137 +        conf.addHttpHandler(new VMInit(), "/vm.js");
  51.138 +        conf.addHttpHandler(new Classes(resources), "/classes/");
  51.139 +        return s;
  51.140 +    }
  51.141 +    
  51.142 +    private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
  51.143 +        wait = new CountDownLatch(1);
  51.144 +        server = initServer();
  51.145 +        ServerConfiguration conf = server.getServerConfiguration();
  51.146 +        conf.addHttpHandler(new Page(resources, 
  51.147 +            "org/apidesign/bck2brwsr/launcher/harness.xhtml"
  51.148 +        ), "/execute");
  51.149 +        conf.addHttpHandler(new HttpHandler() {
  51.150 +            int cnt;
  51.151 +            List<MethodInvocation> cases = new ArrayList<>();
  51.152 +            @Override
  51.153 +            public void service(Request request, Response response) throws Exception {
  51.154 +                String id = request.getParameter("request");
  51.155 +                String value = request.getParameter("result");
  51.156 +                
  51.157 +                if (id != null && value != null) {
  51.158 +                    LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
  51.159 +                    value = decodeURL(value);
  51.160 +                    cases.get(Integer.parseInt(id)).result(value, null);
  51.161 +                }
  51.162 +                
  51.163 +                MethodInvocation mi = methods.take();
  51.164 +                if (mi == END) {
  51.165 +                    response.getWriter().write("");
  51.166 +                    wait.countDown();
  51.167 +                    cnt = 0;
  51.168 +                    LOG.log(Level.INFO, "End of data reached. Exiting.");
  51.169 +                    return;
  51.170 +                }
  51.171 +                
  51.172 +                cases.add(mi);
  51.173 +                final String cn = mi.className;
  51.174 +                final String mn = mi.methodName;
  51.175 +                LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{cnt, cn, mn});
  51.176 +                response.getWriter().write("{"
  51.177 +                    + "className: '" + cn + "', "
  51.178 +                    + "methodName: '" + mn + "', "
  51.179 +                    + "request: " + cnt
  51.180 +                    + "}");
  51.181 +                cnt++;
  51.182 +            }
  51.183 +        }, "/data");
  51.184 +
  51.185 +        this.brwsr = launchServerAndBrwsr(server, "/execute");
  51.186 +    }
  51.187 +    
  51.188 +    @Override
  51.189 +    public void shutdown() throws IOException {
  51.190 +        methods.offer(END);
  51.191 +        for (;;) {
  51.192 +            int prev = methods.size();
  51.193 +            try {
  51.194 +                if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) {
  51.195 +                    break;
  51.196 +                }
  51.197 +            } catch (InterruptedException ex) {
  51.198 +                throw new IOException(ex);
  51.199 +            }
  51.200 +            if (prev == methods.size()) {
  51.201 +                LOG.log(
  51.202 +                    Level.WARNING, 
  51.203 +                    "Timeout and no test has been executed meanwhile (at {0}). Giving up.", 
  51.204 +                    methods.size()
  51.205 +                );
  51.206 +                break;
  51.207 +            }
  51.208 +            LOG.log(Level.INFO, 
  51.209 +                "Timeout, but tests got from {0} to {1}. Trying again.", 
  51.210 +                new Object[]{prev, methods.size()}
  51.211 +            );
  51.212 +        }
  51.213 +        stopServerAndBrwsr(server, brwsr);
  51.214 +    }
  51.215 +    
  51.216 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
  51.217 +        for (;;) {
  51.218 +            int ch = is.read();
  51.219 +            if (ch == -1) {
  51.220 +                break;
  51.221 +            }
  51.222 +            if (ch == '$') {
  51.223 +                int cnt = is.read() - '0';
  51.224 +                if (cnt == 'U' - '0') {
  51.225 +                    os.write(baseURL.getBytes());
  51.226 +                }
  51.227 +                if (cnt < params.length) {
  51.228 +                    os.write(params[cnt].getBytes());
  51.229 +                }
  51.230 +            } else {
  51.231 +                os.write(ch);
  51.232 +            }
  51.233 +        }
  51.234 +    }
  51.235 +
  51.236 +    private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
  51.237 +        server.start();
  51.238 +        NetworkListener listener = server.getListeners().iterator().next();
  51.239 +        int port = listener.getPort();
  51.240 +        
  51.241 +        URI uri = new URI("http://localhost:" + port + page);
  51.242 +        LOG.log(Level.INFO, "Showing {0}", uri);
  51.243 +        if (cmd == null) {
  51.244 +            try {
  51.245 +                java.awt.Desktop.getDesktop().browse(uri);
  51.246 +                LOG.log(Level.INFO, "Desktop.browse successfully finished");
  51.247 +                return null;
  51.248 +            } catch (UnsupportedOperationException ex) {
  51.249 +                LOG.log(Level.INFO, "Desktop.browse not supported", ex);
  51.250 +            }
  51.251 +        }
  51.252 +        {
  51.253 +            String cmdName = cmd == null ? "xdg-open" : cmd;
  51.254 +            String[] cmdArr = { 
  51.255 +                cmdName, uri.toString()
  51.256 +            };
  51.257 +            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
  51.258 +            final Process process = Runtime.getRuntime().exec(cmdArr);
  51.259 +            return new Object[] { process, null };
  51.260 +        }
  51.261 +    }
  51.262 +    
  51.263 +    private static String decodeURL(String s) {
  51.264 +        for (;;) {
  51.265 +            int pos = s.indexOf('%');
  51.266 +            if (pos == -1) {
  51.267 +                return s;
  51.268 +            }
  51.269 +            int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16);
  51.270 +            s = s.substring(0, pos) + (char)i + s.substring(pos + 2);
  51.271 +        }
  51.272 +    }
  51.273 +    
  51.274 +    private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException {
  51.275 +        if (brwsr == null) {
  51.276 +            return;
  51.277 +        }
  51.278 +        Process process = (Process)brwsr[0];
  51.279 +        
  51.280 +        server.stop();
  51.281 +        InputStream stdout = process.getInputStream();
  51.282 +        InputStream stderr = process.getErrorStream();
  51.283 +        drain("StdOut", stdout);
  51.284 +        drain("StdErr", stderr);
  51.285 +        process.destroy();
  51.286 +        int res;
  51.287 +        try {
  51.288 +            res = process.waitFor();
  51.289 +        } catch (InterruptedException ex) {
  51.290 +            throw new IOException(ex);
  51.291 +        }
  51.292 +        LOG.log(Level.INFO, "Exit code: {0}", res);
  51.293 +
  51.294 +        deleteTree((File)brwsr[1]);
  51.295 +    }
  51.296 +    
  51.297 +    private static void drain(String name, InputStream is) throws IOException {
  51.298 +        int av = is.available();
  51.299 +        if (av > 0) {
  51.300 +            StringBuilder sb = new StringBuilder();
  51.301 +            sb.append("v== ").append(name).append(" ==v\n");
  51.302 +            while (av-- > 0) {
  51.303 +                sb.append((char)is.read());
  51.304 +            }
  51.305 +            sb.append("\n^== ").append(name).append(" ==^");
  51.306 +            LOG.log(Level.INFO, sb.toString());
  51.307 +        }
  51.308 +    }
  51.309 +
  51.310 +    private void deleteTree(File file) {
  51.311 +        if (file == null) {
  51.312 +            return;
  51.313 +        }
  51.314 +        File[] arr = file.listFiles();
  51.315 +        if (arr != null) {
  51.316 +            for (File s : arr) {
  51.317 +                deleteTree(s);
  51.318 +            }
  51.319 +        }
  51.320 +        file.delete();
  51.321 +    }
  51.322 +
  51.323 +    @Override
  51.324 +    public void close() throws IOException {
  51.325 +        shutdown();
  51.326 +    }
  51.327 +
  51.328 +    private class Res implements Bck2Brwsr.Resources {
  51.329 +        @Override
  51.330 +        public InputStream get(String resource) throws IOException {
  51.331 +            for (ClassLoader l : loaders) {
  51.332 +                URL u = null;
  51.333 +                Enumeration<URL> en = l.getResources(resource);
  51.334 +                while (en.hasMoreElements()) {
  51.335 +                    u = en.nextElement();
  51.336 +                }
  51.337 +                if (u != null) {
  51.338 +                    return u.openStream();
  51.339 +                }
  51.340 +            }
  51.341 +            throw new IOException("Can't find " + resource);
  51.342 +        }
  51.343 +    }
  51.344 +
  51.345 +    private static class Page extends HttpHandler {
  51.346 +        private final String resource;
  51.347 +        private final String[] args;
  51.348 +        private final Res res;
  51.349 +        
  51.350 +        public Page(Res res, String resource, String... args) {
  51.351 +            this.res = res;
  51.352 +            this.resource = resource;
  51.353 +            this.args = args;
  51.354 +        }
  51.355 +
  51.356 +        @Override
  51.357 +        public void service(Request request, Response response) throws Exception {
  51.358 +            String r = resource;
  51.359 +            if (r == null) {
  51.360 +                r = request.getHttpHandlerPath();
  51.361 +                if (r.startsWith("/")) {
  51.362 +                    r = r.substring(1);
  51.363 +                }
  51.364 +            }
  51.365 +            if (r.endsWith(".html")) {
  51.366 +                response.setContentType("text/html");
  51.367 +                LOG.info("Content type text/html");
  51.368 +            }
  51.369 +            if (r.endsWith(".xhtml")) {
  51.370 +                response.setContentType("application/xhtml+xml");
  51.371 +                LOG.info("Content type application/xhtml+xml");
  51.372 +            }
  51.373 +            OutputStream os = response.getOutputStream();
  51.374 +            try (InputStream is = res.get(r)) {
  51.375 +                copyStream(is, os, request.getRequestURL().toString(), args);
  51.376 +            } catch (IOException ex) {
  51.377 +                response.setDetailMessage(ex.getLocalizedMessage());
  51.378 +                response.setError();
  51.379 +                response.setStatus(404);
  51.380 +            }
  51.381 +        }
  51.382 +    }
  51.383 +
  51.384 +    private static class VM extends HttpHandler {
  51.385 +        private final Res loader;
  51.386 +
  51.387 +        public VM(Res loader) {
  51.388 +            this.loader = loader;
  51.389 +        }
  51.390 +
  51.391 +        @Override
  51.392 +        public void service(Request request, Response response) throws Exception {
  51.393 +            response.setCharacterEncoding("UTF-8");
  51.394 +            response.setContentType("text/javascript");
  51.395 +            Bck2Brwsr.generate(response.getWriter(), loader);
  51.396 +        }
  51.397 +    }
  51.398 +    private static class VMInit extends HttpHandler {
  51.399 +        public VMInit() {
  51.400 +        }
  51.401 +
  51.402 +        @Override
  51.403 +        public void service(Request request, Response response) throws Exception {
  51.404 +            response.setCharacterEncoding("UTF-8");
  51.405 +            response.setContentType("text/javascript");
  51.406 +            response.getWriter().append(
  51.407 +                "function ldCls(res) {\n"
  51.408 +                + "  var request = new XMLHttpRequest();\n"
  51.409 +                + "  request.open('GET', '/classes/' + res, false);\n"
  51.410 +                + "  request.send();\n"
  51.411 +                + "  var arr = eval('(' + request.responseText + ')');\n"
  51.412 +                + "  return arr;\n"
  51.413 +                + "}\n"
  51.414 +                + "var vm = new bck2brwsr(ldCls);\n");
  51.415 +        }
  51.416 +    }
  51.417 +
  51.418 +    private static class Classes extends HttpHandler {
  51.419 +        private final Res loader;
  51.420 +
  51.421 +        public Classes(Res loader) {
  51.422 +            this.loader = loader;
  51.423 +        }
  51.424 +
  51.425 +        @Override
  51.426 +        public void service(Request request, Response response) throws Exception {
  51.427 +            String res = request.getHttpHandlerPath();
  51.428 +            if (res.startsWith("/")) {
  51.429 +                res = res.substring(1);
  51.430 +            }
  51.431 +            try (InputStream is = loader.get(res)) {
  51.432 +                response.setContentType("text/javascript");
  51.433 +                Writer w = response.getWriter();
  51.434 +                w.append("[");
  51.435 +                for (int i = 0;; i++) {
  51.436 +                    int b = is.read();
  51.437 +                    if (b == -1) {
  51.438 +                        break;
  51.439 +                    }
  51.440 +                    if (i > 0) {
  51.441 +                        w.append(", ");
  51.442 +                    }
  51.443 +                    if (i % 20 == 0) {
  51.444 +                        w.write("\n");
  51.445 +                    }
  51.446 +                    if (b > 127) {
  51.447 +                        b = b - 256;
  51.448 +                    }
  51.449 +                    w.append(Integer.toString(b));
  51.450 +                }
  51.451 +                w.append("\n]");
  51.452 +            } catch (IOException ex) {
  51.453 +                response.setError();
  51.454 +                response.setDetailMessage(ex.getMessage());
  51.455 +            }
  51.456 +        }
  51.457 +    }
  51.458 +}
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Console.java	Fri Jan 18 14:27:22 2013 +0100
    52.3 @@ -0,0 +1,208 @@
    52.4 +/**
    52.5 + * Back 2 Browser Bytecode Translator
    52.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    52.7 + *
    52.8 + * This program is free software: you can redistribute it and/or modify
    52.9 + * it under the terms of the GNU General Public License as published by
   52.10 + * the Free Software Foundation, version 2 of the License.
   52.11 + *
   52.12 + * This program is distributed in the hope that it will be useful,
   52.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.15 + * GNU General Public License for more details.
   52.16 + *
   52.17 + * You should have received a copy of the GNU General Public License
   52.18 + * along with this program. Look for COPYING file in the top folder.
   52.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   52.20 + */
   52.21 +package org.apidesign.bck2brwsr.launcher;
   52.22 +
   52.23 +import java.io.IOException;
   52.24 +import java.io.InputStream;
   52.25 +import java.lang.reflect.InvocationTargetException;
   52.26 +import java.lang.reflect.Method;
   52.27 +import java.lang.reflect.Modifier;
   52.28 +import java.net.URL;
   52.29 +import java.util.Enumeration;
   52.30 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   52.31 +
   52.32 +/**
   52.33 + *
   52.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   52.35 + */
   52.36 +public class Console {
   52.37 +    public static String welcome() {
   52.38 +        return "HellofromBck2Brwsr";
   52.39 +    }
   52.40 +    public static String multiply() {
   52.41 +        return String.valueOf(Integer.MAX_VALUE / 2 + Integer.MAX_VALUE);
   52.42 +    }
   52.43 +    
   52.44 +    @JavaScriptBody(args = {"id", "attr"}, body = 
   52.45 +        "return window.document.getElementById(id)[attr].toString();")
   52.46 +    private static native Object getAttr(String id, String attr);
   52.47 +
   52.48 +    @JavaScriptBody(args = {"id", "attr", "value"}, body = 
   52.49 +        "window.document.getElementById(id)[attr] = value;")
   52.50 +    private static native void setAttr(String id, String attr, Object value);
   52.51 +    
   52.52 +    @JavaScriptBody(args = {}, body = "return; window.close();")
   52.53 +    private static native void closeWindow();
   52.54 +
   52.55 +    private static void log(String newText) {
   52.56 +        String id = "result";
   52.57 +        String attr = "value";
   52.58 +        setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
   52.59 +        setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
   52.60 +    }
   52.61 +    
   52.62 +    public static void execute() throws Exception {
   52.63 +        String clazz = (String) getAttr("clazz", "value");
   52.64 +        String method = (String) getAttr("method", "value");
   52.65 +        Object res = invokeMethod(clazz, method);
   52.66 +        setAttr("result", "value", res);
   52.67 +    }
   52.68 +    
   52.69 +    public static void harness(String url) {
   52.70 +        log("Connecting to " + url);
   52.71 +        try {
   52.72 +            URL u = new URL(url);
   52.73 +            for (;;) {
   52.74 +                String data = (String) u.getContent(new Class[] { String.class });
   52.75 +                log("\nGot \"" + data + "\"");
   52.76 +                if (data.isEmpty()) {
   52.77 +                    log("No data, exiting");
   52.78 +                    closeWindow();
   52.79 +                    break;
   52.80 +                }
   52.81 +                
   52.82 +                Case c = Case.parseData(data);
   52.83 +                log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
   52.84 +
   52.85 +                Object result = invokeMethod(c.getClassName(), c.getMethodName());
   52.86 +                
   52.87 +                log("Result: " + result);
   52.88 +                
   52.89 +                result = encodeURL("" + result);
   52.90 +                
   52.91 +                log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
   52.92 +                u = new URL(url + "?request=" + c.getRequestId() + "&result=" + result);
   52.93 +            }
   52.94 +            
   52.95 +            
   52.96 +        } catch (Exception ex) {
   52.97 +            log(ex.getMessage());
   52.98 +        }
   52.99 +    }
  52.100 +    
  52.101 +    private static String encodeURL(String r) {
  52.102 +        StringBuilder sb = new StringBuilder();
  52.103 +        for (int i = 0; i < r.length(); i++) {
  52.104 +            int ch = r.charAt(i);
  52.105 +            if (ch < 32 || ch == '%' || ch == '+') {
  52.106 +                sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
  52.107 +            } else {
  52.108 +                if (ch == 32) {
  52.109 +                    sb.append("+");
  52.110 +                } else {
  52.111 +                    sb.append((char)ch);
  52.112 +                }
  52.113 +            }
  52.114 +        }
  52.115 +        return sb.toString();
  52.116 +    }
  52.117 +    
  52.118 +    static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
  52.119 +        final Object r = invokeMethod(clazz, method);
  52.120 +        return r == null ? "null" : r.toString().toString();
  52.121 +    }
  52.122 +
  52.123 +    /** Helper method that inspects the classpath and loads given resource
  52.124 +     * (usually a class file). Used while running tests in Rhino.
  52.125 +     * 
  52.126 +     * @param name resource name to find
  52.127 +     * @return the array of bytes in the given resource
  52.128 +     * @throws IOException I/O in case something goes wrong
  52.129 +     */
  52.130 +    public static byte[] read(String name) throws IOException {
  52.131 +        URL u = null;
  52.132 +        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
  52.133 +        while (en.hasMoreElements()) {
  52.134 +            u = en.nextElement();
  52.135 +        }
  52.136 +        if (u == null) {
  52.137 +            throw new IOException("Can't find " + name);
  52.138 +        }
  52.139 +        try (InputStream is = u.openStream()) {
  52.140 +            byte[] arr;
  52.141 +            arr = new byte[is.available()];
  52.142 +            int offset = 0;
  52.143 +            while (offset < arr.length) {
  52.144 +                int len = is.read(arr, offset, arr.length - offset);
  52.145 +                if (len == -1) {
  52.146 +                    throw new IOException("Can't read " + name);
  52.147 +                }
  52.148 +                offset += len;
  52.149 +            }
  52.150 +            return arr;
  52.151 +        }
  52.152 +    }
  52.153 +   
  52.154 +    private static Object invokeMethod(String clazz, String method) 
  52.155 +    throws ClassNotFoundException, InvocationTargetException, 
  52.156 +    SecurityException, IllegalAccessException, IllegalArgumentException,
  52.157 +    InstantiationException {
  52.158 +        Method found = null;
  52.159 +        Class<?> c = Class.forName(clazz);
  52.160 +        for (Method m : c.getMethods()) {
  52.161 +            if (m.getName().equals(method)) {
  52.162 +                found = m;
  52.163 +            }
  52.164 +        }
  52.165 +        Object res;
  52.166 +        if (found != null) {
  52.167 +            try {
  52.168 +                if ((found.getModifiers() & Modifier.STATIC) != 0) {
  52.169 +                    res = found.invoke(null);
  52.170 +                } else {
  52.171 +                    res = found.invoke(c.newInstance());
  52.172 +                }
  52.173 +            } catch (Exception ex) {
  52.174 +                res = ex.getClass().getName() + ":" + ex.getMessage();
  52.175 +            }
  52.176 +        } else {
  52.177 +            res = "Can't find method " + method + " in " + clazz;
  52.178 +        }
  52.179 +        return res;
  52.180 +    }
  52.181 +    
  52.182 +    private static final class Case {
  52.183 +        private final Object data;
  52.184 +
  52.185 +        private Case(Object data) {
  52.186 +            this.data = data;
  52.187 +        }
  52.188 +        
  52.189 +        public static Case parseData(String s) {
  52.190 +            return new Case(toJSON(s));
  52.191 +        }
  52.192 +        
  52.193 +        public String getMethodName() {
  52.194 +            return value("methodName", data);
  52.195 +        }
  52.196 +
  52.197 +        public String getClassName() {
  52.198 +            return value("className", data);
  52.199 +        }
  52.200 +        
  52.201 +        public String getRequestId() {
  52.202 +            return value("request", data);
  52.203 +        }
  52.204 +        
  52.205 +        @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
  52.206 +        private static native Object toJSON(String s);
  52.207 +        
  52.208 +        @JavaScriptBody(args = {"p", "d"}, body = "return d[p].toString();")
  52.209 +        private static native String value(String p, Object d);
  52.210 +    }
  52.211 +}
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Fri Jan 18 14:27:22 2013 +0100
    53.3 @@ -0,0 +1,127 @@
    53.4 +/**
    53.5 + * Back 2 Browser Bytecode Translator
    53.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    53.7 + *
    53.8 + * This program is free software: you can redistribute it and/or modify
    53.9 + * it under the terms of the GNU General Public License as published by
   53.10 + * the Free Software Foundation, version 2 of the License.
   53.11 + *
   53.12 + * This program is distributed in the hope that it will be useful,
   53.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   53.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   53.15 + * GNU General Public License for more details.
   53.16 + *
   53.17 + * You should have received a copy of the GNU General Public License
   53.18 + * along with this program. Look for COPYING file in the top folder.
   53.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   53.20 + */
   53.21 +package org.apidesign.bck2brwsr.launcher;
   53.22 +
   53.23 +import java.io.IOException;
   53.24 +import java.io.InputStream;
   53.25 +import java.net.URL;
   53.26 +import java.util.Enumeration;
   53.27 +import java.util.LinkedHashSet;
   53.28 +import java.util.Set;
   53.29 +import java.util.logging.Logger;
   53.30 +import javax.script.Invocable;
   53.31 +import javax.script.ScriptEngine;
   53.32 +import javax.script.ScriptEngineManager;
   53.33 +import javax.script.ScriptException;
   53.34 +import org.apidesign.vm4brwsr.Bck2Brwsr;
   53.35 +
   53.36 +/**
   53.37 + * Tests execution in Java's internal scripting engine.
   53.38 + */
   53.39 +final class JSLauncher extends Launcher {
   53.40 +    private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
   53.41 +    private Set<ClassLoader> loaders = new LinkedHashSet<>();
   53.42 +    private final Res resources = new Res();
   53.43 +    private Invocable code;
   53.44 +    private StringBuilder codeSeq;
   53.45 +    private Object console;
   53.46 +    
   53.47 +    
   53.48 +    @Override
   53.49 +    public MethodInvocation addMethod(Class<?> clazz, String method) {
   53.50 +        loaders.add(clazz.getClassLoader());
   53.51 +        MethodInvocation mi = new MethodInvocation(clazz.getName(), method);
   53.52 +        try {
   53.53 +            mi.result(code.invokeMethod(
   53.54 +                console,
   53.55 +                "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
   53.56 +                mi.className, mi.methodName).toString(), null);
   53.57 +        } catch (ScriptException | NoSuchMethodException ex) {
   53.58 +            mi.result(null, ex);
   53.59 +        }
   53.60 +        return mi;
   53.61 +    }
   53.62 +    
   53.63 +    public void addClassLoader(ClassLoader url) {
   53.64 +        this.loaders.add(url);
   53.65 +    }
   53.66 +
   53.67 +    @Override
   53.68 +    public void initialize() throws IOException {
   53.69 +        try {
   53.70 +            initRhino();
   53.71 +        } catch (Exception ex) {
   53.72 +            if (ex instanceof IOException) {
   53.73 +                throw (IOException)ex;
   53.74 +            }
   53.75 +            if (ex instanceof RuntimeException) {
   53.76 +                throw (RuntimeException)ex;
   53.77 +            }
   53.78 +            throw new IOException(ex);
   53.79 +        }
   53.80 +    }
   53.81 +    
   53.82 +    private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
   53.83 +        StringBuilder sb = new StringBuilder();
   53.84 +        Bck2Brwsr.generate(sb, new Res());
   53.85 +
   53.86 +        ScriptEngineManager sem = new ScriptEngineManager();
   53.87 +        ScriptEngine mach = sem.getEngineByExtension("js");
   53.88 +
   53.89 +        sb.append(
   53.90 +              "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.Console.read);"
   53.91 +            + "\nfunction initVM() { return vm; };"
   53.92 +            + "\n");
   53.93 +
   53.94 +        Object res = mach.eval(sb.toString());
   53.95 +        if (!(mach instanceof Invocable)) {
   53.96 +            throw new IOException("It is invocable object: " + res);
   53.97 +        }
   53.98 +        code = (Invocable) mach;
   53.99 +        codeSeq = sb;
  53.100 +        
  53.101 +        Object vm = code.invokeFunction("initVM");
  53.102 +        console = code.invokeMethod(vm, "loadClass", Console.class.getName());
  53.103 +    }
  53.104 +
  53.105 +    @Override
  53.106 +    public void shutdown() throws IOException {
  53.107 +    }
  53.108 +
  53.109 +    @Override
  53.110 +    public String toString() {
  53.111 +        return codeSeq.toString();
  53.112 +    }
  53.113 +    
  53.114 +    private class Res implements Bck2Brwsr.Resources {
  53.115 +        @Override
  53.116 +        public InputStream get(String resource) throws IOException {
  53.117 +            for (ClassLoader l : loaders) {
  53.118 +                URL u = null;
  53.119 +                Enumeration<URL> en = l.getResources(resource);
  53.120 +                while (en.hasMoreElements()) {
  53.121 +                    u = en.nextElement();
  53.122 +                }
  53.123 +                if (u != null) {
  53.124 +                    return u.openStream();
  53.125 +                }
  53.126 +            }
  53.127 +            throw new IOException("Can't find " + resource);
  53.128 +        }
  53.129 +    }
  53.130 +}
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Fri Jan 18 14:27:22 2013 +0100
    54.3 @@ -0,0 +1,63 @@
    54.4 +/**
    54.5 + * Back 2 Browser Bytecode Translator
    54.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    54.7 + *
    54.8 + * This program is free software: you can redistribute it and/or modify
    54.9 + * it under the terms of the GNU General Public License as published by
   54.10 + * the Free Software Foundation, version 2 of the License.
   54.11 + *
   54.12 + * This program is distributed in the hope that it will be useful,
   54.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   54.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   54.15 + * GNU General Public License for more details.
   54.16 + *
   54.17 + * You should have received a copy of the GNU General Public License
   54.18 + * along with this program. Look for COPYING file in the top folder.
   54.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   54.20 + */
   54.21 +package org.apidesign.bck2brwsr.launcher;
   54.22 +
   54.23 +import java.io.Closeable;
   54.24 +import java.io.IOException;
   54.25 +import java.net.URLClassLoader;
   54.26 +import org.apidesign.vm4brwsr.Bck2Brwsr;
   54.27 +
   54.28 +/** An abstraction for executing tests in a Bck2Brwsr virtual machine.
   54.29 + * Either in JavaScript engine, or in external browser.
   54.30 + *
   54.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   54.32 + */
   54.33 +public abstract class Launcher {
   54.34 +
   54.35 +    Launcher() {
   54.36 +    }
   54.37 +    
   54.38 +    abstract MethodInvocation addMethod(Class<?> clazz, String method) throws IOException; 
   54.39 +
   54.40 +    public abstract void initialize() throws IOException;
   54.41 +    public abstract void shutdown() throws IOException;
   54.42 +    public MethodInvocation invokeMethod(Class<?> clazz, String method) throws IOException {
   54.43 +        return addMethod(clazz, method);
   54.44 +    }
   54.45 +    
   54.46 +    
   54.47 +
   54.48 +    public static Launcher createJavaScript() {
   54.49 +        final JSLauncher l = new JSLauncher();
   54.50 +        l.addClassLoader(Bck2Brwsr.class.getClassLoader());
   54.51 +        return l;
   54.52 +    }
   54.53 +    
   54.54 +    public static Launcher createBrowser(String cmd) {
   54.55 +        final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
   54.56 +        l.addClassLoader(Bck2Brwsr.class.getClassLoader());
   54.57 +        l.setTimeout(180000);
   54.58 +        return l;
   54.59 +    }
   54.60 +    public static Closeable showURL(URLClassLoader classes, String startpage) throws IOException {
   54.61 +        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
   54.62 +        l.addClassLoader(classes);
   54.63 +        l.showURL(startpage);
   54.64 +        return l;
   54.65 +    }
   54.66 +}
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/MethodInvocation.java	Fri Jan 18 14:27:22 2013 +0100
    55.3 @@ -0,0 +1,57 @@
    55.4 +/**
    55.5 + * Back 2 Browser Bytecode Translator
    55.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    55.7 + *
    55.8 + * This program is free software: you can redistribute it and/or modify
    55.9 + * it under the terms of the GNU General Public License as published by
   55.10 + * the Free Software Foundation, version 2 of the License.
   55.11 + *
   55.12 + * This program is distributed in the hope that it will be useful,
   55.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.15 + * GNU General Public License for more details.
   55.16 + *
   55.17 + * You should have received a copy of the GNU General Public License
   55.18 + * along with this program. Look for COPYING file in the top folder.
   55.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   55.20 + */
   55.21 +package org.apidesign.bck2brwsr.launcher;
   55.22 +
   55.23 +import java.util.concurrent.CountDownLatch;
   55.24 +import java.util.concurrent.TimeUnit;
   55.25 +
   55.26 +/**
   55.27 + *
   55.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   55.29 + */
   55.30 +public final class MethodInvocation {
   55.31 +    final CountDownLatch wait = new CountDownLatch(1);
   55.32 +    final String className;
   55.33 +    final String methodName;
   55.34 +    private String result;
   55.35 +    private Throwable exception;
   55.36 +
   55.37 +    MethodInvocation(String className, String methodName) {
   55.38 +        this.className = className;
   55.39 +        this.methodName = methodName;
   55.40 +    }
   55.41 +    
   55.42 +    void await(long timeOut) throws InterruptedException {
   55.43 +        wait.await(timeOut, TimeUnit.MILLISECONDS);
   55.44 +    }
   55.45 +    
   55.46 +    void result(String r, Throwable e) {
   55.47 +        this.result = r;
   55.48 +        this.exception = e;
   55.49 +        wait.countDown();
   55.50 +    }
   55.51 +
   55.52 +    @Override
   55.53 +    public String toString() {
   55.54 +        if (exception != null) {
   55.55 +            return exception.toString();
   55.56 +        }
   55.57 +        return result;
   55.58 +    }
   55.59 +    
   55.60 +}
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/console.xhtml	Fri Jan 18 14:27:22 2013 +0100
    56.3 @@ -0,0 +1,52 @@
    56.4 +<?xml version="1.0" encoding="UTF-8"?>
    56.5 +<!--
    56.6 +
    56.7 +    Back 2 Browser Bytecode Translator
    56.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    56.9 +
   56.10 +    This program is free software: you can redistribute it and/or modify
   56.11 +    it under the terms of the GNU General Public License as published by
   56.12 +    the Free Software Foundation, version 2 of the License.
   56.13 +
   56.14 +    This program is distributed in the hope that it will be useful,
   56.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   56.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   56.17 +    GNU General Public License for more details.
   56.18 +
   56.19 +    You should have received a copy of the GNU General Public License
   56.20 +    along with this program. Look for COPYING file in the top folder.
   56.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   56.22 +
   56.23 +-->
   56.24 +<!DOCTYPE html>
   56.25 +<html xmlns="http://www.w3.org/1999/xhtml">
   56.26 +    <head>
   56.27 +        <title>Bck2Brwsr Launcher</title>
   56.28 +    </head>
   56.29 +    <body>
   56.30 +        <script src="/bck2brwsr.js"></script>
   56.31 +        <script src="/vm.js"></script>
   56.32 +        
   56.33 +        <h1>Bck2Browser Console Launcher</h1>
   56.34 +        
   56.35 +        Class Name:
   56.36 +        <input id="clazz" value="$0"/>
   56.37 +        <br/>
   56.38 +        Method Name:
   56.39 +
   56.40 +        <input id="method" value="$1"/>
   56.41 +        <br/>
   56.42 +        
   56.43 +        <button onclick="vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').execute__V();">Execute!</button>
   56.44 +        
   56.45 +        <hr/>
   56.46 +        <textarea id="result" rows="10" cols="80" disabled="">
   56.47 +        </textarea>
   56.48 +        
   56.49 +        <script type="text/javascript">
   56.50 +            if ($2) {
   56.51 +                vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').execute__V();
   56.52 +            }
   56.53 +        </script>
   56.54 +    </body>
   56.55 +</html>
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Fri Jan 18 14:27:22 2013 +0100
    57.3 @@ -0,0 +1,39 @@
    57.4 +<?xml version="1.0" encoding="UTF-8"?>
    57.5 +<!--
    57.6 +
    57.7 +    Back 2 Browser Bytecode Translator
    57.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    57.9 +
   57.10 +    This program is free software: you can redistribute it and/or modify
   57.11 +    it under the terms of the GNU General Public License as published by
   57.12 +    the Free Software Foundation, version 2 of the License.
   57.13 +
   57.14 +    This program is distributed in the hope that it will be useful,
   57.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   57.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   57.17 +    GNU General Public License for more details.
   57.18 +
   57.19 +    You should have received a copy of the GNU General Public License
   57.20 +    along with this program. Look for COPYING file in the top folder.
   57.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   57.22 +
   57.23 +-->
   57.24 +<!DOCTYPE html>
   57.25 +<html xmlns="http://www.w3.org/1999/xhtml">
   57.26 +    <head>
   57.27 +        <title>Bck2Brwsr Harness</title>
   57.28 +    </head>
   57.29 +    <body>
   57.30 +        <script src="/bck2brwsr.js"></script>
   57.31 +        <script src="/vm.js"></script>
   57.32 +        
   57.33 +        <h1>Bck2Browser Execution Harness</h1>
   57.34 +        
   57.35 +        <textarea id="result" rows="25" style="width: 100%;" disabled="">
   57.36 +        </textarea>
   57.37 +        
   57.38 +        <script type="text/javascript">
   57.39 +            vm.loadClass('org.apidesign.bck2brwsr.launcher.Console').harness__VLjava_lang_String_2('$U/../data');
   57.40 +        </script>
   57.41 +    </body>
   57.42 +</html>
    58.1 --- a/mojo/pom.xml	Fri Jan 18 14:23:18 2013 +0100
    58.2 +++ b/mojo/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    58.3 @@ -11,7 +11,7 @@
    58.4    <artifactId>mojo</artifactId>
    58.5    <version>0.3-SNAPSHOT</version>
    58.6    <packaging>maven-plugin</packaging>
    58.7 -  <name>Maven Mojo to Compile to JavaScript</name>
    58.8 +  <name>Bck2Brwsr Maven Project</name>
    58.9    <url>http://maven.apache.org</url>
   58.10        <build>
   58.11          <plugins>
   58.12 @@ -77,5 +77,10 @@
   58.13        <version>3.0.2</version>
   58.14        <type>jar</type>
   58.15      </dependency>
   58.16 +    <dependency>
   58.17 +        <groupId>${project.groupId}</groupId>
   58.18 +        <artifactId>launcher</artifactId>
   58.19 +      <version>${project.version}</version>
   58.20 +    </dependency>
   58.21  </dependencies>
   58.22  </project>
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java	Fri Jan 18 14:27:22 2013 +0100
    59.3 @@ -0,0 +1,89 @@
    59.4 +/**
    59.5 + * Back 2 Browser Bytecode Translator
    59.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    59.7 + *
    59.8 + * This program is free software: you can redistribute it and/or modify
    59.9 + * it under the terms of the GNU General Public License as published by
   59.10 + * the Free Software Foundation, version 2 of the License.
   59.11 + *
   59.12 + * This program is distributed in the hope that it will be useful,
   59.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   59.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   59.15 + * GNU General Public License for more details.
   59.16 + *
   59.17 + * You should have received a copy of the GNU General Public License
   59.18 + * along with this program. Look for COPYING file in the top folder.
   59.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   59.20 + */
   59.21 +package org.apidesign.bck2brwsr.mojo;
   59.22 +
   59.23 +import java.io.Closeable;
   59.24 +import org.apache.maven.plugin.AbstractMojo;
   59.25 +
   59.26 +import java.io.File;
   59.27 +import java.io.IOException;
   59.28 +import java.net.MalformedURLException;
   59.29 +import java.net.URL;
   59.30 +import java.net.URLClassLoader;
   59.31 +import java.util.ArrayList;
   59.32 +import java.util.Collection;
   59.33 +import java.util.List;
   59.34 +import org.apache.maven.artifact.Artifact;
   59.35 +import org.apache.maven.plugin.MojoExecutionException;
   59.36 +import org.apache.maven.plugins.annotations.LifecyclePhase;
   59.37 +import org.apache.maven.plugins.annotations.Mojo;
   59.38 +import org.apache.maven.plugins.annotations.Parameter;
   59.39 +import org.apache.maven.project.MavenProject;
   59.40 +import org.apidesign.bck2brwsr.launcher.Launcher;
   59.41 +
   59.42 +/** Executes given HTML page in a browser. */
   59.43 +@Mojo(name="brwsr", defaultPhase=LifecyclePhase.DEPLOY)
   59.44 +public class BrswrMojo extends AbstractMojo {
   59.45 +    public BrswrMojo() {
   59.46 +    }
   59.47 +    /** Resource to show as initial page */
   59.48 +    @Parameter
   59.49 +    private String startpage;
   59.50 +
   59.51 +    @Parameter(defaultValue="${project}")
   59.52 +    private MavenProject prj;
   59.53 +    
   59.54 +    /** Root of the class files */
   59.55 +    @Parameter(defaultValue="${project.build.directory}/classes")
   59.56 +    private File classes;
   59.57 +
   59.58 +    @Override
   59.59 +    public void execute() throws MojoExecutionException {
   59.60 +        if (startpage == null) {
   59.61 +            throw new MojoExecutionException("You have to provide a start page");
   59.62 +        }
   59.63 +
   59.64 +        try {
   59.65 +            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
   59.66 +            
   59.67 +            Closeable httpServer;
   59.68 +            try {
   59.69 +                httpServer = Launcher.showURL(url, startpage());
   59.70 +            } catch (Exception ex) {
   59.71 +                throw new MojoExecutionException("Can't open " + startpage(), ex);
   59.72 +            }
   59.73 +            System.in.read();
   59.74 +            httpServer.close();
   59.75 +        } catch (IOException ex) {
   59.76 +            throw new MojoExecutionException("Can't show the browser", ex);
   59.77 +        }
   59.78 +    }
   59.79 +    
   59.80 +    private String startpage() {
   59.81 +        return startpage;
   59.82 +    }
   59.83 +
   59.84 +    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
   59.85 +        List<URL> arr = new ArrayList<URL>();
   59.86 +        arr.add(root.toURI().toURL());
   59.87 +        for (Artifact a : deps) {
   59.88 +            arr.add(a.getFile().toURI().toURL());
   59.89 +        }
   59.90 +        return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader());
   59.91 +    }
   59.92 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml	Fri Jan 18 14:27:22 2013 +0100
    60.3 @@ -0,0 +1,42 @@
    60.4 +<?xml version="1.0" encoding="UTF-8"?>
    60.5 +<!--
    60.6 +
    60.7 +    Back 2 Browser Bytecode Translator
    60.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    60.9 +
   60.10 +    This program is free software: you can redistribute it and/or modify
   60.11 +    it under the terms of the GNU General Public License as published by
   60.12 +    the Free Software Foundation, version 2 of the License.
   60.13 +
   60.14 +    This program is distributed in the hope that it will be useful,
   60.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   60.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   60.17 +    GNU General Public License for more details.
   60.18 +
   60.19 +    You should have received a copy of the GNU General Public License
   60.20 +    along with this program. Look for COPYING file in the top folder.
   60.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   60.22 +
   60.23 +-->
   60.24 +<archetype-descriptor name="bck2brwsr">
   60.25 +  <fileSets>
   60.26 +    <fileSet filtered="true" packaged="true">
   60.27 +      <directory>src/main/java</directory>
   60.28 +      <includes>
   60.29 +        <include>**/*.java</include>
   60.30 +      </includes>
   60.31 +    </fileSet>
   60.32 +    <fileSet filtered="true" packaged="true">
   60.33 +      <directory>src/main/resources</directory>
   60.34 +      <includes>
   60.35 +        <include>**/*.xhtml</include>
   60.36 +      </includes>
   60.37 +    </fileSet>
   60.38 +    <fileSet filtered="false" packaged="false">
   60.39 +      <directory></directory>
   60.40 +      <includes>
   60.41 +        <include>nbactions.xml</include>
   60.42 +      </includes>
   60.43 +    </fileSet>
   60.44 +  </fileSets>    
   60.45 +</archetype-descriptor>
   60.46 \ No newline at end of file
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/mojo/src/main/resources/archetype-resources/nbactions.xml	Fri Jan 18 14:27:22 2013 +0100
    61.3 @@ -0,0 +1,10 @@
    61.4 +<?xml version="1.0" encoding="UTF-8"?>
    61.5 +<actions>
    61.6 +    <action>
    61.7 +        <actionName>run</actionName>
    61.8 +        <goals>
    61.9 +            <goal>process-classes</goal>
   61.10 +            <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
   61.11 +        </goals>
   61.12 +    </action>
   61.13 +</actions>
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/mojo/src/main/resources/archetype-resources/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    62.3 @@ -0,0 +1,57 @@
    62.4 +<?xml version="1.0"?>
    62.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    62.6 +  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    62.7 +  <modelVersion>4.0.0</modelVersion>
    62.8 +
    62.9 +  <groupId>${groupId}</groupId>
   62.10 +  <artifactId>${artifactId}</artifactId>
   62.11 +  <version>${version}</version>
   62.12 +  <packaging>jar</packaging>
   62.13 +
   62.14 +  <name>${artifactId}</name>
   62.15 +
   62.16 +  <properties>
   62.17 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   62.18 +  </properties>
   62.19 +  <build>
   62.20 +      <plugins>
   62.21 +            <plugin>
   62.22 +                <groupId>org.apidesign.bck2brwsr</groupId>
   62.23 +                <artifactId>mojo</artifactId>
   62.24 +                <version>0.3-SNAPSHOT</version>
   62.25 +                <executions>
   62.26 +                    <execution>
   62.27 +                        <goals>
   62.28 +                            <goal>brwsr</goal>
   62.29 +                        </goals>
   62.30 +                    </execution>
   62.31 +                </executions>
   62.32 +                <configuration>
   62.33 +                    <startpage>${package.replace('.','/')}/index.xhtml</startpage>
   62.34 +                </configuration>
   62.35 +            </plugin>
   62.36 +         <plugin>
   62.37 +            <groupId>org.apache.maven.plugins</groupId>
   62.38 +            <artifactId>maven-compiler-plugin</artifactId>
   62.39 +            <version>2.3.2</version>
   62.40 +            <configuration>
   62.41 +               <source>1.7</source>
   62.42 +               <target>1.7</target>
   62.43 +            </configuration>
   62.44 +         </plugin>
   62.45 +      </plugins>
   62.46 +  </build>
   62.47 +
   62.48 +  <dependencies>
   62.49 +    <dependency>
   62.50 +      <groupId>org.apidesign.bck2brwsr</groupId>
   62.51 +      <artifactId>emul</artifactId>
   62.52 +      <version>0.3-SNAPSHOT</version>
   62.53 +    </dependency>
   62.54 +    <dependency>
   62.55 +      <groupId>org.apidesign.bck2brwsr</groupId>
   62.56 +      <artifactId>javaquery.api</artifactId>
   62.57 +      <version>0.3-SNAPSHOT</version>
   62.58 +    </dependency>
   62.59 +  </dependencies>
   62.60 +</project>
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/java/App.java	Fri Jan 18 14:27:22 2013 +0100
    63.3 @@ -0,0 +1,17 @@
    63.4 +package ${package};
    63.5 +
    63.6 +import org.apidesign.bck2brwsr.htmlpage.api.*;
    63.7 +import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
    63.8 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
    63.9 +
   63.10 +/** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
   63.11 + * Use this class to define behavior of the elements.
   63.12 + */
   63.13 +@Page(xhtml="index.xhtml", className="Index")
   63.14 +public class App {
   63.15 +    @On(event = CLICK, id="hello")
   63.16 +    static void hello() {
   63.17 +        Index.HELLO.setDisabled(true);
   63.18 +        Element.alert("Hello World!");
   63.19 +    }
   63.20 +}
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/mojo/src/main/resources/archetype-resources/src/main/resources/index.xhtml	Fri Jan 18 14:27:22 2013 +0100
    64.3 @@ -0,0 +1,16 @@
    64.4 +<?xml version="1.0" encoding="UTF-8"?>
    64.5 +<!DOCTYPE html>
    64.6 +<html xmlns="http://www.w3.org/1999/xhtml">
    64.7 +    <head>
    64.8 +        <title>Bck2Brwsr's Hello World</title>
    64.9 +    </head>
   64.10 +    <body>
   64.11 +        <button id="hello">Hello World!</button>
   64.12 +
   64.13 +        <script src="/bck2brwsr.js"></script>
   64.14 +        <script src="/vm.js"></script>
   64.15 +        <script type="text/javascript">
   64.16 +            vm.loadClass('${package}.Index');
   64.17 +        </script>
   64.18 +    </body>
   64.19 +</html>
    65.1 --- a/pom.xml	Fri Jan 18 14:23:18 2013 +0100
    65.2 +++ b/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    65.3 @@ -14,6 +14,8 @@
    65.4      <module>javaquery</module>
    65.5      <module>javap</module>
    65.6      <module>benchmarks</module>
    65.7 +    <module>launcher</module>
    65.8 +    <module>vmtest</module>
    65.9    </modules>
   65.10    <licenses>
   65.11        <license>
   65.12 @@ -71,6 +73,8 @@
   65.13                         <exclude>javap/**</exclude>
   65.14                         <exclude>*</exclude>
   65.15                         <exclude>.*/**</exclude>
   65.16 +                       <exclude>mojo/src/main/resources/archetype-resources/**</exclude>
   65.17 +                       <exclude>vmtest/src/test/resources/**</exclude>
   65.18                    </excludes>
   65.19                </configuration>
   65.20            </plugin>
   65.21 @@ -108,4 +112,4 @@
   65.22    <properties>
   65.23        <license>COPYING</license>
   65.24    </properties>
   65.25 -</project>
   65.26 +</project>
   65.27 \ No newline at end of file
    66.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Fri Jan 18 14:23:18 2013 +0100
    66.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Fri Jan 18 14:27:22 2013 +0100
    66.3 @@ -37,7 +37,7 @@
    66.4   *   return null; // byte[] for the resource
    66.5   * });
    66.6   * </pre>
    66.7 - * In this scenario, when a request for a unknown class is made, the loader
    66.8 + * In this scenario, when a request for an unknown class is made, the loader
    66.9   * function is asked for its byte code and the system dynamically transforms
   66.10   * it to JavaScript.
   66.11   *
    67.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Jan 18 14:23:18 2013 +0100
    67.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Fri Jan 18 14:27:22 2013 +0100
    67.3 @@ -26,6 +26,8 @@
    67.4  import org.apidesign.javap.MethodData;
    67.5  import org.apidesign.javap.StackMapIterator;
    67.6  import static org.apidesign.javap.RuntimeConstants.*;
    67.7 +import org.apidesign.javap.TrapData;
    67.8 +import org.apidesign.javap.TrapDataIterator;
    67.9  
   67.10  /** Translator of the code inside class files to JavaScript.
   67.11   *
   67.12 @@ -64,6 +66,17 @@
   67.13      /* protected */ String accessClass(String classOperation) {
   67.14          return classOperation;
   67.15      }
   67.16 +    
   67.17 +    /** Prints out a debug message. 
   67.18 +     * 
   67.19 +     * @param msg the message
   67.20 +     * @return true if the message has been printed
   67.21 +     * @throws IOException 
   67.22 +     */
   67.23 +    boolean debug(String msg) throws IOException {
   67.24 +        out.append(msg);
   67.25 +        return true;
   67.26 +    }
   67.27  
   67.28      /**
   67.29       * Converts a given class file to a JavaScript version.
   67.30 @@ -76,6 +89,11 @@
   67.31      
   67.32      public String compile(InputStream classFile) throws IOException {
   67.33          this.jc = new ClassData(classFile);
   67.34 +        if (jc.getMajor_version() < 50) {
   67.35 +            throw new IOException("Can't compile " + jc.getClassName() + ". Class file version " + jc.getMajor_version() + "."
   67.36 +                + jc.getMinor_version() + " - recompile with -target 1.6 (at least)."
   67.37 +            );
   67.38 +        }
   67.39          byte[] arrData = jc.findAnnotationData(true);
   67.40          String[] arr = findAnnotation(arrData, jc, 
   67.41              "org.apidesign.bck2brwsr.core.ExtraJavaScript", 
   67.42 @@ -129,18 +147,27 @@
   67.43                  }
   67.44                  continue;
   67.45              }
   67.46 +            String prefix;
   67.47              String mn;
   67.48              if (m.isStatic()) {
   67.49 -                mn = generateStaticMethod("\n    c.", m, toInitilize);
   67.50 +                prefix = "\n    c.";
   67.51 +                mn = generateStaticMethod(prefix, m, toInitilize);
   67.52              } else {
   67.53 -                mn = generateInstanceMethod("\n    c.", m);
   67.54 +                if (m.isConstructor()) {
   67.55 +                    prefix = "\n    CLS.";
   67.56 +                    mn = generateInstanceMethod(prefix, m);
   67.57 +                } else {
   67.58 +                    prefix = "\n    c.";
   67.59 +                    mn = generateInstanceMethod(prefix, m);
   67.60 +                }
   67.61              }
   67.62              byte[] runAnno = m.findAnnotationData(false);
   67.63              if (runAnno != null) {
   67.64 -                out.append("\n    c.").append(mn).append(".anno = {");
   67.65 +                out.append(prefix).append(mn).append(".anno = {");
   67.66                  generateAnno(jc, out, runAnno);
   67.67                  out.append("\n    };");
   67.68              }
   67.69 +            out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
   67.70          }
   67.71          out.append("\n    c.constructor = CLS;");
   67.72          out.append("\n    c.$instOf_").append(className).append(" = true;");
   67.73 @@ -151,6 +178,7 @@
   67.74          out.append(accessClass("java_lang_Class(true);"));
   67.75          out.append("\n    CLS.$class.jvmName = '").append(jc.getClassName()).append("';");
   67.76          out.append("\n    CLS.$class.superclass = sprcls;");
   67.77 +        out.append("\n    CLS.$class.access = ").append(jc.getAccessFlags()+";");
   67.78          out.append("\n    CLS.$class.cnstr = CLS;");
   67.79          byte[] classAnno = jc.findAnnotationData(false);
   67.80          if (classAnno != null) {
   67.81 @@ -217,17 +245,19 @@
   67.82      private void generateMethod(String prefix, String name, MethodData m)
   67.83              throws IOException {
   67.84          final StackMapIterator stackMapIterator = m.createStackMapIterator();
   67.85 +        TrapDataIterator trap = m.getTrapDataIterator();
   67.86          final LocalsMapper lmapper =
   67.87                  new LocalsMapper(stackMapIterator.getArguments());
   67.88  
   67.89          out.append(prefix).append(name).append(" = function(");
   67.90 -        lmapper.outputArguments(out);
   67.91 +        lmapper.outputArguments(out, m.isStatic());
   67.92          out.append(") {").append("\n");
   67.93  
   67.94          final byte[] byteCodes = m.getCode();
   67.95          if (byteCodes == null) {
   67.96              out.append("  throw 'no code found for ")
   67.97 -               .append(m.getInternalSig()).append("';\n");
   67.98 +               .append(jc.getClassName()).append('.')
   67.99 +               .append(m.getName()).append("';\n");
  67.100              out.append("};");
  67.101              return;
  67.102          }
  67.103 @@ -246,6 +276,9 @@
  67.104                  out.append(';');
  67.105              }
  67.106          }
  67.107 +        if (!m.isStatic()) {
  67.108 +            out.append("  var ").append(" lcA0 = this;\n");
  67.109 +        }
  67.110  
  67.111          // maxStack includes two stack positions for every pushed long / double
  67.112          // so this might generate more stack variables than we need
  67.113 @@ -263,18 +296,31 @@
  67.114          }
  67.115  
  67.116          int lastStackFrame = -1;
  67.117 -
  67.118 +        TrapData[] previousTrap = null;
  67.119 +        
  67.120          out.append("\n  var gt = 0;\n  for(;;) switch(gt) {\n");
  67.121          for (int i = 0; i < byteCodes.length; i++) {
  67.122              int prev = i;
  67.123              stackMapIterator.advanceTo(i);
  67.124 +            boolean changeInCatch = trap.advanceTo(i);
  67.125 +            if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
  67.126 +                if (previousTrap != null) {
  67.127 +                    generateCatch(previousTrap);
  67.128 +                    previousTrap = null;
  67.129 +                }
  67.130 +            }
  67.131              if (lastStackFrame != stackMapIterator.getFrameIndex()) {
  67.132                  lastStackFrame = stackMapIterator.getFrameIndex();
  67.133                  lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
  67.134                  smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
  67.135 -                out.append("    case " + i).append(": ");
  67.136 +                out.append("    case " + i).append(": ");            
  67.137 +                changeInCatch = true;
  67.138              } else {
  67.139 -                out.append("    /* " + i).append(" */ ");
  67.140 +                debug("    /* " + i + " */ ");
  67.141 +            }
  67.142 +            if (changeInCatch && trap.useTry()) {
  67.143 +                out.append("try {");
  67.144 +                previousTrap = trap.current();
  67.145              }
  67.146              final int c = readByte(byteCodes, i);
  67.147              switch (c) {
  67.148 @@ -449,7 +495,7 @@
  67.149                      emit(out, "@1 = @2;", lmapper.setD(3), smapper.popD());
  67.150                      break;
  67.151                  case opc_iadd:
  67.152 -                    emit(out, "@1 += @2;", smapper.getI(1), smapper.popI());
  67.153 +                    emit(out, "@1 = @1.add32(@2);", smapper.getI(1), smapper.popI());
  67.154                      break;
  67.155                  case opc_ladd:
  67.156                      emit(out, "@1 += @2;", smapper.getL(1), smapper.popL());
  67.157 @@ -461,7 +507,7 @@
  67.158                      emit(out, "@1 += @2;", smapper.getD(1), smapper.popD());
  67.159                      break;
  67.160                  case opc_isub:
  67.161 -                    emit(out, "@1 -= @2;", smapper.getI(1), smapper.popI());
  67.162 +                    emit(out, "@1 = @1.sub32(@2);", smapper.getI(1), smapper.popI());
  67.163                      break;
  67.164                  case opc_lsub:
  67.165                      emit(out, "@1 -= @2;", smapper.getL(1), smapper.popL());
  67.166 @@ -473,7 +519,7 @@
  67.167                      emit(out, "@1 -= @2;", smapper.getD(1), smapper.popD());
  67.168                      break;
  67.169                  case opc_imul:
  67.170 -                    emit(out, "@1 *= @2;", smapper.getI(1), smapper.popI());
  67.171 +                    emit(out, "@1 = @1.mul32(@2);", smapper.getI(1), smapper.popI());
  67.172                      break;
  67.173                  case opc_lmul:
  67.174                      emit(out, "@1 *= @2;", smapper.getL(1), smapper.popL());
  67.175 @@ -630,9 +676,13 @@
  67.176                           smapper.popD(), smapper.pushL());
  67.177                      break;
  67.178                  case opc_i2b:
  67.179 +                    emit(out, "@1 = @1.toInt8();", smapper.getI(0));
  67.180 +                    break;
  67.181                  case opc_i2c:
  67.182 +                    out.append("{ /* number conversion */ }");
  67.183 +                    break;
  67.184                  case opc_i2s:
  67.185 -                    out.append("/* number conversion */");
  67.186 +                    emit(out, "@1 = @1.toInt16();", smapper.getI(0));
  67.187                      break;
  67.188                  case opc_aconst_null:
  67.189                      emit(out, "@1 = null;", smapper.pushA());
  67.190 @@ -863,28 +913,53 @@
  67.191                      break;
  67.192                  }
  67.193                  case opc_newarray:
  67.194 -                    ++i; // skip type of array
  67.195 -                    emit(out, "@2 = new Array(@1).fillNulls();",
  67.196 -                         smapper.popI(), smapper.pushA());
  67.197 +                    int atype = readByte(byteCodes, ++i);
  67.198 +                    String jvmType;
  67.199 +                    switch (atype) {
  67.200 +                        case 4: jvmType = "[Z"; break;
  67.201 +                        case 5: jvmType = "[C"; break;
  67.202 +                        case 6: jvmType = "[F"; break;
  67.203 +                        case 7: jvmType = "[D"; break;
  67.204 +                        case 8: jvmType = "[B"; break;
  67.205 +                        case 9: jvmType = "[S"; break;
  67.206 +                        case 10: jvmType = "[I"; break;
  67.207 +                        case 11: jvmType = "[J"; break;
  67.208 +                        default: throw new IllegalStateException("Array type: " + atype);
  67.209 +                    }
  67.210 +                    emit(out, "@2 = new Array(@1).initWith('@3', 0);",
  67.211 +                         smapper.popI(), smapper.pushA(), jvmType);
  67.212                      break;
  67.213 -                case opc_anewarray:
  67.214 -                    i += 2; // skip type of array
  67.215 -                    emit(out, "@2 = new Array(@1).fillNulls();",
  67.216 -                         smapper.popI(), smapper.pushA());
  67.217 +                case opc_anewarray: {
  67.218 +                    int type = readIntArg(byteCodes, i);
  67.219 +                    i += 2;
  67.220 +                    String typeName = jc.getClassName(type);
  67.221 +                    if (typeName.startsWith("[")) {
  67.222 +                        typeName = "[" + typeName;
  67.223 +                    } else {
  67.224 +                        typeName = "[L" + typeName + ";";
  67.225 +                    }
  67.226 +                    emit(out, "@2 = new Array(@1).initWith('@3', null);",
  67.227 +                         smapper.popI(), smapper.pushA(), typeName);
  67.228                      break;
  67.229 +                }
  67.230                  case opc_multianewarray: {
  67.231 +                    int type = readIntArg(byteCodes, i);
  67.232                      i += 2;
  67.233 +                    String typeName = jc.getClassName(type);
  67.234                      int dim = readByte(byteCodes, ++i);
  67.235                      out.append("{ var a0 = new Array(").append(smapper.popI())
  67.236 -                       .append(").fillNulls();");
  67.237 +                       .append(").initWith('").append(typeName).append("', null);");
  67.238                      for (int d = 1; d < dim; d++) {
  67.239 +                        typeName = typeName.substring(1);
  67.240                          out.append("\n  var l" + d).append(" = ")
  67.241                             .append(smapper.popI()).append(';');
  67.242                          out.append("\n  for (var i" + d).append (" = 0; i" + d).
  67.243                              append(" < a" + (d - 1)).
  67.244                              append(".length; i" + d).append("++) {");
  67.245                          out.append("\n    var a" + d).
  67.246 -                            append (" = new Array(l" + d).append(").fillNulls();");
  67.247 +                            append (" = new Array(l" + d).append(").initWith('")
  67.248 +                            .append(typeName).append("', ")
  67.249 +                            .append(typeName.length() == 2 ? "0" : "null").append(");");
  67.250                          out.append("\n    a" + (d - 1)).append("[i" + d).append("] = a" + d).
  67.251                              append(";");
  67.252                      }
  67.253 @@ -898,55 +973,55 @@
  67.254                      emit(out, "@2 = @1.length;", smapper.popA(), smapper.pushI());
  67.255                      break;
  67.256                  case opc_lastore:
  67.257 -                    emit(out, "@3[@2] = @1;",
  67.258 +                    emit(out, "@3.at(@2, @1);",
  67.259                           smapper.popL(), smapper.popI(), smapper.popA());
  67.260                      break;
  67.261                  case opc_fastore:
  67.262 -                    emit(out, "@3[@2] = @1;",
  67.263 +                    emit(out, "@3.at(@2, @1);",
  67.264                           smapper.popF(), smapper.popI(), smapper.popA());
  67.265                      break;
  67.266                  case opc_dastore:
  67.267 -                    emit(out, "@3[@2] = @1;",
  67.268 +                    emit(out, "@3.at(@2, @1);",
  67.269                           smapper.popD(), smapper.popI(), smapper.popA());
  67.270                      break;
  67.271                  case opc_aastore:
  67.272 -                    emit(out, "@3[@2] = @1;",
  67.273 +                    emit(out, "@3.at(@2, @1);",
  67.274                           smapper.popA(), smapper.popI(), smapper.popA());
  67.275                      break;
  67.276                  case opc_iastore:
  67.277                  case opc_bastore:
  67.278                  case opc_castore:
  67.279                  case opc_sastore:
  67.280 -                    emit(out, "@3[@2] = @1;",
  67.281 +                    emit(out, "@3.at(@2, @1);",
  67.282                           smapper.popI(), smapper.popI(), smapper.popA());
  67.283                      break;
  67.284                  case opc_laload:
  67.285 -                    emit(out, "@3 = @2[@1];",
  67.286 +                    emit(out, "@3 = @2.at(@1);",
  67.287                           smapper.popI(), smapper.popA(), smapper.pushL());
  67.288                      break;
  67.289                  case opc_faload:
  67.290 -                    emit(out, "@3 = @2[@1];",
  67.291 +                    emit(out, "@3 = @2.at(@1);",
  67.292                           smapper.popI(), smapper.popA(), smapper.pushF());
  67.293                      break;
  67.294                  case opc_daload:
  67.295 -                    emit(out, "@3 = @2[@1];",
  67.296 +                    emit(out, "@3 = @2.at(@1);",
  67.297                           smapper.popI(), smapper.popA(), smapper.pushD());
  67.298                      break;
  67.299                  case opc_aaload:
  67.300 -                    emit(out, "@3 = @2[@1];",
  67.301 +                    emit(out, "@3 = @2.at(@1);",
  67.302                           smapper.popI(), smapper.popA(), smapper.pushA());
  67.303                      break;
  67.304                  case opc_iaload:
  67.305                  case opc_baload:
  67.306                  case opc_caload:
  67.307                  case opc_saload:
  67.308 -                    emit(out, "@3 = @2[@1];",
  67.309 +                    emit(out, "@3 = @2.at(@1);",
  67.310                           smapper.popI(), smapper.popA(), smapper.pushI());
  67.311                      break;
  67.312                  case opc_pop:
  67.313                  case opc_pop2:
  67.314                      smapper.pop(1);
  67.315 -                    out.append("/* pop */");
  67.316 +                    debug("/* pop */");
  67.317                      break;
  67.318                  case opc_dup: {
  67.319                      final Variable v = smapper.get(0);
  67.320 @@ -1024,7 +1099,7 @@
  67.321                      int indx = readIntArg(byteCodes, i);
  67.322                      String[] fi = jc.getFieldInfoName(indx);
  67.323                      final int type = VarType.fromFieldType(fi[2].charAt(0));
  67.324 -                    emit(out, "@1 = @2.@3;",
  67.325 +                    emit(out, "@1 = @2(false).constructor.@3;",
  67.326                           smapper.pushT(type),
  67.327                           accessClass(fi[0].replace('/', '_')), fi[1]);
  67.328                      i += 2;
  67.329 @@ -1044,7 +1119,7 @@
  67.330                      int indx = readIntArg(byteCodes, i);
  67.331                      String[] fi = jc.getFieldInfoName(indx);
  67.332                      final int type = VarType.fromFieldType(fi[2].charAt(0));
  67.333 -                    emit(out, "@1.@2 = @3;",
  67.334 +                    emit(out, "@1(false).constructor.@2 = @3;",
  67.335                           accessClass(fi[0].replace('/', '_')), fi[1],
  67.336                           smapper.popT(type));
  67.337                      i += 2;
  67.338 @@ -1099,13 +1174,17 @@
  67.339                           Integer.toString(c));
  67.340                  }
  67.341              }
  67.342 -            out.append(" //");
  67.343 -            for (int j = prev; j <= i; j++) {
  67.344 -                out.append(" ");
  67.345 -                final int cc = readByte(byteCodes, j);
  67.346 -                out.append(Integer.toString(cc));
  67.347 +            if (debug(" //")) {
  67.348 +                for (int j = prev; j <= i; j++) {
  67.349 +                    out.append(" ");
  67.350 +                    final int cc = readByte(byteCodes, j);
  67.351 +                    out.append(Integer.toString(cc));
  67.352 +                }
  67.353              }
  67.354 -            out.append("\n");
  67.355 +            out.append("\n");            
  67.356 +        }
  67.357 +        if (previousTrap != null) {
  67.358 +            generateCatch(previousTrap);
  67.359          }
  67.360          out.append("  }\n");
  67.361          out.append("};");
  67.362 @@ -1204,6 +1283,7 @@
  67.363                          returnType[0] = 'L';
  67.364                      }
  67.365                      i = next + 1;
  67.366 +                    array = false;
  67.367                      continue;
  67.368                  case '[':
  67.369                      array = true;
  67.370 @@ -1279,8 +1359,15 @@
  67.371          final String in = mi[0];
  67.372          out.append(accessClass(in.replace('/', '_')));
  67.373          out.append("(false).");
  67.374 +        if (mn.startsWith("cons_")) {
  67.375 +            out.append("constructor.");
  67.376 +        }
  67.377          out.append(mn);
  67.378 -        out.append('(');
  67.379 +        if (isStatic) {
  67.380 +            out.append('(');
  67.381 +        } else {
  67.382 +            out.append(".call(");
  67.383 +        }
  67.384          if (numArguments > 0) {
  67.385              out.append(vars[0]);
  67.386              for (int j = 1; j < numArguments; ++j) {
  67.387 @@ -1316,10 +1403,11 @@
  67.388          out.append(vars[0]).append('.');
  67.389          out.append(mn);
  67.390          out.append('(');
  67.391 -        out.append(vars[0]);
  67.392 +        String sep = "";
  67.393          for (int j = 1; j < numArguments; ++j) {
  67.394 -            out.append(", ");
  67.395 +            out.append(sep);
  67.396              out.append(vars[j]);
  67.397 +            sep = ", ";
  67.398          }
  67.399          out.append(");");
  67.400          i += 2;
  67.401 @@ -1328,7 +1416,7 @@
  67.402  
  67.403      private void addReference(String cn) throws IOException {
  67.404          if (requireReference(cn)) {
  67.405 -            out.append(" /* needs ").append(cn).append(" */");
  67.406 +            debug(" /* needs " + cn + " */");
  67.407          }
  67.408      }
  67.409  
  67.410 @@ -1393,15 +1481,8 @@
  67.411          final String mn = findMethodName(m, cnt);
  67.412          out.append(prefix).append(mn);
  67.413          out.append(" = function(");
  67.414 -        String space;
  67.415 -        int index;
  67.416 -        if (!isStatic) {                
  67.417 -            space = outputArg(out, p.args, 0);
  67.418 -            index = 1;
  67.419 -        } else {
  67.420 -            space = "";
  67.421 -            index = 0;
  67.422 -        }
  67.423 +        String space = "";
  67.424 +        int index = 0;
  67.425          for (int i = 0; i < cnt.length(); i++) {
  67.426              out.append(space);
  67.427              space = outputArg(out, p.args, index);
  67.428 @@ -1534,4 +1615,39 @@
  67.429  
  67.430          out.append(format, processed, length);
  67.431      }
  67.432 +
  67.433 +    private void generateCatch(TrapData[] traps) throws IOException {
  67.434 +        out.append("} catch (e) {\n");
  67.435 +        int finallyPC = -1;
  67.436 +        for (TrapData e : traps) {
  67.437 +            if (e == null) {
  67.438 +                break;
  67.439 +            }
  67.440 +            if (e.catch_cpx != 0) { //not finally
  67.441 +                final String classInternalName = jc.getClassName(e.catch_cpx);
  67.442 +                addReference(classInternalName);
  67.443 +                if ("java/lang/Throwable".equals(classInternalName)) {
  67.444 +                    out.append("if (e.$instOf_java_lang_Throwable) {");
  67.445 +                    out.append("  stA0 = e;");
  67.446 +                    out.append("} else {");
  67.447 +                    out.append("  stA0 = vm.java_lang_Throwable(true);");
  67.448 +                    out.append("  vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
  67.449 +                    out.append("}");
  67.450 +                    out.append("gt=" + e.handler_pc + "; continue;");
  67.451 +                } else {
  67.452 +                    out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
  67.453 +                    out.append("gt=" + e.handler_pc + "; stA0 = e; continue;");
  67.454 +                    out.append("}\n");
  67.455 +                }
  67.456 +            } else {
  67.457 +                finallyPC = e.handler_pc;
  67.458 +            }
  67.459 +        }
  67.460 +        if (finallyPC == -1) {
  67.461 +            out.append("throw e;");
  67.462 +        } else {
  67.463 +            out.append("gt=" + finallyPC + "; stA0 = e; continue;");
  67.464 +        }
  67.465 +        out.append("\n}");
  67.466 +    }
  67.467  }
    68.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java	Fri Jan 18 14:23:18 2013 +0100
    68.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java	Fri Jan 18 14:27:22 2013 +0100
    68.3 @@ -33,13 +33,14 @@
    68.4          localTypeRecords = new TypeArray(initTypeRecords);
    68.5      }
    68.6  
    68.7 -    public void outputArguments(final Appendable out) throws IOException {
    68.8 +    public void outputArguments(final Appendable out, boolean isStatic) throws IOException {
    68.9          final int argRecordCount = argTypeRecords.getSize();
   68.10 -        if (argRecordCount > 0) {
   68.11 -            Variable variable = getVariable(argTypeRecords, 0);
   68.12 +        int first = isStatic ? 0 : 1;
   68.13 +        if (argRecordCount > first) {
   68.14 +            Variable variable = getVariable(argTypeRecords, first);
   68.15              out.append(variable);
   68.16  
   68.17 -            int i = variable.isCategory2() ? 2 : 1;
   68.18 +            int i = first + (variable.isCategory2() ? 2 : 1);
   68.19              while (i < argRecordCount) {
   68.20                  variable = getVariable(argTypeRecords, i);
   68.21                  out.append(", ");
    69.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Fri Jan 18 14:23:18 2013 +0100
    69.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Fri Jan 18 14:27:22 2013 +0100
    69.3 @@ -33,6 +33,11 @@
    69.4          // uses VMLazy to load dynamic classes
    69.5          VMLazy.init();
    69.6      }
    69.7 +
    69.8 +    @Override
    69.9 +    boolean debug(String msg) throws IOException {
   69.10 +        return false;
   69.11 +    }
   69.12      
   69.13      static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
   69.14          new VM(out).doCompile(l, names);
   69.15 @@ -112,12 +117,19 @@
   69.16              + "    var loader = {};\n"
   69.17              + "    loader.vm = vm;\n"
   69.18              + "    loader.loadClass = function(name) {\n"
   69.19 -            + "      var attr = name.replace__Ljava_lang_String_2CC(name, '.','_');\n"
   69.20 +            + "      var attr = name.replace__Ljava_lang_String_2CC('.','_');\n"
   69.21              + "      var fn = vm[attr];\n"
   69.22              + "      if (fn) return fn(false);\n"
   69.23              + "      if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
   69.24              + "      return vm.org_apidesign_vm4brwsr_VMLazy(false).\n"
   69.25 -            + "        load___3Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
   69.26 +            + "        load__Ljava_lang_Object_2Ljava_lang_Object_2Ljava_lang_String_2_3Ljava_lang_Object_2(loader, name, args);\n"
   69.27 +            + "    }\n"
   69.28 +            + "    if (args[0]) {\n"
   69.29 +            + "      vm.loadClass = loader.loadClass;\n"
   69.30 +            + "      vm.loadBytes = function(name) {\n"
   69.31 +            + "        if (!args[0]) throw 'bck2brwsr initialized without loader function, cannot load ' + name;\n"
   69.32 +            + "        return args[0](name);\n"
   69.33 +            + "      }\n"
   69.34              + "    }\n"
   69.35              + "    return loader;\n"
   69.36              + "  };\n");
    70.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Fri Jan 18 14:23:18 2013 +0100
    70.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Fri Jan 18 14:27:22 2013 +0100
    70.3 @@ -47,10 +47,10 @@
    70.4      
    70.5      static Object load(Object loader, String name, Object[] arguments) 
    70.6      throws IOException, ClassNotFoundException {
    70.7 -        return new VMLazy(loader, arguments).load(name);
    70.8 +        return new VMLazy(loader, arguments).load(name, false);
    70.9      }
   70.10      
   70.11 -    private Object load(String name)
   70.12 +    private Object load(String name, boolean instance)
   70.13      throws IOException, ClassNotFoundException {
   70.14          String res = name.replace('.', '/') + ".class";
   70.15          byte[] arr = read(loader, res, args);
   70.16 @@ -61,10 +61,27 @@
   70.17          StringBuilder out = new StringBuilder();
   70.18          out.append("var loader = arguments[0];\n");
   70.19          out.append("var vm = loader.vm;\n");
   70.20 -        new Gen(this, out).compile(new ByteArrayInputStream(arr));
   70.21 +        int prelude = out.length();
   70.22 +        String initCode = new Gen(this, out).compile(new ByteArrayInputStream(arr));
   70.23          String code = out.toString().toString();
   70.24 +//        dump("Loading " + name);
   70.25 +        dump(code);
   70.26          String under = name.replace('.', '_');
   70.27 -        return applyCode(loader, under, code);
   70.28 +        Object fn = applyCode(loader, under, code, instance);
   70.29 +        
   70.30 +        if (!initCode.isEmpty()) {
   70.31 +            out.setLength(prelude);
   70.32 +            out.append(initCode);
   70.33 +            code = out.toString().toString();
   70.34 +            dump(code);
   70.35 +            applyCode(loader, null, code, false);
   70.36 +        }            
   70.37 +        
   70.38 +        return fn;
   70.39 +    }
   70.40 +
   70.41 +//    @JavaScriptBody(args = "s", body = "java.lang.System.out.println(s.toString());")
   70.42 +    static void dump(String s) {
   70.43      }
   70.44  
   70.45  /* possibly not needed:
   70.46 @@ -76,15 +93,15 @@
   70.47  */
   70.48      
   70.49  
   70.50 -    @JavaScriptBody(args = {"loader", "name", "script" }, body =
   70.51 +    @JavaScriptBody(args = {"loader", "name", "script", "instance" }, body =
   70.52          "try {\n" +
   70.53          "  new Function(script)(loader, name);\n" +
   70.54          "} catch (ex) {\n" +
   70.55          "  throw 'Cannot compile ' + ex + ' line: ' + ex.lineNumber + ' script:\\n' + script;\n" +
   70.56          "}\n" +
   70.57 -        "return vm[name](false);\n"
   70.58 +        "return name != null ? vm[name](instance) : null;\n"
   70.59      )
   70.60 -    private static native Object applyCode(Object loader, String name, String script);
   70.61 +    private static native Object applyCode(Object loader, String name, String script, boolean instance);
   70.62      
   70.63      
   70.64      private static final class Gen extends ByteCodeToJavaScript {
   70.65 @@ -95,16 +112,17 @@
   70.66              this.lazy = vm;
   70.67          }
   70.68          
   70.69 -        @JavaScriptBody(args = {"self", "n"},
   70.70 +        @JavaScriptBody(args = {"n"},
   70.71          body =
   70.72 -        "var cls = n.replace__Ljava_lang_String_2CC(n, '/','_').toString();"
   70.73 -        + "\nvar dot = n.replace__Ljava_lang_String_2CC(n,'/','.').toString();"
   70.74 -        + "\nvar lazy = self.fld_lazy;"
   70.75 +        "var cls = n.replace__Ljava_lang_String_2CC('/','_').toString();"
   70.76 +        + "\nvar dot = n.replace__Ljava_lang_String_2CC('/','.').toString();"
   70.77 +        + "\nvar lazy = this.fld_lazy;"
   70.78          + "\nvar loader = lazy.fld_loader;"
   70.79          + "\nvar vm = loader.vm;"
   70.80          + "\nif (vm[cls]) return false;"
   70.81          + "\nvm[cls] = function() {"
   70.82 -        + "\n  return lazy.load__Ljava_lang_Object_2Ljava_lang_String_2(lazy, dot);"
   70.83 +        + "\n  var instance = arguments.length == 0 || arguments[0] === true;"
   70.84 +        + "\n  return lazy.load__Ljava_lang_Object_2Ljava_lang_String_2Z(dot, instance);"
   70.85          + "\n};"
   70.86          + "\nreturn true;")
   70.87          @Override
    71.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Array.java	Fri Jan 18 14:23:18 2013 +0100
    71.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Array.java	Fri Jan 18 14:27:22 2013 +0100
    71.3 @@ -51,6 +51,16 @@
    71.4          return doubles[4][0];
    71.5      }
    71.6      
    71.7 +    static double[][] dbls = new double[1][2];
    71.8 +    public static double twoDoubles() {
    71.9 +        return dbls[0][0] + dbls[0][0];
   71.10 +    }
   71.11 +
   71.12 +    static int[][] tints = new int[1][2];
   71.13 +    public static int twoInts() {
   71.14 +        return tints[0][0] + tints[0][0];
   71.15 +    }
   71.16 +    
   71.17      private static final Array[] ARR = { new Array(), new Array(), new Array() };
   71.18      
   71.19      private static Array[][] arr() {
   71.20 @@ -82,16 +92,27 @@
   71.21          }
   71.22          return sum;
   71.23      }
   71.24 -    public static int simple() {
   71.25 -        int[] arr = { 0, 1, 2, 3, 4, 5 };
   71.26 +    private static final int[] arr = { 0, 1, 2, 3, 4, 5 };
   71.27 +    public static int simple(boolean clone) {
   71.28 +        int[] ar;
   71.29 +        if (clone) {
   71.30 +            ar = arr.clone();
   71.31 +        } else {
   71.32 +            ar = arr;
   71.33 +        }
   71.34          
   71.35          int sum = 0;
   71.36 -        for (int a : arr) {
   71.37 +        for (int a : ar) {
   71.38              sum += a;
   71.39          }
   71.40          return sum;
   71.41      }
   71.42      
   71.43 +    public static int sum(int size) {
   71.44 +        int[] arr = new int[size];
   71.45 +        return arr[0] + arr[1];
   71.46 +    }
   71.47 +    
   71.48      static void arraycopy(char[] value, int srcBegin, char[] dst, int dstBegin, int count) {
   71.49          while (count-- > 0) {
   71.50              dst[dstBegin++] = value[srcBegin++];
    72.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java	Fri Jan 18 14:23:18 2013 +0100
    72.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java	Fri Jan 18 14:27:22 2013 +0100
    72.3 @@ -18,7 +18,6 @@
    72.4  package org.apidesign.vm4brwsr;
    72.5  
    72.6  import javax.script.Invocable;
    72.7 -import javax.script.ScriptException;
    72.8  import static org.testng.Assert.*;
    72.9  import org.testng.annotations.BeforeClass;
   72.10  import org.testng.annotations.Test;
   72.11 @@ -28,9 +27,20 @@
   72.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
   72.13   */
   72.14  public class ArrayTest {
   72.15 +    @Test public void intArrayShouldBeFilledWithZeroes() throws Exception {
   72.16 +            assertExec("0 + 0", Array.class, "sum__II", 
   72.17 +            Double.valueOf(0), 2
   72.18 +        );
   72.19 +    }
   72.20      @Test public void verifySimpleIntOperation() throws Exception {
   72.21 -            assertExec("CheckTheSum", Array.class, "simple__I", 
   72.22 -            Double.valueOf(15)
   72.23 +            assertExec("CheckTheSum", Array.class, "simple__IZ", 
   72.24 +            Double.valueOf(15), false
   72.25 +        );
   72.26 +    }
   72.27 +    
   72.28 +    @Test public void cloneOnArray() throws Exception {
   72.29 +            assertExec("CheckTheSum on clone", Array.class, "simple__IZ", 
   72.30 +            Double.valueOf(15), true
   72.31          );
   72.32      }
   72.33      
   72.34 @@ -43,6 +53,17 @@
   72.35              Double.valueOf(105)
   72.36          );
   72.37      }
   72.38 +
   72.39 +    @Test public void twoDoubles() throws Exception {
   72.40 +        assertExec("Elements are initialized", Array.class, "twoDoubles__D", 
   72.41 +            Double.valueOf(0)
   72.42 +        );
   72.43 +    }
   72.44 +    @Test public void twoInts() throws Exception {
   72.45 +        assertExec("Elements are initialized", Array.class, "twoInts__I", 
   72.46 +            Double.valueOf(0)
   72.47 +        );
   72.48 +    }
   72.49      
   72.50      @Test public void doesCopyArrayWork() throws Exception {
   72.51          assertExec("Returns 'a'", Array.class, "copyArray__C", Double.valueOf('a'));
    73.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java	Fri Jan 18 14:23:18 2013 +0100
    73.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/BytesLoader.java	Fri Jan 18 14:27:22 2013 +0100
    73.3 @@ -19,6 +19,8 @@
    73.4  
    73.5  import java.io.IOException;
    73.6  import java.io.InputStream;
    73.7 +import java.net.URL;
    73.8 +import java.util.Enumeration;
    73.9  import java.util.Set;
   73.10  import java.util.TreeSet;
   73.11  
   73.12 @@ -33,15 +35,7 @@
   73.13          if (!requested.add(name)) {
   73.14              throw new IllegalStateException("Requested for second time: " + name);
   73.15          }
   73.16 -        InputStream is = BytesLoader.class.getClassLoader().getResourceAsStream(name);
   73.17 -        if (is == null) {
   73.18 -            throw new IOException("Can't find " + name);
   73.19 -        }
   73.20 -        byte[] arr = new byte[is.available()];
   73.21 -        int len = is.read(arr);
   73.22 -        if (len != arr.length) {
   73.23 -            throw new IOException("Read only " + len + " wanting " + arr.length);
   73.24 -        }
   73.25 +        byte[] arr = readClass(name);
   73.26          /*
   73.27          System.err.print("loader['" + name + "'] = [");
   73.28          for (int i = 0; i < arr.length; i++) {
   73.29 @@ -54,5 +48,29 @@
   73.30           */
   73.31          return arr;
   73.32      }
   73.33 +
   73.34 +    static byte[] readClass(String name) throws IOException {
   73.35 +        URL u = null;
   73.36 +        Enumeration<URL> en = BytesLoader.class.getClassLoader().getResources(name);
   73.37 +        while (en.hasMoreElements()) {
   73.38 +            u = en.nextElement();
   73.39 +        }
   73.40 +        if (u == null) {
   73.41 +            throw new IOException("Can't find " + name);
   73.42 +        }
   73.43 +        try (InputStream is = u.openStream()) {
   73.44 +            byte[] arr;
   73.45 +            arr = new byte[is.available()];
   73.46 +            int offset = 0;
   73.47 +            while (offset < arr.length) {
   73.48 +                int len = is.read(arr, offset, arr.length - offset);
   73.49 +                if (len == -1) {
   73.50 +                    throw new IOException("Can't read " + name);
   73.51 +                }
   73.52 +                offset += len;
   73.53 +            }
   73.54 +            return arr;
   73.55 +        }
   73.56 +    }
   73.57      
   73.58  }
    74.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Fri Jan 18 14:23:18 2013 +0100
    74.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Fri Jan 18 14:27:22 2013 +0100
    74.3 @@ -74,6 +74,16 @@
    74.4      @Test public void jsNewInstance() throws Exception {
    74.5          assertExec("Check new instance", Classes.class, "newInstance__Z", Double.valueOf(1));
    74.6      }
    74.7 +    @Test public void javaNoNewInstance() throws Exception {
    74.8 +        assertEquals("java.lang.InstantiationException:java.lang.Float", 
    74.9 +            Classes.newInstanceNoPubConstructor()
   74.10 +        );
   74.11 +    }
   74.12 +    @Test public void jsNoNewInstance() throws Exception {
   74.13 +        assertExec("Check problems with new instance", Classes.class, "newInstanceNoPubConstructor__Ljava_lang_String_2", 
   74.14 +            "java.lang.InstantiationException:java.lang.Float"
   74.15 +        );
   74.16 +    }
   74.17      @Test public void jsAnnotation() throws Exception {
   74.18          assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
   74.19      }
   74.20 @@ -92,6 +102,11 @@
   74.21              "java.io.IOException", true, "name"
   74.22          );
   74.23      }
   74.24 +    @Test public void jsInvokeParamMethod() throws Exception {
   74.25 +        assertExec("sums two numbers via reflection", Classes.class, 
   74.26 +            "reflectiveSum__III", Double.valueOf(5), 2, 3
   74.27 +        );
   74.28 +    }
   74.29      @Test public void javaFindMethod() throws Exception {
   74.30          assertEquals(Classes.reflectiveMethodCall(false, "name"), "java.io.IOException", "Calls the name() method via reflection");
   74.31      }
   74.32 @@ -101,6 +116,18 @@
   74.33              "java.io.IOException", false, "name"
   74.34          );
   74.35      }
   74.36 +    @Test public void primitiveReturnType() throws Exception {
   74.37 +        assertExec("Tries to get an integer via reflection", Classes.class, 
   74.38 +            "primitiveType__Ljava_lang_String_2Ljava_lang_String_2", 
   74.39 +            Classes.primitiveType("primitive"), "primitive"
   74.40 +        );
   74.41 +    }
   74.42 +    @Test public void primitiveBoolReturnType() throws Exception {
   74.43 +        assertExec("Tries to get an integer via reflection", Classes.class, 
   74.44 +            "primitiveType__Ljava_lang_String_2Ljava_lang_String_2", 
   74.45 +            Classes.primitiveType("primitiveB"), "primitiveB"
   74.46 +        );
   74.47 +    }
   74.48      @Test public void javaAnnotatedMethod() throws Exception {
   74.49          assertEquals(Classes.reflectiveMethodCall(false, null), "java.io.IOException", "Calls the name() method via reflection");
   74.50      }
   74.51 @@ -116,6 +143,26 @@
   74.52              "java.io.IOException"
   74.53          );
   74.54      }
   74.55 +    @Test public void noInterface() throws Exception {
   74.56 +        assertExec("Calls Class.isInterface", Classes.class, 
   74.57 +            "isInterface__ZLjava_lang_String_2", 
   74.58 +            0.0, "java.lang.String"
   74.59 +        );
   74.60 +    }
   74.61 +    /*
   74.62 +    @Test public void isInterface() throws Exception {
   74.63 +        assertExec("Calls Class.isInterface", Classes.class, 
   74.64 +            "isInterface__ZLjava_lang_String_2", 
   74.65 +            1.0, "java.lang.Runnable"
   74.66 +        );
   74.67 +    }
   74.68 +    */
   74.69 +    @Test public void integerType() throws Exception {
   74.70 +        assertExec("Computes the type", Classes.class, 
   74.71 +            "intType__Ljava_lang_String_2", 
   74.72 +            Classes.intType()
   74.73 +        );
   74.74 +    }
   74.75      
   74.76      private static CharSequence codeSeq;
   74.77      private static Invocable code;
    75.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Fri Jan 18 14:23:18 2013 +0100
    75.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Fri Jan 18 14:27:22 2013 +0100
    75.3 @@ -38,6 +38,10 @@
    75.4          return c.getName();
    75.5      }
    75.6      
    75.7 +    public static boolean isInterface(String s) throws ClassNotFoundException {
    75.8 +        return Class.forName(s).isInterface();
    75.9 +    }
   75.10 +    
   75.11      public static boolean equalsClassesOfExceptions() {
   75.12          return MalformedURLException.class.getSuperclass() == IOException.class;
   75.13      }
   75.14 @@ -68,6 +72,14 @@
   75.15          }
   75.16          throw new IllegalStateException("Not a subtype: " + ioe);
   75.17      }
   75.18 +    public static String newInstanceNoPubConstructor() throws Exception {
   75.19 +        try {
   75.20 +            Float f = Float.class.newInstance();
   75.21 +            return "wrong, can't instantiate: " + f;
   75.22 +        } catch (Exception ex) {
   75.23 +            return (ex.getClass().getName() + ":" + ex.getMessage()).toString().toString();
   75.24 +        }
   75.25 +    }
   75.26      public static int getMarker() {
   75.27          if (!Classes.class.isAnnotationPresent(ClassesMarker.class)) {
   75.28              return -2;
   75.29 @@ -88,6 +100,21 @@
   75.30          return null;
   75.31      }
   75.32      
   75.33 +    public static String intType() {
   75.34 +        return Integer.TYPE.getName();
   75.35 +    }
   75.36 +    
   75.37 +    public static int primitive() {
   75.38 +        return 1;
   75.39 +    }
   75.40 +    public static boolean primitiveB() {
   75.41 +        return true;
   75.42 +    }
   75.43 +    
   75.44 +    public static String primitiveType(String method) throws Exception {
   75.45 +        return reflectiveMethodCall(false, method).getClass().getName();
   75.46 +    }
   75.47 +    
   75.48      @JavaScriptBody(args = "msg", body = "throw msg;")
   75.49      private static native void thrw(String msg);
   75.50      
   75.51 @@ -119,4 +146,9 @@
   75.52          }
   75.53          return find.invoke(null);
   75.54      }
   75.55 +    
   75.56 +    public static int reflectiveSum(int a, int b) throws Exception {
   75.57 +        Method m = StaticMethod.class.getMethod("sum", int.class, int.class);
   75.58 +        return (int) m.invoke(null, a, b);
   75.59 +    }
   75.60  }
    76.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Compare.java	Fri Jan 18 14:23:18 2013 +0100
    76.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.3 @@ -1,36 +0,0 @@
    76.4 -/**
    76.5 - * Back 2 Browser Bytecode Translator
    76.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    76.7 - *
    76.8 - * This program is free software: you can redistribute it and/or modify
    76.9 - * it under the terms of the GNU General Public License as published by
   76.10 - * the Free Software Foundation, version 2 of the License.
   76.11 - *
   76.12 - * This program is distributed in the hope that it will be useful,
   76.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   76.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   76.15 - * GNU General Public License for more details.
   76.16 - *
   76.17 - * You should have received a copy of the GNU General Public License
   76.18 - * along with this program. Look for COPYING file in the top folder.
   76.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   76.20 - */
   76.21 -package org.apidesign.vm4brwsr;
   76.22 -
   76.23 -import java.lang.annotation.ElementType;
   76.24 -import java.lang.annotation.Retention;
   76.25 -import java.lang.annotation.RetentionPolicy;
   76.26 -import java.lang.annotation.Target;
   76.27 -
   76.28 -/** Can be applied on a method that yields a return value. 
   76.29 - * Together with {@link VMCompare#create} it can be used to write
   76.30 - * methods which are executed in real as well as JavaScript VMs and
   76.31 - * their results are compared.
   76.32 - *
   76.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   76.34 - */
   76.35 -@Retention(RetentionPolicy.RUNTIME)
   76.36 -@Target(ElementType.METHOD)
   76.37 -public @interface Compare {
   76.38 -    
   76.39 -}
    77.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/CompareVMs.java	Fri Jan 18 14:23:18 2013 +0100
    77.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.3 @@ -1,197 +0,0 @@
    77.4 -/**
    77.5 - * Back 2 Browser Bytecode Translator
    77.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    77.7 - *
    77.8 - * This program is free software: you can redistribute it and/or modify
    77.9 - * it under the terms of the GNU General Public License as published by
   77.10 - * the Free Software Foundation, version 2 of the License.
   77.11 - *
   77.12 - * This program is distributed in the hope that it will be useful,
   77.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   77.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   77.15 - * GNU General Public License for more details.
   77.16 - *
   77.17 - * You should have received a copy of the GNU General Public License
   77.18 - * along with this program. Look for COPYING file in the top folder.
   77.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   77.20 - */
   77.21 -package org.apidesign.vm4brwsr;
   77.22 -
   77.23 -import java.lang.reflect.Method;
   77.24 -import java.util.Map;
   77.25 -import java.util.WeakHashMap;
   77.26 -import javax.script.Invocable;
   77.27 -import javax.script.ScriptContext;
   77.28 -import javax.script.ScriptEngine;
   77.29 -import javax.script.ScriptEngineManager;
   77.30 -import org.testng.Assert;
   77.31 -import org.testng.ITest;
   77.32 -import org.testng.annotations.Factory;
   77.33 -import org.testng.annotations.Test;
   77.34 -
   77.35 -/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
   77.36 - * in provided class and builds set of tests that compare the computations
   77.37 - * in real as well as JavaScript virtual machines. Use as:<pre>
   77.38 - * {@code @}{@link Factory} public static create() {
   77.39 - *   return @{link CompareVMs}.{@link #create(YourClass.class);
   77.40 - * }</pre>
   77.41 - *
   77.42 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   77.43 - */
   77.44 -public final class CompareVMs implements ITest {
   77.45 -    private final Run first, second;
   77.46 -    private final Method m;
   77.47 -    
   77.48 -    private CompareVMs(Method m, Run first, Run second) {
   77.49 -        this.first = first;
   77.50 -        this.second = second;
   77.51 -        this.m = m;
   77.52 -    }
   77.53 -
   77.54 -    public static Object[] create(Class<?> clazz) {
   77.55 -        Method[] arr = clazz.getMethods();
   77.56 -        Object[] ret = new Object[3 * arr.length];
   77.57 -        int cnt = 0;
   77.58 -        for (Method m : arr) {
   77.59 -            Compare c = m.getAnnotation(Compare.class);
   77.60 -            if (c == null) {
   77.61 -                continue;
   77.62 -            }
   77.63 -            final Run real = new Run(m, false);
   77.64 -            final Run js = new Run(m, true);
   77.65 -            ret[cnt++] = real;
   77.66 -            ret[cnt++] = js;
   77.67 -            ret[cnt++] = new CompareVMs(m, real, js);
   77.68 -        }
   77.69 -        Object[] r = new Object[cnt];
   77.70 -        for (int i = 0; i < cnt; i++) {
   77.71 -            r[i] = ret[i];
   77.72 -        }
   77.73 -        return r;
   77.74 -    }
   77.75 -    
   77.76 -    @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
   77.77 -        Object v1 = first.value;
   77.78 -        Object v2 = second.value;
   77.79 -        if (v1 instanceof Number) {
   77.80 -            v1 = ((Number)v1).doubleValue();
   77.81 -        }
   77.82 -        Assert.assertEquals(v2, v1, "Comparing results");
   77.83 -    }
   77.84 -    
   77.85 -    @Override
   77.86 -    public String getTestName() {
   77.87 -        return m.getName() + "[Compare]";
   77.88 -    }
   77.89 -    
   77.90 -    public static final class Run implements ITest {
   77.91 -        private final Method m;
   77.92 -        private final boolean js;
   77.93 -        Object value;
   77.94 -        private Invocable code;
   77.95 -        private CharSequence codeSeq;
   77.96 -        private static final Map<Class,Object[]> compiled = new WeakHashMap<Class,Object[]>();
   77.97 -
   77.98 -        private Run(Method m, boolean js) {
   77.99 -            this.m = m;
  77.100 -            this.js = js;
  77.101 -        }
  77.102 -
  77.103 -        private void compileTheCode(Class<?> clazz) throws Exception {
  77.104 -            final Object[] data = compiled.get(clazz);
  77.105 -            if (data != null) {
  77.106 -                code = (Invocable) data[0];
  77.107 -                codeSeq = (CharSequence) data[1];
  77.108 -                return;
  77.109 -            }
  77.110 -            StringBuilder sb = new StringBuilder();
  77.111 -            Bck2Brwsr.generate(sb, CompareVMs.class.getClassLoader());
  77.112 -
  77.113 -            ScriptEngineManager sem = new ScriptEngineManager();
  77.114 -            ScriptEngine js = sem.getEngineByExtension("js");
  77.115 -            js.getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
  77.116 -            
  77.117 -            sb.append("\nfunction initVM() {"
  77.118 -                + "\n  return bck2brwsr("
  77.119 -                + "\n    function(name) { return loader.get(name);}"
  77.120 -                + "\n  );"
  77.121 -                + "\n};");
  77.122 -
  77.123 -            Object res = js.eval(sb.toString());
  77.124 -            Assert.assertTrue(js instanceof Invocable, "It is invocable object: " + res);
  77.125 -            code = (Invocable) js;
  77.126 -            codeSeq = sb;
  77.127 -            compiled.put(clazz, new Object[] { code, codeSeq });
  77.128 -        }
  77.129 -
  77.130 -        @Test(groups = "run") public void executeCode() throws Throwable {
  77.131 -            if (js) {
  77.132 -                try {
  77.133 -                    compileTheCode(m.getDeclaringClass());
  77.134 -                    Object vm = code.invokeFunction("initVM");
  77.135 -                    Object inst = code.invokeMethod(vm, "loadClass", m.getDeclaringClass().getName());
  77.136 -                    value = code.invokeMethod(inst, m.getName() + "__" + computeSignature(m));
  77.137 -                } catch (Exception ex) {
  77.138 -                    throw new AssertionError(StaticMethodTest.dumpJS(codeSeq)).initCause(ex);
  77.139 -                }
  77.140 -            } else {
  77.141 -                value = m.invoke(m.getDeclaringClass().newInstance());
  77.142 -            }
  77.143 -        }
  77.144 -        @Override
  77.145 -        public String getTestName() {
  77.146 -            return m.getName() + (js ? "[JavaScript]" : "[Java]");
  77.147 -        }
  77.148 -        
  77.149 -        private static String computeSignature(Method m) {
  77.150 -            StringBuilder sb = new StringBuilder();
  77.151 -            appendType(sb, m.getReturnType());
  77.152 -            for (Class<?> c : m.getParameterTypes()) {
  77.153 -                appendType(sb, c);
  77.154 -            }
  77.155 -            return sb.toString();
  77.156 -        }
  77.157 -        
  77.158 -        private static void appendType(StringBuilder sb, Class<?> t) {
  77.159 -            if (t == null) {
  77.160 -                sb.append('V');
  77.161 -                return;
  77.162 -            }
  77.163 -            if (t.isPrimitive()) {
  77.164 -                int ch = -1;
  77.165 -                if (t == int.class) {
  77.166 -                    ch = 'I';
  77.167 -                }
  77.168 -                if (t == short.class) {
  77.169 -                    ch = 'S';
  77.170 -                }
  77.171 -                if (t == byte.class) {
  77.172 -                    ch = 'B';
  77.173 -                }
  77.174 -                if (t == boolean.class) {
  77.175 -                    ch = 'Z';
  77.176 -                }
  77.177 -                if (t == long.class) {
  77.178 -                    ch = 'J';
  77.179 -                }
  77.180 -                if (t == float.class) {
  77.181 -                    ch = 'F';
  77.182 -                }
  77.183 -                if (t == double.class) {
  77.184 -                    ch = 'D';
  77.185 -                }
  77.186 -                assert ch != -1 : "Unknown primitive type " + t;
  77.187 -                sb.append((char)ch);
  77.188 -                return;
  77.189 -            }
  77.190 -            if (t.isArray()) {
  77.191 -                sb.append("_3");
  77.192 -                appendType(sb, t.getComponentType());
  77.193 -                return;
  77.194 -            }
  77.195 -            sb.append('L');
  77.196 -            sb.append(t.getName().replace('.', '_'));
  77.197 -            sb.append("_2");
  77.198 -        }
  77.199 -    }
  77.200 -}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Exceptions.java	Fri Jan 18 14:27:22 2013 +0100
    78.3 @@ -0,0 +1,88 @@
    78.4 +/**
    78.5 + * Back 2 Browser Bytecode Translator
    78.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    78.7 + *
    78.8 + * This program is free software: you can redistribute it and/or modify
    78.9 + * it under the terms of the GNU General Public License as published by
   78.10 + * the Free Software Foundation, version 2 of the License.
   78.11 + *
   78.12 + * This program is distributed in the hope that it will be useful,
   78.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   78.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   78.15 + * GNU General Public License for more details.
   78.16 + *
   78.17 + * You should have received a copy of the GNU General Public License
   78.18 + * along with this program. Look for COPYING file in the top folder.
   78.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   78.20 + */
   78.21 +package org.apidesign.vm4brwsr;
   78.22 +
   78.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   78.24 +
   78.25 +/**
   78.26 + *
   78.27 + * @author tom
   78.28 + */
   78.29 +public class Exceptions {
   78.30 +    private Exceptions() {
   78.31 +    }
   78.32 +
   78.33 +    public static int methodWithTryCatchNoThrow() {
   78.34 +        int res = 0;
   78.35 +        try {
   78.36 +            res = 1;
   78.37 +        } catch (IllegalArgumentException e) {
   78.38 +            res = 2;
   78.39 +        }
   78.40 +        //join point
   78.41 +        return res;
   78.42 +    }
   78.43 +
   78.44 +    public static int methodWithTryCatchThrow() {
   78.45 +        int res = 0;
   78.46 +        try {
   78.47 +            res = 1;
   78.48 +            throw new IllegalArgumentException();
   78.49 +        } catch (IllegalArgumentException e) {
   78.50 +            res = 2;
   78.51 +        }
   78.52 +        //join point
   78.53 +        return res;
   78.54 +    }
   78.55 +    
   78.56 +    @JavaScriptBody(args = "msg", body = "throw msg;")
   78.57 +    public static void thrw(String msg) {}
   78.58 +    
   78.59 +    public static String catchThrowableCatchesAll() {
   78.60 +        try {
   78.61 +            thrw("Hello!");
   78.62 +            return "Not here!";
   78.63 +        } catch (Throwable ex) {
   78.64 +            return ex.getMessage();
   78.65 +        }
   78.66 +    }
   78.67 +
   78.68 +    public static String newInstance(String n) {
   78.69 +        try {
   78.70 +            Class c;
   78.71 +            try {
   78.72 +                c = Class.forName(n);
   78.73 +            } catch (ClassNotFoundException ex) {
   78.74 +                return ("CNFE:" + ex.getMessage()).toString();
   78.75 +            }
   78.76 +            return c.newInstance().getClass().getName();
   78.77 +        } catch (InstantiationException | IllegalAccessException ex) {
   78.78 +            return ex.getMessage();
   78.79 +        }
   78.80 +    }
   78.81 +    
   78.82 +    private static int counter;
   78.83 +    public static int readCounter(String n) throws ClassNotFoundException {
   78.84 +        try {
   78.85 +            Class.forName(n);
   78.86 +        } finally {
   78.87 +            counter++;
   78.88 +        }
   78.89 +        return counter;
   78.90 +    }
   78.91 +}
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java	Fri Jan 18 14:27:22 2013 +0100
    79.3 @@ -0,0 +1,121 @@
    79.4 +/**
    79.5 + * Back 2 Browser Bytecode Translator
    79.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    79.7 + *
    79.8 + * This program is free software: you can redistribute it and/or modify
    79.9 + * it under the terms of the GNU General Public License as published by
   79.10 + * the Free Software Foundation, version 2 of the License.
   79.11 + *
   79.12 + * This program is distributed in the hope that it will be useful,
   79.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   79.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   79.15 + * GNU General Public License for more details.
   79.16 + *
   79.17 + * You should have received a copy of the GNU General Public License
   79.18 + * along with this program. Look for COPYING file in the top folder.
   79.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   79.20 + */
   79.21 +package org.apidesign.vm4brwsr;
   79.22 +
   79.23 +import javax.script.Invocable;
   79.24 +import javax.script.ScriptException;
   79.25 +import static org.testng.Assert.*;
   79.26 +import org.testng.annotations.BeforeClass;
   79.27 +import org.testng.annotations.Test;
   79.28 +
   79.29 +/**
   79.30 + *
   79.31 + * @author Tomas Zezula <tzezula@netbeans.org>
   79.32 + */
   79.33 +public class ExceptionsTest {
   79.34 +    @Test
   79.35 +    public void verifyMethodWithTryCatchNoThrow() throws Exception {
   79.36 +            assertExec(
   79.37 +                    "No throw",
   79.38 +                    Exceptions.class,
   79.39 +                    "methodWithTryCatchNoThrow__I",
   79.40 +                    new Double(1.0));
   79.41 +    }
   79.42 +
   79.43 +    @Test
   79.44 +    public void catchJavaScriptStringAsThrowable() throws Exception {
   79.45 +        assertExec(
   79.46 +            "Throw hello!",
   79.47 +            Exceptions.class,
   79.48 +            "catchThrowableCatchesAll__Ljava_lang_String_2",
   79.49 +            "Hello!"
   79.50 +        );
   79.51 +    }
   79.52 +
   79.53 +    @Test
   79.54 +    public void verifyMethodWithTryCatchThrow() throws Exception {
   79.55 +            assertExec(
   79.56 +                    "Throw",
   79.57 +                    Exceptions.class,
   79.58 +                    "methodWithTryCatchThrow__I",
   79.59 +                    new Double(2.0));
   79.60 +    }
   79.61 +    
   79.62 +    @Test public void createObject() throws Exception {
   79.63 +        assertExec("Object created", Exceptions.class, 
   79.64 +            "newInstance__Ljava_lang_String_2Ljava_lang_String_2",
   79.65 +            "java.lang.Object",
   79.66 +            "java.lang.Object"
   79.67 +        );
   79.68 +    }
   79.69 +
   79.70 +    @Test public void createFloatFails() throws Exception {
   79.71 +        assertExec("Float not created", Exceptions.class, 
   79.72 +            "newInstance__Ljava_lang_String_2Ljava_lang_String_2",
   79.73 +            "java.lang.Float",
   79.74 +            "java.lang.Float"
   79.75 +        );
   79.76 +    }
   79.77 +
   79.78 +    @Test public void createUnknownFails() throws Exception {
   79.79 +        assertExec("Object created", Exceptions.class, 
   79.80 +            "newInstance__Ljava_lang_String_2Ljava_lang_String_2",
   79.81 +            "CNFE:org.apidesign.Unknown",
   79.82 +            "org.apidesign.Unknown"
   79.83 +        );
   79.84 +    }
   79.85 +    
   79.86 +    @Test public void testThreeCalls() throws Exception {
   79.87 +        Object vm = code.invokeFunction("bck2brwsr");
   79.88 +        Object clazz = code.invokeMethod(vm, "loadClass", Exceptions.class.getName());
   79.89 +        
   79.90 +        String method = "readCounter__ILjava_lang_String_2";
   79.91 +        
   79.92 +        try {
   79.93 +            Object ret = code.invokeMethod(clazz, method, "org.apidesign.Unknown");
   79.94 +            fail("We expect an CNFE!");
   79.95 +        } catch (ScriptException scriptException) {
   79.96 +            // script exception should be OK
   79.97 +        }
   79.98 +        {
   79.99 +            // 2nd invocation
  79.100 +            Object ret = code.invokeMethod(clazz, method, "java.lang.String");
  79.101 +            assertEquals(ret, Double.valueOf(2));
  79.102 +        }
  79.103 +        {
  79.104 +            // 3rd invocation
  79.105 +            Object ret = code.invokeMethod(clazz, method, "java.lang.Integer");
  79.106 +            assertEquals(ret, Double.valueOf(3));
  79.107 +        }
  79.108 +    }
  79.109 +    
  79.110 +    private static CharSequence codeSeq;
  79.111 +    private static Invocable code;
  79.112 +    
  79.113 +    @BeforeClass 
  79.114 +    public void compileTheCode() throws Exception {
  79.115 +        StringBuilder sb = new StringBuilder();
  79.116 +        code = StaticMethodTest.compileClass(sb, 
  79.117 +            "org/apidesign/vm4brwsr/Exceptions"
  79.118 +        );
  79.119 +        codeSeq = sb;
  79.120 +    }
  79.121 +    private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
  79.122 +        StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args);
  79.123 +    }
  79.124 +}
    80.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Fri Jan 18 14:23:18 2013 +0100
    80.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Instance.java	Fri Jan 18 14:27:22 2013 +0100
    80.3 @@ -125,4 +125,11 @@
    80.4      public static boolean iofObject() {
    80.5          return jsObj() instanceof Object;
    80.6      }
    80.7 +    
    80.8 +    public static int jscall() {
    80.9 +        return jsgetbytes(new Instance());
   80.10 +    }
   80.11 +    
   80.12 +    @JavaScriptBody(args = { "instance" }, body = "return instance.getByte__B();")
   80.13 +    private static native int jsgetbytes(Instance instance);
   80.14  }
    81.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Fri Jan 18 14:23:18 2013 +0100
    81.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Fri Jan 18 14:27:22 2013 +0100
    81.3 @@ -131,6 +131,14 @@
    81.4              Double.valueOf(1)
    81.5          );
    81.6      }
    81.7 +
    81.8 +    @Test public void jsCallingConvention() throws Exception {
    81.9 +        assertExec(
   81.10 +            "Pointer to 'this' is passed automatically (and not as a first argument)",
   81.11 +            Instance.class, "jscall__I",
   81.12 +            Double.valueOf(31)
   81.13 +        );
   81.14 +    }
   81.15      
   81.16      protected String startCompilationWith() {
   81.17          return "org/apidesign/vm4brwsr/Instance";
    82.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Fri Jan 18 14:23:18 2013 +0100
    82.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Fri Jan 18 14:27:22 2013 +0100
    82.3 @@ -20,7 +20,6 @@
    82.4  import java.io.File;
    82.5  import java.io.FileWriter;
    82.6  import java.io.IOException;
    82.7 -import java.io.InputStream;
    82.8  import static org.testng.Assert.*;
    82.9  import javax.script.Invocable;
   82.10  import org.testng.annotations.BeforeClass;
   82.11 @@ -36,13 +35,13 @@
   82.12      private static Invocable code;
   82.13      
   82.14      @Test public void compareGeneratedCodeForArrayClass() throws Exception {
   82.15 -        compareCode("/org/apidesign/vm4brwsr/Array.class");
   82.16 +        compareCode("org/apidesign/vm4brwsr/Array.class");
   82.17      }
   82.18  
   82.19      @Test public void compareGeneratedCodeForClassesClass() throws Exception {
   82.20 -        compareCode("/org/apidesign/vm4brwsr/Classes.class");
   82.21 +        compareCode("org/apidesign/vm4brwsr/Classes.class");
   82.22      }
   82.23 -    
   82.24 +
   82.25      @BeforeClass
   82.26      public void compileTheCode() throws Exception {
   82.27          StringBuilder sb = new StringBuilder();
   82.28 @@ -52,20 +51,8 @@
   82.29          codeSeq = sb;
   82.30      }
   82.31      
   82.32 -    private static byte[] readClass(String res) throws IOException {
   82.33 -        InputStream is1 = VMinVMTest.class.getResourceAsStream(res);
   82.34 -        assertNotNull(is1, "Stream found");
   82.35 -        byte[] arr = new byte[is1.available()];
   82.36 -        int len = is1.read(arr);
   82.37 -        is1.close();
   82.38 -        if (len != arr.length) {
   82.39 -            throw new IOException("Wrong len " + len + " for arr: " + arr.length);
   82.40 -        }
   82.41 -        return arr;
   82.42 -    }
   82.43 -
   82.44      private void compareCode(final String nm) throws Exception, IOException {
   82.45 -        byte[] arr = readClass(nm);
   82.46 +        byte[] arr = BytesLoader.readClass(nm);
   82.47          String ret1 = VMinVM.toJavaScript(arr);
   82.48          
   82.49          Object ret;
    83.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareHashTest.java	Fri Jan 18 14:23:18 2013 +0100
    83.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.3 @@ -1,37 +0,0 @@
    83.4 -/**
    83.5 - * Back 2 Browser Bytecode Translator
    83.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    83.7 - *
    83.8 - * This program is free software: you can redistribute it and/or modify
    83.9 - * it under the terms of the GNU General Public License as published by
   83.10 - * the Free Software Foundation, version 2 of the License.
   83.11 - *
   83.12 - * This program is distributed in the hope that it will be useful,
   83.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   83.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   83.15 - * GNU General Public License for more details.
   83.16 - *
   83.17 - * You should have received a copy of the GNU General Public License
   83.18 - * along with this program. Look for COPYING file in the top folder.
   83.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   83.20 - */
   83.21 -package org.apidesign.vm4brwsr.tck;
   83.22 -
   83.23 -import org.apidesign.vm4brwsr.Compare;
   83.24 -import org.apidesign.vm4brwsr.CompareVMs;
   83.25 -import org.testng.annotations.Factory;
   83.26 -
   83.27 -/**
   83.28 - *
   83.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   83.30 - */
   83.31 -public class CompareHashTest {
   83.32 -    @Compare public int hashOfString() {
   83.33 -        return "Ahoj".hashCode();
   83.34 -    }
   83.35 -    
   83.36 -    @Factory
   83.37 -    public static Object[] create() {
   83.38 -        return CompareVMs.create(CompareHashTest.class);
   83.39 -    }
   83.40 -}
    84.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/tck/CompareStringsTest.java	Fri Jan 18 14:23:18 2013 +0100
    84.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.3 @@ -1,43 +0,0 @@
    84.4 -/**
    84.5 - * Back 2 Browser Bytecode Translator
    84.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    84.7 - *
    84.8 - * This program is free software: you can redistribute it and/or modify
    84.9 - * it under the terms of the GNU General Public License as published by
   84.10 - * the Free Software Foundation, version 2 of the License.
   84.11 - *
   84.12 - * This program is distributed in the hope that it will be useful,
   84.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   84.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   84.15 - * GNU General Public License for more details.
   84.16 - *
   84.17 - * You should have received a copy of the GNU General Public License
   84.18 - * along with this program. Look for COPYING file in the top folder.
   84.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
   84.20 - */
   84.21 -package org.apidesign.vm4brwsr.tck;
   84.22 -
   84.23 -import org.apidesign.vm4brwsr.Compare;
   84.24 -import org.apidesign.vm4brwsr.CompareVMs;
   84.25 -import org.testng.annotations.Factory;
   84.26 -
   84.27 -/**
   84.28 - *
   84.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
   84.30 - */
   84.31 -public class CompareStringsTest {
   84.32 -    @Compare public String deleteLastTwoCharacters() {
   84.33 -        StringBuilder sb = new StringBuilder();
   84.34 -        sb.append("453.0");
   84.35 -        if (sb.toString().endsWith(".0")) {
   84.36 -            final int l = sb.length();
   84.37 -            sb.delete(l - 2, l);
   84.38 -        }
   84.39 -        return sb.toString().toString();
   84.40 -    }
   84.41 -    
   84.42 -    @Factory
   84.43 -    public static Object[] create() {
   84.44 -        return CompareVMs.create(CompareStringsTest.class);
   84.45 -    }
   84.46 -}
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/vmtest/pom.xml	Fri Jan 18 14:27:22 2013 +0100
    85.3 @@ -0,0 +1,61 @@
    85.4 +<?xml version="1.0"?>
    85.5 +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    85.6 +    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    85.7 +  <modelVersion>4.0.0</modelVersion>
    85.8 +  <parent>
    85.9 +    <groupId>org.apidesign</groupId>
   85.10 +    <artifactId>bck2brwsr</artifactId>
   85.11 +    <version>0.3-SNAPSHOT</version>
   85.12 +  </parent>
   85.13 +  <groupId>org.apidesign.bck2brwsr</groupId>
   85.14 +  <artifactId>vmtest</artifactId>
   85.15 +  <version>0.3-SNAPSHOT</version>
   85.16 +  
   85.17 +  <name>VM Testing APIs</name>
   85.18 +  <url>http://bck2brwsr.apidesign.org</url>
   85.19 +    <build>
   85.20 +        <plugins>
   85.21 +            <plugin>
   85.22 +                <groupId>org.apache.maven.plugins</groupId>
   85.23 +                <artifactId>maven-compiler-plugin</artifactId>
   85.24 +                <version>2.3.2</version>
   85.25 +                <configuration>
   85.26 +                    <source>1.7</source>
   85.27 +                    <target>1.7</target>
   85.28 +                </configuration>
   85.29 +            </plugin>
   85.30 +        </plugins>
   85.31 +    </build>
   85.32 +    <properties>
   85.33 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   85.34 +  </properties>
   85.35 +  <dependencies>
   85.36 +    <dependency>
   85.37 +      <groupId>org.testng</groupId>
   85.38 +      <artifactId>testng</artifactId>
   85.39 +      <scope>compile</scope>
   85.40 +      <exclusions>
   85.41 +        <exclusion>
   85.42 +          <artifactId>junit</artifactId>
   85.43 +          <groupId>junit</groupId>
   85.44 +        </exclusion>
   85.45 +      </exclusions>
   85.46 +    </dependency>
   85.47 +    <dependency>
   85.48 +      <groupId>${project.groupId}</groupId>
   85.49 +      <artifactId>vm4brwsr</artifactId>
   85.50 +      <version>0.3-SNAPSHOT</version>
   85.51 +      <type>jar</type>
   85.52 +    </dependency>
   85.53 +    <dependency>
   85.54 +      <groupId>${project.groupId}</groupId>
   85.55 +      <artifactId>emul</artifactId>
   85.56 +      <version>0.3-SNAPSHOT</version>
   85.57 +    </dependency>
   85.58 +    <dependency>
   85.59 +      <groupId>${project.groupId}</groupId>
   85.60 +      <artifactId>launcher</artifactId>
   85.61 +      <version>${project.version}</version>
   85.62 +    </dependency>
   85.63 +  </dependencies>
   85.64 +</project>
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Compare.java	Fri Jan 18 14:27:22 2013 +0100
    86.3 @@ -0,0 +1,36 @@
    86.4 +/**
    86.5 + * Back 2 Browser Bytecode Translator
    86.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    86.7 + *
    86.8 + * This program is free software: you can redistribute it and/or modify
    86.9 + * it under the terms of the GNU General Public License as published by
   86.10 + * the Free Software Foundation, version 2 of the License.
   86.11 + *
   86.12 + * This program is distributed in the hope that it will be useful,
   86.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   86.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   86.15 + * GNU General Public License for more details.
   86.16 + *
   86.17 + * You should have received a copy of the GNU General Public License
   86.18 + * along with this program. Look for COPYING file in the top folder.
   86.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   86.20 + */
   86.21 +package org.apidesign.bck2brwsr.vmtest;
   86.22 +
   86.23 +import java.lang.annotation.ElementType;
   86.24 +import java.lang.annotation.Retention;
   86.25 +import java.lang.annotation.RetentionPolicy;
   86.26 +import java.lang.annotation.Target;
   86.27 +
   86.28 +/** Can be applied on a method that yields a return value. 
   86.29 + * Together with {@link VMTest#create} it can be used to write
   86.30 + * methods which are executed in real as well as JavaScript VMs and
   86.31 + * their results are compared.
   86.32 + *
   86.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   86.34 + */
   86.35 +@Retention(RetentionPolicy.RUNTIME)
   86.36 +@Target(ElementType.METHOD)
   86.37 +public @interface Compare {
   86.38 +    
   86.39 +}
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Fri Jan 18 14:27:22 2013 +0100
    87.3 @@ -0,0 +1,43 @@
    87.4 +/**
    87.5 + * Back 2 Browser Bytecode Translator
    87.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    87.7 + *
    87.8 + * This program is free software: you can redistribute it and/or modify
    87.9 + * it under the terms of the GNU General Public License as published by
   87.10 + * the Free Software Foundation, version 2 of the License.
   87.11 + *
   87.12 + * This program is distributed in the hope that it will be useful,
   87.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   87.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   87.15 + * GNU General Public License for more details.
   87.16 + *
   87.17 + * You should have received a copy of the GNU General Public License
   87.18 + * along with this program. Look for COPYING file in the top folder.
   87.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   87.20 + */
   87.21 +package org.apidesign.bck2brwsr.vmtest;
   87.22 +
   87.23 +import org.apidesign.bck2brwsr.vmtest.impl.CompareCase;
   87.24 +import org.testng.annotations.Factory;
   87.25 +
   87.26 +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
   87.27 + * in provided class and builds set of tests that compare the computations
   87.28 + * in real as well as JavaScript virtual machines. Use as:<pre>
   87.29 + * {@code @}{@link Factory} public static create() {
   87.30 + *   return @{link VMTest}.{@link #create(YourClass.class);
   87.31 + * }</pre>
   87.32 + *
   87.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   87.34 + */
   87.35 +public final class VMTest {
   87.36 +    /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
   87.37 +     * instances of tests. Each instance runs the test in different virtual
   87.38 +     * machine and at the end they compare the results.
   87.39 +     * 
   87.40 +     * @param clazz the class to inspect
   87.41 +     * @return the set of created tests
   87.42 +     */
   87.43 +    public static Object[] create(Class<?> clazz) {
   87.44 +        return CompareCase.create(clazz);
   87.45 +    }
   87.46 +}
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Fri Jan 18 14:27:22 2013 +0100
    88.3 @@ -0,0 +1,80 @@
    88.4 +/**
    88.5 + * Back 2 Browser Bytecode Translator
    88.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    88.7 + *
    88.8 + * This program is free software: you can redistribute it and/or modify
    88.9 + * it under the terms of the GNU General Public License as published by
   88.10 + * the Free Software Foundation, version 2 of the License.
   88.11 + *
   88.12 + * This program is distributed in the hope that it will be useful,
   88.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   88.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   88.15 + * GNU General Public License for more details.
   88.16 + *
   88.17 + * You should have received a copy of the GNU General Public License
   88.18 + * along with this program. Look for COPYING file in the top folder.
   88.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   88.20 + */
   88.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   88.22 +
   88.23 +import java.io.File;
   88.24 +import java.io.FileWriter;
   88.25 +import java.io.IOException;
   88.26 +import java.lang.reflect.InvocationTargetException;
   88.27 +import java.lang.reflect.Method;
   88.28 +import java.util.Map;
   88.29 +import java.util.WeakHashMap;
   88.30 +import org.apidesign.bck2brwsr.launcher.Launcher;
   88.31 +import org.apidesign.bck2brwsr.launcher.MethodInvocation;
   88.32 +import org.testng.ITest;
   88.33 +import org.testng.annotations.Test;
   88.34 +
   88.35 +/**
   88.36 + *
   88.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   88.38 + */
   88.39 +public final class Bck2BrwsrCase implements ITest {
   88.40 +    private final Method m;
   88.41 +    private final Launcher l;
   88.42 +    private final String type;
   88.43 +    Object value;
   88.44 +    private static final Map<Class, Object[]> compiled = new WeakHashMap<>();
   88.45 +    private Object inst;
   88.46 +
   88.47 +    Bck2BrwsrCase(Method m, String type, Launcher l) {
   88.48 +        this.l = l;
   88.49 +        this.m = m;
   88.50 +        this.type = type;
   88.51 +    }
   88.52 +
   88.53 +    @Test(groups = "run")
   88.54 +    public void executeCode() throws Throwable {
   88.55 +        if (l != null) {
   88.56 +            MethodInvocation c = l.invokeMethod(m.getDeclaringClass(), m.getName());
   88.57 +            value = c.toString();
   88.58 +        } else {
   88.59 +            try {
   88.60 +                value = m.invoke(m.getDeclaringClass().newInstance());
   88.61 +            } catch (InvocationTargetException ex) {
   88.62 +                Throwable t = ex.getTargetException();
   88.63 +                value = t.getClass().getName() + ":" + t.getMessage();
   88.64 +            }
   88.65 +        }
   88.66 +    }
   88.67 +
   88.68 +    @Override
   88.69 +    public String getTestName() {
   88.70 +        return m.getName() + "[" + typeName() + "]";
   88.71 +    }
   88.72 +
   88.73 +    final String typeName() {
   88.74 +        return type;
   88.75 +    }
   88.76 +    static void dumpJS(StringBuilder sb, Bck2BrwsrCase c) throws IOException {
   88.77 +        File f = File.createTempFile(c.m.getName(), ".js");
   88.78 +        try (final FileWriter w = new FileWriter(f)) {
   88.79 +            w.append(c.l.toString());
   88.80 +        }
   88.81 +        sb.append("Path: ").append(f.getPath());
   88.82 +    }
   88.83 +}
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Fri Jan 18 14:27:22 2013 +0100
    89.3 @@ -0,0 +1,126 @@
    89.4 +/**
    89.5 + * Back 2 Browser Bytecode Translator
    89.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    89.7 + *
    89.8 + * This program is free software: you can redistribute it and/or modify
    89.9 + * it under the terms of the GNU General Public License as published by
   89.10 + * the Free Software Foundation, version 2 of the License.
   89.11 + *
   89.12 + * This program is distributed in the hope that it will be useful,
   89.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   89.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   89.15 + * GNU General Public License for more details.
   89.16 + *
   89.17 + * You should have received a copy of the GNU General Public License
   89.18 + * along with this program. Look for COPYING file in the top folder.
   89.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   89.20 + */
   89.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   89.22 +
   89.23 +import org.apidesign.bck2brwsr.vmtest.*;
   89.24 +import java.io.File;
   89.25 +import java.io.FileWriter;
   89.26 +import java.io.IOException;
   89.27 +import java.lang.reflect.Method;
   89.28 +import java.util.ArrayList;
   89.29 +import java.util.List;
   89.30 +import org.apidesign.bck2brwsr.launcher.Launcher;
   89.31 +import org.testng.Assert;
   89.32 +import org.testng.ITest;
   89.33 +import org.testng.annotations.Factory;
   89.34 +import org.testng.annotations.Test;
   89.35 +
   89.36 +/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
   89.37 + * in provided class and builds set of tests that compare the computations
   89.38 + * in real as well as JavaScript virtual machines. Use as:<pre>
   89.39 + * {@code @}{@link Factory} public static create() {
   89.40 + *   return @{link VMTest}.{@link #create(YourClass.class);
   89.41 + * }</pre>
   89.42 + *
   89.43 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   89.44 + */
   89.45 +public final class CompareCase implements ITest {
   89.46 +    private final Bck2BrwsrCase first, second;
   89.47 +    private final Method m;
   89.48 +    
   89.49 +    private CompareCase(Method m, Bck2BrwsrCase first, Bck2BrwsrCase second) {
   89.50 +        this.first = first;
   89.51 +        this.second = second;
   89.52 +        this.m = m;
   89.53 +    }
   89.54 +
   89.55 +    /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
   89.56 +     * instances of tests. Each instance runs the test in different virtual
   89.57 +     * machine and at the end they compare the results.
   89.58 +     * 
   89.59 +     * @param clazz the class to inspect
   89.60 +     * @return the set of created tests
   89.61 +     */
   89.62 +    public static Object[] create(Class<?> clazz) {
   89.63 +        Method[] arr = clazz.getMethods();
   89.64 +        List<Object> ret = new ArrayList<>();
   89.65 +        
   89.66 +        final LaunchSetup l = LaunchSetup.INSTANCE;
   89.67 +        ret.add(l);
   89.68 +        
   89.69 +        String[] brwsr;
   89.70 +        {
   89.71 +            String p = System.getProperty("vmtest.brwsrs");
   89.72 +            if (p != null) {
   89.73 +                brwsr = p.split(",");
   89.74 +            } else {
   89.75 +                brwsr = new String[0];
   89.76 +            }
   89.77 +        }
   89.78 +        
   89.79 +        for (Method m : arr) {
   89.80 +            Compare c = m.getAnnotation(Compare.class);
   89.81 +            if (c == null) {
   89.82 +                continue;
   89.83 +            }
   89.84 +            final Bck2BrwsrCase real = new Bck2BrwsrCase(m, "Java", null);
   89.85 +            final Bck2BrwsrCase js = new Bck2BrwsrCase(m, "JavaScript", l.javaScript());
   89.86 +            ret.add(real);
   89.87 +            ret.add(js);
   89.88 +            ret.add(new CompareCase(m, real, js));
   89.89 +
   89.90 +            for (String b : brwsr) {
   89.91 +                final Launcher s = l.brwsr(b);
   89.92 +                ret.add(s);
   89.93 +                final Bck2BrwsrCase cse = new Bck2BrwsrCase(m, b, s);
   89.94 +                ret.add(cse);
   89.95 +                ret.add(new CompareCase(m, real, cse));
   89.96 +            }
   89.97 +        }
   89.98 +        return ret.toArray();
   89.99 +    }
  89.100 +
  89.101 +    /** Test that compares the previous results.
  89.102 +     * @throws Throwable 
  89.103 +     */
  89.104 +    @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
  89.105 +        Object v1 = first.value;
  89.106 +        Object v2 = second.value;
  89.107 +        if (v1 != null) {
  89.108 +            v1 = v1.toString();
  89.109 +        } else {
  89.110 +            v1 = "null";
  89.111 +        }
  89.112 +        try {
  89.113 +            Assert.assertEquals(v2, v1, "Comparing results");
  89.114 +        } catch (AssertionError e) {
  89.115 +            StringBuilder sb = new StringBuilder();
  89.116 +            sb.append(e.getMessage());
  89.117 +            Bck2BrwsrCase.dumpJS(sb, second);
  89.118 +            throw new AssertionError(sb.toString());
  89.119 +        }
  89.120 +    }
  89.121 +    
  89.122 +    /** Test name.
  89.123 +     * @return name of the tested method followed by a suffix
  89.124 +     */
  89.125 +    @Override
  89.126 +    public String getTestName() {
  89.127 +        return m.getName() + "[Compare " + second.typeName() + "]";
  89.128 +    }
  89.129 +}
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/LaunchSetup.java	Fri Jan 18 14:27:22 2013 +0100
    90.3 @@ -0,0 +1,68 @@
    90.4 +/**
    90.5 + * Back 2 Browser Bytecode Translator
    90.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    90.7 + *
    90.8 + * This program is free software: you can redistribute it and/or modify
    90.9 + * it under the terms of the GNU General Public License as published by
   90.10 + * the Free Software Foundation, version 2 of the License.
   90.11 + *
   90.12 + * This program is distributed in the hope that it will be useful,
   90.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   90.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   90.15 + * GNU General Public License for more details.
   90.16 + *
   90.17 + * You should have received a copy of the GNU General Public License
   90.18 + * along with this program. Look for COPYING file in the top folder.
   90.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   90.20 + */
   90.21 +package org.apidesign.bck2brwsr.vmtest.impl;
   90.22 +
   90.23 +import java.io.IOException;
   90.24 +import java.util.LinkedHashMap;
   90.25 +import java.util.Map;
   90.26 +import org.apidesign.bck2brwsr.launcher.Launcher;
   90.27 +import org.testng.annotations.AfterGroups;
   90.28 +import org.testng.annotations.BeforeGroups;
   90.29 +
   90.30 +/**
   90.31 + *
   90.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   90.33 + */
   90.34 +public final class LaunchSetup {
   90.35 +    static LaunchSetup INSTANCE = new LaunchSetup();
   90.36 +    
   90.37 +    private final Launcher js = Launcher.createJavaScript();
   90.38 +    private final Map<String,Launcher> brwsrs = new LinkedHashMap<>();
   90.39 +    
   90.40 +    private LaunchSetup() {
   90.41 +    }
   90.42 +    
   90.43 +    public  Launcher javaScript() {
   90.44 +        return js;
   90.45 +    } 
   90.46 +    
   90.47 +    public synchronized Launcher brwsr(String cmd) {
   90.48 +        Launcher s = brwsrs.get(cmd);
   90.49 +        if (s == null) {
   90.50 +            s = Launcher.createBrowser(cmd);
   90.51 +            brwsrs.put(cmd, s);
   90.52 +        }
   90.53 +        return s;
   90.54 +    }
   90.55 +
   90.56 +    @BeforeGroups("run")
   90.57 +    public void initializeLauncher() throws IOException {
   90.58 +        js.initialize();
   90.59 +        for (Launcher launcher : brwsrs.values()) {
   90.60 +            launcher.initialize();
   90.61 +        }
   90.62 +    }
   90.63 +
   90.64 +    @AfterGroups("run")
   90.65 +    public void shutDownLauncher() throws IOException, InterruptedException {
   90.66 +        js.shutdown();
   90.67 +        for (Launcher launcher : brwsrs.values()) {
   90.68 +            launcher.shutdown();
   90.69 +        }
   90.70 +    }
   90.71 +}
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java	Fri Jan 18 14:27:22 2013 +0100
    91.3 @@ -0,0 +1,102 @@
    91.4 +/**
    91.5 + * Back 2 Browser Bytecode Translator
    91.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    91.7 + *
    91.8 + * This program is free software: you can redistribute it and/or modify
    91.9 + * it under the terms of the GNU General Public License as published by
   91.10 + * the Free Software Foundation, version 2 of the License.
   91.11 + *
   91.12 + * This program is distributed in the hope that it will be useful,
   91.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   91.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   91.15 + * GNU General Public License for more details.
   91.16 + *
   91.17 + * You should have received a copy of the GNU General Public License
   91.18 + * along with this program. Look for COPYING file in the top folder.
   91.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   91.20 + */
   91.21 +package org.apidesign.bck2brwsr.tck;
   91.22 +
   91.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   91.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   91.25 +import org.testng.annotations.Factory;
   91.26 +
   91.27 +/**
   91.28 + *
   91.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   91.30 + */
   91.31 +public class ByteArithmeticTest {
   91.32 +    
   91.33 +    private static byte add(byte x, byte y) {
   91.34 +        return (byte)(x + y);
   91.35 +    }
   91.36 +    
   91.37 +    private static byte sub(byte x, byte y) {
   91.38 +        return (byte)(x - y);
   91.39 +    }
   91.40 +    
   91.41 +    private static byte mul(byte x, byte y) {
   91.42 +        return (byte)(x * y);
   91.43 +    }
   91.44 +    
   91.45 +    private static byte div(byte x, byte y) {
   91.46 +        return (byte)(x / y);
   91.47 +    }
   91.48 +    
   91.49 +    private static byte mod(byte x, byte y) {
   91.50 +        return (byte)(x % y);
   91.51 +    }
   91.52 +    
   91.53 +    @Compare public byte conversion() {
   91.54 +        return (byte)123456;
   91.55 +    }
   91.56 +    
   91.57 +    @Compare public byte addOverflow() {
   91.58 +        return add(Byte.MAX_VALUE, (byte)1);
   91.59 +    }
   91.60 +    
   91.61 +    @Compare public byte subUnderflow() {
   91.62 +        return sub(Byte.MIN_VALUE, (byte)1);
   91.63 +    }
   91.64 +    
   91.65 +    @Compare public byte addMaxByteAndMaxByte() {
   91.66 +        return add(Byte.MAX_VALUE, Byte.MAX_VALUE);
   91.67 +    }
   91.68 +    
   91.69 +    @Compare public byte subMinByteAndMinByte() {
   91.70 +        return sub(Byte.MIN_VALUE, Byte.MIN_VALUE);
   91.71 +    }
   91.72 +    
   91.73 +    @Compare public byte multiplyMaxByte() {
   91.74 +        return mul(Byte.MAX_VALUE, (byte)2);
   91.75 +    }
   91.76 +    
   91.77 +    @Compare public byte multiplyMaxByteAndMaxByte() {
   91.78 +        return mul(Byte.MAX_VALUE, Byte.MAX_VALUE);
   91.79 +    }
   91.80 +    
   91.81 +    @Compare public byte multiplyMinByte() {
   91.82 +        return mul(Byte.MIN_VALUE, (byte)2);
   91.83 +    }
   91.84 +    
   91.85 +    @Compare public byte multiplyMinByteAndMinByte() {
   91.86 +        return mul(Byte.MIN_VALUE, Byte.MIN_VALUE);
   91.87 +    }
   91.88 +    
   91.89 +    @Compare public byte multiplyPrecision() {
   91.90 +        return mul((byte)17638, (byte)1103);
   91.91 +    }
   91.92 +    
   91.93 +    @Compare public byte division() {
   91.94 +        return div((byte)1, (byte)2);
   91.95 +    }
   91.96 +    
   91.97 +    @Compare public byte divisionReminder() {
   91.98 +        return mod((byte)1, (byte)2);
   91.99 +    }
  91.100 +    
  91.101 +    @Factory
  91.102 +    public static Object[] create() {
  91.103 +        return VMTest.create(ByteArithmeticTest.class);
  91.104 +    }
  91.105 +}
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java	Fri Jan 18 14:27:22 2013 +0100
    92.3 @@ -0,0 +1,73 @@
    92.4 +/**
    92.5 + * Back 2 Browser Bytecode Translator
    92.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    92.7 + *
    92.8 + * This program is free software: you can redistribute it and/or modify
    92.9 + * it under the terms of the GNU General Public License as published by
   92.10 + * the Free Software Foundation, version 2 of the License.
   92.11 + *
   92.12 + * This program is distributed in the hope that it will be useful,
   92.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   92.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   92.15 + * GNU General Public License for more details.
   92.16 + *
   92.17 + * You should have received a copy of the GNU General Public License
   92.18 + * along with this program. Look for COPYING file in the top folder.
   92.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   92.20 + */
   92.21 +package org.apidesign.bck2brwsr.tck;
   92.22 +
   92.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   92.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   92.25 +import org.testng.annotations.Factory;
   92.26 +
   92.27 +/**
   92.28 + *
   92.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   92.30 + */
   92.31 +public class CloneTest {
   92.32 +    private int value;
   92.33 +    
   92.34 +    @Compare
   92.35 +    public Object notSupported() throws CloneNotSupportedException {
   92.36 +        return this.clone();
   92.37 +    }
   92.38 +
   92.39 +    @Compare public String sameClass() throws CloneNotSupportedException {
   92.40 +        return new Clnbl().clone().getClass().getName();
   92.41 +    }
   92.42 +
   92.43 +    @Compare public boolean differentInstance() throws CloneNotSupportedException {
   92.44 +        Clnbl orig = new Clnbl();
   92.45 +        return orig == orig.clone();
   92.46 +    }
   92.47 +
   92.48 +    @Compare public int sameReference() throws CloneNotSupportedException {
   92.49 +        CloneTest self = this;
   92.50 +        Clnbl orig = new Clnbl();
   92.51 +        self.value = 33;
   92.52 +        orig.ref = self;
   92.53 +        return ((Clnbl)orig.clone()).ref.value;
   92.54 +    }
   92.55 +
   92.56 +    @Compare public int sameValue() throws CloneNotSupportedException {
   92.57 +        Clnbl orig = new Clnbl();
   92.58 +        orig.value = 10;
   92.59 +        return ((Clnbl)orig.clone()).value;
   92.60 +    }
   92.61 +    
   92.62 +    @Factory
   92.63 +    public static Object[] create() {
   92.64 +        return VMTest.create(CloneTest.class);
   92.65 +    }
   92.66 +    
   92.67 +    public static final class Clnbl implements Cloneable {
   92.68 +        public CloneTest ref;
   92.69 +        private int value;
   92.70 +
   92.71 +        @Override
   92.72 +        public Object clone() throws CloneNotSupportedException {
   92.73 +            return super.clone();
   92.74 +        }
   92.75 +    }
   92.76 +}
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java	Fri Jan 18 14:27:22 2013 +0100
    93.3 @@ -0,0 +1,93 @@
    93.4 +/**
    93.5 + * Back 2 Browser Bytecode Translator
    93.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    93.7 + *
    93.8 + * This program is free software: you can redistribute it and/or modify
    93.9 + * it under the terms of the GNU General Public License as published by
   93.10 + * the Free Software Foundation, version 2 of the License.
   93.11 + *
   93.12 + * This program is distributed in the hope that it will be useful,
   93.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   93.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   93.15 + * GNU General Public License for more details.
   93.16 + *
   93.17 + * You should have received a copy of the GNU General Public License
   93.18 + * along with this program. Look for COPYING file in the top folder.
   93.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   93.20 + */
   93.21 +package org.apidesign.bck2brwsr.tck;
   93.22 +
   93.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   93.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   93.25 +import org.testng.annotations.Factory;
   93.26 +
   93.27 +/**
   93.28 + *
   93.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   93.30 + */
   93.31 +public class CompareByteArrayTest {
   93.32 +    @Compare public int byteArraySum() {
   93.33 +        byte[] arr = createArray();
   93.34 +        return sumByteArr(arr);
   93.35 +    }
   93.36 +    
   93.37 +    @Compare public int countZeros() {
   93.38 +        int zeros = 0;
   93.39 +        for (Byte b : createArray()) {
   93.40 +            if (b == 0) {
   93.41 +                zeros++;
   93.42 +            }
   93.43 +        }
   93.44 +        return zeros;
   93.45 +    }
   93.46 +    
   93.47 +    private static int sumByteArr(byte[] arr) {
   93.48 +        int sum = 0;
   93.49 +        for (int i = 0; i < arr.length; i++) {
   93.50 +            sum += arr[i];
   93.51 +        }
   93.52 +        return sum;
   93.53 +    }
   93.54 +    
   93.55 +    @Compare public String noOutOfBounds() {
   93.56 +        return atIndex(1);
   93.57 +    }
   93.58 +
   93.59 +    @Compare public String outOfBounds() {
   93.60 +        return atIndex(5);
   93.61 +    }
   93.62 +
   93.63 +    @Compare public String outOfBoundsMinus() {
   93.64 +        return atIndex(-1);
   93.65 +    }
   93.66 +
   93.67 +    @Compare public String toOfBounds() {
   93.68 +        return toIndex(5);
   93.69 +    }
   93.70 +
   93.71 +    @Compare public String toOfBoundsMinus() {
   93.72 +        return toIndex(-1);
   93.73 +    }
   93.74 +
   93.75 +    private static final int[] arr = { 0, 1, 2 };
   93.76 +    public static String atIndex(int at) {
   93.77 +        return "at@" + arr[at];
   93.78 +    }
   93.79 +    public static String toIndex(int at) {
   93.80 +        arr[at] = 10;
   93.81 +        return "ok";
   93.82 +    }
   93.83 +    
   93.84 +    
   93.85 +    @Factory
   93.86 +    public static Object[] create() {
   93.87 +        return VMTest.create(CompareByteArrayTest.class);
   93.88 +    }
   93.89 +
   93.90 +    private byte[] createArray() {
   93.91 +        byte[] arr = new byte[10];
   93.92 +        arr[5] = 3;
   93.93 +        arr[7] = 8;
   93.94 +        return arr;
   93.95 +    }
   93.96 +}
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java	Fri Jan 18 14:27:22 2013 +0100
    94.3 @@ -0,0 +1,50 @@
    94.4 +/**
    94.5 + * Back 2 Browser Bytecode Translator
    94.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    94.7 + *
    94.8 + * This program is free software: you can redistribute it and/or modify
    94.9 + * it under the terms of the GNU General Public License as published by
   94.10 + * the Free Software Foundation, version 2 of the License.
   94.11 + *
   94.12 + * This program is distributed in the hope that it will be useful,
   94.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   94.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   94.15 + * GNU General Public License for more details.
   94.16 + *
   94.17 + * You should have received a copy of the GNU General Public License
   94.18 + * along with this program. Look for COPYING file in the top folder.
   94.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   94.20 + */
   94.21 +package org.apidesign.bck2brwsr.tck;
   94.22 +
   94.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   94.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   94.25 +import org.testng.annotations.Factory;
   94.26 +
   94.27 +/**
   94.28 + *
   94.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   94.30 + */
   94.31 +public class CompareHashTest {
   94.32 +    @Compare public int hashOfString() {
   94.33 +        return "Ahoj".hashCode();
   94.34 +    }
   94.35 +    
   94.36 +    @Compare public int hashRemainsYieldsZero() {
   94.37 +        Object o = new Object();
   94.38 +        return o.hashCode() - o.hashCode();
   94.39 +    }
   94.40 +    
   94.41 +    @Compare public int initializeInStatic() {
   94.42 +        return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode();
   94.43 +    }
   94.44 +    
   94.45 +    @Compare public int hashOfInt() {
   94.46 +        return Integer.valueOf(Integer.MAX_VALUE).hashCode();
   94.47 +    }
   94.48 +    
   94.49 +    @Factory
   94.50 +    public static Object[] create() {
   94.51 +        return VMTest.create(CompareHashTest.class);
   94.52 +    }
   94.53 +}
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java	Fri Jan 18 14:27:22 2013 +0100
    95.3 @@ -0,0 +1,63 @@
    95.4 +/**
    95.5 + * Back 2 Browser Bytecode Translator
    95.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    95.7 + *
    95.8 + * This program is free software: you can redistribute it and/or modify
    95.9 + * it under the terms of the GNU General Public License as published by
   95.10 + * the Free Software Foundation, version 2 of the License.
   95.11 + *
   95.12 + * This program is distributed in the hope that it will be useful,
   95.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   95.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   95.15 + * GNU General Public License for more details.
   95.16 + *
   95.17 + * You should have received a copy of the GNU General Public License
   95.18 + * along with this program. Look for COPYING file in the top folder.
   95.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   95.20 + */
   95.21 +package org.apidesign.bck2brwsr.tck;
   95.22 +
   95.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
   95.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   95.25 +import org.testng.annotations.Factory;
   95.26 +
   95.27 +/**
   95.28 + *
   95.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   95.30 + */
   95.31 +public class CompareIntArrayTest {
   95.32 +    @Compare public int integerArraySum() {
   95.33 +        int[] arr = createArray();
   95.34 +        return sumIntArr(arr);
   95.35 +    }
   95.36 +    
   95.37 +    @Compare public int countZeros() {
   95.38 +        int zeros = 0;
   95.39 +        for (Integer i : createArray()) {
   95.40 +            if (i == 0) {
   95.41 +                zeros++;
   95.42 +            }
   95.43 +        }
   95.44 +        return zeros;
   95.45 +    }
   95.46 +    
   95.47 +    private static int sumIntArr(int[] arr) {
   95.48 +        int sum = 0;
   95.49 +        for (int i = 0; i < arr.length; i++) {
   95.50 +            sum += arr[i];
   95.51 +        }
   95.52 +        return sum;
   95.53 +    }
   95.54 +    
   95.55 +    @Factory
   95.56 +    public static Object[] create() {
   95.57 +        return VMTest.create(CompareIntArrayTest.class);
   95.58 +    }
   95.59 +
   95.60 +    private int[] createArray() {
   95.61 +        int[] arr = new int[10];
   95.62 +        arr[5] = 3;
   95.63 +        arr[7] = 8;
   95.64 +        return arr;
   95.65 +    }
   95.66 +}
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Fri Jan 18 14:27:22 2013 +0100
    96.3 @@ -0,0 +1,129 @@
    96.4 +/**
    96.5 + * Back 2 Browser Bytecode Translator
    96.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    96.7 + *
    96.8 + * This program is free software: you can redistribute it and/or modify
    96.9 + * it under the terms of the GNU General Public License as published by
   96.10 + * the Free Software Foundation, version 2 of the License.
   96.11 + *
   96.12 + * This program is distributed in the hope that it will be useful,
   96.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   96.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   96.15 + * GNU General Public License for more details.
   96.16 + *
   96.17 + * You should have received a copy of the GNU General Public License
   96.18 + * along with this program. Look for COPYING file in the top folder.
   96.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   96.20 + */
   96.21 +package org.apidesign.bck2brwsr.tck;
   96.22 +
   96.23 +import java.net.MalformedURLException;
   96.24 +import java.net.URL;
   96.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
   96.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   96.27 +import org.testng.annotations.Factory;
   96.28 +
   96.29 +/**
   96.30 + *
   96.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   96.32 + */
   96.33 +public class CompareStringsTest {
   96.34 +    @Compare public String firstChar() {
   96.35 +        return "" + ("Hello".toCharArray()[0]);
   96.36 +    }
   96.37 +    
   96.38 +    @Compare public String classCast() {
   96.39 +        Object o = firstChar();
   96.40 +        return String.class.cast(o);
   96.41 +    }
   96.42 +
   96.43 +    @Compare public String classCastThrown() {
   96.44 +        Object o = null;
   96.45 +        return String.class.cast(o);
   96.46 +    }
   96.47 +    
   96.48 +    @Compare public static Object compareURLs() throws MalformedURLException {
   96.49 +        return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
   96.50 +    }
   96.51 +    
   96.52 +    @Compare public String deleteLastTwoCharacters() {
   96.53 +        StringBuilder sb = new StringBuilder();
   96.54 +        sb.append("453.0");
   96.55 +        if (sb.toString().endsWith(".0")) {
   96.56 +            final int l = sb.length();
   96.57 +            sb.delete(l - 2, l);
   96.58 +        }
   96.59 +        return sb.toString().toString();
   96.60 +    }
   96.61 +    
   96.62 +    @Compare public String nameOfStringClass() throws Exception {
   96.63 +        return Class.forName("java.lang.String").getName();
   96.64 +    }
   96.65 +    @Compare public String nameOfArrayClass() throws Exception {
   96.66 +        return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName();
   96.67 +    }
   96.68 +    
   96.69 +    @Compare public String lowerHello() {
   96.70 +        return "HeLlO".toLowerCase();
   96.71 +    }
   96.72 +    
   96.73 +    @Compare public String lowerA() {
   96.74 +        return String.valueOf(Character.toLowerCase('A')).toString();
   96.75 +    }
   96.76 +    @Compare public String upperHello() {
   96.77 +        return "hello".toUpperCase();
   96.78 +    }
   96.79 +    
   96.80 +    @Compare public String upperA() {
   96.81 +        return String.valueOf(Character.toUpperCase('a')).toString();
   96.82 +    }
   96.83 +    
   96.84 +    @Compare public boolean matchRegExp() throws Exception {
   96.85 +        return "58038503".matches("\\d*");
   96.86 +    }
   96.87 +
   96.88 +    @Compare public boolean doesNotMatchRegExp() throws Exception {
   96.89 +        return "58038503GH".matches("\\d*");
   96.90 +    }
   96.91 +
   96.92 +    @Compare public boolean doesNotMatchRegExpFully() throws Exception {
   96.93 +        return "Hello".matches("Hell");
   96.94 +    }
   96.95 +    
   96.96 +    @Compare public String emptyCharArray() {
   96.97 +        char[] arr = new char[10];
   96.98 +        return new String(arr);
   96.99 +    }
  96.100 +    
  96.101 +    @Compare public String variousCharacterTests() throws Exception {
  96.102 +        StringBuilder sb = new StringBuilder();
  96.103 +        
  96.104 +        sb.append(Character.isUpperCase('a'));
  96.105 +        sb.append(Character.isUpperCase('A'));
  96.106 +        sb.append(Character.isLowerCase('a'));
  96.107 +        sb.append(Character.isLowerCase('A'));
  96.108 +        
  96.109 +        sb.append(Character.isLetter('A'));
  96.110 +        sb.append(Character.isLetterOrDigit('9'));
  96.111 +        sb.append(Character.isLetterOrDigit('A'));
  96.112 +        sb.append(Character.isLetter('0'));
  96.113 +        
  96.114 +        return sb.toString().toString();
  96.115 +    }
  96.116 +        
  96.117 +    @Compare
  96.118 +    public String nullFieldInitialized() {
  96.119 +        NullField nf = new NullField();
  96.120 +        return ("" + nf.name).toString();
  96.121 +    }
  96.122 +
  96.123 +    @Factory
  96.124 +    public static Object[] create() {
  96.125 +        return VMTest.create(CompareStringsTest.class);
  96.126 +    }
  96.127 +
  96.128 +    private static final class NullField {
  96.129 +
  96.130 +        String name;
  96.131 +    }
  96.132 +}
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java	Fri Jan 18 14:27:22 2013 +0100
    97.3 @@ -0,0 +1,108 @@
    97.4 +/**
    97.5 + * Back 2 Browser Bytecode Translator
    97.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>