Revision: 6215
Author: j...@google.com
Date: Fri Sep 25 11:00:02 2009
Log: Fix GC handling for HtmlUnit in development mode.

Patch by: jat
Review by: amitmanjhi


http://code.google.com/p/google-web-toolkit/source/detail?r=6215

Added:
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/RemoteObjectTable.java
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/ServerObjectsTable.java
   
/branches/farewellSwt/dev/oophm/test/com/google/gwt/dev/shell/RemoteObjectTableTest.java
Deleted:
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/ObjectsTable.java
Modified:
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannel.java
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelClient.java
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelServer.java
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/JsValueOOPHM.java
   
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/OophmSessionHandler.java
   
/branches/farewellSwt/dev/oophm/test/com/google/gwt/dev/shell/BrowserChannelTest.java
  /branches/farewellSwt/user/src/com/google/gwt/junit/RunStyle.java

=======================================
--- /dev/null
+++  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/RemoteObjectTable.java
      
Fri Sep 25 11:00:02 2009
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.dev.shell;
+
+import com.google.gwt.dev.shell.BrowserChannel.RemoteObjectRef;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Keeps track of references to remote objects.  When the objects are no  
longer
+ * needed, their ids are returned in {...@link #getRefIdsForCleanup()}.
+ *
+ * @param <T> subtype of RemoteObjectRef contained in this table
+ */
+public class RemoteObjectTable<T extends RemoteObjectRef> {
+
+  /**
+   * This maps References to RemoteObjectRefs back to the original refId.
+   * Because we need the refId of the RemoteObjectRef after it's been
+   * garbage-collected, this state must be stored externally.
+   */
+  private final Map<Reference<T>, Integer> idFromRemoteObject;
+
+  /**
+   * This accumulates remote objects that are no longer referenced on this  
side
+   * of the channel.
+   */
+  private final ReferenceQueue<T> refQueue;
+
+  /**
+   * This map associates a remote object ID with a Reference to the
+   * RemoteObjectRef that currently represents that id.
+   */
+  private final Map<Integer, Reference<T>> remoteObjectFromId;
+
+  /**
+   * Create a new RemoteObjectTable.
+   */
+  public RemoteObjectTable() {
+    refQueue = new ReferenceQueue<T>();
+    remoteObjectFromId = new HashMap<Integer, Reference<T>>();
+    idFromRemoteObject = new IdentityHashMap<Reference<T>, Integer>();
+  }
+
+  /**
+   * @return the set of remote object reference IDs that should be freed.
+   */
+  public synchronized Set<Integer> getRefIdsForCleanup() {
+    // Access to these objects is inherently synchronous
+    Map<Integer, Reference<T>> objectMap = remoteObjectFromId;
+    Map<Reference<T>, Integer> refIdMap = idFromRemoteObject;
+    Set<Integer> toReturn = new HashSet<Integer>();
+
+    // Find all refIds associated with previous garbage collection cycles
+    Reference<? extends RemoteObjectRef> ref;
+    while ((ref = refQueue.poll()) != null) {
+      Integer i = refIdMap.remove(ref);
+      assert i != null;
+      toReturn.add(i);
+    }
+
+    /*
+     * Check for liveness. This is necessary because the last reference to  
a
+     * RemoteObjectRef could have been cleared and a new reference to that  
refId
+     * created before this method has been called.
+     */
+    for (Iterator<Integer> i = toReturn.iterator(); i.hasNext();) {
+      Integer refId = i.next();
+      if (objectMap.containsKey(refId)) {
+        if (objectMap.get(refId).get() != null) {
+          i.remove();
+        } else {
+          objectMap.remove(refId);
+        }
+      }
+    }
+
+    return toReturn;
+  }
+
+  /**
+   * Obtain the RemoteObjectRef that is currently in use to act as a proxy  
for
+   * the given remote object ID.
+   *
+   * @return the RemoteObjectRef or null if the ID is not currently in use
+   */
+  public synchronized T getRemoteObjectRef(int refId) {
+    if (remoteObjectFromId.containsKey(refId)) {
+      Reference<T> ref = remoteObjectFromId.get(refId);
+      T toReturn = ref.get();
+      if (toReturn != null) {
+        return toReturn;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Check to see if this ID does not already exist.
+   *
+   * @param refId reference ID to check
+   * @return true if this ID is not currently in use
+   */
+  public synchronized boolean isNewObjectId(int refId) {
+    return !remoteObjectFromId.containsKey(refId)
+    || (remoteObjectFromId.get(refId).get() == null);
+  }
+
+  /**
+   * Store a remote object reference in the table.
+   *
+   * @param refId
+   * @param remoteObjectRef
+   */
+  public synchronized void putRemoteObjectRef(int refId,
+      T remoteObjectRef) {
+    Reference<T> ref = new WeakReference<T>(remoteObjectRef, refQueue);
+    remoteObjectFromId.put(refId, ref);
+    idFromRemoteObject.put(ref, refId);
+  }
+}
=======================================
--- /dev/null
+++  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/ServerObjectsTable.java
     
Fri Sep 25 11:00:02 2009
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.dev.shell;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * A class that keeps track of Java objects which have been exposed to the  
other
+ * side and assigns unique ids.
+ */
+public class ServerObjectsTable {
+
+  /**
+   * A type that records the next-available free id slot to use, without  
itself
+   * being a valid return type.
+   */
+  private static class Tombstone {
+    private final int nextFree;
+
+    public Tombstone(int nextFree) {
+      this.nextFree = nextFree;
+    }
+  }
+
+  private int nextFree = -1;
+  private int nextId = 0;
+  private final Map<Integer, Object> objects = new TreeMap<Integer,  
Object>();
+  private final Map<Object, Integer> refMap = new IdentityHashMap<Object,  
Integer>();
+
+  public int add(Object obj) {
+    int id = find(obj);
+    if (id >= 0) {
+      return id;
+    }
+    if (nextFree >= 0) {
+      id = nextFree;
+      nextFree = ((Tombstone) objects.get(id)).nextFree;
+    } else {
+      id = nextId++;
+    }
+    objects.put(id, obj);
+    refMap.put(obj, id);
+    return id;
+  }
+
+  public int find(Object obj) {
+    Integer objId = refMap.get(obj);
+    return objId != null ? objId.intValue() : -1;
+  }
+
+  public void free(int id) {
+    Object object = objects.get(id);
+    assert object != null : "Trying to free never-used id " + id;
+    assert !(object instanceof Tombstone) : "Duplicate free " + id;
+    refMap.remove(object);
+    objects.put(id, new Tombstone(nextFree));
+    nextFree = id;
+  }
+
+  public Object get(int id) {
+    Object toReturn = objects.get(id);
+    assert !(toReturn instanceof Tombstone) : id + " is not an active id";
+    return toReturn;
+  }
+}
=======================================
--- /dev/null
+++  
/branches/farewellSwt/dev/oophm/test/com/google/gwt/dev/shell/RemoteObjectTableTest.java
         
Fri Sep 25 11:00:02 2009
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
+ * use this file except in compliance with the License. You may obtain a  
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations  
under
+ * the License.
+ */
+package com.google.gwt.dev.shell;
+
+import com.google.gwt.dev.shell.BrowserChannel.RemoteObjectRef;
+
+import junit.framework.TestCase;
+
+import java.util.Set;
+
+/**
+ * Test RemoteObjectTable.
+ */
+public class RemoteObjectTableTest extends TestCase {
+
+  /**
+   * Mock implementation of a RemoteObjectRef.
+   */
+  public class MockRemoteObjectRef implements RemoteObjectRef {
+
+    public final int refId;
+
+    public MockRemoteObjectRef(int refId) {
+      this.refId = refId;
+    }
+
+    public int getRefid() {
+      return refId;
+    }
+  }
+
+  public void testFree() throws InterruptedException {
+    RemoteObjectTable<MockRemoteObjectRef> table = new RemoteObjectTable<
+        MockRemoteObjectRef>();
+    MockRemoteObjectRef ref = new MockRemoteObjectRef(1);
+    table.putRemoteObjectRef(1, ref);
+    Set<Integer> freed = table.getRefIdsForCleanup();
+    ensureGC();
+    assertEquals(0, freed.size());
+    ref = null;
+    ensureGC();
+    freed = table.getRefIdsForCleanup();
+    assertEquals(1, freed.size());
+  }
+
+  /**
+   * This method attempts to ensure that a GC has happened and any weak
+   * references have been cleaned up.
+   *
+   * @throws InterruptedException
+   */
+  private void ensureGC() throws InterruptedException {
+    // TODO(jat): is this sufficient across all VMs?
+    System.gc();
+    Thread.sleep(10);
+    System.gc();
+  }
+}
=======================================
---  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/ObjectsTable.java  
 
Tue Nov 25 16:21:22 2008
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2008 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may  
not
- * use this file except in compliance with the License. You may obtain a  
copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,  
WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations  
under
- * the License.
- */
-package com.google.gwt.dev.shell;
-
-import java.util.IdentityHashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * A class that keeps track of Java objects which have been exposed to the  
other
- * side and assigns unique ids.
- */
-public class ObjectsTable {
-
-  /**
-   * A type that records the next-available free id slot to use, without  
itself
-   * being a valid return type.
-   */
-  private static class Tombstone {
-    private final int nextFree;
-
-    public Tombstone(int nextFree) {
-      this.nextFree = nextFree;
-    }
-  }
-
-  private int nextFree = -1;
-  private int nextId = 0;
-  private final Map<Integer, Object> objects = new TreeMap<Integer,  
Object>();
-  private final Map<Object, Integer> refMap = new IdentityHashMap<Object,  
Integer>();
-
-  public int add(Object obj) {
-    int id = find(obj);
-    if (id >= 0) {
-      return id;
-    }
-    if (nextFree >= 0) {
-      id = nextFree;
-      nextFree = ((Tombstone) objects.get(id)).nextFree;
-    } else {
-      id = nextId++;
-    }
-    objects.put(id, obj);
-    refMap.put(obj, id);
-    return id;
-  }
-
-  public int find(Object obj) {
-    Integer objId = refMap.get(obj);
-    return objId != null ? objId.intValue() : -1;
-  }
-
-  public void free(int id) {
-    assert objects.get(id) != null : "Trying to free never-used id " + id;
-    assert !(objects.get(id) instanceof Tombstone) : "Duplicate free " +  
id;
-    refMap.remove(objects.get(id));
-    objects.put(id, new Tombstone(nextFree));
-    nextFree = id;
-  }
-
-  public Object get(int id) {
-    Object toReturn = objects.get(id);
-    assert !(toReturn instanceof Tombstone) : id + " is not an active id";
-    return toReturn;
-  }
-}
=======================================
---  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannel.java
         
Thu Sep 10 16:26:01 2009
+++  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannel.java
         
Fri Sep 25 11:00:02 2009
@@ -29,16 +29,9 @@
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.io.UnsupportedEncodingException;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.WeakReference;
  import java.net.Socket;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.Collections;
  import java.util.Set;
-import java.util.TreeMap;

  /**
   *
@@ -48,7 +41,7 @@
    /**
     * Class representing a reference to a Java object.
     */
-  public static class JavaObjectRef {
+  public static class JavaObjectRef implements RemoteObjectRef {
      private int refId;

      public JavaObjectRef(int refId) {
@@ -58,6 +51,15 @@
      public int getRefid() {
        return Math.abs(refId);
      }
+
+    @Override
+    public int hashCode() {
+      return refId;
+    }
+
+    public boolean isException() {
+      return refId < 0;
+    }

      @Override
      public String toString() {
@@ -68,14 +70,8 @@
    /**
     * Class representing a reference to a JS object.
     */
-  public static class JsObjectRef {
-
-    // TODO: refactor and remove this method.
-    public static void checkIdMap(int refId) {
-      assert !JSOBJECT_ID_MAP.get().containsKey(refId)
-      || (JSOBJECT_ID_MAP.get().get(refId).get() == null);
-    }
-
+  public static class JsObjectRef implements RemoteObjectRef  {
+
      private int refId;

      public JsObjectRef(int refId) {
@@ -110,13 +106,77 @@
    /**
     * Enumeration of message type ids.
     *
-   * NOTE: order is important as this defines the ordinals used in the wire
-   * protocol.
+   * <p>Ids are used instead of relying on the ordinal to avoid  
sychronization
+   * problems with the client.
     */
    public enum MessageType {
-    INVOKE, RETURN, OLD_LOAD_MODULE, QUIT, LOAD_JSNI, INVOKE_SPECIAL,  
FREE_VALUE,
-    FATAL_ERROR, CHECK_VERSIONS, PROTOCOL_VERSION, CHOOSE_TRANSPORT,
-    SWITCH_TRANSPORT, LOAD_MODULE;
+    /**
+     * A message to invoke a method on the other side of the wire.  Note  
that
+     * the messages are asymmetric -- see {...@link InvokeOnClientMessage} and
+     * {...@link InvokeOnServerMessage}.
+     */
+    INVOKE(0),
+
+    /**
+     * Returns the result of an INVOKE, INVOKE_SPECIAL, or LOAD_MODULE  
message.
+     */
+    RETURN(1),
+
+    /**
+     * v1 LOAD_MODULE message.
+     */
+    OLD_LOAD_MODULE(2),
+
+    /**
+     * Normal closure of the connection.
+     */
+    QUIT(3),
+
+    /**
+     * A request by the server to load JSNI source into the client's JS  
engine.
+     */
+    LOAD_JSNI(4),
+
+    INVOKE_SPECIAL(5),
+
+    FREE_VALUE(6),
+
+    /**
+     * Abnormal termination of the connection.
+     */
+    FATAL_ERROR(7),
+
+    CHECK_VERSIONS(8),
+
+    PROTOCOL_VERSION(9),
+
+    CHOOSE_TRANSPORT(10),
+
+    SWITCH_TRANSPORT(11),
+
+    LOAD_MODULE(12);
+
+    private final int id;
+
+    private MessageType(int id) {
+      this.id = id;
+    }
+
+    public int getId() {
+      return id;
+    }
+  }
+
+  /**
+   * Represents an object on the other side of the channel, known to this  
side
+   * by an reference ID.
+   */
+  public interface RemoteObjectRef {
+
+    /**
+      * Return the reference ID for this object.
+      */
+    int getRefid();
    }

    /**
@@ -149,10 +209,23 @@
      /**
       * Enumeration of dispatch IDs on object 0 (the ServerMethods object).
       *
+     * <p>Ids are set specifically rather than relying on the ordinal to  
avoid
+     * synchronization problems with the client.
+     *
       * TODO: hasMethod/hasProperty no longer used, remove them!
       */
      public enum SpecialDispatchId {
-      HasMethod, HasProperty, GetProperty, SetProperty,
+      HasMethod(0), HasProperty(1), GetProperty(2), SetProperty(3);
+
+      private final int id;
+
+      private SpecialDispatchId(int id) {
+        this.id = id;
+      }
+
+      public int getId() {
+        return id;
+      }
      }

      public abstract void freeValue(BrowserChannel channel, int[] ids);
@@ -197,24 +270,28 @@
        /**
         * Primitive values.
         */
-      NULL, BOOLEAN, BYTE, CHAR, SHORT, INT, LONG, FLOAT, DOUBLE, STRING,
+      NULL(0), BOOLEAN(1), BYTE(2), CHAR(3), SHORT(4), INT(5), LONG(6),
+      FLOAT(7), DOUBLE(8), STRING(9),

        /**
         * Representations of Java or JS objects, sent as an index into a  
table
         * kept on the side holding the actual object.
         */
-      JAVA_OBJECT, JS_OBJECT,
+      JAVA_OBJECT(10), JS_OBJECT(11),

        /**
         * A Javascript undef value, also used for void returns.
         */
-      UNDEFINED;
-
-      ValueType() {
+      UNDEFINED(12);
+
+      private final int id;
+
+      private ValueType(int id) {
+        this.id = id;
        }

        byte getTag() {
-        return (byte) this.ordinal();
+        return (byte) id;
        }
      }

@@ -556,11 +633,11 @@
            hostedHtmlVersion);
      }

-    private final int minVersion;
+    private final String hostedHtmlVersion;

      private final int maxVersion;

-    private final String hostedHtmlVersion;
+    private final int minVersion;

      public CheckVersionsMessage(BrowserChannel channel, int minVersion,
          int maxVersion, String hostedHtmlVersion) {
@@ -585,7 +662,7 @@
      @Override
      public void send() throws IOException {
        DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.CHECK_VERSIONS.ordinal());
+      stream.writeByte(MessageType.CHECK_VERSIONS.getId());
        stream.writeInt(minVersion);
        stream.writeInt(maxVersion);
        writeUtf8String(stream, hostedHtmlVersion);
@@ -625,7 +702,7 @@
      @Override
      public void send() throws IOException {
        DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.CHOOSE_TRANSPORT.ordinal());
+      stream.writeByte(MessageType.CHOOSE_TRANSPORT.getId());
        stream.writeInt(transports.length);
        for (String transport : transports) {
          writeUtf8String(stream, transport);
@@ -660,7 +737,7 @@
      @Override
      public void send() throws IOException {
        DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.FATAL_ERROR.ordinal());
+      stream.writeByte(MessageType.FATAL_ERROR.getId());
        writeUtf8String(stream, error);
      }
    }
@@ -686,7 +763,7 @@
      public static void send(BrowserChannel channel, int[] ids)
          throws IOException {
        DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.FREE_VALUE.ordinal());
+      stream.writeByte(MessageType.FREE_VALUE.getId());
        stream.writeInt(ids.length);
        for (int id : ids) {
          stream.writeInt(id);
@@ -730,19 +807,18 @@
        DataInputStream stream = channel.getStreamFromOtherSide();
        // NOTE: Tag has already been read.
        String methodName = readUtf8String(stream);
-      Value thisRef = readValue(stream);
+      Value thisRef = channel.readValue(stream);
        int argLen = stream.readInt();
        Value[] args = new Value[argLen];
        for (int i = 0; i < argLen; i++) {
-        args[i] = readValue(stream);
+        args[i] = channel.readValue(stream);
        }
        return new InvokeOnClientMessage(channel, methodName, thisRef, args);
      }

+    private final Value[] args;
      private final String methodName;
-
      private final Value thisRef;
-    private final Value[] args;

      public InvokeOnClientMessage(BrowserChannel channel, String methodName,
          Value thisRef, Value[] args) {
@@ -768,12 +844,12 @@
      public void send() throws IOException {
        final DataOutputStream stream =  
getBrowserChannel().getStreamToOtherSide();

-      stream.writeByte(MessageType.INVOKE.ordinal());
+      stream.writeByte(MessageType.INVOKE.getId());
        writeUtf8String(stream, methodName);
-      writeValue(stream, thisRef);
+      getBrowserChannel().writeValue(stream, thisRef);
        stream.writeInt(args.length);
        for (int i = 0; i < args.length; i++) {
-        writeValue(stream, args[i]);
+        getBrowserChannel().writeValue(stream, args[i]);
        }
        stream.flush();
      }
@@ -793,19 +869,19 @@
        DataInputStream stream = channel.getStreamFromOtherSide();
        // NOTE: Tag has already been read.
        int methodDispatchId = stream.readInt();
-      Value thisRef = readValue(stream);
+      Value thisRef = channel.readValue(stream);
        int argLen = stream.readInt();
        Value[] args = new Value[argLen];
        for (int i = 0; i < argLen; i++) {
-        args[i] = readValue(stream);
+        args[i] = channel.readValue(stream);
        }
        return new InvokeOnServerMessage(channel, methodDispatchId, thisRef,
            args);
      }

+    private final Value[] args;
      private final int methodDispatchId;
      private final Value thisRef;
-    private final Value[] args;

      public InvokeOnServerMessage(BrowserChannel channel, int  
methodDispatchId,
          Value thisRef, Value[] args) {
@@ -831,12 +907,12 @@
      public void send() throws IOException {
        final DataOutputStream stream =  
getBrowserChannel().getStreamToOtherSide();

-      stream.writeByte(MessageType.INVOKE.ordinal());
+      stream.writeByte(MessageType.INVOKE.getId());
        stream.writeInt(methodDispatchId);
-      writeValue(stream, thisRef);
+      getBrowserChannel().writeValue(stream, thisRef);
        stream.writeInt(args.length);
        for (int i = 0; i < args.length; i++) {
-        writeValue(stream, args[i]);
+        getBrowserChannel().writeValue(stream, args[i]);
        }
        stream.flush();
      }
@@ -860,13 +936,13 @@
        final int argLen = stream.readInt();
        final Value[] args = new Value[argLen];
        for (int i = 0; i < argLen; i++) {
-        args[i] = readValue(stream);
+        args[i] = channel.readValue(stream);
        }
        return new InvokeSpecialMessage(channel, dispatchId, args);
      }

-    private final SpecialDispatchId dispatchId;
      private final Value[] args;
+    private final SpecialDispatchId dispatchId;

      public InvokeSpecialMessage(BrowserChannel channel,
          SpecialDispatchId dispatchId, Value[] args) {
@@ -887,11 +963,11 @@
      public void send() throws IOException {
        final DataOutputStream stream =  
getBrowserChannel().getStreamToOtherSide();

-      stream.writeByte(MessageType.INVOKE_SPECIAL.ordinal());
-      stream.writeByte(dispatchId.ordinal());
+      stream.writeByte(MessageType.INVOKE_SPECIAL.getId());
+      stream.writeByte(dispatchId.getId());
        stream.writeInt(args.length);
        for (int i = 0; i < args.length; i++) {
-        writeValue(stream, args[i]);
+        getBrowserChannel().writeValue(stream, args[i]);
        }
        stream.flush();
      }
@@ -913,7 +989,7 @@
      public static void send(BrowserChannel channel, String js)
          throws IOException {
        DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.write(MessageType.LOAD_JSNI.ordinal());
+      stream.write(MessageType.LOAD_JSNI.getId());
        writeUtf8String(stream, js);
        stream.flush();
      }
@@ -959,13 +1035,13 @@

      private final String moduleName;

-    private final String userAgent;
-
-    private final String url;
-
      private final String sessionKey;

      private final String tabKey;
+
+    private final String url;
+
+    private final String userAgent;

      /**
       * Creates a LoadModule message to be sent to the server.
@@ -1017,7 +1093,7 @@
      @Override
      public void send() throws IOException {
        DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.LOAD_MODULE.ordinal());
+      stream.writeByte(MessageType.LOAD_MODULE.getId());
        writeUtf8String(stream, url);
        writeUtf8String(stream, tabKey);
        writeUtf8String(stream, sessionKey);
@@ -1067,6 +1143,20 @@
            + " is a message format that can only be received.");
      }
    }
+
+  /**
+   * Provides a way of allocating JS and Java object ids without knowing
+   * which one is the remote type, so code can be shared between client and
+   * server.
+   */
+  protected interface ObjectRefFactory {
+
+    JavaObjectRef getJavaObjectRef(int refId);
+
+    JsObjectRef getJsObjectRef(int refId);
+
+    Set<Integer> getRefIdsForCleanup();
+  }

    /**
     * A request from the client that the server load and initialize a given
@@ -1085,9 +1175,9 @@

      private final String moduleName;

-    private final String userAgent;
-
      private final int protoVersion;
+
+    private final String userAgent;

      public OldLoadModuleMessage(BrowserChannel channel, int protoVersion,
          String moduleName, String userAgent) {
@@ -1112,7 +1202,7 @@
      @Override
      public void send() throws IOException {
        DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.OLD_LOAD_MODULE.ordinal());
+      stream.writeByte(MessageType.OLD_LOAD_MODULE.getId());
        stream.writeInt(protoVersion);
        writeUtf8String(stream, moduleName);
        writeUtf8String(stream, userAgent);
@@ -1146,7 +1236,7 @@
      @Override
      public void send() throws IOException {
        DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.PROTOCOL_VERSION.ordinal());
+      stream.writeByte(MessageType.PROTOCOL_VERSION.getId());
        stream.writeInt(protocolVersion);
        stream.flush();
      }
@@ -1162,7 +1252,7 @@

      public static void send(BrowserChannel channel) throws IOException {
        final DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.QUIT.ordinal());
+      stream.writeByte(MessageType.QUIT.getId());
        stream.flush();
      }

@@ -1184,16 +1274,16 @@
          throws IOException {
        final DataInputStream stream = channel.getStreamFromOtherSide();
        final boolean isException = stream.readBoolean();
-      final Value returnValue = readValue(stream);
+      final Value returnValue = channel.readValue(stream);
        return new ReturnMessage(channel, isException, returnValue);
      }

      public static void send(BrowserChannel channel, boolean isException,
          Value returnValue) throws IOException {
        final DataOutputStream stream = channel.getStreamToOtherSide();
-      stream.writeByte(MessageType.RETURN.ordinal());
+      stream.writeByte(MessageType.RETURN.getId());
        stream.writeBoolean(isException);
-      writeValue(stream, returnValue);
+      channel.writeValue(stream, returnValue);
        stream.flush();
      }

@@ -1203,8 +1293,8 @@
            returnOrException.getReturnValue());
      }

-    private final Value returnValue;
      private final boolean isException;
+    private final Value returnValue;

      public ReturnMessage(BrowserChannel channel, boolean isException,
          Value returnValue) {
@@ -1270,7 +1360,7 @@
      @Override
      public void send() throws IOException {
        DataOutputStream stream = getBrowserChannel().getStreamToOtherSide();
-      stream.writeByte(MessageType.SWITCH_TRANSPORT.ordinal());
+      stream.writeByte(MessageType.SWITCH_TRANSPORT.getId());
        writeUtf8String(stream, transport);
        writeUtf8String(stream, transportArgs);
      }
@@ -1282,61 +1372,8 @@

    public static final int SPECIAL_SERVERMETHODS_OBJECT = 0;

-  /**
-   * This accumulates JsObjectRefs that are no longer referenced in the  
JVM.
-   */
-  private static final ThreadLocal<ReferenceQueue<JsObjectRef>>  
JSOBJECT_REF_QUEUE = new ThreadLocal<ReferenceQueue<JsObjectRef>>() {
-    @Override
-    protected ReferenceQueue<JsObjectRef> initialValue() {
-      return new ReferenceQueue<JsObjectRef>();
-    }
-  };
-
-  /**
-   * This map associates a JS reference id with a Reference to the  
JSObjectRef
-   * that currently represents that id.
-   */
-  private static final ThreadLocal<Map<Integer, Reference<JsObjectRef>>>  
JSOBJECT_ID_MAP = new ThreadLocal<Map<Integer, Reference<JsObjectRef>>>() {
-    @Override
-    protected Map<Integer, Reference<JsObjectRef>> initialValue() {
-      return new TreeMap<Integer, Reference<JsObjectRef>>();
-    }
-  };
-
-  /**
-   * This maps References to JsObjectRefs back to the original refId.  
Because we
-   * need the refId of the JsValueRef after it's been garbage-collected,  
this
-   * state must be stored externally.
-   */
-  private static final ThreadLocal<Map<Reference<JsObjectRef>, Integer>>  
REFERENCE_ID_MAP = new ThreadLocal<Map<Reference<JsObjectRef>, Integer>>() {
-    @Override
-    protected Map<Reference<JsObjectRef>, Integer> initialValue() {
-      return new IdentityHashMap<Reference<JsObjectRef>, Integer>();
-    }
-  };
-
-  /**
-   * Obtain the JsObjectRef that is currently in use to act as a proxy for  
the
-   * given JS object id.
-   */
-  protected static JsObjectRef getJsObjectRef(int refId) {
-    // Access is implicitly synchronous due to ThreadLocal
-    Map<Integer, Reference<JsObjectRef>> map = JSOBJECT_ID_MAP.get();
-    if (map.containsKey(refId)) {
-      Reference<JsObjectRef> ref = map.get(refId);
-      JsObjectRef toReturn = ref.get();
-      if (toReturn != null) {
-        return toReturn;
-      }
-    }
-
-    JsObjectRef.checkIdMap(refId);
-    JsObjectRef toReturn = new JsObjectRef(refId);
-    Reference<JsObjectRef> ref = new WeakReference<JsObjectRef>(toReturn,
-        JSOBJECT_REF_QUEUE.get());
-    map.put(refId, ref);
-    REFERENCE_ID_MAP.get().put(ref, refId);
-    return toReturn;
+  protected static JavaObjectRef getJavaObjectRef(int refId) {
+    return new JavaObjectRef(refId);
    }

    protected static String readUtf8String(DataInputStream stream)
@@ -1346,60 +1383,6 @@
      stream.readFully(data);
      return new String(data, "UTF8");
    }
-
-  protected static Value readValue(DataInputStream stream) throws  
IOException {
-    ValueType tag;
-    try {
-      tag = readValueType(stream);
-    } catch (BrowserChannelException e) {
-      IOException ee = new IOException();
-      ee.initCause(e);
-      throw ee;
-    }
-    Value value = new Value();
-    switch (tag) {
-      case NULL:
-        value.setNull();
-        break;
-      case UNDEFINED:
-        value.setUndefined();
-        break;
-      case BOOLEAN:
-        value.setBoolean(stream.readByte() != 0);
-        break;
-      case BYTE:
-        value.setByte(stream.readByte());
-        break;
-      case CHAR:
-        value.setChar(stream.readChar());
-        break;
-      case FLOAT:
-        value.setFloat(stream.readFloat());
-        break;
-      case INT:
-        value.setInt(stream.readInt());
-        break;
-      case LONG:
-        value.setLong(stream.readLong());
-        break;
-      case DOUBLE:
-        value.setDouble(stream.readDouble());
-        break;
-      case SHORT:
-        value.setShort(stream.readShort());
-        break;
-      case STRING:
-        value.setString(readUtf8String(stream));
-        break;
-      case JS_OBJECT:
-        value.setJsObject(getJsObjectRef(stream.readInt()));
-        break;
-      case JAVA_OBJECT:
-        value.setJavaObject(new JavaObjectRef(stream.readInt()));
-        break;
-    }
-    return value;
-  }

    protected static ValueType readValueType(DataInputStream stream)
        throws IOException, BrowserChannelException {
@@ -1486,60 +1469,35 @@
        throw new RuntimeException();
      }
    }
-
-  protected static void writeValue(DataOutputStream stream, Value value)
-      throws IOException {
-    if (value.isNull()) {
-      writeNull(stream);
-    } else if (value.isUndefined()) {
-      writeUndefined(stream);
-    } else if (value.isJsObject()) {
-      writeJsObject(stream, value.getJsObject());
-    } else if (value.isJavaObject()) {
-      writeJavaObject(stream, value.getJavaObject());
-    } else if (value.isBoolean()) {
-      writeTaggedBoolean(stream, value.getBoolean());
-    } else if (value.isByte()) {
-      writeTaggedByte(stream, value.getByte());
-    } else if (value.isChar()) {
-      writeTaggedChar(stream, value.getChar());
-    } else if (value.isShort()) {
-      writeTaggedShort(stream, value.getShort());
-    } else if (value.isDouble()) {
-      writeTaggedDouble(stream, value.getDouble());
-    } else if (value.isFloat()) {
-      writeTaggedFloat(stream, value.getFloat());
-    } else if (value.isInt()) {
-      writeTaggedInt(stream, value.getInt());
-    } else if (value.isString()) {
-      writeTaggedString(stream, value.getString());
-    } else {
-      assert false;
-    }
-  }

    private static void writeUndefined(DataOutputStream stream)
        throws IOException {
      stream.writeByte(ValueType.UNDEFINED.getTag());
    }
+
+  private final ObjectRefFactory objectRefFactory;
+
+  private Socket socket;

    private final DataInputStream streamFromOtherSide;

    private final DataOutputStream streamToOtherSide;

-  private Socket socket;
-
-  public BrowserChannel(Socket socket) throws IOException {
+  public BrowserChannel(Socket socket, ObjectRefFactory objectRefFactory)
+      throws IOException {
      this(new BufferedInputStream(socket.getInputStream()),
-        new BufferedOutputStream(socket.getOutputStream()));
+        new BufferedOutputStream(socket.getOutputStream()),
+        objectRefFactory);
      this.socket = socket;
    }

-  protected BrowserChannel(InputStream inputStream, OutputStream  
outputStream)
+  protected BrowserChannel(InputStream inputStream, OutputStream  
outputStream,
+      ObjectRefFactory objectRefFactory)
        throws IOException {
      streamFromOtherSide = new DataInputStream(inputStream);
      streamToOtherSide = new DataOutputStream(outputStream);
      socket = null;
+    this.objectRefFactory = objectRefFactory;
    }

    public void endSession() {
@@ -1548,38 +1506,11 @@
      Utility.close(socket);
    }

+  /**
+   * @return a set of remote object reference IDs to be freed.
+   */
    public Set<Integer> getRefIdsForCleanup() {
-    // Access to these objects is inherently synchronous
-    Map<Integer, Reference<JsObjectRef>> objectMap = JSOBJECT_ID_MAP.get();
-    Map<Reference<JsObjectRef>, Integer> refIdMap = REFERENCE_ID_MAP.get();
-    ReferenceQueue<JsObjectRef> q = JSOBJECT_REF_QUEUE.get();
-    Set<Integer> toReturn = new HashSet<Integer>();
-
-    // Find all refIds associated with previous garbage collection cycles
-    Reference<? extends JsObjectRef> ref;
-    while ((ref = q.poll()) != null) {
-      Integer i = refIdMap.remove(ref);
-      assert i != null;
-      toReturn.add(i);
-    }
-
-    /*
-     * Check for liveness. This is necessary because the last reference to  
a
-     * JsObjectRef could have been cleared and a new reference to that  
refId
-     * created before this method has been called.
-     */
-    for (Iterator<Integer> i = toReturn.iterator(); i.hasNext();) {
-      Integer refId = i.next();
-      if (objectMap.containsKey(refId)) {
-        if (objectMap.get(refId).get() != null) {
-          i.remove();
-        } else {
-          objectMap.remove(refId);
-        }
-      }
-    }
-
-    return toReturn;
+    return objectRefFactory.getRefIdsForCleanup();
    }

    public String getRemoteEndpoint() {
@@ -1609,8 +1540,10 @@
            break;
          case INVOKE:
            final InvokeOnServerMessage imsg =  
InvokeOnServerMessage.receive(this);
-          ReturnMessage.send(this, handler.invoke(this, imsg.getThis(),
-              imsg.getMethodDispatchId(), imsg.getArgs()));
+          ExceptionOrReturnValue result = handler.invoke(this,  
imsg.getThis(),
+              imsg.getMethodDispatchId(), imsg.getArgs());
+          sendFreedValues();
+          ReturnMessage.send(this, result);
            break;
          case INVOKE_SPECIAL:
            handleInvokeSpecial(handler);
@@ -1638,8 +1571,10 @@
            return ReturnMessage.receive(this);
          case INVOKE:
            final InvokeOnServerMessage imsg =  
InvokeOnServerMessage.receive(this);
-          ReturnMessage.send(this, handler.invoke(this, imsg.getThis(),
-              imsg.getMethodDispatchId(), imsg.getArgs()));
+          ExceptionOrReturnValue result = handler.invoke(this,  
imsg.getThis(),
+              imsg.getMethodDispatchId(), imsg.getArgs());
+          sendFreedValues();
+          ReturnMessage.send(this, result);
            break;
          case INVOKE_SPECIAL:
            handleInvokeSpecial(handler);
@@ -1658,6 +1593,92 @@
    protected DataOutputStream getStreamToOtherSide() {
      return streamToOtherSide;
    }
+
+  protected Value readValue(DataInputStream stream) throws IOException {
+    ValueType tag;
+    try {
+      tag = readValueType(stream);
+    } catch (BrowserChannelException e) {
+      IOException ee = new IOException();
+      ee.initCause(e);
+      throw ee;
+    }
+    Value value = new Value();
+    switch (tag) {
+      case NULL:
+        value.setNull();
+        break;
+      case UNDEFINED:
+        value.setUndefined();
+        break;
+      case BOOLEAN:
+        value.setBoolean(stream.readByte() != 0);
+        break;
+      case BYTE:
+        value.setByte(stream.readByte());
+        break;
+      case CHAR:
+        value.setChar(stream.readChar());
+        break;
+      case FLOAT:
+        value.setFloat(stream.readFloat());
+        break;
+      case INT:
+        value.setInt(stream.readInt());
+        break;
+      case LONG:
+        value.setLong(stream.readLong());
+        break;
+      case DOUBLE:
+        value.setDouble(stream.readDouble());
+        break;
+      case SHORT:
+        value.setShort(stream.readShort());
+        break;
+      case STRING:
+        value.setString(readUtf8String(stream));
+        break;
+      case JS_OBJECT:
+         
value.setJsObject(objectRefFactory.getJsObjectRef(stream.readInt()));
+        break;
+      case JAVA_OBJECT:
+        value.setJavaObject(objectRefFactory.getJavaObjectRef(
+            stream.readInt()));
+        break;
+    }
+    return value;
+  }
+
+  protected void writeValue(DataOutputStream stream, Value value)
+      throws IOException {
+    if (value.isNull()) {
+      writeNull(stream);
+    } else if (value.isUndefined()) {
+      writeUndefined(stream);
+    } else if (value.isJsObject()) {
+      writeJsObject(stream, value.getJsObject());
+    } else if (value.isJavaObject()) {
+      writeJavaObject(stream, value.getJavaObject());
+    } else if (value.isBoolean()) {
+      writeTaggedBoolean(stream, value.getBoolean());
+    } else if (value.isByte()) {
+      writeTaggedByte(stream, value.getByte());
+    } else if (value.isChar()) {
+      writeTaggedChar(stream, value.getChar());
+    } else if (value.isShort()) {
+      writeTaggedShort(stream, value.getShort());
+    } else if (value.isDouble()) {
+      writeTaggedDouble(stream, value.getDouble());
+    } else if (value.isFloat()) {
+      writeTaggedFloat(stream, value.getFloat());
+    } else if (value.isInt()) {
+      writeTaggedInt(stream, value.getInt());
+    } else if (value.isString()) {
+      writeTaggedString(stream, value.getString());
+    } else {
+      assert false;
+    }
+  }

    private void handleInvokeSpecial(SessionHandler handler) throws  
IOException,
        BrowserChannelException {
@@ -1680,4 +1701,17 @@
      }
      ReturnMessage.send(this, retExc);
    }
-}
+
+  private void sendFreedValues() throws IOException {
+    Set<Integer> freed = objectRefFactory.getRefIdsForCleanup();
+    int n = freed.size();
+    if (n > 0) {
+      int[] ids = new int[n];
+      int i = 0;
+      for (Integer id : freed) {
+        ids[i++] = id;
+      }
+      FreeMessage.send(this, ids);
+    }
+  }
+}
=======================================
---  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelClient.java
   
Thu Sep 10 16:26:01 2009
+++  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelClient.java
   
Fri Sep 25 11:00:02 2009
@@ -21,6 +21,7 @@

  import java.io.IOException;
  import java.net.Socket;
+import java.util.Set;

  /**
   * Implementation of the BrowserChannel for the client side.
@@ -28,7 +29,32 @@
   */
  public class BrowserChannelClient extends BrowserChannel {

-  private static final int PROTOCOL_VERSION = 2;
+  private static class ClientObjectRefFactory implements ObjectRefFactory {
+
+    private final RemoteObjectTable<JavaObjectRef> remoteObjectTable;
+
+    public ClientObjectRefFactory() {
+      remoteObjectTable = new RemoteObjectTable<JavaObjectRef>();
+    }
+
+    public JavaObjectRef getJavaObjectRef(int refId) {
+      JavaObjectRef objectRef =  
remoteObjectTable.getRemoteObjectRef(refId);
+      if (objectRef == null) {
+        objectRef = new JavaObjectRef(refId);
+        remoteObjectTable.putRemoteObjectRef(refId, objectRef);
+      }
+      return objectRef;
+    }
+
+    public JsObjectRef getJsObjectRef(int refId) {
+      return new JsObjectRef(refId);
+    }
+
+    public Set<Integer> getRefIdsForCleanup() {
+      return remoteObjectTable.getRefIdsForCleanup();
+    }
+  }
+
    private final HtmlUnitSessionHandler htmlUnitSessionHandler;
    private final PrintWriterTreeLogger logger = new PrintWriterTreeLogger();
    private final String moduleName;
@@ -41,7 +67,8 @@
    public BrowserChannelClient(String addressParts[], String url,
        String sessionKey, String moduleName, String versionString,
        HtmlUnitSessionHandler htmlUnitSessionHandler) throws IOException {
-    super(new Socket(addressParts[0], Integer.parseInt(addressParts[1])));
+    super(new Socket(addressParts[0], Integer.parseInt(addressParts[1])),
+        new ClientObjectRefFactory());
      connected = true;
      this.url = url;
      this.sessionKey = sessionKey;
@@ -108,8 +135,8 @@
    private boolean init() throws IOException, BrowserChannelException {
      logger.log(TreeLogger.DEBUG, "sending " + MessageType.CHECK_VERSIONS
          + " message");
-    new CheckVersionsMessage(this, PROTOCOL_VERSION, PROTOCOL_VERSION,
-        versionString).send();
+    new CheckVersionsMessage(this, BROWSERCHANNEL_PROTOCOL_VERSION,
+        BROWSERCHANNEL_PROTOCOL_VERSION, versionString).send();
      MessageType type = Message.readMessageType(getStreamFromOtherSide());
      switch (type) {
        case PROTOCOL_VERSION:
=======================================
---  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelServer.java
   
Sat Aug 22 16:01:38 2009
+++  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/BrowserChannelServer.java
   
Fri Sep 25 11:00:02 2009
@@ -20,6 +20,7 @@

  import java.io.IOException;
  import java.net.Socket;
+import java.util.Set;

  /**
   *
@@ -27,11 +28,37 @@
  public final class BrowserChannelServer extends BrowserChannel
      implements Runnable {

+  private static class ServerObjectRefFactory implements ObjectRefFactory {
+
+    private final RemoteObjectTable<JsObjectRef> remoteObjectTable;
+
+    public ServerObjectRefFactory() {
+      remoteObjectTable = new RemoteObjectTable<JsObjectRef>();
+    }
+
+    public JavaObjectRef getJavaObjectRef(int refId) {
+      return new JavaObjectRef(refId);
+    }
+
+    public JsObjectRef getJsObjectRef(int refId) {
+      JsObjectRef objectRef = remoteObjectTable.getRemoteObjectRef(refId);
+      if (objectRef == null) {
+        objectRef = new JsObjectRef(refId);
+        remoteObjectTable.putRemoteObjectRef(refId, objectRef);
+      }
+      return objectRef;
+    }
+
+    public Set<Integer> getRefIdsForCleanup() {
+      return remoteObjectTable.getRefIdsForCleanup();
+    }
+  }
+
    public static final String JSO_CLASS  
= "com.google.gwt.core.client.JavaScriptObject";

    private SessionHandler handler;

-  private final ObjectsTable javaObjectsInBrowser = new ObjectsTable();
+  private final ServerObjectsTable javaObjectsInBrowser = new  
ServerObjectsTable();

    private TreeLogger logger;

@@ -43,7 +70,7 @@

    public BrowserChannelServer(TreeLogger initialLogger, Socket socket,
        SessionHandler handler) throws IOException {
-    super(socket);
+    super(socket, new ServerObjectRefFactory());
      this.handler = handler;
      this.logger = initialLogger;
      Thread thread = new Thread(this);
@@ -62,7 +89,7 @@
      }
    }

-  public ObjectsTable getJavaObjectsExposedInBrowser() {
+  public ServerObjectsTable getJavaObjectsExposedInBrowser() {
      return javaObjectsInBrowser;
    }

@@ -84,7 +111,7 @@
    public void invokeJavascript(CompilingClassLoader ccl, JsValueOOPHM  
jsthis,
        String methodName, JsValueOOPHM[] args, JsValueOOPHM returnJsValue)
        throws Throwable {
-    final ObjectsTable remoteObjects = getJavaObjectsExposedInBrowser();
+    final ServerObjectsTable remoteObjects =  
getJavaObjectsExposedInBrowser();
      Value vthis = convertFromJsValue(remoteObjects, jsthis);
      Value[] vargs = new Value[args.length];
      for (int i = 0; i < args.length; ++i) {
@@ -175,7 +202,7 @@
     * @param jsval value to convert
     * @return jsval as a Value object.
     */
-  Value convertFromJsValue(ObjectsTable localObjects, JsValueOOPHM jsval) {
+  Value convertFromJsValue(ServerObjectsTable localObjects, JsValueOOPHM  
jsval) {
      Value value = new Value();
      if (jsval.isNull()) {
        value.setNull();
@@ -214,7 +241,7 @@
     * @param val Value to convert
     * @param jsval JsValue object to receive converted value.
     */
-  void convertToJsValue(CompilingClassLoader ccl, ObjectsTable  
localObjects,
+  void convertToJsValue(CompilingClassLoader ccl, ServerObjectsTable  
localObjects,
        Value val, JsValueOOPHM jsval) {
      switch (val.getType()) {
        case NULL:
=======================================
---  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/JsValueOOPHM.java  
 
Thu Sep 10 16:26:01 2009
+++  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/JsValueOOPHM.java  
 
Fri Sep 25 11:00:02 2009
@@ -144,7 +144,6 @@
     * @param jsRefId pointer to underlying JsRootedValue as an integer.
     */
    public JsValueOOPHM(int jsRefId) {
-    JsObjectRef.checkIdMap(jsRefId);
      this.value = new JsObjectRef(jsRefId);
    }

=======================================
---  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/OophmSessionHandler.java
    
Sat Aug 22 16:01:38 2009
+++  
/branches/farewellSwt/dev/oophm/src/com/google/gwt/dev/shell/OophmSessionHandler.java
    
Fri Sep 25 11:00:02 2009
@@ -48,7 +48,7 @@
    @Override
    public void freeValue(BrowserChannel channel, int[] ids) {
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-    ObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
+    ServerObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
      for (int id : ids) {
        localObjects.free(id);
      }
@@ -60,7 +60,7 @@
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
      ModuleSpace moduleSpace = moduleMap.get(serverChannel);
      assert moduleSpace != null;
-    ObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
+    ServerObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
      try {
        JsValueOOPHM obj = new JsValueOOPHM();
        DispatchObject dispObj;
@@ -91,7 +91,7 @@
    public ExceptionOrReturnValue invoke(BrowserChannel channel, Value  
thisVal,
        int methodDispatchId, Value[] args) {
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
-    ObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
+    ServerObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
      ModuleSpace moduleSpace = moduleMap.get(serverChannel);
      assert moduleSpace != null;
      CompilingClassLoader cl = moduleSpace.getIsolatedClassLoader();
@@ -190,7 +190,7 @@
      BrowserChannelServer serverChannel = (BrowserChannelServer) channel;
      ModuleSpace moduleSpace = moduleMap.get(serverChannel);
      assert moduleSpace != null;
-    ObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
+    ServerObjectsTable localObjects =  
serverChannel.getJavaObjectsExposedInBrowser();
      try {
        JsValueOOPHM obj = new JsValueOOPHM();
        DispatchObject dispObj;
=======================================
---  
/branches/farewellSwt/dev/oophm/test/com/google/gwt/dev/shell/BrowserChannelTest.java
    
Mon Aug 10 16:15:14 2009
+++  
/branches/farewellSwt/dev/oophm/test/com/google/gwt/dev/shell/BrowserChannelTest.java
    
Fri Sep 25 11:00:02 2009
@@ -44,6 +44,7 @@
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.util.Arrays;
+import java.util.Set;

  /**
   * Test for {...@link BrowserChannel}.
@@ -55,7 +56,22 @@
    private class TestBrowserChannel extends BrowserChannel {
      public TestBrowserChannel(InputStream inputStream,
          OutputStream outputStream) throws IOException {
-      super(inputStream, outputStream);
+      super(inputStream, outputStream, new ObjectRefFactory() {
+        public JavaObjectRef getJavaObjectRef(int refId) {
+          fail("getJavaObjectRef mocked");
+          return null;
+        }
+
+        public JsObjectRef getJsObjectRef(int refId) {
+          fail("getJsObjectRef mocked");
+          return null;
+        }
+
+        public Set<Integer> getRefIdsForCleanup() {
+          fail("getRefIdsForCleanup mocked");
+          return null;
+        }
+      });
      }

      public MessageType readMessageType() throws IOException,
@@ -80,13 +96,13 @@
    public void testBooleanValue() throws IOException {
      Value val = new Value();
      val.setBoolean(true);
-    BrowserChannel.writeValue(oStr, val);
-    val = BrowserChannel.readValue(iStr);
+    channel.writeValue(oStr, val);
+    val = channel.readValue(iStr);
      assertEquals(ValueType.BOOLEAN, val.getType());
      assertEquals(true, val.getBoolean());
      val.setBoolean(false);
-    BrowserChannel.writeValue(oStr, val);
-    val = BrowserChannel.readValue(iStr);
+    channel.writeValue(oStr, val);
+    val = channel.readValue(iStr);
      assertEquals(ValueType.BOOLEAN, val.getType());
      assertEquals(false, val.getBoolean());
    }
=======================================
--- /branches/farewellSwt/user/src/com/google/gwt/junit/RunStyle.java   Sun  
Sep 20 12:33:31 2009
+++ /branches/farewellSwt/user/src/com/google/gwt/junit/RunStyle.java   Fri  
Sep 25 11:00:02 2009
@@ -33,10 +33,7 @@
     * the same signature since this will be how the RunStyle is created via
     * reflection.
     *
-   * @param logger TreeLogger instance
     * @param shell the containing shell
-   * @param args arguments (after the colon in the argument to -runStyle)
-   *     may be null if no argument is supplied
     */
    public RunStyle(JUnitShell shell) {
      this.shell = shell;

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Reply via email to