Merging improved (inner) annotation support to allow its usage in emul branch emul
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 05 Feb 2013 08:27:42 +0100
branchemul
changeset 6668338ab1991e6
parent 647 6b77554987e0
parent 665 799a8cfefe35
child 667 5866e89ef568
Merging improved (inner) annotation support to allow its usage in emul branch
emul/mini/src/main/java/java/lang/Class.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java
emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
     1.1 --- a/emul/compact/src/main/java/java/io/BufferedReader.java	Sat Feb 02 06:01:44 2013 +0100
     1.2 +++ b/emul/compact/src/main/java/java/io/BufferedReader.java	Tue Feb 05 08:27:42 2013 +0100
     1.3 @@ -25,7 +25,6 @@
     1.4  
     1.5  package java.io;
     1.6  
     1.7 -import org.apidesign.bck2brwsr.emul.lang.System;
     1.8  
     1.9  
    1.10  /**
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/emul/compact/src/main/java/java/lang/AbstractMethodError.java	Tue Feb 05 08:27:42 2013 +0100
     2.3 @@ -0,0 +1,58 @@
     2.4 +/*
     2.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
     2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 + *
     2.8 + * This code is free software; you can redistribute it and/or modify it
     2.9 + * under the terms of the GNU General Public License version 2 only, as
    2.10 + * published by the Free Software Foundation.  Oracle designates this
    2.11 + * particular file as subject to the "Classpath" exception as provided
    2.12 + * by Oracle in the LICENSE file that accompanied this code.
    2.13 + *
    2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.17 + * version 2 for more details (a copy is included in the LICENSE file that
    2.18 + * accompanied this code).
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License version
    2.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.23 + *
    2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.25 + * or visit www.oracle.com if you need additional information or have any
    2.26 + * questions.
    2.27 + */
    2.28 +
    2.29 +package java.lang;
    2.30 +
    2.31 +/**
    2.32 + * Thrown when an application tries to call an abstract method.
    2.33 + * Normally, this error is caught by the compiler; this error can
    2.34 + * only occur at run time if the definition of some class has
    2.35 + * incompatibly changed since the currently executing method was last
    2.36 + * compiled.
    2.37 + *
    2.38 + * @author  unascribed
    2.39 + * @since   JDK1.0
    2.40 + */
    2.41 +public
    2.42 +class AbstractMethodError extends IncompatibleClassChangeError {
    2.43 +    private static final long serialVersionUID = -1654391082989018462L;
    2.44 +
    2.45 +    /**
    2.46 +     * Constructs an <code>AbstractMethodError</code> with no detail  message.
    2.47 +     */
    2.48 +    public AbstractMethodError() {
    2.49 +        super();
    2.50 +    }
    2.51 +
    2.52 +    /**
    2.53 +     * Constructs an <code>AbstractMethodError</code> with the specified
    2.54 +     * detail message.
    2.55 +     *
    2.56 +     * @param   s   the detail message.
    2.57 +     */
    2.58 +    public AbstractMethodError(String s) {
    2.59 +        super(s);
    2.60 +    }
    2.61 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/emul/compact/src/main/java/java/lang/IncompatibleClassChangeError.java	Tue Feb 05 08:27:42 2013 +0100
     3.3 @@ -0,0 +1,57 @@
     3.4 +/*
     3.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.  Oracle designates this
    3.11 + * particular file as subject to the "Classpath" exception as provided
    3.12 + * by Oracle in the LICENSE file that accompanied this code.
    3.13 + *
    3.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.17 + * version 2 for more details (a copy is included in the LICENSE file that
    3.18 + * accompanied this code).
    3.19 + *
    3.20 + * You should have received a copy of the GNU General Public License version
    3.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.23 + *
    3.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    3.25 + * or visit www.oracle.com if you need additional information or have any
    3.26 + * questions.
    3.27 + */
    3.28 +
    3.29 +package java.lang;
    3.30 +
    3.31 +/**
    3.32 + * Thrown when an incompatible class change has occurred to some class
    3.33 + * definition. The definition of some class, on which the currently
    3.34 + * executing method depends, has since changed.
    3.35 + *
    3.36 + * @author  unascribed
    3.37 + * @since   JDK1.0
    3.38 + */
    3.39 +public
    3.40 +class IncompatibleClassChangeError extends LinkageError {
    3.41 +    private static final long serialVersionUID = -4914975503642802119L;
    3.42 +
    3.43 +    /**
    3.44 +     * Constructs an <code>IncompatibleClassChangeError</code> with no
    3.45 +     * detail message.
    3.46 +     */
    3.47 +    public IncompatibleClassChangeError () {
    3.48 +        super();
    3.49 +    }
    3.50 +
    3.51 +    /**
    3.52 +     * Constructs an <code>IncompatibleClassChangeError</code> with the
    3.53 +     * specified detail message.
    3.54 +     *
    3.55 +     * @param   s   the detail message.
    3.56 +     */
    3.57 +    public IncompatibleClassChangeError(String s) {
    3.58 +        super(s);
    3.59 +    }
    3.60 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/emul/compact/src/main/java/java/lang/NoSuchFieldError.java	Tue Feb 05 08:27:42 2013 +0100
     4.3 @@ -0,0 +1,59 @@
     4.4 +/*
     4.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Oracle designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Oracle in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.25 + * or visit www.oracle.com if you need additional information or have any
    4.26 + * questions.
    4.27 + */
    4.28 +
    4.29 +package java.lang;
    4.30 +
    4.31 +/**
    4.32 + * Thrown if an application tries to access or modify a specified
    4.33 + * field of an object, and that object no longer has that field.
    4.34 + * <p>
    4.35 + * Normally, this error is caught by the compiler; this error can
    4.36 + * only occur at run time if the definition of a class has
    4.37 + * incompatibly changed.
    4.38 + *
    4.39 + * @author  unascribed
    4.40 + * @since   JDK1.0
    4.41 + */
    4.42 +public
    4.43 +class NoSuchFieldError extends IncompatibleClassChangeError {
    4.44 +    private static final long serialVersionUID = -3456430195886129035L;
    4.45 +
    4.46 +    /**
    4.47 +     * Constructs a <code>NoSuchFieldError</code> with no detail message.
    4.48 +     */
    4.49 +    public NoSuchFieldError() {
    4.50 +        super();
    4.51 +    }
    4.52 +
    4.53 +    /**
    4.54 +     * Constructs a <code>NoSuchFieldError</code> with the specified
    4.55 +     * detail message.
    4.56 +     *
    4.57 +     * @param   s   the detail message.
    4.58 +     */
    4.59 +    public NoSuchFieldError(String s) {
    4.60 +        super(s);
    4.61 +    }
    4.62 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/emul/compact/src/main/java/java/lang/System.java	Tue Feb 05 08:27:42 2013 +0100
     5.3 @@ -0,0 +1,36 @@
     5.4 +/**
     5.5 + * Back 2 Browser Bytecode Translator
     5.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     5.7 + *
     5.8 + * This program is free software: you can redistribute it and/or modify
     5.9 + * it under the terms of the GNU General Public License as published by
    5.10 + * the Free Software Foundation, version 2 of the License.
    5.11 + *
    5.12 + * This program is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU General Public License
    5.18 + * along with this program. Look for COPYING file in the top folder.
    5.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    5.20 + */
    5.21 +package java.lang;
    5.22 +
    5.23 +/** Poor man's re-implementation of most important System methods.
    5.24 + *
    5.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    5.26 + */
    5.27 +public class System {
    5.28 +    private System() {
    5.29 +    }
    5.30 +    
    5.31 +    public static void arraycopy(Object value, int srcBegin, Object dst, int dstBegin, int count) {
    5.32 +        org.apidesign.bck2brwsr.emul.lang.System.arraycopy(value, srcBegin, dst, dstBegin, count);
    5.33 +    }
    5.34 +    
    5.35 +    public static long currentTimeMillis() {
    5.36 +        return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
    5.37 +    }
    5.38 +    
    5.39 +}
     6.1 --- a/emul/compact/src/main/java/java/util/ArrayDeque.java	Sat Feb 02 06:01:44 2013 +0100
     6.2 +++ b/emul/compact/src/main/java/java/util/ArrayDeque.java	Tue Feb 05 08:27:42 2013 +0100
     6.3 @@ -34,7 +34,6 @@
     6.4  
     6.5  package java.util;
     6.6  import java.io.*;
     6.7 -import org.apidesign.bck2brwsr.emul.lang.System;
     6.8  
     6.9  /**
    6.10   * Resizable-array implementation of the {@link Deque} interface.  Array
     7.1 --- a/emul/compact/src/main/java/java/util/ArrayList.java	Sat Feb 02 06:01:44 2013 +0100
     7.2 +++ b/emul/compact/src/main/java/java/util/ArrayList.java	Tue Feb 05 08:27:42 2013 +0100
     7.3 @@ -25,7 +25,6 @@
     7.4  
     7.5  package java.util;
     7.6  
     7.7 -import org.apidesign.bck2brwsr.emul.lang.System;
     7.8  
     7.9  /**
    7.10   * Resizable-array implementation of the <tt>List</tt> interface.  Implements
     8.1 --- a/emul/compact/src/main/java/java/util/Arrays.java	Sat Feb 02 06:01:44 2013 +0100
     8.2 +++ b/emul/compact/src/main/java/java/util/Arrays.java	Tue Feb 05 08:27:42 2013 +0100
     8.3 @@ -26,7 +26,6 @@
     8.4  package java.util;
     8.5  
     8.6  import java.lang.reflect.*;
     8.7 -import org.apidesign.bck2brwsr.emul.lang.System;
     8.8  
     8.9  /**
    8.10   * This class contains various methods for manipulating arrays (such as
     9.1 --- a/emul/compact/src/main/java/java/util/Collections.java	Sat Feb 02 06:01:44 2013 +0100
     9.2 +++ b/emul/compact/src/main/java/java/util/Collections.java	Tue Feb 05 08:27:42 2013 +0100
     9.3 @@ -27,7 +27,6 @@
     9.4  import java.io.Serializable;
     9.5  import java.io.IOException;
     9.6  import java.lang.reflect.Array;
     9.7 -import org.apidesign.bck2brwsr.emul.lang.System;
     9.8  
     9.9  /**
    9.10   * This class consists exclusively of static methods that operate on or return
    10.1 --- a/emul/compact/src/main/java/java/util/ComparableTimSort.java	Sat Feb 02 06:01:44 2013 +0100
    10.2 +++ b/emul/compact/src/main/java/java/util/ComparableTimSort.java	Tue Feb 05 08:27:42 2013 +0100
    10.3 @@ -25,7 +25,6 @@
    10.4  
    10.5  package java.util;
    10.6  
    10.7 -import org.apidesign.bck2brwsr.emul.lang.System;
    10.8  
    10.9  /**
   10.10   * This is a near duplicate of {@link TimSort}, modified for use with
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/emul/compact/src/main/java/java/util/PriorityQueue.java	Tue Feb 05 08:27:42 2013 +0100
    11.3 @@ -0,0 +1,731 @@
    11.4 +/*
    11.5 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
    11.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    11.7 + *
    11.8 + * This code is free software; you can redistribute it and/or modify it
    11.9 + * under the terms of the GNU General Public License version 2 only, as
   11.10 + * published by the Free Software Foundation.  Oracle designates this
   11.11 + * particular file as subject to the "Classpath" exception as provided
   11.12 + * by Oracle in the LICENSE file that accompanied this code.
   11.13 + *
   11.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
   11.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   11.17 + * version 2 for more details (a copy is included in the LICENSE file that
   11.18 + * accompanied this code).
   11.19 + *
   11.20 + * You should have received a copy of the GNU General Public License version
   11.21 + * 2 along with this work; if not, write to the Free Software Foundation,
   11.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   11.23 + *
   11.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   11.25 + * or visit www.oracle.com if you need additional information or have any
   11.26 + * questions.
   11.27 + */
   11.28 +
   11.29 +package java.util;
   11.30 +
   11.31 +
   11.32 +/**
   11.33 + * An unbounded priority {@linkplain Queue queue} based on a priority heap.
   11.34 + * The elements of the priority queue are ordered according to their
   11.35 + * {@linkplain Comparable natural ordering}, or by a {@link Comparator}
   11.36 + * provided at queue construction time, depending on which constructor is
   11.37 + * used.  A priority queue does not permit {@code null} elements.
   11.38 + * A priority queue relying on natural ordering also does not permit
   11.39 + * insertion of non-comparable objects (doing so may result in
   11.40 + * {@code ClassCastException}).
   11.41 + *
   11.42 + * <p>The <em>head</em> of this queue is the <em>least</em> element
   11.43 + * with respect to the specified ordering.  If multiple elements are
   11.44 + * tied for least value, the head is one of those elements -- ties are
   11.45 + * broken arbitrarily.  The queue retrieval operations {@code poll},
   11.46 + * {@code remove}, {@code peek}, and {@code element} access the
   11.47 + * element at the head of the queue.
   11.48 + *
   11.49 + * <p>A priority queue is unbounded, but has an internal
   11.50 + * <i>capacity</i> governing the size of an array used to store the
   11.51 + * elements on the queue.  It is always at least as large as the queue
   11.52 + * size.  As elements are added to a priority queue, its capacity
   11.53 + * grows automatically.  The details of the growth policy are not
   11.54 + * specified.
   11.55 + *
   11.56 + * <p>This class and its iterator implement all of the
   11.57 + * <em>optional</em> methods of the {@link Collection} and {@link
   11.58 + * Iterator} interfaces.  The Iterator provided in method {@link
   11.59 + * #iterator()} is <em>not</em> guaranteed to traverse the elements of
   11.60 + * the priority queue in any particular order. If you need ordered
   11.61 + * traversal, consider using {@code Arrays.sort(pq.toArray())}.
   11.62 + *
   11.63 + * <p> <strong>Note that this implementation is not synchronized.</strong>
   11.64 + * Multiple threads should not access a {@code PriorityQueue}
   11.65 + * instance concurrently if any of the threads modifies the queue.
   11.66 + * Instead, use the thread-safe {@link
   11.67 + * java.util.concurrent.PriorityBlockingQueue} class.
   11.68 + *
   11.69 + * <p>Implementation note: this implementation provides
   11.70 + * O(log(n)) time for the enqueing and dequeing methods
   11.71 + * ({@code offer}, {@code poll}, {@code remove()} and {@code add});
   11.72 + * linear time for the {@code remove(Object)} and {@code contains(Object)}
   11.73 + * methods; and constant time for the retrieval methods
   11.74 + * ({@code peek}, {@code element}, and {@code size}).
   11.75 + *
   11.76 + * <p>This class is a member of the
   11.77 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
   11.78 + * Java Collections Framework</a>.
   11.79 + *
   11.80 + * @since 1.5
   11.81 + * @author Josh Bloch, Doug Lea
   11.82 + * @param <E> the type of elements held in this collection
   11.83 + */
   11.84 +public class PriorityQueue<E> extends AbstractQueue<E>
   11.85 +    implements java.io.Serializable {
   11.86 +
   11.87 +    private static final long serialVersionUID = -7720805057305804111L;
   11.88 +
   11.89 +    private static final int DEFAULT_INITIAL_CAPACITY = 11;
   11.90 +
   11.91 +    /**
   11.92 +     * Priority queue represented as a balanced binary heap: the two
   11.93 +     * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The
   11.94 +     * priority queue is ordered by comparator, or by the elements'
   11.95 +     * natural ordering, if comparator is null: For each node n in the
   11.96 +     * heap and each descendant d of n, n <= d.  The element with the
   11.97 +     * lowest value is in queue[0], assuming the queue is nonempty.
   11.98 +     */
   11.99 +    private transient Object[] queue;
  11.100 +
  11.101 +    /**
  11.102 +     * The number of elements in the priority queue.
  11.103 +     */
  11.104 +    private int size = 0;
  11.105 +
  11.106 +    /**
  11.107 +     * The comparator, or null if priority queue uses elements'
  11.108 +     * natural ordering.
  11.109 +     */
  11.110 +    private final Comparator<? super E> comparator;
  11.111 +
  11.112 +    /**
  11.113 +     * The number of times this priority queue has been
  11.114 +     * <i>structurally modified</i>.  See AbstractList for gory details.
  11.115 +     */
  11.116 +    private transient int modCount = 0;
  11.117 +
  11.118 +    /**
  11.119 +     * Creates a {@code PriorityQueue} with the default initial
  11.120 +     * capacity (11) that orders its elements according to their
  11.121 +     * {@linkplain Comparable natural ordering}.
  11.122 +     */
  11.123 +    public PriorityQueue() {
  11.124 +        this(DEFAULT_INITIAL_CAPACITY, null);
  11.125 +    }
  11.126 +
  11.127 +    /**
  11.128 +     * Creates a {@code PriorityQueue} with the specified initial
  11.129 +     * capacity that orders its elements according to their
  11.130 +     * {@linkplain Comparable natural ordering}.
  11.131 +     *
  11.132 +     * @param initialCapacity the initial capacity for this priority queue
  11.133 +     * @throws IllegalArgumentException if {@code initialCapacity} is less
  11.134 +     *         than 1
  11.135 +     */
  11.136 +    public PriorityQueue(int initialCapacity) {
  11.137 +        this(initialCapacity, null);
  11.138 +    }
  11.139 +
  11.140 +    /**
  11.141 +     * Creates a {@code PriorityQueue} with the specified initial capacity
  11.142 +     * that orders its elements according to the specified comparator.
  11.143 +     *
  11.144 +     * @param  initialCapacity the initial capacity for this priority queue
  11.145 +     * @param  comparator the comparator that will be used to order this
  11.146 +     *         priority queue.  If {@code null}, the {@linkplain Comparable
  11.147 +     *         natural ordering} of the elements will be used.
  11.148 +     * @throws IllegalArgumentException if {@code initialCapacity} is
  11.149 +     *         less than 1
  11.150 +     */
  11.151 +    public PriorityQueue(int initialCapacity,
  11.152 +                         Comparator<? super E> comparator) {
  11.153 +        // Note: This restriction of at least one is not actually needed,
  11.154 +        // but continues for 1.5 compatibility
  11.155 +        if (initialCapacity < 1)
  11.156 +            throw new IllegalArgumentException();
  11.157 +        this.queue = new Object[initialCapacity];
  11.158 +        this.comparator = comparator;
  11.159 +    }
  11.160 +
  11.161 +    /**
  11.162 +     * Creates a {@code PriorityQueue} containing the elements in the
  11.163 +     * specified collection.  If the specified collection is an instance of
  11.164 +     * a {@link SortedSet} or is another {@code PriorityQueue}, this
  11.165 +     * priority queue will be ordered according to the same ordering.
  11.166 +     * Otherwise, this priority queue will be ordered according to the
  11.167 +     * {@linkplain Comparable natural ordering} of its elements.
  11.168 +     *
  11.169 +     * @param  c the collection whose elements are to be placed
  11.170 +     *         into this priority queue
  11.171 +     * @throws ClassCastException if elements of the specified collection
  11.172 +     *         cannot be compared to one another according to the priority
  11.173 +     *         queue's ordering
  11.174 +     * @throws NullPointerException if the specified collection or any
  11.175 +     *         of its elements are null
  11.176 +     */
  11.177 +    @SuppressWarnings("unchecked")
  11.178 +    public PriorityQueue(Collection<? extends E> c) {
  11.179 +        if (c instanceof SortedSet<?>) {
  11.180 +            SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
  11.181 +            this.comparator = (Comparator<? super E>) ss.comparator();
  11.182 +            initElementsFromCollection(ss);
  11.183 +        }
  11.184 +        else if (c instanceof PriorityQueue<?>) {
  11.185 +            PriorityQueue<? extends E> pq = (PriorityQueue<? extends E>) c;
  11.186 +            this.comparator = (Comparator<? super E>) pq.comparator();
  11.187 +            initFromPriorityQueue(pq);
  11.188 +        }
  11.189 +        else {
  11.190 +            this.comparator = null;
  11.191 +            initFromCollection(c);
  11.192 +        }
  11.193 +    }
  11.194 +
  11.195 +    /**
  11.196 +     * Creates a {@code PriorityQueue} containing the elements in the
  11.197 +     * specified priority queue.  This priority queue will be
  11.198 +     * ordered according to the same ordering as the given priority
  11.199 +     * queue.
  11.200 +     *
  11.201 +     * @param  c the priority queue whose elements are to be placed
  11.202 +     *         into this priority queue
  11.203 +     * @throws ClassCastException if elements of {@code c} cannot be
  11.204 +     *         compared to one another according to {@code c}'s
  11.205 +     *         ordering
  11.206 +     * @throws NullPointerException if the specified priority queue or any
  11.207 +     *         of its elements are null
  11.208 +     */
  11.209 +    @SuppressWarnings("unchecked")
  11.210 +    public PriorityQueue(PriorityQueue<? extends E> c) {
  11.211 +        this.comparator = (Comparator<? super E>) c.comparator();
  11.212 +        initFromPriorityQueue(c);
  11.213 +    }
  11.214 +
  11.215 +    /**
  11.216 +     * Creates a {@code PriorityQueue} containing the elements in the
  11.217 +     * specified sorted set.   This priority queue will be ordered
  11.218 +     * according to the same ordering as the given sorted set.
  11.219 +     *
  11.220 +     * @param  c the sorted set whose elements are to be placed
  11.221 +     *         into this priority queue
  11.222 +     * @throws ClassCastException if elements of the specified sorted
  11.223 +     *         set cannot be compared to one another according to the
  11.224 +     *         sorted set's ordering
  11.225 +     * @throws NullPointerException if the specified sorted set or any
  11.226 +     *         of its elements are null
  11.227 +     */
  11.228 +    @SuppressWarnings("unchecked")
  11.229 +    public PriorityQueue(SortedSet<? extends E> c) {
  11.230 +        this.comparator = (Comparator<? super E>) c.comparator();
  11.231 +        initElementsFromCollection(c);
  11.232 +    }
  11.233 +
  11.234 +    private void initFromPriorityQueue(PriorityQueue<? extends E> c) {
  11.235 +        if (c.getClass() == PriorityQueue.class) {
  11.236 +            this.queue = c.toArray();
  11.237 +            this.size = c.size();
  11.238 +        } else {
  11.239 +            initFromCollection(c);
  11.240 +        }
  11.241 +    }
  11.242 +
  11.243 +    private void initElementsFromCollection(Collection<? extends E> c) {
  11.244 +        Object[] a = c.toArray();
  11.245 +        // If c.toArray incorrectly doesn't return Object[], copy it.
  11.246 +        if (a.getClass() != Object[].class)
  11.247 +            a = Arrays.copyOf(a, a.length, Object[].class);
  11.248 +        int len = a.length;
  11.249 +        if (len == 1 || this.comparator != null)
  11.250 +            for (int i = 0; i < len; i++)
  11.251 +                if (a[i] == null)
  11.252 +                    throw new NullPointerException();
  11.253 +        this.queue = a;
  11.254 +        this.size = a.length;
  11.255 +    }
  11.256 +
  11.257 +    /**
  11.258 +     * Initializes queue array with elements from the given Collection.
  11.259 +     *
  11.260 +     * @param c the collection
  11.261 +     */
  11.262 +    private void initFromCollection(Collection<? extends E> c) {
  11.263 +        initElementsFromCollection(c);
  11.264 +        heapify();
  11.265 +    }
  11.266 +
  11.267 +    /**
  11.268 +     * The maximum size of array to allocate.
  11.269 +     * Some VMs reserve some header words in an array.
  11.270 +     * Attempts to allocate larger arrays may result in
  11.271 +     * OutOfMemoryError: Requested array size exceeds VM limit
  11.272 +     */
  11.273 +    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  11.274 +
  11.275 +    /**
  11.276 +     * Increases the capacity of the array.
  11.277 +     *
  11.278 +     * @param minCapacity the desired minimum capacity
  11.279 +     */
  11.280 +    private void grow(int minCapacity) {
  11.281 +        int oldCapacity = queue.length;
  11.282 +        // Double size if small; else grow by 50%
  11.283 +        int newCapacity = oldCapacity + ((oldCapacity < 64) ?
  11.284 +                                         (oldCapacity + 2) :
  11.285 +                                         (oldCapacity >> 1));
  11.286 +        // overflow-conscious code
  11.287 +        if (newCapacity - MAX_ARRAY_SIZE > 0)
  11.288 +            newCapacity = hugeCapacity(minCapacity);
  11.289 +        queue = Arrays.copyOf(queue, newCapacity);
  11.290 +    }
  11.291 +
  11.292 +    private static int hugeCapacity(int minCapacity) {
  11.293 +        if (minCapacity < 0) // overflow
  11.294 +            throw new OutOfMemoryError();
  11.295 +        return (minCapacity > MAX_ARRAY_SIZE) ?
  11.296 +            Integer.MAX_VALUE :
  11.297 +            MAX_ARRAY_SIZE;
  11.298 +    }
  11.299 +
  11.300 +    /**
  11.301 +     * Inserts the specified element into this priority queue.
  11.302 +     *
  11.303 +     * @return {@code true} (as specified by {@link Collection#add})
  11.304 +     * @throws ClassCastException if the specified element cannot be
  11.305 +     *         compared with elements currently in this priority queue
  11.306 +     *         according to the priority queue's ordering
  11.307 +     * @throws NullPointerException if the specified element is null
  11.308 +     */
  11.309 +    public boolean add(E e) {
  11.310 +        return offer(e);
  11.311 +    }
  11.312 +
  11.313 +    /**
  11.314 +     * Inserts the specified element into this priority queue.
  11.315 +     *
  11.316 +     * @return {@code true} (as specified by {@link Queue#offer})
  11.317 +     * @throws ClassCastException if the specified element cannot be
  11.318 +     *         compared with elements currently in this priority queue
  11.319 +     *         according to the priority queue's ordering
  11.320 +     * @throws NullPointerException if the specified element is null
  11.321 +     */
  11.322 +    public boolean offer(E e) {
  11.323 +        if (e == null)
  11.324 +            throw new NullPointerException();
  11.325 +        modCount++;
  11.326 +        int i = size;
  11.327 +        if (i >= queue.length)
  11.328 +            grow(i + 1);
  11.329 +        size = i + 1;
  11.330 +        if (i == 0)
  11.331 +            queue[0] = e;
  11.332 +        else
  11.333 +            siftUp(i, e);
  11.334 +        return true;
  11.335 +    }
  11.336 +
  11.337 +    public E peek() {
  11.338 +        if (size == 0)
  11.339 +            return null;
  11.340 +        return (E) queue[0];
  11.341 +    }
  11.342 +
  11.343 +    private int indexOf(Object o) {
  11.344 +        if (o != null) {
  11.345 +            for (int i = 0; i < size; i++)
  11.346 +                if (o.equals(queue[i]))
  11.347 +                    return i;
  11.348 +        }
  11.349 +        return -1;
  11.350 +    }
  11.351 +
  11.352 +    /**
  11.353 +     * Removes a single instance of the specified element from this queue,
  11.354 +     * if it is present.  More formally, removes an element {@code e} such
  11.355 +     * that {@code o.equals(e)}, if this queue contains one or more such
  11.356 +     * elements.  Returns {@code true} if and only if this queue contained
  11.357 +     * the specified element (or equivalently, if this queue changed as a
  11.358 +     * result of the call).
  11.359 +     *
  11.360 +     * @param o element to be removed from this queue, if present
  11.361 +     * @return {@code true} if this queue changed as a result of the call
  11.362 +     */
  11.363 +    public boolean remove(Object o) {
  11.364 +        int i = indexOf(o);
  11.365 +        if (i == -1)
  11.366 +            return false;
  11.367 +        else {
  11.368 +            removeAt(i);
  11.369 +            return true;
  11.370 +        }
  11.371 +    }
  11.372 +
  11.373 +    /**
  11.374 +     * Version of remove using reference equality, not equals.
  11.375 +     * Needed by iterator.remove.
  11.376 +     *
  11.377 +     * @param o element to be removed from this queue, if present
  11.378 +     * @return {@code true} if removed
  11.379 +     */
  11.380 +    boolean removeEq(Object o) {
  11.381 +        for (int i = 0; i < size; i++) {
  11.382 +            if (o == queue[i]) {
  11.383 +                removeAt(i);
  11.384 +                return true;
  11.385 +            }
  11.386 +        }
  11.387 +        return false;
  11.388 +    }
  11.389 +
  11.390 +    /**
  11.391 +     * Returns {@code true} if this queue contains the specified element.
  11.392 +     * More formally, returns {@code true} if and only if this queue contains
  11.393 +     * at least one element {@code e} such that {@code o.equals(e)}.
  11.394 +     *
  11.395 +     * @param o object to be checked for containment in this queue
  11.396 +     * @return {@code true} if this queue contains the specified element
  11.397 +     */
  11.398 +    public boolean contains(Object o) {
  11.399 +        return indexOf(o) != -1;
  11.400 +    }
  11.401 +
  11.402 +    /**
  11.403 +     * Returns an array containing all of the elements in this queue.
  11.404 +     * The elements are in no particular order.
  11.405 +     *
  11.406 +     * <p>The returned array will be "safe" in that no references to it are
  11.407 +     * maintained by this queue.  (In other words, this method must allocate
  11.408 +     * a new array).  The caller is thus free to modify the returned array.
  11.409 +     *
  11.410 +     * <p>This method acts as bridge between array-based and collection-based
  11.411 +     * APIs.
  11.412 +     *
  11.413 +     * @return an array containing all of the elements in this queue
  11.414 +     */
  11.415 +    public Object[] toArray() {
  11.416 +        return Arrays.copyOf(queue, size);
  11.417 +    }
  11.418 +
  11.419 +    /**
  11.420 +     * Returns an array containing all of the elements in this queue; the
  11.421 +     * runtime type of the returned array is that of the specified array.
  11.422 +     * The returned array elements are in no particular order.
  11.423 +     * If the queue fits in the specified array, it is returned therein.
  11.424 +     * Otherwise, a new array is allocated with the runtime type of the
  11.425 +     * specified array and the size of this queue.
  11.426 +     *
  11.427 +     * <p>If the queue fits in the specified array with room to spare
  11.428 +     * (i.e., the array has more elements than the queue), the element in
  11.429 +     * the array immediately following the end of the collection is set to
  11.430 +     * {@code null}.
  11.431 +     *
  11.432 +     * <p>Like the {@link #toArray()} method, this method acts as bridge between
  11.433 +     * array-based and collection-based APIs.  Further, this method allows
  11.434 +     * precise control over the runtime type of the output array, and may,
  11.435 +     * under certain circumstances, be used to save allocation costs.
  11.436 +     *
  11.437 +     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
  11.438 +     * The following code can be used to dump the queue into a newly
  11.439 +     * allocated array of <tt>String</tt>:
  11.440 +     *
  11.441 +     * <pre>
  11.442 +     *     String[] y = x.toArray(new String[0]);</pre>
  11.443 +     *
  11.444 +     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
  11.445 +     * <tt>toArray()</tt>.
  11.446 +     *
  11.447 +     * @param a the array into which the elements of the queue are to
  11.448 +     *          be stored, if it is big enough; otherwise, a new array of the
  11.449 +     *          same runtime type is allocated for this purpose.
  11.450 +     * @return an array containing all of the elements in this queue
  11.451 +     * @throws ArrayStoreException if the runtime type of the specified array
  11.452 +     *         is not a supertype of the runtime type of every element in
  11.453 +     *         this queue
  11.454 +     * @throws NullPointerException if the specified array is null
  11.455 +     */
  11.456 +    public <T> T[] toArray(T[] a) {
  11.457 +        if (a.length < size)
  11.458 +            // Make a new array of a's runtime type, but my contents:
  11.459 +            return (T[]) Arrays.copyOf(queue, size, a.getClass());
  11.460 +        System.arraycopy(queue, 0, a, 0, size);
  11.461 +        if (a.length > size)
  11.462 +            a[size] = null;
  11.463 +        return a;
  11.464 +    }
  11.465 +
  11.466 +    /**
  11.467 +     * Returns an iterator over the elements in this queue. The iterator
  11.468 +     * does not return the elements in any particular order.
  11.469 +     *
  11.470 +     * @return an iterator over the elements in this queue
  11.471 +     */
  11.472 +    public Iterator<E> iterator() {
  11.473 +        return new Itr();
  11.474 +    }
  11.475 +
  11.476 +    private final class Itr implements Iterator<E> {
  11.477 +        /**
  11.478 +         * Index (into queue array) of element to be returned by
  11.479 +         * subsequent call to next.
  11.480 +         */
  11.481 +        private int cursor = 0;
  11.482 +
  11.483 +        /**
  11.484 +         * Index of element returned by most recent call to next,
  11.485 +         * unless that element came from the forgetMeNot list.
  11.486 +         * Set to -1 if element is deleted by a call to remove.
  11.487 +         */
  11.488 +        private int lastRet = -1;
  11.489 +
  11.490 +        /**
  11.491 +         * A queue of elements that were moved from the unvisited portion of
  11.492 +         * the heap into the visited portion as a result of "unlucky" element
  11.493 +         * removals during the iteration.  (Unlucky element removals are those
  11.494 +         * that require a siftup instead of a siftdown.)  We must visit all of
  11.495 +         * the elements in this list to complete the iteration.  We do this
  11.496 +         * after we've completed the "normal" iteration.
  11.497 +         *
  11.498 +         * We expect that most iterations, even those involving removals,
  11.499 +         * will not need to store elements in this field.
  11.500 +         */
  11.501 +        private ArrayDeque<E> forgetMeNot = null;
  11.502 +
  11.503 +        /**
  11.504 +         * Element returned by the most recent call to next iff that
  11.505 +         * element was drawn from the forgetMeNot list.
  11.506 +         */
  11.507 +        private E lastRetElt = null;
  11.508 +
  11.509 +        /**
  11.510 +         * The modCount value that the iterator believes that the backing
  11.511 +         * Queue should have.  If this expectation is violated, the iterator
  11.512 +         * has detected concurrent modification.
  11.513 +         */
  11.514 +        private int expectedModCount = modCount;
  11.515 +
  11.516 +        public boolean hasNext() {
  11.517 +            return cursor < size ||
  11.518 +                (forgetMeNot != null && !forgetMeNot.isEmpty());
  11.519 +        }
  11.520 +
  11.521 +        public E next() {
  11.522 +            if (expectedModCount != modCount)
  11.523 +                throw new ConcurrentModificationException();
  11.524 +            if (cursor < size)
  11.525 +                return (E) queue[lastRet = cursor++];
  11.526 +            if (forgetMeNot != null) {
  11.527 +                lastRet = -1;
  11.528 +                lastRetElt = forgetMeNot.poll();
  11.529 +                if (lastRetElt != null)
  11.530 +                    return lastRetElt;
  11.531 +            }
  11.532 +            throw new NoSuchElementException();
  11.533 +        }
  11.534 +
  11.535 +        public void remove() {
  11.536 +            if (expectedModCount != modCount)
  11.537 +                throw new ConcurrentModificationException();
  11.538 +            if (lastRet != -1) {
  11.539 +                E moved = PriorityQueue.this.removeAt(lastRet);
  11.540 +                lastRet = -1;
  11.541 +                if (moved == null)
  11.542 +                    cursor--;
  11.543 +                else {
  11.544 +                    if (forgetMeNot == null)
  11.545 +                        forgetMeNot = new ArrayDeque<>();
  11.546 +                    forgetMeNot.add(moved);
  11.547 +                }
  11.548 +            } else if (lastRetElt != null) {
  11.549 +                PriorityQueue.this.removeEq(lastRetElt);
  11.550 +                lastRetElt = null;
  11.551 +            } else {
  11.552 +                throw new IllegalStateException();
  11.553 +            }
  11.554 +            expectedModCount = modCount;
  11.555 +        }
  11.556 +    }
  11.557 +
  11.558 +    public int size() {
  11.559 +        return size;
  11.560 +    }
  11.561 +
  11.562 +    /**
  11.563 +     * Removes all of the elements from this priority queue.
  11.564 +     * The queue will be empty after this call returns.
  11.565 +     */
  11.566 +    public void clear() {
  11.567 +        modCount++;
  11.568 +        for (int i = 0; i < size; i++)
  11.569 +            queue[i] = null;
  11.570 +        size = 0;
  11.571 +    }
  11.572 +
  11.573 +    public E poll() {
  11.574 +        if (size == 0)
  11.575 +            return null;
  11.576 +        int s = --size;
  11.577 +        modCount++;
  11.578 +        E result = (E) queue[0];
  11.579 +        E x = (E) queue[s];
  11.580 +        queue[s] = null;
  11.581 +        if (s != 0)
  11.582 +            siftDown(0, x);
  11.583 +        return result;
  11.584 +    }
  11.585 +
  11.586 +    /**
  11.587 +     * Removes the ith element from queue.
  11.588 +     *
  11.589 +     * Normally this method leaves the elements at up to i-1,
  11.590 +     * inclusive, untouched.  Under these circumstances, it returns
  11.591 +     * null.  Occasionally, in order to maintain the heap invariant,
  11.592 +     * it must swap a later element of the list with one earlier than
  11.593 +     * i.  Under these circumstances, this method returns the element
  11.594 +     * that was previously at the end of the list and is now at some
  11.595 +     * position before i. This fact is used by iterator.remove so as to
  11.596 +     * avoid missing traversing elements.
  11.597 +     */
  11.598 +    private E removeAt(int i) {
  11.599 +        assert i >= 0 && i < size;
  11.600 +        modCount++;
  11.601 +        int s = --size;
  11.602 +        if (s == i) // removed last element
  11.603 +            queue[i] = null;
  11.604 +        else {
  11.605 +            E moved = (E) queue[s];
  11.606 +            queue[s] = null;
  11.607 +            siftDown(i, moved);
  11.608 +            if (queue[i] == moved) {
  11.609 +                siftUp(i, moved);
  11.610 +                if (queue[i] != moved)
  11.611 +                    return moved;
  11.612 +            }
  11.613 +        }
  11.614 +        return null;
  11.615 +    }
  11.616 +
  11.617 +    /**
  11.618 +     * Inserts item x at position k, maintaining heap invariant by
  11.619 +     * promoting x up the tree until it is greater than or equal to
  11.620 +     * its parent, or is the root.
  11.621 +     *
  11.622 +     * To simplify and speed up coercions and comparisons. the
  11.623 +     * Comparable and Comparator versions are separated into different
  11.624 +     * methods that are otherwise identical. (Similarly for siftDown.)
  11.625 +     *
  11.626 +     * @param k the position to fill
  11.627 +     * @param x the item to insert
  11.628 +     */
  11.629 +    private void siftUp(int k, E x) {
  11.630 +        if (comparator != null)
  11.631 +            siftUpUsingComparator(k, x);
  11.632 +        else
  11.633 +            siftUpComparable(k, x);
  11.634 +    }
  11.635 +
  11.636 +    private void siftUpComparable(int k, E x) {
  11.637 +        Comparable<? super E> key = (Comparable<? super E>) x;
  11.638 +        while (k > 0) {
  11.639 +            int parent = (k - 1) >>> 1;
  11.640 +            Object e = queue[parent];
  11.641 +            if (key.compareTo((E) e) >= 0)
  11.642 +                break;
  11.643 +            queue[k] = e;
  11.644 +            k = parent;
  11.645 +        }
  11.646 +        queue[k] = key;
  11.647 +    }
  11.648 +
  11.649 +    private void siftUpUsingComparator(int k, E x) {
  11.650 +        while (k > 0) {
  11.651 +            int parent = (k - 1) >>> 1;
  11.652 +            Object e = queue[parent];
  11.653 +            if (comparator.compare(x, (E) e) >= 0)
  11.654 +                break;
  11.655 +            queue[k] = e;
  11.656 +            k = parent;
  11.657 +        }
  11.658 +        queue[k] = x;
  11.659 +    }
  11.660 +
  11.661 +    /**
  11.662 +     * Inserts item x at position k, maintaining heap invariant by
  11.663 +     * demoting x down the tree repeatedly until it is less than or
  11.664 +     * equal to its children or is a leaf.
  11.665 +     *
  11.666 +     * @param k the position to fill
  11.667 +     * @param x the item to insert
  11.668 +     */
  11.669 +    private void siftDown(int k, E x) {
  11.670 +        if (comparator != null)
  11.671 +            siftDownUsingComparator(k, x);
  11.672 +        else
  11.673 +            siftDownComparable(k, x);
  11.674 +    }
  11.675 +
  11.676 +    private void siftDownComparable(int k, E x) {
  11.677 +        Comparable<? super E> key = (Comparable<? super E>)x;
  11.678 +        int half = size >>> 1;        // loop while a non-leaf
  11.679 +        while (k < half) {
  11.680 +            int child = (k << 1) + 1; // assume left child is least
  11.681 +            Object c = queue[child];
  11.682 +            int right = child + 1;
  11.683 +            if (right < size &&
  11.684 +                ((Comparable<? super E>) c).compareTo((E) queue[right]) > 0)
  11.685 +                c = queue[child = right];
  11.686 +            if (key.compareTo((E) c) <= 0)
  11.687 +                break;
  11.688 +            queue[k] = c;
  11.689 +            k = child;
  11.690 +        }
  11.691 +        queue[k] = key;
  11.692 +    }
  11.693 +
  11.694 +    private void siftDownUsingComparator(int k, E x) {
  11.695 +        int half = size >>> 1;
  11.696 +        while (k < half) {
  11.697 +            int child = (k << 1) + 1;
  11.698 +            Object c = queue[child];
  11.699 +            int right = child + 1;
  11.700 +            if (right < size &&
  11.701 +                comparator.compare((E) c, (E) queue[right]) > 0)
  11.702 +                c = queue[child = right];
  11.703 +            if (comparator.compare(x, (E) c) <= 0)
  11.704 +                break;
  11.705 +            queue[k] = c;
  11.706 +            k = child;
  11.707 +        }
  11.708 +        queue[k] = x;
  11.709 +    }
  11.710 +
  11.711 +    /**
  11.712 +     * Establishes the heap invariant (described above) in the entire tree,
  11.713 +     * assuming nothing about the order of the elements prior to the call.
  11.714 +     */
  11.715 +    private void heapify() {
  11.716 +        for (int i = (size >>> 1) - 1; i >= 0; i--)
  11.717 +            siftDown(i, (E) queue[i]);
  11.718 +    }
  11.719 +
  11.720 +    /**
  11.721 +     * Returns the comparator used to order the elements in this
  11.722 +     * queue, or {@code null} if this queue is sorted according to
  11.723 +     * the {@linkplain Comparable natural ordering} of its elements.
  11.724 +     *
  11.725 +     * @return the comparator used to order this queue, or
  11.726 +     *         {@code null} if this queue is sorted according to the
  11.727 +     *         natural ordering of its elements
  11.728 +     */
  11.729 +    public Comparator<? super E> comparator() {
  11.730 +        return comparator;
  11.731 +    }
  11.732 +
  11.733 +
  11.734 +}
    12.1 --- a/emul/compact/src/main/java/java/util/TimSort.java	Sat Feb 02 06:01:44 2013 +0100
    12.2 +++ b/emul/compact/src/main/java/java/util/TimSort.java	Tue Feb 05 08:27:42 2013 +0100
    12.3 @@ -25,7 +25,6 @@
    12.4  
    12.5  package java.util;
    12.6  
    12.7 -import org.apidesign.bck2brwsr.emul.lang.System;
    12.8  
    12.9  /**
   12.10   * A stable, adaptive, iterative mergesort that requires far fewer than
    13.1 --- a/emul/compact/src/main/java/java/util/Vector.java	Sat Feb 02 06:01:44 2013 +0100
    13.2 +++ b/emul/compact/src/main/java/java/util/Vector.java	Tue Feb 05 08:27:42 2013 +0100
    13.3 @@ -25,7 +25,6 @@
    13.4  
    13.5  package java.util;
    13.6  
    13.7 -import org.apidesign.bck2brwsr.emul.lang.System;
    13.8  
    13.9  /**
   13.10   * The {@code Vector} class implements a growable array of
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/emul/compact/src/main/java/java/util/concurrent/TimeUnit.java	Tue Feb 05 08:27:42 2013 +0100
    14.3 @@ -0,0 +1,367 @@
    14.4 +/*
    14.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    14.6 + *
    14.7 + * This code is free software; you can redistribute it and/or modify it
    14.8 + * under the terms of the GNU General Public License version 2 only, as
    14.9 + * published by the Free Software Foundation.  Oracle designates this
   14.10 + * particular file as subject to the "Classpath" exception as provided
   14.11 + * by Oracle in the LICENSE file that accompanied this code.
   14.12 + *
   14.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
   14.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14.16 + * version 2 for more details (a copy is included in the LICENSE file that
   14.17 + * accompanied this code).
   14.18 + *
   14.19 + * You should have received a copy of the GNU General Public License version
   14.20 + * 2 along with this work; if not, write to the Free Software Foundation,
   14.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   14.22 + *
   14.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   14.24 + * or visit www.oracle.com if you need additional information or have any
   14.25 + * questions.
   14.26 + */
   14.27 +
   14.28 +/*
   14.29 + * This file is available under and governed by the GNU General Public
   14.30 + * License version 2 only, as published by the Free Software Foundation.
   14.31 + * However, the following notice accompanied the original version of this
   14.32 + * file:
   14.33 + *
   14.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
   14.35 + * Expert Group and released to the public domain, as explained at
   14.36 + * http://creativecommons.org/publicdomain/zero/1.0/
   14.37 + */
   14.38 +
   14.39 +package java.util.concurrent;
   14.40 +
   14.41 +/**
   14.42 + * A <tt>TimeUnit</tt> represents time durations at a given unit of
   14.43 + * granularity and provides utility methods to convert across units,
   14.44 + * and to perform timing and delay operations in these units.  A
   14.45 + * <tt>TimeUnit</tt> does not maintain time information, but only
   14.46 + * helps organize and use time representations that may be maintained
   14.47 + * separately across various contexts.  A nanosecond is defined as one
   14.48 + * thousandth of a microsecond, a microsecond as one thousandth of a
   14.49 + * millisecond, a millisecond as one thousandth of a second, a minute
   14.50 + * as sixty seconds, an hour as sixty minutes, and a day as twenty four
   14.51 + * hours.
   14.52 + *
   14.53 + * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
   14.54 + * how a given timing parameter should be interpreted. For example,
   14.55 + * the following code will timeout in 50 milliseconds if the {@link
   14.56 + * java.util.concurrent.locks.Lock lock} is not available:
   14.57 + *
   14.58 + * <pre>  Lock lock = ...;
   14.59 + *  if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ...
   14.60 + * </pre>
   14.61 + * while this code will timeout in 50 seconds:
   14.62 + * <pre>
   14.63 + *  Lock lock = ...;
   14.64 + *  if (lock.tryLock(50L, TimeUnit.SECONDS)) ...
   14.65 + * </pre>
   14.66 + *
   14.67 + * Note however, that there is no guarantee that a particular timeout
   14.68 + * implementation will be able to notice the passage of time at the
   14.69 + * same granularity as the given <tt>TimeUnit</tt>.
   14.70 + *
   14.71 + * @since 1.5
   14.72 + * @author Doug Lea
   14.73 + */
   14.74 +public enum TimeUnit {
   14.75 +    NANOSECONDS {
   14.76 +        public long toNanos(long d)   { return d; }
   14.77 +        public long toMicros(long d)  { return d/(C1/C0); }
   14.78 +        public long toMillis(long d)  { return d/(C2/C0); }
   14.79 +        public long toSeconds(long d) { return d/(C3/C0); }
   14.80 +        public long toMinutes(long d) { return d/(C4/C0); }
   14.81 +        public long toHours(long d)   { return d/(C5/C0); }
   14.82 +        public long toDays(long d)    { return d/(C6/C0); }
   14.83 +        public long convert(long d, TimeUnit u) { return u.toNanos(d); }
   14.84 +        int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
   14.85 +    },
   14.86 +    MICROSECONDS {
   14.87 +        public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
   14.88 +        public long toMicros(long d)  { return d; }
   14.89 +        public long toMillis(long d)  { return d/(C2/C1); }
   14.90 +        public long toSeconds(long d) { return d/(C3/C1); }
   14.91 +        public long toMinutes(long d) { return d/(C4/C1); }
   14.92 +        public long toHours(long d)   { return d/(C5/C1); }
   14.93 +        public long toDays(long d)    { return d/(C6/C1); }
   14.94 +        public long convert(long d, TimeUnit u) { return u.toMicros(d); }
   14.95 +        int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
   14.96 +    },
   14.97 +    MILLISECONDS {
   14.98 +        public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
   14.99 +        public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
  14.100 +        public long toMillis(long d)  { return d; }
  14.101 +        public long toSeconds(long d) { return d/(C3/C2); }
  14.102 +        public long toMinutes(long d) { return d/(C4/C2); }
  14.103 +        public long toHours(long d)   { return d/(C5/C2); }
  14.104 +        public long toDays(long d)    { return d/(C6/C2); }
  14.105 +        public long convert(long d, TimeUnit u) { return u.toMillis(d); }
  14.106 +        int excessNanos(long d, long m) { return 0; }
  14.107 +    },
  14.108 +    SECONDS {
  14.109 +        public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
  14.110 +        public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
  14.111 +        public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
  14.112 +        public long toSeconds(long d) { return d; }
  14.113 +        public long toMinutes(long d) { return d/(C4/C3); }
  14.114 +        public long toHours(long d)   { return d/(C5/C3); }
  14.115 +        public long toDays(long d)    { return d/(C6/C3); }
  14.116 +        public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
  14.117 +        int excessNanos(long d, long m) { return 0; }
  14.118 +    },
  14.119 +    MINUTES {
  14.120 +        public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
  14.121 +        public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
  14.122 +        public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
  14.123 +        public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
  14.124 +        public long toMinutes(long d) { return d; }
  14.125 +        public long toHours(long d)   { return d/(C5/C4); }
  14.126 +        public long toDays(long d)    { return d/(C6/C4); }
  14.127 +        public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
  14.128 +        int excessNanos(long d, long m) { return 0; }
  14.129 +    },
  14.130 +    HOURS {
  14.131 +        public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
  14.132 +        public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
  14.133 +        public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
  14.134 +        public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
  14.135 +        public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
  14.136 +        public long toHours(long d)   { return d; }
  14.137 +        public long toDays(long d)    { return d/(C6/C5); }
  14.138 +        public long convert(long d, TimeUnit u) { return u.toHours(d); }
  14.139 +        int excessNanos(long d, long m) { return 0; }
  14.140 +    },
  14.141 +    DAYS {
  14.142 +        public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
  14.143 +        public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
  14.144 +        public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
  14.145 +        public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
  14.146 +        public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
  14.147 +        public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
  14.148 +        public long toDays(long d)    { return d; }
  14.149 +        public long convert(long d, TimeUnit u) { return u.toDays(d); }
  14.150 +        int excessNanos(long d, long m) { return 0; }
  14.151 +    };
  14.152 +
  14.153 +    // Handy constants for conversion methods
  14.154 +    static final long C0 = 1L;
  14.155 +    static final long C1 = C0 * 1000L;
  14.156 +    static final long C2 = C1 * 1000L;
  14.157 +    static final long C3 = C2 * 1000L;
  14.158 +    static final long C4 = C3 * 60L;
  14.159 +    static final long C5 = C4 * 60L;
  14.160 +    static final long C6 = C5 * 24L;
  14.161 +
  14.162 +    static final long MAX = Long.MAX_VALUE;
  14.163 +
  14.164 +    /**
  14.165 +     * Scale d by m, checking for overflow.
  14.166 +     * This has a short name to make above code more readable.
  14.167 +     */
  14.168 +    static long x(long d, long m, long over) {
  14.169 +        if (d >  over) return Long.MAX_VALUE;
  14.170 +        if (d < -over) return Long.MIN_VALUE;
  14.171 +        return d * m;
  14.172 +    }
  14.173 +
  14.174 +    // To maintain full signature compatibility with 1.5, and to improve the
  14.175 +    // clarity of the generated javadoc (see 6287639: Abstract methods in
  14.176 +    // enum classes should not be listed as abstract), method convert
  14.177 +    // etc. are not declared abstract but otherwise act as abstract methods.
  14.178 +
  14.179 +    /**
  14.180 +     * Convert the given time duration in the given unit to this
  14.181 +     * unit.  Conversions from finer to coarser granularities
  14.182 +     * truncate, so lose precision. For example converting
  14.183 +     * <tt>999</tt> milliseconds to seconds results in
  14.184 +     * <tt>0</tt>. Conversions from coarser to finer granularities
  14.185 +     * with arguments that would numerically overflow saturate to
  14.186 +     * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
  14.187 +     * if positive.
  14.188 +     *
  14.189 +     * <p>For example, to convert 10 minutes to milliseconds, use:
  14.190 +     * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
  14.191 +     *
  14.192 +     * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
  14.193 +     * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
  14.194 +     * @return the converted duration in this unit,
  14.195 +     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  14.196 +     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  14.197 +     */
  14.198 +    public long convert(long sourceDuration, TimeUnit sourceUnit) {
  14.199 +        throw new AbstractMethodError();
  14.200 +    }
  14.201 +
  14.202 +    /**
  14.203 +     * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
  14.204 +     * @param duration the duration
  14.205 +     * @return the converted duration,
  14.206 +     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  14.207 +     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  14.208 +     * @see #convert
  14.209 +     */
  14.210 +    public long toNanos(long duration) {
  14.211 +        throw new AbstractMethodError();
  14.212 +    }
  14.213 +
  14.214 +    /**
  14.215 +     * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
  14.216 +     * @param duration the duration
  14.217 +     * @return the converted duration,
  14.218 +     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  14.219 +     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  14.220 +     * @see #convert
  14.221 +     */
  14.222 +    public long toMicros(long duration) {
  14.223 +        throw new AbstractMethodError();
  14.224 +    }
  14.225 +
  14.226 +    /**
  14.227 +     * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
  14.228 +     * @param duration the duration
  14.229 +     * @return the converted duration,
  14.230 +     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  14.231 +     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  14.232 +     * @see #convert
  14.233 +     */
  14.234 +    public long toMillis(long duration) {
  14.235 +        throw new AbstractMethodError();
  14.236 +    }
  14.237 +
  14.238 +    /**
  14.239 +     * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
  14.240 +     * @param duration the duration
  14.241 +     * @return the converted duration,
  14.242 +     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  14.243 +     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  14.244 +     * @see #convert
  14.245 +     */
  14.246 +    public long toSeconds(long duration) {
  14.247 +        throw new AbstractMethodError();
  14.248 +    }
  14.249 +
  14.250 +    /**
  14.251 +     * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
  14.252 +     * @param duration the duration
  14.253 +     * @return the converted duration,
  14.254 +     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  14.255 +     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  14.256 +     * @see #convert
  14.257 +     * @since 1.6
  14.258 +     */
  14.259 +    public long toMinutes(long duration) {
  14.260 +        throw new AbstractMethodError();
  14.261 +    }
  14.262 +
  14.263 +    /**
  14.264 +     * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
  14.265 +     * @param duration the duration
  14.266 +     * @return the converted duration,
  14.267 +     * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
  14.268 +     * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
  14.269 +     * @see #convert
  14.270 +     * @since 1.6
  14.271 +     */
  14.272 +    public long toHours(long duration) {
  14.273 +        throw new AbstractMethodError();
  14.274 +    }
  14.275 +
  14.276 +    /**
  14.277 +     * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
  14.278 +     * @param duration the duration
  14.279 +     * @return the converted duration
  14.280 +     * @see #convert
  14.281 +     * @since 1.6
  14.282 +     */
  14.283 +    public long toDays(long duration) {
  14.284 +        throw new AbstractMethodError();
  14.285 +    }
  14.286 +
  14.287 +    /**
  14.288 +     * Utility to compute the excess-nanosecond argument to wait,
  14.289 +     * sleep, join.
  14.290 +     * @param d the duration
  14.291 +     * @param m the number of milliseconds
  14.292 +     * @return the number of nanoseconds
  14.293 +     */
  14.294 +    abstract int excessNanos(long d, long m);
  14.295 +
  14.296 +    /**
  14.297 +     * Performs a timed {@link Object#wait(long, int) Object.wait}
  14.298 +     * using this time unit.
  14.299 +     * This is a convenience method that converts timeout arguments
  14.300 +     * into the form required by the <tt>Object.wait</tt> method.
  14.301 +     *
  14.302 +     * <p>For example, you could implement a blocking <tt>poll</tt>
  14.303 +     * method (see {@link BlockingQueue#poll BlockingQueue.poll})
  14.304 +     * using:
  14.305 +     *
  14.306 +     *  <pre> {@code
  14.307 +     * public synchronized Object poll(long timeout, TimeUnit unit)
  14.308 +     *     throws InterruptedException {
  14.309 +     *   while (empty) {
  14.310 +     *     unit.timedWait(this, timeout);
  14.311 +     *     ...
  14.312 +     *   }
  14.313 +     * }}</pre>
  14.314 +     *
  14.315 +     * @param obj the object to wait on
  14.316 +     * @param timeout the maximum time to wait. If less than
  14.317 +     * or equal to zero, do not wait at all.
  14.318 +     * @throws InterruptedException if interrupted while waiting
  14.319 +     */
  14.320 +    public void timedWait(Object obj, long timeout)
  14.321 +            throws InterruptedException {
  14.322 +        if (timeout > 0) {
  14.323 +            long ms = toMillis(timeout);
  14.324 +            int ns = excessNanos(timeout, ms);
  14.325 +            obj.wait(ms, ns);
  14.326 +        }
  14.327 +    }
  14.328 +
  14.329 +    /**
  14.330 +     * Performs a timed {@link Thread#join(long, int) Thread.join}
  14.331 +     * using this time unit.
  14.332 +     * This is a convenience method that converts time arguments into the
  14.333 +     * form required by the <tt>Thread.join</tt> method.
  14.334 +     *
  14.335 +     * @param thread the thread to wait for
  14.336 +     * @param timeout the maximum time to wait. If less than
  14.337 +     * or equal to zero, do not wait at all.
  14.338 +     * @throws InterruptedException if interrupted while waiting
  14.339 +     */
  14.340 +//    public void timedJoin(Thread thread, long timeout)
  14.341 +//            throws InterruptedException {
  14.342 +//        if (timeout > 0) {
  14.343 +//            long ms = toMillis(timeout);
  14.344 +//            int ns = excessNanos(timeout, ms);
  14.345 +//            thread.join(ms, ns);
  14.346 +//        }
  14.347 +//    }
  14.348 +
  14.349 +    /**
  14.350 +     * Performs a {@link Thread#sleep(long, int) Thread.sleep} using
  14.351 +     * this time unit.
  14.352 +     * This is a convenience method that converts time arguments into the
  14.353 +     * form required by the <tt>Thread.sleep</tt> method.
  14.354 +     *
  14.355 +     * @param timeout the minimum time to sleep. If less than
  14.356 +     * or equal to zero, do not sleep at all.
  14.357 +     * @throws InterruptedException if interrupted while sleeping
  14.358 +     */
  14.359 +    public void sleep(long timeout) throws InterruptedException {
  14.360 +        if (timeout > 0) {
  14.361 +            long ms = toMillis(timeout);
  14.362 +            int ns = excessNanos(timeout, ms);
  14.363 +            Object o = new Object();
  14.364 +            synchronized (o) {
  14.365 +                o.wait(ms, ns);
  14.366 +            }
  14.367 +        }
  14.368 +    }
  14.369 +
  14.370 +}
    15.1 --- a/emul/mini/pom.xml	Sat Feb 02 06:01:44 2013 +0100
    15.2 +++ b/emul/mini/pom.xml	Tue Feb 05 08:27:42 2013 +0100
    15.3 @@ -22,6 +22,12 @@
    15.4        <version>0.3-SNAPSHOT</version>
    15.5        <type>jar</type>
    15.6      </dependency>
    15.7 +    <dependency>
    15.8 +      <groupId>org.testng</groupId>
    15.9 +      <artifactId>testng</artifactId>
   15.10 +      <version>6.5.2</version>
   15.11 +      <scope>test</scope>
   15.12 +    </dependency>
   15.13    </dependencies>
   15.14    <build>
   15.15        <plugins>
    16.1 --- a/emul/mini/src/main/java/java/lang/Class.java	Sat Feb 02 06:01:44 2013 +0100
    16.2 +++ b/emul/mini/src/main/java/java/lang/Class.java	Tue Feb 05 08:27:42 2013 +0100
    16.3 @@ -231,12 +231,14 @@
    16.4      }
    16.5      
    16.6      @JavaScriptBody(args = {"n", "c" }, body =
    16.7 -        "if (vm[c]) return vm[c].$class;\n"
    16.8 -      + "if (vm.loadClass) {\n"
    16.9 -      + "  vm.loadClass(n);\n"
   16.10 -      + "  if (vm[c]) return vm[c].$class;\n"
   16.11 +        "if (!vm[c]) {\n"
   16.12 +      + "  if (vm.loadClass) {\n"
   16.13 +      + "    vm.loadClass(n);\n"
   16.14 +      + "  }\n"
   16.15 +      + "  if (!vm[c]) return null;\n"
   16.16        + "}\n"
   16.17 -      + "return null;"
   16.18 +      + "vm[c](false);"
   16.19 +      + "return vm[c].$class;"
   16.20      )
   16.21      private static native Class<?> loadCls(String n, String c);
   16.22  
    17.1 --- a/emul/mini/src/main/java/java/lang/Math.java	Sat Feb 02 06:01:44 2013 +0100
    17.2 +++ b/emul/mini/src/main/java/java/lang/Math.java	Tue Feb 05 08:27:42 2013 +0100
    17.3 @@ -991,9 +991,11 @@
    17.4       * @author Joseph D. Darcy
    17.5       * @since 1.5
    17.6       */
    17.7 -//    public static double signum(double d) {
    17.8 -//        return sun.misc.FpUtils.signum(d);
    17.9 -//    }
   17.10 +    public static double signum(double d) {
   17.11 +        if (d < 0.0) { return -1.0; }
   17.12 +        if (d > 0.0) { return 1.0; }
   17.13 +        return d;
   17.14 +    }
   17.15  
   17.16      /**
   17.17       * Returns the signum function of the argument; zero if the argument
   17.18 @@ -1012,9 +1014,11 @@
   17.19       * @author Joseph D. Darcy
   17.20       * @since 1.5
   17.21       */
   17.22 -//    public static float signum(float f) {
   17.23 -//        return sun.misc.FpUtils.signum(f);
   17.24 -//    }
   17.25 +    public static float signum(float f) {
   17.26 +        if (f < 0.0f) { return -1.0f; }
   17.27 +        if (f > 0.0f) { return 1.0f; }
   17.28 +        return f;
   17.29 +    }
   17.30  
   17.31      /**
   17.32       * Returns the first floating-point argument with the sign of the
    18.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Sat Feb 02 06:01:44 2013 +0100
    18.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Tue Feb 05 08:27:42 2013 +0100
    18.3 @@ -45,10 +45,13 @@
    18.4      )
    18.5      public static native byte[] expandArray(byte[] arr, int expectedSize);
    18.6  
    18.7 -    @JavaScriptBody(args = {}, body = "new Date().getMilliseconds() * 1000;")
    18.8 -    public static native long nanoTime();
    18.9 +    @JavaScriptBody(args = {}, body = "new Date().getMilliseconds();")
   18.10 +    public static native long currentTimeMillis();
   18.11      
   18.12      @JavaScriptBody(args = { "obj" }, body="return vm.java_lang_Object(false).hashCode__I.call(obj);")
   18.13      public static native int identityHashCode(Object obj);
   18.14      
   18.15 +    public static long nanoTime() {
   18.16 +        return 1000L * currentTimeMillis();
   18.17 +    }
   18.18  }
    19.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java	Sat Feb 02 06:01:44 2013 +0100
    19.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/AnnotationImpl.java	Tue Feb 05 08:27:42 2013 +0100
    19.3 @@ -18,6 +18,8 @@
    19.4  package org.apidesign.bck2brwsr.emul.reflect;
    19.5  
    19.6  import java.lang.annotation.Annotation;
    19.7 +import java.lang.reflect.Method;
    19.8 +import java.lang.reflect.Modifier;
    19.9  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   19.10  
   19.11  /**
   19.12 @@ -25,39 +27,73 @@
   19.13   * @author Jaroslav Tulach <jtulach@netbeans.org>
   19.14   */
   19.15  public final class AnnotationImpl implements Annotation {
   19.16 +    private final Class<? extends Annotation> type;
   19.17 +
   19.18 +    public AnnotationImpl(Class<? extends Annotation> type) {
   19.19 +        this.type = type;
   19.20 +    }
   19.21 +    
   19.22      public Class<? extends Annotation> annotationType() {
   19.23 -        return getClass();
   19.24 +        return type;
   19.25      }
   19.26  
   19.27 -    @JavaScriptBody(args = { "a", "n", "values" }, body = ""
   19.28 -        + "function f(v, p) {\n"
   19.29 -        + "  var val = v;\n"
   19.30 -        + "  var prop = p;\n"
   19.31 +    @JavaScriptBody(args = { "a", "n", "arr", "values" }, body = ""
   19.32 +        + "function f(val, prop, clazz) {\n"
   19.33          + "  return function() {\n"
   19.34 -        + "    return val[prop];\n"
   19.35 +        + "    if (clazz == null) return val[prop];\n"
   19.36 +        + "    if (clazz.isArray__Z()) {\n"
   19.37 +        + "      var valarr = val[prop];\n"
   19.38 +        + "      var cmp = clazz.getComponentType__Ljava_lang_Class_2();\n"
   19.39 +        + "      var retarr = vm.java_lang_reflect_Array(false).newInstance__Ljava_lang_Object_2Ljava_lang_Class_2I(cmp, valarr.length);\n"
   19.40 +        + "      for (var i = 0; i < valarr.length; i++) {\n"
   19.41 +        + "        retarr[i] = CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(cmp, valarr[i]);\n"
   19.42 +        + "      }\n"
   19.43 +        + "      return retarr;\n"
   19.44 +        + "    }\n"
   19.45 +        + "    return CLS.prototype.c__Ljava_lang_Object_2Ljava_lang_Class_2Ljava_lang_Object_2(clazz, val[prop]);\n"
   19.46          + "  };\n"
   19.47          + "}\n"
   19.48 -        + "var props = Object.getOwnPropertyNames(values);\n"
   19.49 -        + "for (var i = 0; i < props.length; i++) {\n"
   19.50 -        + "  var p = props[i];\n"
   19.51 -        + "  a[p] = new f(values, p);\n"
   19.52 +        + "for (var i = 0; i < arr.length; i += 3) {\n"
   19.53 +        + "  var m = arr[i];\n"
   19.54 +        + "  var p = arr[i + 1];\n"
   19.55 +        + "  var c = arr[i + 2];\n"
   19.56 +        + "  a[m] = f(values, p, c);\n"
   19.57          + "}\n"
   19.58          + "a['$instOf_' + n] = true;\n"
   19.59          + "return a;"
   19.60      )
   19.61 -    private static <T extends Annotation> T create(AnnotationImpl a, String n, Object values) {
   19.62 -        return null;
   19.63 +    private static native <T extends Annotation> T create(
   19.64 +        AnnotationImpl a, String n, Object[] methodsAndProps, Object values
   19.65 +    );
   19.66 +    
   19.67 +    private static Object c(Class<? extends Annotation> a, Object v) {
   19.68 +        return create(a, v);
   19.69      }
   19.70 +    
   19.71      public static <T extends Annotation> T create(Class<T> annoClass, Object values) {
   19.72 -        return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
   19.73 +        return create(new AnnotationImpl(annoClass), 
   19.74 +            annoClass.getName().replace('.', '_'), 
   19.75 +            findProps(annoClass), values
   19.76 +        );
   19.77      }
   19.78  
   19.79      public static Annotation[] create(Object anno) {
   19.80          String[] names = findNames(anno);
   19.81          Annotation[] ret = new Annotation[names.length];
   19.82          for (int i = 0; i < names.length; i++) {
   19.83 -            String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
   19.84 -            ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
   19.85 +            String annoNameSlash = names[i].substring(1, names[i].length() - 1);
   19.86 +            Class<? extends Annotation> annoClass;
   19.87 +            try {
   19.88 +                annoClass = (Class<? extends Annotation>)Class.forName(annoNameSlash.replace('/', '.'));
   19.89 +            } catch (ClassNotFoundException ex) {
   19.90 +                throw new IllegalStateException("Can't find annotation class " + annoNameSlash);
   19.91 +            }
   19.92 +            ret[i] = create(
   19.93 +                new AnnotationImpl(annoClass), 
   19.94 +                annoNameSlash.replace('/', '_'),
   19.95 +                findProps(annoClass),
   19.96 +                findData(anno, names[i])
   19.97 +            );
   19.98          }
   19.99          return ret;
  19.100      }
  19.101 @@ -70,12 +106,25 @@
  19.102          + "}"
  19.103          + "return arr;"
  19.104      )
  19.105 -    private static String[] findNames(Object anno) {
  19.106 -        throw new UnsupportedOperationException();
  19.107 -    }
  19.108 +    private static native String[] findNames(Object anno);
  19.109  
  19.110      @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
  19.111 -    private static Object findData(Object anno, String p) {
  19.112 -        throw new UnsupportedOperationException();
  19.113 +    private static native Object findData(Object anno, String p);
  19.114 +
  19.115 +    private static Object[] findProps(Class<?> annoClass) {
  19.116 +        final Method[] marr = MethodImpl.findMethods(annoClass, Modifier.PUBLIC);
  19.117 +        Object[] arr = new Object[marr.length * 3];
  19.118 +        int pos = 0;
  19.119 +        for (Method m : marr) {
  19.120 +            arr[pos++] = MethodImpl.toSignature(m);
  19.121 +            arr[pos++] = m.getName();
  19.122 +            final Class<?> rt = m.getReturnType();
  19.123 +            if (rt.isArray()) {
  19.124 +                arr[pos++] = rt.getComponentType().isAnnotation() ? rt : null;
  19.125 +            } else {
  19.126 +                arr[pos++] = rt.isAnnotation() ? rt : null;
  19.127 +            }
  19.128 +        }
  19.129 +        return arr;
  19.130      }
  19.131  }
    20.1 --- a/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Sat Feb 02 06:01:44 2013 +0100
    20.2 +++ b/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/reflect/MethodImpl.java	Tue Feb 05 08:27:42 2013 +0100
    20.3 @@ -17,6 +17,7 @@
    20.4   */
    20.5  package org.apidesign.bck2brwsr.emul.reflect;
    20.6  
    20.7 +import java.lang.reflect.Array;
    20.8  import java.lang.reflect.Method;
    20.9  import java.util.Enumeration;
   20.10  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   20.11 @@ -34,7 +35,7 @@
   20.12              throw new IllegalStateException(ex);
   20.13          }
   20.14      }
   20.15 -    
   20.16 +
   20.17      protected abstract Method create(Class<?> declaringClass, String name, Object data, String sig);
   20.18      
   20.19      
   20.20 @@ -48,8 +49,10 @@
   20.21          + "var arr = new Array();\n"
   20.22          + "for (m in c) {\n"
   20.23          + "  if (m.indexOf(prefix) === 0) {\n"
   20.24 +        + "     if (!c[m].cls) continue;\n"
   20.25          + "     arr.push(m);\n"
   20.26          + "     arr.push(c[m]);\n"
   20.27 +        + "     arr.push(c[m].cls.$class);\n"
   20.28          + "  }"
   20.29          + "}\n"
   20.30          + "return arr;")
   20.31 @@ -59,9 +62,10 @@
   20.32      public static Method findMethod(
   20.33          Class<?> clazz, String name, Class<?>... parameterTypes) {
   20.34          Object[] data = findMethodData(clazz, name + "__");
   20.35 -        BIG: for (int i = 0; i < data.length; i += 2) {
   20.36 -            String sig = ((String) data[0]).substring(name.length() + 2);
   20.37 -            Method tmp = INSTANCE.create(clazz, name, data[1], sig);
   20.38 +        BIG: for (int i = 0; i < data.length; i += 3) {
   20.39 +            String sig = ((String) data[i]).substring(name.length() + 2);
   20.40 +            Class<?> cls = (Class<?>) data[i + 2];
   20.41 +            Method tmp = INSTANCE.create(cls, name, data[i + 1], sig);
   20.42              Class<?>[] tmpParms = tmp.getParameterTypes();
   20.43              if (parameterTypes.length != tmpParms.length) {
   20.44                  continue;
   20.45 @@ -79,7 +83,7 @@
   20.46      public static Method[] findMethods(Class<?> clazz, int mask) {
   20.47          Object[] namesAndData = findMethodData(clazz, "");
   20.48          int cnt = 0;
   20.49 -        for (int i = 0; i < namesAndData.length; i += 2) {
   20.50 +        for (int i = 0; i < namesAndData.length; i += 3) {
   20.51              String sig = (String) namesAndData[i];
   20.52              Object data = namesAndData[i + 1];
   20.53              int middle = sig.indexOf("__");
   20.54 @@ -88,7 +92,8 @@
   20.55              }
   20.56              String name = sig.substring(0, middle);
   20.57              sig = sig.substring(middle + 2);
   20.58 -            final Method m = INSTANCE.create(clazz, name, data, sig);
   20.59 +            Class<?> cls = (Class<?>) namesAndData[i + 2];
   20.60 +            final Method m = INSTANCE.create(cls, name, data, sig);
   20.61              if ((m.getModifiers() & mask) == 0) {
   20.62                  continue;
   20.63              }
   20.64 @@ -100,6 +105,62 @@
   20.65          }
   20.66          return arr;
   20.67      }
   20.68 +    static String toSignature(Method m) {
   20.69 +        StringBuilder sb = new StringBuilder();
   20.70 +        sb.append(m.getName()).append("__");
   20.71 +        appendType(sb, m.getReturnType());
   20.72 +        Class<?>[] arr = m.getParameterTypes();
   20.73 +        for (int i = 0; i < arr.length; i++) {
   20.74 +            appendType(sb, arr[i]);
   20.75 +        }
   20.76 +        return sb.toString();
   20.77 +    }
   20.78 +    
   20.79 +    private static void appendType(StringBuilder sb, Class<?> type) {
   20.80 +        if (type == Integer.TYPE) {
   20.81 +            sb.append('I');
   20.82 +            return;
   20.83 +        }
   20.84 +        if (type == Long.TYPE) {
   20.85 +            sb.append('J');
   20.86 +            return;
   20.87 +        }
   20.88 +        if (type == Double.TYPE) {
   20.89 +            sb.append('D');
   20.90 +            return;
   20.91 +        }
   20.92 +        if (type == Float.TYPE) {
   20.93 +            sb.append('F');
   20.94 +            return;
   20.95 +        }
   20.96 +        if (type == Byte.TYPE) {
   20.97 +            sb.append('B');
   20.98 +            return;
   20.99 +        }
  20.100 +        if (type == Boolean.TYPE) {
  20.101 +            sb.append('Z');
  20.102 +            return;
  20.103 +        }
  20.104 +        if (type == Short.TYPE) {
  20.105 +            sb.append('S');
  20.106 +            return;
  20.107 +        }
  20.108 +        if (type == Void.TYPE) {
  20.109 +            sb.append('V');
  20.110 +            return;
  20.111 +        }
  20.112 +        if (type == Character.TYPE) {
  20.113 +            sb.append('C');
  20.114 +            return;
  20.115 +        }
  20.116 +        if (type.isArray()) {
  20.117 +            sb.append("_3");
  20.118 +            appendType(sb, type.getComponentType());
  20.119 +            return;
  20.120 +        }
  20.121 +        sb.append('L').append(type.getName().replace('.', '_'));
  20.122 +        sb.append("_2");
  20.123 +    }
  20.124  
  20.125      public static int signatureElements(String sig) {
  20.126          Enumeration<Class> en = signatureParser(sig);
  20.127 @@ -141,13 +202,19 @@
  20.128                          return Character.TYPE;
  20.129                      case 'L':
  20.130                          try {
  20.131 -                            int up = sig.indexOf("_2");
  20.132 -                            String type = sig.substring(1, up);
  20.133 +                            int up = sig.indexOf("_2", pos);
  20.134 +                            String type = sig.substring(pos, up);
  20.135                              pos = up + 2;
  20.136 -                            return Class.forName(type);
  20.137 +                            return Class.forName(type.replace('_', '.'));
  20.138                          } catch (ClassNotFoundException ex) {
  20.139 -                            // should not happen
  20.140 +                            throw new IllegalStateException(ex);
  20.141                          }
  20.142 +                    case '_': {
  20.143 +                        char nch = sig.charAt(pos++);
  20.144 +                        assert nch == '3' : "Can't find '3' at " + sig.substring(pos - 1);
  20.145 +                        final Class compType = nextElement();
  20.146 +                        return Array.newInstance(compType, 0).getClass();
  20.147 +                    }
  20.148                  }
  20.149                  throw new UnsupportedOperationException(sig + " at " + pos);
  20.150              }
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/emul/mini/src/test/java/org/apidesign/bck2brwsr/emul/reflect/MethodImplTest.java	Tue Feb 05 08:27:42 2013 +0100
    21.3 @@ -0,0 +1,49 @@
    21.4 +/**
    21.5 + * Back 2 Browser Bytecode Translator
    21.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    21.7 + *
    21.8 + * This program is free software: you can redistribute it and/or modify
    21.9 + * it under the terms of the GNU General Public License as published by
   21.10 + * the Free Software Foundation, version 2 of the License.
   21.11 + *
   21.12 + * This program is distributed in the hope that it will be useful,
   21.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.15 + * GNU General Public License for more details.
   21.16 + *
   21.17 + * You should have received a copy of the GNU General Public License
   21.18 + * along with this program. Look for COPYING file in the top folder.
   21.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   21.20 + */
   21.21 +package org.apidesign.bck2brwsr.emul.reflect;
   21.22 +
   21.23 +import java.lang.reflect.Method;
   21.24 +import java.util.Enumeration;
   21.25 +import org.testng.annotations.Test;
   21.26 +
   21.27 +/**
   21.28 + *
   21.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   21.30 + */
   21.31 +public class MethodImplTest {
   21.32 +    
   21.33 +    public MethodImplTest() {
   21.34 +    }
   21.35 +    
   21.36 +    public static String[] arr(String... arr) {
   21.37 +        return arr;
   21.38 +    }
   21.39 +
   21.40 +    @Test
   21.41 +    public void testSignatureForMethodWithAnArray() throws NoSuchMethodException {
   21.42 +        Method m = MethodImplTest.class.getMethod("arr", String[].class);
   21.43 +        String sig = MethodImpl.toSignature(m);
   21.44 +        int sep = sig.indexOf("__");
   21.45 +        assert sep > 0 : "Separator found " + sig;
   21.46 +        
   21.47 +        Enumeration<Class> en = MethodImpl.signatureParser(sig.substring(sep + 2));
   21.48 +        
   21.49 +        assert en.nextElement() == m.getReturnType() : "Return type is the same";
   21.50 +        assert en.nextElement() == m.getParameterTypes()[0] : "1st param type is the same";
   21.51 +    }
   21.52 +}
   21.53 \ No newline at end of file
    22.1 --- a/javap/src/main/java/org/apidesign/javap/AnnotationParser.java	Sat Feb 02 06:01:44 2013 +0100
    22.2 +++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java	Tue Feb 05 08:27:42 2013 +0100
    22.3 @@ -35,22 +35,37 @@
    22.4   */
    22.5  public class AnnotationParser {
    22.6      private final boolean textual;
    22.7 +    private final boolean iterateArray;
    22.8      
    22.9 -    protected AnnotationParser(boolean textual) {
   22.10 +    protected AnnotationParser(boolean textual, boolean iterateArray) {
   22.11          this.textual = textual;
   22.12 +        this.iterateArray = iterateArray;
   22.13      }
   22.14  
   22.15 -    protected void visitAnnotationStart(String type) throws IOException {
   22.16 +    protected void visitAnnotationStart(String type, boolean top) throws IOException {
   22.17      }
   22.18  
   22.19 -    protected void visitAnnotationEnd(String type) throws IOException {
   22.20 +    protected void visitAnnotationEnd(String type, boolean top) throws IOException {
   22.21      }
   22.22 +
   22.23 +    protected void visitValueStart(String attrName, char type) throws IOException {
   22.24 +    }
   22.25 +
   22.26 +    protected void visitValueEnd(String attrName, char type) throws IOException {
   22.27 +    }
   22.28 +
   22.29      
   22.30      protected void visitAttr(
   22.31          String annoType, String attr, String attrType, String value
   22.32      ) throws IOException {
   22.33      }
   22.34      
   22.35 +    protected void visitEnumAttr(
   22.36 +        String annoType, String attr, String attrType, String value
   22.37 +    ) throws IOException {
   22.38 +        visitAttr(annoType, attr, attrType, value);
   22.39 +    }
   22.40 +    
   22.41      /** Initialize the parsing with constant pool from <code>cd</code>.
   22.42       * 
   22.43       * @param attr the attribute defining annotations
   22.44 @@ -70,30 +85,32 @@
   22.45      private void read(DataInputStream dis, ClassData cd) throws IOException {
   22.46      	int cnt = dis.readUnsignedShort();
   22.47          for (int i = 0; i < cnt; i++) {
   22.48 -            readAnno(dis, cd);
   22.49 +            readAnno(dis, cd, true);
   22.50          }
   22.51      }
   22.52  
   22.53 -    private void readAnno(DataInputStream dis, ClassData cd) throws IOException {
   22.54 +    private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
   22.55          int type = dis.readUnsignedShort();
   22.56          String typeName = cd.StringValue(type);
   22.57 -        visitAnnotationStart(typeName);
   22.58 +        visitAnnotationStart(typeName, top);
   22.59      	int cnt = dis.readUnsignedShort();
   22.60      	for (int i = 0; i < cnt; i++) {
   22.61              String attrName = cd.StringValue(dis.readUnsignedShort());
   22.62              readValue(dis, cd, typeName, attrName);
   22.63          }
   22.64 -        visitAnnotationEnd(typeName);
   22.65 +        visitAnnotationEnd(typeName, top);
   22.66          if (cnt == 0) {
   22.67              visitAttr(typeName, null, null, null);
   22.68          }
   22.69      }
   22.70  
   22.71 -    private void readValue(DataInputStream dis, ClassData cd, String typeName, String attrName) 
   22.72 -    throws IOException {
   22.73 +    private void readValue(
   22.74 +        DataInputStream dis, ClassData cd, String typeName, String attrName
   22.75 +    ) throws IOException {
   22.76          char type = (char)dis.readByte();
   22.77 +        visitValueStart(attrName, type);
   22.78          if (type == '@') {
   22.79 -            readAnno(dis, cd);
   22.80 +            readAnno(dis, cd, false);
   22.81          } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
   22.82              int primitive = dis.readUnsignedShort();
   22.83              String val = cd.stringValue(primitive, textual);
   22.84 @@ -112,13 +129,17 @@
   22.85          } else if (type == '[') {
   22.86              int cnt = dis.readUnsignedShort();
   22.87              for (int i = 0; i < cnt; i++) {
   22.88 -                readValue(dis, cd, typeName, attrName);
   22.89 +                readValue(dis, cd, typeName, iterateArray ? attrName : null);
   22.90              }
   22.91          } else if (type == 'e') {
   22.92              int enumT = dis.readUnsignedShort();
   22.93 +            String attrType = cd.stringValue(enumT, textual);
   22.94              int enumN = dis.readUnsignedShort();
   22.95 +            String val = cd.stringValue(enumN, textual);
   22.96 +            visitEnumAttr(typeName, attrName, attrType, val);
   22.97          } else {
   22.98              throw new IOException("Unknown type " + type);
   22.99          }
  22.100 +        visitValueEnd(attrName, type);
  22.101      }
  22.102  }
    23.1 --- a/mojo/src/main/resources/archetype-resources/pom.xml	Sat Feb 02 06:01:44 2013 +0100
    23.2 +++ b/mojo/src/main/resources/archetype-resources/pom.xml	Tue Feb 05 08:27:42 2013 +0100
    23.3 @@ -60,7 +60,7 @@
    23.4        <scope>test</scope>
    23.5      </dependency>
    23.6      <dependency>
    23.7 -      <groupId>${project.groupId}</groupId>
    23.8 +      <groupId>org.apidesign.bck2brwsr</groupId>
    23.9        <artifactId>vmtest</artifactId>
   23.10        <version>0.3-SNAPSHOT</version>
   23.11        <scope>test</scope>
    24.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Sat Feb 02 06:01:44 2013 +0100
    24.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Tue Feb 05 08:27:42 2013 +0100
    24.3 @@ -175,6 +175,7 @@
    24.4                  out.append("\n    };");
    24.5              }
    24.6              out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
    24.7 +            out.append(prefix).append(mn).append(".cls = CLS;");
    24.8          }
    24.9          out.append("\n    c.constructor = CLS;");
   24.10          out.append("\n    c.$instOf_").append(className).append(" = true;");
   24.11 @@ -1605,7 +1606,7 @@
   24.12          final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
   24.13          class P extends AnnotationParser {
   24.14              public P() {
   24.15 -                super(false);
   24.16 +                super(false, true);
   24.17              }
   24.18              
   24.19              int cnt;
   24.20 @@ -1661,7 +1662,7 @@
   24.21          final String[] values = new String[attrNames.length];
   24.22          final boolean[] found = { false };
   24.23          final String jvmType = "L" + className.replace('.', '/') + ";";
   24.24 -        AnnotationParser ap = new AnnotationParser(false) {
   24.25 +        AnnotationParser ap = new AnnotationParser(false, true) {
   24.26              @Override
   24.27              protected void visitAttr(String type, String attr, String at, String value) {
   24.28                  if (type.equals(jvmType)) {
   24.29 @@ -1698,35 +1699,71 @@
   24.30          return " = null;";
   24.31      }
   24.32  
   24.33 -    private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
   24.34 -        AnnotationParser ap = new AnnotationParser(true) {
   24.35 -            int anno;
   24.36 -            int cnt;
   24.37 +    private void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException {
   24.38 +        AnnotationParser ap = new AnnotationParser(true, false) {
   24.39 +            int[] cnt = new int[32];
   24.40 +            int depth;
   24.41              
   24.42              @Override
   24.43 -            protected void visitAnnotationStart(String type) throws IOException {
   24.44 -                if (anno++ > 0) {
   24.45 +            protected void visitAnnotationStart(String attrType, boolean top) throws IOException {
   24.46 +                final String slashType = attrType.substring(1, attrType.length() - 1);
   24.47 +                requireReference(slashType);
   24.48 +                
   24.49 +                if (cnt[depth]++ > 0) {
   24.50                      out.append(",");
   24.51                  }
   24.52 -                out.append('"').append(type).append("\" : {\n");
   24.53 -                cnt = 0;
   24.54 +                if (top) {
   24.55 +                    out.append('"').append(attrType).append("\" : ");
   24.56 +                }
   24.57 +                out.append("{\n");
   24.58 +                cnt[++depth] = 0;
   24.59              }
   24.60  
   24.61              @Override
   24.62 -            protected void visitAnnotationEnd(String type) throws IOException {
   24.63 +            protected void visitAnnotationEnd(String type, boolean top) throws IOException {
   24.64                  out.append("\n}\n");
   24.65 +                depth--;
   24.66 +            }
   24.67 +
   24.68 +            @Override
   24.69 +            protected void visitValueStart(String attrName, char type) throws IOException {
   24.70 +                if (cnt[depth]++ > 0) {
   24.71 +                    out.append(",\n");
   24.72 +                }
   24.73 +                cnt[++depth] = 0;
   24.74 +                if (attrName != null) {
   24.75 +                    out.append(attrName).append(" : ");
   24.76 +                }
   24.77 +                if (type == '[') {
   24.78 +                    out.append("[");
   24.79 +                }
   24.80 +            }
   24.81 +
   24.82 +            @Override
   24.83 +            protected void visitValueEnd(String attrName, char type) throws IOException {
   24.84 +                if (type == '[') {
   24.85 +                    out.append("]");
   24.86 +                }
   24.87 +                depth--;
   24.88              }
   24.89              
   24.90              @Override
   24.91              protected void visitAttr(String type, String attr, String attrType, String value) 
   24.92              throws IOException {
   24.93 -                if (attr == null) {
   24.94 +                if (attr == null && value == null) {
   24.95                      return;
   24.96                  }
   24.97 -                if (cnt++ > 0) {
   24.98 -                    out.append(",\n");
   24.99 -                }
  24.100 -                out.append(attr).append("__").append(attrType).append(" : ").append(value);
  24.101 +                out.append(value);
  24.102 +            }
  24.103 +
  24.104 +            @Override
  24.105 +            protected void visitEnumAttr(String type, String attr, String attrType, String value) 
  24.106 +            throws IOException {
  24.107 +                final String slashType = attrType.substring(1, attrType.length() - 1);
  24.108 +                requireReference(slashType);
  24.109 +                
  24.110 +                out.append(accessClass(slashType.replace('/', '_')))
  24.111 +                   .append("(false).constructor.").append(value);
  24.112              }
  24.113          };
  24.114          ap.parse(data, cd);
    25.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Sat Feb 02 06:01:44 2013 +0100
    25.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Tue Feb 05 08:27:42 2013 +0100
    25.3 @@ -87,12 +87,27 @@
    25.4      @Test public void jsAnnotation() throws Exception {
    25.5          assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10));
    25.6      }
    25.7 +    @Test public void jsArrayAnnotation() throws Exception {
    25.8 +        assertExec("Check array annotation", Classes.class, "getMarkerNicknames__Ljava_lang_String_2", Classes.getMarkerNicknames());
    25.9 +    }
   25.10 +    @Test public void jsEnumAnnotation() throws Exception {
   25.11 +        assertExec("Check enum annotation", Classes.class, "getMarkerE__Ljava_lang_String_2", Classes.getMarkerE());
   25.12 +    }
   25.13 +    @Test public void jsRetentionAnnotation() throws Exception {
   25.14 +        assertExec("Check enum annotation", Classes.class, "getRetention__Ljava_lang_String_2", Classes.getRetention());
   25.15 +    }
   25.16      @Test public void jsStringAnnotation() throws Exception {
   25.17          assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true);
   25.18      }
   25.19      @Test public void jsStringAnnotationFromArray() throws Exception {
   25.20          assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", false);
   25.21      }
   25.22 +    @Test public void jsInnerAnnotation() throws Exception {
   25.23 +        assertExec("Check inner annotation", Classes.class, "getInnerNamer__I", Double.valueOf(Classes.getInnerNamer()));
   25.24 +    }
   25.25 +    @Test public void jsInnerAnnotationFromArray() throws Exception {
   25.26 +        assertExec("Check inner annotation", Classes.class, "getInnerNamers__I", Double.valueOf(Classes.getInnerNamers()));
   25.27 +    }
   25.28      @Test public void javaInvokeMethod() throws Exception {
   25.29          assertEquals(Classes.reflectiveMethodCall(true, "name"), "java.io.IOException", "Calls the name() method via reflection");
   25.30      }
   25.31 @@ -102,6 +117,14 @@
   25.32              "java.io.IOException", true, "name"
   25.33          );
   25.34      }
   25.35 +    
   25.36 +    @Test public void jsMethodDeclaredInObject() throws Exception {
   25.37 +        assertExec("Defined in Object", Classes.class, 
   25.38 +            "objectName__Ljava_lang_String_2", 
   25.39 +            "java.lang.Object"
   25.40 +        );
   25.41 +    }
   25.42 +    
   25.43      @Test public void jsInvokeParamMethod() throws Exception {
   25.44          assertExec("sums two numbers via reflection", Classes.class, 
   25.45              "reflectiveSum__III", Double.valueOf(5), 2, 3
   25.46 @@ -149,14 +172,12 @@
   25.47              0.0, "java.lang.String"
   25.48          );
   25.49      }
   25.50 -    /*
   25.51      @Test public void isInterface() throws Exception {
   25.52          assertExec("Calls Class.isInterface", Classes.class, 
   25.53              "isInterface__ZLjava_lang_String_2", 
   25.54              1.0, "java.lang.Runnable"
   25.55          );
   25.56      }
   25.57 -    */
   25.58      @Test public void integerType() throws Exception {
   25.59          assertExec("Computes the type", Classes.class, 
   25.60              "intType__Ljava_lang_String_2", 
    26.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Sat Feb 02 06:01:44 2013 +0100
    26.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Tue Feb 05 08:27:42 2013 +0100
    26.3 @@ -19,6 +19,8 @@
    26.4  
    26.5  import java.io.IOException;
    26.6  import java.lang.annotation.Annotation;
    26.7 +import java.lang.annotation.Retention;
    26.8 +import java.lang.annotation.RetentionPolicy;
    26.9  import java.lang.reflect.Method;
   26.10  import java.net.MalformedURLException;
   26.11  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   26.12 @@ -27,8 +29,11 @@
   26.13   *
   26.14   * @author Jaroslav Tulach <jtulach@netbeans.org>
   26.15   */
   26.16 -@ClassesMarker(number = 10)
   26.17 -@ClassesNamer(name = "my text")
   26.18 +@ClassesMarker(number = 10, nicknames = { "Ten", "Deset" }, count = ClassesMarker.E.TWO, subs = {
   26.19 +    @ClassesMarker.Anno(Integer.SIZE),
   26.20 +    @ClassesMarker.Anno(Integer.MIN_VALUE)
   26.21 +})
   26.22 +@ClassesNamer(name = "my text", anno = @ClassesMarker.Anno(333))
   26.23  public class Classes {
   26.24      public static String nameOfIO() {
   26.25          return nameFor(IOException.class);
   26.26 @@ -38,6 +43,8 @@
   26.27          return c.getName();
   26.28      }
   26.29      
   26.30 +    private static final Class<?> PRELOAD = Runnable.class;
   26.31 +    
   26.32      public static boolean isInterface(String s) throws ClassNotFoundException {
   26.33          return Class.forName(s).isInterface();
   26.34      }
   26.35 @@ -55,7 +62,7 @@
   26.36          return new IOException().getClass().getName().toString();
   26.37      }
   26.38      
   26.39 -    @ClassesMarker(number = 1)
   26.40 +    @ClassesMarker(number = 1, nicknames = { "One", "Jedna" } )
   26.41      public static String name() {
   26.42          return IOException.class.getName().toString();
   26.43      }
   26.44 @@ -65,6 +72,11 @@
   26.45      public static String canonicalName() {
   26.46          return IOException.class.getCanonicalName();
   26.47      }
   26.48 +    
   26.49 +    public static String objectName() throws NoSuchMethodException {
   26.50 +        return IOException.class.getMethod("wait").getDeclaringClass().getName();
   26.51 +    }
   26.52 +    
   26.53      public static boolean newInstance() throws Exception {
   26.54          IOException ioe = IOException.class.newInstance();
   26.55          if (ioe instanceof IOException) {
   26.56 @@ -85,8 +97,45 @@
   26.57              return -2;
   26.58          }
   26.59          ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
   26.60 +        assert cm instanceof Object : "Is object " + cm;
   26.61 +        assert cm instanceof Annotation : "Is annotation " + cm;
   26.62 +        assert !((Object)cm instanceof Class) : "Is not Class " + cm;
   26.63          return cm == null ? -1 : cm.number();
   26.64      }
   26.65 +    public static String getMarkerNicknames() {
   26.66 +        ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
   26.67 +        if (cm == null) {
   26.68 +            return null;
   26.69 +        }
   26.70 +        
   26.71 +        final Object[] arr = cm.nicknames();
   26.72 +        assert arr instanceof Object[] : "Instance of Object array: " + arr;
   26.73 +        assert arr instanceof String[] : "Instance of String array: " + arr;
   26.74 +        assert !(arr instanceof Integer[]) : "Not instance of Integer array: " + arr;
   26.75 +        
   26.76 +        StringBuilder sb = new StringBuilder();
   26.77 +        for (String s : cm.nicknames()) {
   26.78 +            sb.append(s).append("\n");
   26.79 +        }
   26.80 +        return sb.toString().toString();
   26.81 +    }
   26.82 +    @Retention(RetentionPolicy.CLASS)
   26.83 +    @interface Ann {
   26.84 +    }
   26.85 +    
   26.86 +    public static String getRetention() throws Exception {
   26.87 +        Retention r = Ann.class.getAnnotation(Retention.class);
   26.88 +        assert r != null : "Annotation is present";
   26.89 +        assert r.value() == RetentionPolicy.CLASS : "Policy value is OK: " + r.value();
   26.90 +        return r.annotationType().getName();
   26.91 +    }
   26.92 +    public static String getMarkerE() {
   26.93 +        ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
   26.94 +        if (cm == null) {
   26.95 +            return null;
   26.96 +        }
   26.97 +        return cm.count().name();
   26.98 +    }
   26.99      public static String getNamer(boolean direct) {
  26.100          if (direct) {
  26.101              ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
  26.102 @@ -99,6 +148,20 @@
  26.103          }
  26.104          return null;
  26.105      }
  26.106 +    public static int getInnerNamer() {
  26.107 +        ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class);
  26.108 +        assert cm != null : "ClassesNamer is present";
  26.109 +        return cm.anno().value();
  26.110 +    }
  26.111 +    public static int getInnerNamers() {
  26.112 +        ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class);
  26.113 +        assert cm != null : "ClassesNamer is present";
  26.114 +        int sum = 0;
  26.115 +        for (ClassesMarker.Anno anno : cm.subs()) {
  26.116 +            sum += anno.value();
  26.117 +        }
  26.118 +        return sum;
  26.119 +    }
  26.120      
  26.121      public static String intType() {
  26.122          return Integer.TYPE.getName();
    27.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java	Sat Feb 02 06:01:44 2013 +0100
    27.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java	Tue Feb 05 08:27:42 2013 +0100
    27.3 @@ -27,4 +27,16 @@
    27.4  @Retention(RetentionPolicy.RUNTIME)
    27.5  public @interface ClassesMarker {
    27.6      int number();
    27.7 +    String[] nicknames();
    27.8 +    E count() default E.ONE;
    27.9 +    
   27.10 +    enum E {
   27.11 +        ONE, TWO;
   27.12 +    }
   27.13 +    
   27.14 +    Anno[] subs() default {};
   27.15 +    
   27.16 +    public @interface Anno {
   27.17 +        int value();
   27.18 +    }
   27.19  }
    28.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java	Sat Feb 02 06:01:44 2013 +0100
    28.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java	Tue Feb 05 08:27:42 2013 +0100
    28.3 @@ -27,4 +27,5 @@
    28.4  @Retention(RetentionPolicy.RUNTIME)
    28.5  public @interface ClassesNamer {
    28.6      String name();
    28.7 +    ClassesMarker.Anno anno();
    28.8  }
    29.1 --- a/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Sat Feb 02 06:01:44 2013 +0100
    29.2 +++ b/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Tue Feb 05 08:27:42 2013 +0100
    29.3 @@ -17,6 +17,8 @@
    29.4   */
    29.5  package org.apidesign.bck2brwsr.tck;
    29.6  
    29.7 +import java.lang.annotation.Retention;
    29.8 +import java.lang.annotation.RetentionPolicy;
    29.9  import java.lang.reflect.Method;
   29.10  import java.util.Arrays;
   29.11  import java.util.Collections;
   29.12 @@ -47,6 +49,14 @@
   29.13          return long.class.toString();
   29.14      }
   29.15      
   29.16 +    @Compare public boolean isRunnableInterface() {
   29.17 +        return Runnable.class.isInterface();
   29.18 +    }
   29.19 +
   29.20 +    @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
   29.21 +        return Runnable.class.getMethod("run").getName();
   29.22 +    }
   29.23 +    
   29.24      @Compare public String namesOfMethods() {
   29.25          StringBuilder sb = new StringBuilder();
   29.26          String[] arr = new String[20];
   29.27 @@ -59,6 +69,19 @@
   29.28          }
   29.29          return sb.toString();
   29.30      }
   29.31 +
   29.32 +    @Compare public String namesOfDeclaringClassesOfMethods() {
   29.33 +        StringBuilder sb = new StringBuilder();
   29.34 +        String[] arr = new String[20];
   29.35 +        int i = 0;
   29.36 +        for (Method m : StaticUse.class.getMethods()) {
   29.37 +            arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
   29.38 +        }
   29.39 +        for (String s : sort(arr, i)) {
   29.40 +            sb.append(s).append("\n");
   29.41 +        }
   29.42 +        return sb.toString();
   29.43 +    }
   29.44      
   29.45      @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
   29.46          StaticUse.class.getMethod("instanceMethod").invoke(null);
   29.47 @@ -69,6 +92,26 @@
   29.48          return StaticUse.class.getMethod("instanceMethod").getReturnType();
   29.49      }
   29.50      
   29.51 +    @Retention(RetentionPolicy.RUNTIME)
   29.52 +    @interface Ann {
   29.53 +    }
   29.54 +    
   29.55 +    @Compare public String annoClass() throws Exception {
   29.56 +        Retention r = Ann.class.getAnnotation(Retention.class);
   29.57 +        assert r != null : "Annotation is present";
   29.58 +        assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
   29.59 +        return r.annotationType().getName();
   29.60 +    }
   29.61 +    
   29.62 +    @Compare public boolean isAnnotation() {
   29.63 +        return Ann.class.isAnnotation();
   29.64 +    }
   29.65 +    @Compare public boolean isNotAnnotation() {
   29.66 +        return String.class.isAnnotation();
   29.67 +    }
   29.68 +    @Compare public boolean isNotAnnotationEnum() {
   29.69 +        return E.class.isAnnotation();
   29.70 +    }
   29.71      enum E { A, B };
   29.72      @Compare public boolean isEnum() {
   29.73          return E.A.getClass().isEnum();