Bug 2065 - Pull updated Chrome Developer Tools into the workspace
authorEugene Ostroukhov <eugeneo@symbian.org>
Thu, 18 Mar 2010 11:56:59 -0700
changeset 276 f2f4a1259de8
parent 275 12c2ea2194c7
child 277 7cca3bcacbc1
Bug 2065 - Pull updated Chrome Developer Tools into the workspace
chrome-dev-tools-patches/Chrome-Java5-Patch.txt
org.chromium.debug.core/META-INF/MANIFEST.MF
org.chromium.debug.core/build.properties
org.chromium.debug.core/src/org/chromium/debug/core/efs/ChromiumScriptFileSystem.java
org.chromium.debug.core/src/org/chromium/debug/core/model/ArrayValue.java
org.chromium.debug.core/src/org/chromium/debug/core/model/DebugTargetImpl.java
org.chromium.debug.core/src/org/chromium/debug/core/model/Messages.java
org.chromium.debug.core/src/org/chromium/debug/core/model/StackFrame.java
org.chromium.debug.core/src/org/chromium/debug/core/model/VProjectWorkspaceBridge.java
org.chromium.debug.core/src/org/chromium/debug/core/model/Value.java
org.chromium.debug.core/src/org/chromium/debug/core/model/WorkspaceBridge.java
org.chromium.debug.core/src/org/chromium/debug/core/model/messages.properties
org.chromium.debug.core/src/org/chromium/debug/core/util/ChromiumDebugPluginUtil.java
org.chromium.debug.ui/META-INF/MANIFEST.MF
org.chromium.debug.ui/build.properties
org.chromium.sdk/META-INF/MANIFEST.MF
org.chromium.sdk/build.properties
org.chromium.sdk/src/org/chromium/sdk/ChromiumIOException.java
org.chromium.sdk/src/org/chromium/sdk/JavascriptVm.java
org.chromium.sdk/src/org/chromium/sdk/internal/BrowserImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/BrowserTabImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/CallFrameImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/ContextBuilder.java
org.chromium.sdk/src/org/chromium/sdk/internal/DebugSession.java
org.chromium.sdk/src/org/chromium/sdk/internal/JavascriptVmImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/JsArrayImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/JsEvaluateContextImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/JsObjectImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/JsScopeImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/JsVariableImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/PropertyReference.java
org.chromium.sdk/src/org/chromium/sdk/internal/ScriptImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/ScriptManager.java
org.chromium.sdk/src/org/chromium/sdk/internal/StandaloneVmImpl.java
org.chromium.sdk/src/org/chromium/sdk/internal/protocol/data/PropertyWithValue.java
org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/BreakpointManager.java
org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8CommandCallbackBase.java
org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8Helper.java
org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8ProtocolUtil.java
org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/AfterCompileProcessor.java
org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/BacktraceProcessor.java
org.chromium.sdk/src/org/chromium/sdk/internal/transport/Handshaker.java
org.symbian.tools.wrttools.previewer/preview/wrt_preview.html
--- a/chrome-dev-tools-patches/Chrome-Java5-Patch.txt	Thu Mar 18 11:10:35 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-### Eclipse Workspace Patch 1.0
-#P org.chromium.sdk
-Index: src/org/chromium/sdk/ChromiumIOException.java
-===================================================================
---- src/org/chromium/sdk/ChromiumIOException.java	(revision 0)
-+++ src/org/chromium/sdk/ChromiumIOException.java	(revision 0)
-@@ -0,0 +1,23 @@
-+package org.chromium.sdk;
-+
-+import java.io.IOException;
-+
-+public class ChromiumIOException extends IOException {
-+	private static final long serialVersionUID = 3412049732071131594L;
-+	private final Throwable cause;
-+
-+	public ChromiumIOException(Throwable cause) {
-+		super();
-+		this.cause = cause;
-+	}
-+	
-+	public ChromiumIOException(String message, Throwable cause) {
-+		super(message);
-+		this.cause = cause;
-+	}
-+	
-+	@Override
-+	public Throwable getCause() {
-+		return cause;
-+	}
-+}
-Index: src/org/chromium/sdk/internal/BrowserImpl.java
-===================================================================
---- src/org/chromium/sdk/internal/BrowserImpl.java	(revision 306)
-+++ src/org/chromium/sdk/internal/BrowserImpl.java	(working copy)
-@@ -17,6 +17,7 @@
- 
- import org.chromium.sdk.Browser;
- import org.chromium.sdk.BrowserTab;
-+import org.chromium.sdk.ChromiumIOException;
- import org.chromium.sdk.TabDebugEventListener;
- import org.chromium.sdk.UnsupportedVersionException;
- import org.chromium.sdk.Version;
-@@ -102,7 +103,7 @@
-       try {
-         serverVersionString = devToolsHandler.version(OPERATION_TIMEOUT_MS);
-       } catch (TimeoutException e) {
--        throw new IOException("Failed to get protocol version from remote", e);
-+        throw new ChromiumIOException("Failed to get protocol version from remote", e);
-       }
-       if (serverVersionString == null) {
-         throw new UnsupportedVersionException(BrowserImpl.PROTOCOL_VERSION, null);
-@@ -291,7 +292,7 @@
-         ticket = connectInternal();
-       } catch (UnsupportedVersionException e) {
-         // This exception should have happened on tab fetcher creation.
--        throw new IOException("Unexpected version problem", e);
-+        throw new ChromiumIOException("Unexpected version problem", e);
-       }
- 
-       Session session = ticket.getSession();
-Index: META-INF/MANIFEST.MF
-===================================================================
---- META-INF/MANIFEST.MF	(revision 306)
-+++ META-INF/MANIFEST.MF	(working copy)
-@@ -13,4 +13,5 @@
-  org.chromium.sdk.internal.tools.v8.processor;x-internal:=true,
-  org.chromium.sdk.internal.tools.v8.request;x-internal:=true,
-  org.chromium.sdk.internal.transport;x-internal:=true
--Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-+Bundle-RequiredExecutionEnvironment: J2SE-1.5,
-+ JavaSE-1.6
-Index: src/org/chromium/sdk/internal/BrowserTabImpl.java
-===================================================================
---- src/org/chromium/sdk/internal/BrowserTabImpl.java	(revision 306)
-+++ src/org/chromium/sdk/internal/BrowserTabImpl.java	(working copy)
-@@ -8,6 +8,7 @@
- 
- import org.chromium.sdk.Browser;
- import org.chromium.sdk.BrowserTab;
-+import org.chromium.sdk.ChromiumIOException;
- import org.chromium.sdk.DebugEventListener;
- import org.chromium.sdk.TabDebugEventListener;
- import org.chromium.sdk.internal.tools.ToolHandler;
-@@ -89,7 +90,7 @@
-       try {
-         result = devToolSessionManager.attachToTab();
-       } catch (AttachmentFailureException e) {
--        throw new IOException(e);
-+        throw new ChromiumIOException(e);
-       }
-       if (Result.OK != result) {
-         throw new IOException("Failed to attach with result: " + result);
-Index: src/org/chromium/sdk/internal/StandaloneVmImpl.java
-===================================================================
---- src/org/chromium/sdk/internal/StandaloneVmImpl.java	(revision 306)
-+++ src/org/chromium/sdk/internal/StandaloneVmImpl.java	(working copy)
-@@ -12,6 +12,7 @@
- import java.util.logging.Level;
- import java.util.logging.Logger;
- 
-+import org.chromium.sdk.ChromiumIOException;
- import org.chromium.sdk.DebugEventListener;
- import org.chromium.sdk.StandaloneVm;
- import org.chromium.sdk.UnsupportedVersionException;
-@@ -121,9 +122,9 @@
-     } catch (InterruptedException e) {
-       throw new RuntimeException(e);
-     } catch (ExecutionException e) {
--      throw new IOException("Failed to get version", e);
-+      throw new ChromiumIOException("Failed to get version", e);
-     } catch (TimeoutException e) {
--      throw new IOException("Timed out waiting for version", e);
-+      throw new ChromiumIOException("Timed out waiting for version", e);
-     }
- 
-     String versionString = remoteInfo.getProtocolVersion();
-Index: src/org/chromium/sdk/internal/transport/Handshaker.java
-===================================================================
---- src/org/chromium/sdk/internal/transport/Handshaker.java	(revision 306)
-+++ src/org/chromium/sdk/internal/transport/Handshaker.java	(working copy)
-@@ -10,8 +10,8 @@
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.Future;
- import java.util.concurrent.FutureTask;
--import java.util.concurrent.RunnableFuture;
- 
-+import org.chromium.sdk.ChromiumIOException;
- import org.chromium.sdk.LineReader;
- import org.chromium.sdk.internal.transport.Message.MalformedMessageException;
- 
-@@ -85,7 +85,7 @@
-       return runnableFuture;
-     }
- 
--    private final RunnableFuture<RemoteInfo> runnableFuture =
-+    private final FutureTask<RemoteInfo> runnableFuture =
-         new FutureTask<RemoteInfo>(new HandshakeTaks());
- 
-     private LineReader input = null;
-@@ -100,7 +100,7 @@
-       } catch (InterruptedException e) {
-         throw new RuntimeException(e);
-       } catch (ExecutionException e) {
--        throw new IOException("Failed to perform handshake", e);
-+        throw new ChromiumIOException("Failed to perform handshake", e);
-       }
- 
-     }
-@@ -111,7 +111,7 @@
-         try {
-           message = Message.fromBufferedReader(input);
-         } catch (MalformedMessageException e) {
--          throw new IOException("Unrecognized handshake message from remote", e);
-+          throw new ChromiumIOException("Unrecognized handshake message from remote", e);
-         }
-         if (message == null) {
-           throw new IOException("End of stream");
-#P org.chromium.debug.core
-Index: META-INF/MANIFEST.MF
-===================================================================
---- META-INF/MANIFEST.MF	(revision 306)
-+++ META-INF/MANIFEST.MF	(working copy)
-@@ -20,4 +20,5 @@
-  org.chromium.debug.core.model,
-  org.chromium.debug.core.util
- Eclipse-LazyStart: true
--Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-+Bundle-RequiredExecutionEnvironment: J2SE-1.5,
-+ JavaSE-1.6
-#P org.chromium.debug.ui
-Index: META-INF/MANIFEST.MF
-===================================================================
---- META-INF/MANIFEST.MF	(revision 306)
-+++ META-INF/MANIFEST.MF	(working copy)
-@@ -16,4 +16,5 @@
-  org.chromium.debug.core;bundle-version="0.1.5",
-  org.chromium.sdk;bundle-version="0.1.5"
- Bundle-ActivationPolicy: lazy
--Bundle-RequiredExecutionEnvironment: JavaSE-1.6
-+Bundle-RequiredExecutionEnvironment: J2SE-1.5,
-+ JavaSE-1.6
--- a/org.chromium.debug.core/META-INF/MANIFEST.MF	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/META-INF/MANIFEST.MF	Thu Mar 18 11:56:59 2010 -0700
@@ -20,5 +20,4 @@
  org.chromium.debug.core.model,
  org.chromium.debug.core.util
 Eclipse-LazyStart: true
-Bundle-RequiredExecutionEnvironment: J2SE-1.5,
- JavaSE-1.6
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
--- a/org.chromium.debug.core/build.properties	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/build.properties	Thu Mar 18 11:56:59 2010 -0700
@@ -6,8 +6,3 @@
 source.. = src/
 output.. = bin/
 src.includes = LICENSE
-# javac 
-javacSource=1.5
-javacTarget=1.5
-javacVerbose=true
-
--- a/org.chromium.debug.core/src/org/chromium/debug/core/efs/ChromiumScriptFileSystem.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/efs/ChromiumScriptFileSystem.java	Thu Mar 18 11:56:59 2010 -0700
@@ -42,6 +42,10 @@
     }
   }
 
+  public static boolean isChromiumDebugURI(URI uri) {
+    return CHROMIUMDEBUG_SCHEME.equals(uri.getScheme());
+  }
+
   /**
    * Converts a chromiumdebug FS FileStore URI into a path relative to the FS root.
    *
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/ArrayValue.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/ArrayValue.java	Thu Mar 18 11:56:59 2010 -0700
@@ -4,12 +4,10 @@
 
 package org.chromium.debug.core.model;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.SortedMap;
+import java.util.Collections;
+import java.util.Set;
 
 import org.chromium.sdk.JsArray;
-import org.chromium.sdk.JsVariable;
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.model.IIndexedValue;
 import org.eclipse.debug.core.model.IVariable;
@@ -28,12 +26,11 @@
   }
 
   private IVariable[] createElements() {
-    SortedMap<Integer, ? extends JsVariable> elements = ((JsArray) getJsValue()).toSparseArray();
-    List<IVariable> variables = new ArrayList<IVariable>(elements.size());
-    for (JsVariable jsVar : elements.values()) {
-      variables.add(new Variable(getDebugTarget(), jsVar, false));
-    }
-    return variables.toArray(new IVariable[variables.size()]);
+    JsArray jsArray = (JsArray) getJsValue();
+    return StackFrame.wrapVariables(getDebugTarget(), jsArray.getProperties(),
+        ARRAY_HIDDEN_PROPERTY_NAMES,
+        // Do not show internal properties for arrays (this may be an option).
+        null);
   }
 
   public int getInitialOffset() {
@@ -64,4 +61,5 @@
     return elements.length > 0;
   }
 
+  private static final Set<String> ARRAY_HIDDEN_PROPERTY_NAMES = Collections.singleton("length");
 }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/DebugTargetImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/DebugTargetImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -57,7 +57,7 @@
 
   private WorkspaceBridge workspaceRelations = null;
 
-  private final ListenerBlock listenerBlock = new ListenerBlock();
+  private ListenerBlock listenerBlock = null;
 
   public DebugTargetImpl(ILaunch launch, WorkspaceBridge.Factory workspaceBridgeFactory) {
     super(null);
@@ -86,25 +86,30 @@
       return false;
     }
     monitor.worked(1);
-    final JavascriptVmEmbedder embedder = connector.attach(embedderListener, debugEventListener);
-    // From this moment V8 may call our listeners. We block them by listenerBlock for a while.
+    this.listenerBlock = new ListenerBlock();
+    try {
+      final JavascriptVmEmbedder embedder = connector.attach(embedderListener, debugEventListener);
+      // From this moment V8 may call our listeners. We block them by listenerBlock for a while.
 
-    Destructable embedderDestructor = new Destructable() {
-      public void destruct() {
-        embedder.getJavascriptVm().detach();
-      }
-    };
+      Destructable embedderDestructor = new Destructable() {
+        public void destruct() {
+          embedder.getJavascriptVm().detach();
+        }
+      };
 
-    destructingGuard.addValue(embedderDestructor);
+      destructingGuard.addValue(embedderDestructor);
 
-    this.vmEmbedder = embedder;
+      this.vmEmbedder = embedder;
+
+      // We'd like to know when launch is removed to remove our project.
+      DebugPlugin.getDefault().getLaunchManager().addLaunchListener(launchListener);
 
-    // We'd like to know when launch is removed to remove our project.
-    DebugPlugin.getDefault().getLaunchManager().addLaunchListener(launchListener);
-
-    this.workspaceRelations = workspaceBridgeFactory.attachedToVm(this,
-        vmEmbedder.getJavascriptVm());
-    listenerBlock.unblock();
+      this.workspaceRelations = workspaceBridgeFactory.attachedToVm(this,
+          vmEmbedder.getJavascriptVm());
+      listenerBlock.setProperlyInitialized();
+    } finally {
+      listenerBlock.unblock();
+    }
 
     DebugPlugin.getDefault().getBreakpointManager().addBreakpointListener(this);
     reloadScriptsAndPossiblyResume(attachCallback);
@@ -417,29 +422,26 @@
   private void logExceptionFromContext(DebugContext context) {
     ExceptionData exceptionData = context.getExceptionData();
     List<? extends CallFrame> callFrames = context.getCallFrames();
+    String scriptName;
+    Object lineNumber;
     if (callFrames.size() > 0) {
       CallFrame topFrame = callFrames.get(0);
       Script script = topFrame.getScript();
-      ChromiumDebugPlugin.logError(
-          Messages.DebugTargetImpl_LogExceptionFormat,
-          exceptionData.isUncaught()
-              ? Messages.DebugTargetImpl_Uncaught
-              : Messages.DebugTargetImpl_Caught,
-          exceptionData.getExceptionMessage(),
-          script != null ? script.getName() : "<unknown>", //$NON-NLS-1$
-          topFrame.getLineNumber(),
-          trim(exceptionData.getSourceText(), 80));
+      scriptName = script != null ? script.getName() : Messages.DebugTargetImpl_Unknown;
+      lineNumber = topFrame.getLineNumber();
     } else {
-      ChromiumDebugPlugin.logError(
-          Messages.DebugTargetImpl_LogExceptionFormat,
-          exceptionData.isUncaught()
-              ? Messages.DebugTargetImpl_Uncaught
-              : Messages.DebugTargetImpl_Caught,
-          exceptionData.getExceptionMessage(),
-          "<unknown>", //$NON-NLS-1$
-          "<unknown>",
-          trim(exceptionData.getSourceText(), 80));
+      scriptName = Messages.DebugTargetImpl_Unknown;
+      lineNumber = Messages.DebugTargetImpl_Unknown;
     }
+    ChromiumDebugPlugin.logError(
+        Messages.DebugTargetImpl_LogExceptionFormat,
+        exceptionData.isUncaught()
+            ? Messages.DebugTargetImpl_Uncaught
+            : Messages.DebugTargetImpl_Caught,
+        exceptionData.getExceptionMessage(),
+        scriptName,
+        lineNumber,
+        trim(exceptionData.getSourceText(), 80));
   }
 
   private final JavascriptVmEmbedder.Listener embedderListener =
@@ -489,33 +491,39 @@
   public WorkspaceBridge.JsLabelProvider getLabelProvider() {
     return workspaceBridgeFactory.getLabelProvider();
   }
+  
+  public int getLineNumber(CallFrame stackFrame) {
+    return workspaceRelations.getLineNumber(stackFrame);
+  }
 
   private static class ListenerBlock {
     private volatile boolean isBlocked = true;
+    private volatile boolean hasBeenProperlyInitialized = false;
     private final Object monitor = new Object();
     void waitUntilReady() {
       if (isBlocked) {
-        return;
-      }
-      synchronized (monitor) {
-        while (isBlocked) {
-          try {
-            monitor.wait();
-          } catch (InterruptedException e) {
-            throw new RuntimeException(e);
+        synchronized (monitor) {
+          while (isBlocked) {
+            try {
+              monitor.wait();
+            } catch (InterruptedException e) {
+              throw new RuntimeException(e);
+            }
           }
         }
       }
+      if (!hasBeenProperlyInitialized) {
+        throw new RuntimeException("DebugTarget has not been properly initialized"); //$NON-NLS-1$
+      }
+    }
+    void setProperlyInitialized() {
+      hasBeenProperlyInitialized = true;
     }
     void unblock() {
-      isBlocked = true;
+      isBlocked = false;
       synchronized (monitor) {
         monitor.notifyAll();
       }
     }
   }
-
-	public int getLineNumber(CallFrame stackFrame) {
-		return workspaceRelations.getLineNumber(stackFrame);
-	}
 }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/Messages.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/Messages.java	Thu Mar 18 11:56:59 2010 -0700
@@ -41,6 +41,8 @@
 
   public static String DebugTargetImpl_Uncaught;
 
+  public static String DebugTargetImpl_Unknown;
+
   public static String JavascriptVmEmbedderFactory_TargetName0;
 
   public static String JavascriptVmEmbedderFactory_Terminated;
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/StackFrame.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/StackFrame.java	Thu Mar 18 11:56:59 2010 -0700
@@ -9,6 +9,7 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Set;
 
 import org.chromium.debug.core.ChromiumDebugPlugin;
 import org.chromium.sdk.CallFrame;
@@ -79,16 +80,22 @@
 
   static IVariable[] wrapVariables(
       DebugTargetImpl debugTarget, Collection<? extends JsVariable> jsVars,
+      Set<? extends String> propertyNameBlackList,
       Collection <? extends JsVariable> jsInternalProperties) {
     List<Variable> vars = new ArrayList<Variable>(jsVars.size());
     for (JsVariable jsVar : jsVars) {
+      if (propertyNameBlackList.contains(jsVar.getName())) {
+        continue;
+      }
       vars.add(new Variable(debugTarget, jsVar, false));
     }
     // Sort all regular properties by name.
     Collections.sort(vars, VARIABLE_COMPARATOR);
     // Always put internal properties in the end.
-    for (JsVariable jsMetaVar : jsInternalProperties) {
-      vars.add(new Variable(debugTarget, jsMetaVar, true));
+    if (jsInternalProperties != null) {
+      for (JsVariable jsMetaVar : jsInternalProperties) {
+        vars.add(new Variable(debugTarget, jsMetaVar, true));
+      }
     }
     return vars.toArray(new IVariable[vars.size()]);
   }
@@ -194,7 +201,6 @@
   }
 
   public int getLineNumber() throws DebugException {
-    // convert 0-based to 1-based
     return getDebugTarget().getLineNumber(stackFrame);
   }
 
@@ -307,8 +313,40 @@
 
   private final static Comparator<Variable> VARIABLE_COMPARATOR = new Comparator<Variable>() {
     public int compare(Variable var1, Variable var2) {
-      return var1.getName().compareTo(var2.getName());
+      return compareNameObjects(getNameObject(var1), getNameObject(var2));
+    }
+    // Get property name as String or Integer.
+    private Object getNameObject(Variable var) {
+      String name = var.getName();
+      int len = name.length();
+      if (len >= 3 && name.charAt(0) == '[' && name.charAt(len-1) == ']') {
+        Integer i = Integer.valueOf(name.substring(1, len - 1));
+        return i;
+      }
+      return name;
     }
+    // Compare property name (either string or integer).
+    private int compareNameObjects(Object nameObj1, Object nameObj2) {
+      if (nameObj1 instanceof Integer) {
+        Integer i1 = (Integer) nameObj1;
+        if (nameObj2 instanceof Integer) {
+          Integer i2 = (Integer) nameObj2;
+          return i1.compareTo(i2);
+        } else {
+          return COMPARE_INT_WITH_STRING;
+        }
+      } else {
+        String s1 = (String) nameObj1;
+        if (nameObj2 instanceof String) {
+          String s2 = (String) nameObj2;
+          return s1.compareTo(s2);
+        } else {
+          return -COMPARE_INT_WITH_STRING;
+        }
+      }
+    }
+    // Strings go before numbers.
+    private static final int COMPARE_INT_WITH_STRING = 1;
   };
 
   @Override
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/VProjectWorkspaceBridge.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/VProjectWorkspaceBridge.java	Thu Mar 18 11:56:59 2010 -0700
@@ -233,7 +233,8 @@
   };
 
   public int getLineNumber(CallFrame stackFrame) {
-	  return stackFrame.getLineNumber() + 1;
+    // convert 0-based to 1-based
+    return stackFrame.getLineNumber() + 1;
   }
   
   /**
@@ -267,13 +268,22 @@
 
     public String getThreadLabel(JavascriptThread thread) {
       String url = thread.getDebugTarget().getJavascriptEmbedder().getThreadName();
-      return NLS.bind(Messages.JsThread_ThreadLabelFormat, getThreadStateLabel(thread), (url.length() > 0
-          ? (" : " + url) : "")); //$NON-NLS-1$ //$NON-NLS-2$
+      return NLS.bind(Messages.JsThread_ThreadLabelFormat,
+          getThreadStateLabel(thread),
+          (url.length() > 0 ? (" : " + url) : "")); //$NON-NLS-1$ //$NON-NLS-2$
     }
 
     private String getThreadStateLabel(JavascriptThread thread) {
+      DebugContext context;
       if (thread.isSuspended()) {
-        DebugContext context = thread.getDebugTarget().getDebugContext();
+        // Theoretically the context may be null.
+        context = thread.getDebugTarget().getDebugContext();
+      } else {
+        context = null;
+      }
+      if (context == null) {
+        return Messages.JsThread_ThreadLabelRunning;
+      } else {
         ExceptionData exceptionData = context.getExceptionData();
         if (exceptionData != null) {
           return NLS.bind(Messages.JsThread_ThreadLabelSuspendedExceptionFormat,
@@ -281,8 +291,6 @@
         } else {
           return Messages.JsThread_ThreadLabelSuspended;
         }
-      } else {
-        return Messages.JsThread_ThreadLabelRunning;
       }
     }
 
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/Value.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/Value.java	Thu Mar 18 11:56:59 2010 -0700
@@ -4,6 +4,8 @@
 
 package org.chromium.debug.core.model;
 
+import java.util.Collections;
+
 import org.chromium.debug.core.ChromiumDebugPlugin;
 import org.chromium.debug.core.util.JsValueStringifier;
 import org.chromium.sdk.JsArray;
@@ -56,7 +58,8 @@
     try {
       if (variables == null) {
         if (value.asObject() != null) {
-          variables = StackFrame.wrapVariables(getDebugTarget(), value.asObject().getProperties(),
+          variables = StackFrame.wrapVariables(getDebugTarget(),
+              value.asObject().getProperties(), Collections.<String>emptySet(),
               value.asObject().getInternalProperties());
         } else {
           variables = EMPTY_VARIABLES;
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/WorkspaceBridge.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/WorkspaceBridge.java	Thu Mar 18 11:56:59 2010 -0700
@@ -119,5 +119,4 @@
      */
     String getStackFrameLabel(StackFrame stackFrame) throws DebugException;
   }
-
 }
--- a/org.chromium.debug.core/src/org/chromium/debug/core/model/messages.properties	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/model/messages.properties	Thu Mar 18 11:56:59 2010 -0700
@@ -16,6 +16,7 @@
 DebugTargetImpl_LogExceptionFormat={0} {1} (in {2}:{3}): {4}
 DebugTargetImpl_TargetName=Chromium
 DebugTargetImpl_Uncaught=Uncaught
+DebugTargetImpl_Unknown=<unknown>
 JavascriptVmEmbedderFactory_TargetName0=Remote "{0}" embedding V8 {1}
 JavascriptVmEmbedderFactory_Terminated=terminated
 JavascriptVmEmbedderFactory_TerminatedWithReason=terminated: {0}
@@ -23,7 +24,7 @@
 JsThread_ThreadLabelFormat=JavaScript Thread ({0}){1}
 JsThread_ThreadLabelRunning=Running
 JsThread_ThreadLabelSuspended=Suspended
-JsThread_ThreadLabelSuspendedExceptionFormat=Suspended (exception ''{0}'')
+JsThread_ThreadLabelSuspendedExceptionFormat=Suspended (exception "{0}")
 ResourceManager_UnnamedScriptName=(program)
 StackFrame_NameFormat={0} [{1}:{2}]
 StackFrame_UnknownScriptName=<unknown>
--- a/org.chromium.debug.core/src/org/chromium/debug/core/util/ChromiumDebugPluginUtil.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.core/src/org/chromium/debug/core/util/ChromiumDebugPluginUtil.java	Thu Mar 18 11:56:59 2010 -0700
@@ -20,9 +20,9 @@
 import org.eclipse.core.resources.ResourceAttributes;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.swt.widgets.Display;
@@ -71,14 +71,13 @@
   /**
    * Creates an empty workspace project with the name starting with the given projectNameBase.
    * Created project is guaranteed to be new in EFS, but workspace may happen to
-   * alreay have project with such url (left uncleaned from previous runs). Such project
+   * already have project with such url (left uncleaned from previous runs). Such project
    * silently gets deleted.
    * @param projectNameBase project name template
    * @return the newly created project, or {@code null} if the creation failed
    */
   public static IProject createEmptyProject(String projectNameBase) {
-    URI projectUri;
-    String projectName;
+    ProjectCheckData projectProject;
     try {
       for (int uniqueNumber = 0; ; uniqueNumber++) {
         String projectNameTry;
@@ -87,14 +86,8 @@
         } else {
           projectNameTry = projectNameBase + " (" + uniqueNumber + ")"; //$NON-NLS-1$ //$NON-NLS-2$
         }
-        URI projectUriTry = ChromiumScriptFileSystem.getFileStoreUri(
-            new Path(null, "/" + projectNameTry)); //$NON-NLS-1$
-        IFileStore projectStore = EFS.getStore(projectUriTry);
-        if (projectStore.fetchInfo().exists()) {
-          continue;
-        } else {
-          projectUri = projectUriTry;
-          projectName = projectNameTry;
+        projectProject = checkProjectName(projectNameTry);
+        if (projectProject != null) {
           break;
         }
       }
@@ -102,15 +95,21 @@
       ChromiumDebugPlugin.log(e);
       return null;
     }
-    IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+    IProject project = projectProject.getProject();
+    if (project.exists()) {
+      try {
+        project.delete(true, null);
+      } catch (CoreException e) {
+        ChromiumDebugPlugin.log(e);
+        return null;
+      }
+    }
+
     IProjectDescription description =
-        ResourcesPlugin.getWorkspace().newProjectDescription(projectName);
-    description.setLocationURI(projectUri);
+        ResourcesPlugin.getWorkspace().newProjectDescription(project.getName());
+    description.setLocationURI(projectProject.getProjectUri());
     description.setNatureIds(new String[] { JS_DEBUG_PROJECT_NATURE });
     try {
-      if (project.exists()) {
-        project.delete(true, null);
-      }
 
       project.create(description, null);
       project.open(null);
@@ -118,9 +117,44 @@
       return project;
     } catch (CoreException e) {
       ChromiumDebugPlugin.log(e);
+      return null;
     }
+  }
+
+  private interface ProjectCheckData {
+    IProject getProject();
+    URI getProjectUri();
+  }
 
-    return null;
+  /**
+   * Checks whether debug virtual project can be created.
+   * @param projectNameTry desired project name
+   * @return project project with parameters data or null if project with desired name cannot be
+   *         created
+   */
+  private static ProjectCheckData checkProjectName(String projectNameTry) throws CoreException {
+    final IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectNameTry);
+    if (project.exists()) {
+      URI projectURI = project.getLocationURI();
+      if (!ChromiumScriptFileSystem.isChromiumDebugURI(projectURI)) {
+        // This is not our project. Do not touch it.
+        return null;
+      }
+    }
+    IPath newPath = project.getFullPath();
+    final URI projectUriTry = ChromiumScriptFileSystem.getFileStoreUri(newPath);
+    IFileStore projectStore = EFS.getStore(projectUriTry);
+    if (projectStore.fetchInfo().exists()) {
+      return null;
+    }
+    return new ProjectCheckData() {
+      public IProject getProject() {
+        return project;
+      }
+      public URI getProjectUri() {
+        return projectUriTry;
+      }
+    };
   }
 
 
--- a/org.chromium.debug.ui/META-INF/MANIFEST.MF	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.ui/META-INF/MANIFEST.MF	Thu Mar 18 11:56:59 2010 -0700
@@ -16,5 +16,4 @@
  org.chromium.debug.core;bundle-version="0.1.5",
  org.chromium.sdk;bundle-version="0.1.5"
 Bundle-ActivationPolicy: lazy
-Bundle-RequiredExecutionEnvironment: J2SE-1.5,
- JavaSE-1.6
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
--- a/org.chromium.debug.ui/build.properties	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.debug.ui/build.properties	Thu Mar 18 11:56:59 2010 -0700
@@ -7,9 +7,3 @@
 source.. = src/
 output.. = bin/
 src.includes = LICENSE
-
-# javac 
-javacSource=1.5
-javacTarget=1.5
-javacVerbose=true
-
--- a/org.chromium.sdk/META-INF/MANIFEST.MF	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/META-INF/MANIFEST.MF	Thu Mar 18 11:56:59 2010 -0700
@@ -13,5 +13,4 @@
  org.chromium.sdk.internal.tools.v8.processor;x-internal:=true,
  org.chromium.sdk.internal.tools.v8.request;x-internal:=true,
  org.chromium.sdk.internal.transport;x-internal:=true
-Bundle-RequiredExecutionEnvironment: J2SE-1.5,
- JavaSE-1.6
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
--- a/org.chromium.sdk/build.properties	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/build.properties	Thu Mar 18 11:56:59 2010 -0700
@@ -6,9 +6,3 @@
 source.. = src/
 output.. = bin/
 src.includes = LICENSE
-
-# javac 
-javacSource=1.5
-javacTarget=1.5
-javacVerbose=true
-
--- a/org.chromium.sdk/src/org/chromium/sdk/ChromiumIOException.java	Thu Mar 18 11:10:35 2010 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-package org.chromium.sdk;
-
-import java.io.IOException;
-
-public class ChromiumIOException extends IOException {
-	private static final long serialVersionUID = 1L;
-
-	private final Throwable cause;
-
-	public ChromiumIOException(Throwable cause) {
-		this.cause = cause;
-	}
-	
-	public ChromiumIOException(String message, Throwable cause) {
-		super(message);
-		this.cause = cause;
-	}
-	
-	@Override
-	public Throwable getCause() {
-		return cause;
-	}
-}
--- a/org.chromium.sdk/src/org/chromium/sdk/JavascriptVm.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/JavascriptVm.java	Thu Mar 18 11:56:59 2010 -0700
@@ -70,6 +70,8 @@
    *        may be {@code null}
    * @throws MethodIsBlockingException if called from a callback because it
    *         blocks until scripts are received
+   * TODO(peter.rybin): get rid of callback (return result explicitly)
+   * TODO(peter.rybin): support notification about collected scripts
    */
   void getScripts(ScriptsCallback callback) throws MethodIsBlockingException;
 
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/BrowserImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/BrowserImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -17,7 +17,6 @@
 
 import org.chromium.sdk.Browser;
 import org.chromium.sdk.BrowserTab;
-import org.chromium.sdk.ChromiumIOException;
 import org.chromium.sdk.TabDebugEventListener;
 import org.chromium.sdk.UnsupportedVersionException;
 import org.chromium.sdk.Version;
@@ -103,7 +102,7 @@
       try {
         serverVersionString = devToolsHandler.version(OPERATION_TIMEOUT_MS);
       } catch (TimeoutException e) {
-        throw new ChromiumIOException("Failed to get protocol version from remote", e);
+        throw JavascriptVmImpl.newIOException("Failed to get protocol version from remote", e);
       }
       if (serverVersionString == null) {
         throw new UnsupportedVersionException(BrowserImpl.PROTOCOL_VERSION, null);
@@ -292,7 +291,7 @@
         ticket = connectInternal();
       } catch (UnsupportedVersionException e) {
         // This exception should have happened on tab fetcher creation.
-        throw new ChromiumIOException("Unexpected version problem", e);
+        throw JavascriptVmImpl.newIOException("Unexpected version problem", e);
       }
 
       Session session = ticket.getSession();
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/BrowserTabImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/BrowserTabImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -8,7 +8,6 @@
 
 import org.chromium.sdk.Browser;
 import org.chromium.sdk.BrowserTab;
-import org.chromium.sdk.ChromiumIOException;
 import org.chromium.sdk.DebugEventListener;
 import org.chromium.sdk.TabDebugEventListener;
 import org.chromium.sdk.internal.tools.ToolHandler;
@@ -90,7 +89,7 @@
       try {
         result = devToolSessionManager.attachToTab();
       } catch (AttachmentFailureException e) {
-        throw new ChromiumIOException(e);
+        throw newIOException(null, e);
       }
       if (Result.OK != result) {
         throw new IOException("Failed to attach with result: " + result);
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/CallFrameImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/CallFrameImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -98,7 +98,9 @@
         ValueLoader valueLoader = context.getValueLoader();
         ValueMirror mirror =
             valueLoader.getOrLoadValueFromRefs(Collections.singletonList(ref)).get(0);
-        this.receiverVariable = new JsVariableImpl(this.context, mirror, ref.getName());
+        // This name should be string. We are making it string as a fall-back strategy.
+        String varNameStr = ref.getName().toString();
+        this.receiverVariable = new JsVariableImpl(this.context, mirror, varNameStr);
       }
       this.receiverVariableLoaded = true;
     }
@@ -145,7 +147,9 @@
     List<ValueMirror> mirrors = context.getValueLoader().getOrLoadValueFromRefs(refs);
     Collection<JsVariableImpl> result = new ArrayList<JsVariableImpl>(refs.size());
     for (int i = 0; i < refs.size(); i++) {
-      result.add(new JsVariableImpl(this.context, mirrors.get(i), refs.get(i).getName()));
+      // This name should be string. We are making it string as a fall-back strategy.
+      String varNameStr = refs.get(i).getName().toString();
+      result.add(new JsVariableImpl(this.context, mirrors.get(i), varNameStr));
     }
     return result;
   }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/ContextBuilder.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/ContextBuilder.java	Thu Mar 18 11:56:59 2010 -0700
@@ -16,8 +16,8 @@
 import org.chromium.sdk.JsEvaluateContext;
 import org.chromium.sdk.Script;
 import org.chromium.sdk.SyncCallback;
-import org.chromium.sdk.internal.protocol.CommandResponse;
 import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
+import org.chromium.sdk.internal.tools.v8.V8CommandCallbackBase;
 import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
 import org.chromium.sdk.internal.tools.v8.V8CommandProcessor.V8HandlerCallback;
 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessage;
@@ -281,14 +281,9 @@
 
         DebuggerMessage message = DebuggerMessageFactory.goOn(stepAction, stepCount);
         V8CommandProcessor.V8HandlerCallback commandCallback
-            = new V8CommandProcessor.V8HandlerCallback() {
-          public void messageReceived(CommandResponse response) {
-            SuccessCommandResponse successResponse = response.asSuccess();
-            if (successResponse == null) {
-              this.failure(response.asFailure().getMessage());
-              return;
-            }
-
+            = new V8CommandCallbackBase() {
+          @Override
+          public void success(SuccessCommandResponse successResponse) {
             contextDismissed(UserContext.this);
 
             if (callback != null) {
@@ -296,6 +291,7 @@
             }
             getDebugSession().getDebugEventListener().resumed();
           }
+          @Override
           public void failure(String message) {
             synchronized (sendContextCommandsMonitor) {
               // resurrected
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/DebugSession.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/DebugSession.java	Thu Mar 18 11:56:59 2010 -0700
@@ -4,11 +4,15 @@
 
 package org.chromium.sdk.internal;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.List;
 
 import org.chromium.sdk.Breakpoint;
 import org.chromium.sdk.DebugEventListener;
 import org.chromium.sdk.InvalidContextException;
+import org.chromium.sdk.Script;
 import org.chromium.sdk.SyncCallback;
 import org.chromium.sdk.Version;
 import org.chromium.sdk.JavascriptVm.ScriptsCallback;
@@ -19,11 +23,11 @@
 import org.chromium.sdk.internal.tools.v8.BreakpointManager;
 import org.chromium.sdk.internal.tools.v8.DefaultResponseHandler;
 import org.chromium.sdk.internal.tools.v8.V8BlockingCallback;
+import org.chromium.sdk.internal.tools.v8.V8CommandCallbackBase;
 import org.chromium.sdk.internal.tools.v8.V8CommandOutput;
 import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
 import org.chromium.sdk.internal.tools.v8.V8Helper;
 import org.chromium.sdk.internal.tools.v8.V8ProtocolUtil;
-import org.chromium.sdk.internal.tools.v8.V8CommandProcessor.V8HandlerCallback;
 import org.chromium.sdk.internal.tools.v8.request.ContextlessDebuggerMessage;
 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessageFactory;
 
@@ -122,20 +126,15 @@
   }
 
   public void suspend(final SuspendCallback suspendCallback) {
-    V8CommandProcessor.V8HandlerCallback v8Callback = new V8CommandProcessor.V8HandlerCallback() {
+    V8CommandProcessor.V8HandlerCallback v8Callback = new V8CommandCallbackBase() {
+      @Override
       public void failure(String message) {
         if (suspendCallback != null) {
           suspendCallback.failure(new Exception(message));
         }
       }
-      public void messageReceived(CommandResponse response) {
-        SuccessCommandResponse successResponse = response.asSuccess();
-        if (successResponse == null) {
-          if (suspendCallback != null) {
-            suspendCallback.failure(new Exception("Unsuccessful command"));
-          }
-          return;
-        }
+      @Override
+      public void success(SuccessCommandResponse successResponse) {
         if (suspendCallback != null) {
           suspendCallback.success();
         }
@@ -154,38 +153,34 @@
 
   public class ScriptLoader {
 
-    /** Whether the initial script loading has completed. */
-    private volatile boolean doneInitialScriptLoad = false;
+    private final Object monitor = new Object();
+    /**
+     * Stores the callbacks that are waiting for result.
+     * This field being reset to null means that result is ready (loaded into ScriptManager)
+     * and no more callbacks are accepted.
+     */
+    private List<ScriptsCallback> pendingCallbacks = new ArrayList<ScriptsCallback>(2);
+    private List<SyncCallback> pendingSyncCallbacks = new ArrayList<SyncCallback>(2);
 
     /**
      * Loads all scripts from the remote if necessary, and feeds them into the
      * callback provided (if any).
-     *
-     * @param callback nullable callback to invoke when the scripts are ready
      */
-    public void loadAllScripts(final ScriptsCallback callback, SyncCallback syncCallback) {
-      if (!doneInitialScriptLoad) {
-        this.doneInitialScriptLoad = true;
-        // Not loaded the scripts initially, do full load.
-        v8Helper.reloadAllScriptsAsync(new V8HandlerCallback() {
-          public void messageReceived(CommandResponse response) {
-            if (callback != null) {
-              SuccessCommandResponse successResponse = response.asSuccess();
-              if (successResponse != null) {
-                callback.success(getScriptManager().allScripts());
-              } else {
-                callback.failure(response.asFailure().getMessage());
-              }
-            }
-          }
-
-          public void failure(String message) {
-            if (callback != null) {
-              callback.failure(message);
-            }
-          }
-        }, syncCallback);
-      } else {
+    public void loadAllScripts(ScriptsCallback callback, SyncCallback syncCallback) {
+      boolean resultIsReady;
+      boolean sendMessage;
+      synchronized (monitor) {
+        if (pendingCallbacks == null) {
+          resultIsReady = true;
+          sendMessage = false;
+        } else {
+          resultIsReady = false;
+          sendMessage = pendingCallbacks.isEmpty();
+          pendingCallbacks.add(callback);
+          pendingSyncCallbacks.add(syncCallback);
+        }
+      }
+      if (resultIsReady) {
         try {
           if (callback != null) {
             callback.success(getScriptManager().allScripts());
@@ -195,8 +190,68 @@
             syncCallback.callbackDone(null);
           }
         }
+        return;
+      }
+      if (sendMessage) {
+        sendAsyncMessage();
       }
     }
+    private void sendAsyncMessage() {
+      V8Helper.ScriptLoadCallback groupCallback = new V8Helper.ScriptLoadCallback() {
+        public void success() {
+          final Collection<Script> scripts = scriptManager.allScripts();
+          processCall(new CallbackCaller() {
+            @Override
+            void call(ScriptsCallback callback) {
+              callback.success(scripts);
+            }
+          });
+        }
+
+        public void failure(final String message) {
+          processCall(new CallbackCaller() {
+            @Override
+            void call(ScriptsCallback callback) {
+              callback.failure(message);
+            }
+          });
+        }
+
+        private void processCall(CallbackCaller caller) {
+          List<ScriptsCallback> savedCallbacks;
+          synchronized (monitor) {
+            savedCallbacks = pendingCallbacks;
+            pendingCallbacks = null;
+          }
+          for (ScriptsCallback callback : savedCallbacks) {
+            if (callback != null) {
+              caller.call(callback);
+            }
+          }
+        }
+        abstract class CallbackCaller {
+          abstract void call(ScriptsCallback callback);
+        }
+      };
+
+      SyncCallback groupSyncCallback = new SyncCallback() {
+        public void callbackDone(RuntimeException e) {
+          List<SyncCallback> savedCallbacks;
+          synchronized (monitor) {
+            savedCallbacks = pendingSyncCallbacks;
+            pendingSyncCallbacks = null;
+          }
+          for (SyncCallback callback : savedCallbacks) {
+            if (callback != null) {
+              callback.callbackDone(e);
+            }
+          }
+        }
+      };
+
+      V8Helper.reloadAllScriptsAsync(DebugSession.this, groupCallback, groupSyncCallback);
+    }
+
   }
 
   /**
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JavascriptVmImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JavascriptVmImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -4,6 +4,8 @@
 
 package org.chromium.sdk.internal;
 
+import java.io.IOException;
+
 import org.chromium.sdk.Breakpoint;
 import org.chromium.sdk.CallbackSemaphore;
 import org.chromium.sdk.JavascriptVm;
@@ -39,4 +41,11 @@
   }
 
   protected abstract DebugSession getDebugSession();
+
+  // TODO(peter.rybin): This message will be obsolete in JavaSE-1.6.
+  public static IOException newIOException(String message, Throwable cause) {
+    IOException result = new IOException(message);
+    result.initCause(cause);
+    return result;
+  }
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsArrayImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsArrayImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -29,11 +29,11 @@
    * This constructor implies lazy resolution of object properties.
    *
    * @param context this array belongs in
-   * @param parentFqn the fully qualified name of this array parent
+   * @param variableFqn the fully qualified name of the variable holding this array
    * @param valueState the mirror corresponding to this array
    */
-  JsArrayImpl(InternalContext context, String parentFqn, ValueMirror valueState) {
-    super(context, parentFqn, valueState);
+  JsArrayImpl(InternalContext context, String variableFqn, ValueMirror valueState) {
+    super(context, variableFqn, valueState);
   }
 
   private synchronized void ensureElementsMap() throws MethodIsBlockingException {
@@ -49,12 +49,12 @@
         });
 
     for (JsVariableImpl prop : getProperties()) {
-      String name = prop.getRawName();
-      Integer index = getAsArrayIndex(name);
-      if (index == null) {
+      Object name = prop.getRawNameAsObject();
+      if (name instanceof Number == false) {
         continue;
       }
-      map.put(index, prop);
+      Number index = (Number) name;
+      map.put(index.intValue(), prop);
     }
     indexToElementMap = Collections.unmodifiableSortedMap(map);
   }
@@ -76,13 +76,14 @@
     List<JsVariableImpl> properties = getSubpropertiesHelper().getPropertiesLazily();
     // TODO(peter.rybin): rename propRefs
     for (JsVariableImpl prop : properties) {
-      String name = prop.getRawName();
-      Integer index = getAsArrayIndex(name);
-      if (index == null) {
+      Object name = prop.getRawNameAsObject();
+      if (name instanceof Number == false) {
         continue;
       }
-      if (index > lastIndex) {
-        lastIndex = index;
+      Number index = (Number) name;
+      int intIndex = index.intValue();
+      if (intIndex > lastIndex) {
+        lastIndex = intIndex;
       }
     }
     return lastIndex + 1;
@@ -109,47 +110,4 @@
   public JsArrayImpl asArray() {
     return this;
   }
-
-  @Override
-  protected JsVariableImpl.NameDecorator getChildPropertyNameDecorator() {
-    return ARRAY_ELEMENT_DECORATOR;
-  }
-
-  /**
-   * @return integer representation of the index or null if it is not an integer
-   */
-  static Integer getAsArrayIndex(String varName) {
-    if (!JsonUtil.isInteger(varName)) {
-      return null;
-    }
-    try {
-      int index = Integer.parseInt(varName);
-      return index;
-    } catch (NumberFormatException e) {
-      return null;
-    }
-  }
-
-  private final static JsVariableImpl.NameDecorator ARRAY_ELEMENT_DECORATOR =
-      new JsVariableImpl.NameDecorator() {
-    @Override
-    String decorateVarName(String rawName) {
-      Integer index = getAsArrayIndex(rawName);
-      if (index == null) {
-        return rawName;
-      }
-      // Fix array element indices
-      return OPEN_BRACKET + rawName + CLOSE_BRACKET;
-    }
-    @Override
-    String buildAccessSuffix(String rawName) {
-      Integer index = getAsArrayIndex(rawName);
-      if (index == null) {
-        return NOOP.buildAccessSuffix(rawName);
-      }
-      return OPEN_BRACKET + rawName + CLOSE_BRACKET;
-    }
-    private static final String OPEN_BRACKET = "[";
-    private static final String CLOSE_BRACKET = "]";
-  };
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsEvaluateContextImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsEvaluateContextImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -9,11 +9,11 @@
 import org.chromium.sdk.JsVariable;
 import org.chromium.sdk.SyncCallback;
 import org.chromium.sdk.internal.InternalContext.ContextDismissedCheckedException;
-import org.chromium.sdk.internal.protocol.CommandResponse;
 import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
 import org.chromium.sdk.internal.protocol.data.ValueHandle;
 import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
 import org.chromium.sdk.internal.tools.v8.MethodIsBlockingException;
+import org.chromium.sdk.internal.tools.v8.V8CommandCallbackBase;
 import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
 import org.chromium.sdk.internal.tools.v8.V8Helper;
 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessage;
@@ -59,29 +59,25 @@
 
     V8CommandProcessor.V8HandlerCallback commandCallback = callback == null
         ? null
-        : new V8CommandProcessor.V8HandlerCallback() {
-          public void messageReceived(CommandResponse response) {
-            SuccessCommandResponse successResponse = response.asSuccess();
-            if (successResponse != null) {
-              ValueHandle body;
-              try {
-                body = successResponse.getBody().asEvaluateBody();
-              } catch (JsonProtocolParseException e) {
-                throw new RuntimeException(e);
-              }
-              JsVariable variable =
-                  new JsVariableImpl(JsEvaluateContextImpl.this.getInternalContext(),
-                      V8Helper.createMirrorFromLookup(body).getValueMirror(), expression);
-              if (variable != null) {
-                callback.success(variable);
-              } else {
-                callback.failure("Evaluation failed");
-              }
+        : new V8CommandCallbackBase() {
+          @Override
+          public void success(SuccessCommandResponse successResponse) {
+            ValueHandle body;
+            try {
+              body = successResponse.getBody().asEvaluateBody();
+            } catch (JsonProtocolParseException e) {
+              throw new RuntimeException(e);
+            }
+            JsVariable variable =
+                new JsVariableImpl(JsEvaluateContextImpl.this.getInternalContext(),
+                    V8Helper.createMirrorFromLookup(body).getValueMirror(), expression);
+            if (variable != null) {
+              callback.success(variable);
             } else {
-              callback.failure(response.asFailure().getMessage());
+              callback.failure("Evaluation failed");
             }
           }
-
+          @Override
           public void failure(String message) {
             callback.failure(message);
           }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsObjectImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsObjectImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -23,19 +23,22 @@
 
   private final InternalContext context;
 
-  private final String parentFqn;
+  /**
+   * Fully qualified name of variable holding this object.
+   */
+  private final String variableFqn;
 
   /**
    * This constructor implies the lazy resolution of object properties.
    *
    * @param context where this instance belongs in
-   * @param parentFqn the fully qualified name of the object parent
+   * @param variableFqn the fully qualified name of the variable holding this object
    * @param valueState the value data from the JS VM
    */
-  JsObjectImpl(InternalContext context, String parentFqn, ValueMirror valueState) {
+  JsObjectImpl(InternalContext context, String variableFqn, ValueMirror valueState) {
     super(valueState);
     this.context = context;
-    this.parentFqn = parentFqn;
+    this.variableFqn = variableFqn;
   }
 
   public Collection<JsVariableImpl> getProperties() throws MethodIsBlockingException {
@@ -92,10 +95,6 @@
     return getMirror().getClassName();
   }
 
-  protected JsVariableImpl.NameDecorator getChildPropertyNameDecorator() {
-    return JsVariableImpl.NameDecorator.NOOP;
-  }
-
   protected InternalContext getInternalContext() {
     return context;
   }
@@ -136,23 +135,29 @@
       List<JsVariableImpl> result = new ArrayList<JsVariableImpl>(mirrorProperties.size());
       for (int i = 0; i < mirrorProperties.size(); i++) {
         ValueMirror mirror = mirrorProperties.get(i);
-        String varName = propertyRefs.get(i).getName();
+        Object varName = propertyRefs.get(i).getName();
         String fqn = getFullyQualifiedName(varName);
         if (fqn == null) {
           continue;
         }
-        result.add(new JsVariableImpl(context, mirror, varName, fqn,
-            getNameDecorator()));
+        String decoratedName = JsVariableImpl.NameDecorator.decorateVarName(varName);
+        result.add(new JsVariableImpl(context, mirror, varName, decoratedName, fqn));
       }
       return result;
     }
 
-    private String getFullyQualifiedName(String propName) {
-      if (propName.startsWith(".")) {
-        // ".arguments" is not legal
+    private String getFullyQualifiedName(Object propName) {
+      if (variableFqn == null) {
         return null;
       }
-      return parentFqn + getNameDecorator().buildAccessSuffix(propName);
+      if (propName instanceof String) {
+        String propNameStr = (String) propName;
+        if (propNameStr.startsWith(".")) {
+          // ".arguments" is not legal
+          return null;
+        }
+      }
+      return variableFqn + JsVariableImpl.NameDecorator.buildAccessSuffix(propName);
     }
 
     JsVariableImpl getProperty(String propertyName) {
@@ -175,17 +180,12 @@
       }
     }
 
-    abstract JsVariableImpl.NameDecorator getNameDecorator();
     abstract List<? extends PropertyReference> getPropertyRefs(
         SubpropertiesMirror subpropertiesMirror);
   }
 
   private final Subproperties subproperties = new Subproperties() {
     @Override
-    JsVariableImpl.NameDecorator getNameDecorator() {
-      return getChildPropertyNameDecorator();
-    }
-    @Override
     List<? extends PropertyReference> getPropertyRefs(SubpropertiesMirror subpropertiesMirror) {
       return subpropertiesMirror.getProperties();
     }
@@ -193,10 +193,6 @@
 
   private final Subproperties internalProperties = new Subproperties() {
     @Override
-    JsVariableImpl.NameDecorator getNameDecorator() {
-      return JsVariableImpl.NameDecorator.NOOP;
-    }
-    @Override
     List<? extends PropertyReference> getPropertyRefs(SubpropertiesMirror subpropertiesMirror) {
       return subpropertiesMirror.getInternalProperties();
     }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsScopeImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsScopeImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -43,8 +43,10 @@
 
       properties = new ArrayList<JsVariable>(propertyMirrors.size());
       for (int i = 0; i < propertyMirrors.size(); i++) {
+        // This name should be string. We are making it string as a fall-back strategy.
+        String varNameStr = propertyRefs.get(i).getName().toString();
         properties.add(new JsVariableImpl(callFrameImpl.getInternalContext(),
-            propertyMirrors.get(i), propertyRefs.get(i).getName()));
+            propertyMirrors.get(i), varNameStr));
       }
     }
     return properties;
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/JsVariableImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/JsVariableImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -23,15 +23,16 @@
   private final InternalContext context;
 
   /** The fully qualified name of this variable. */
-  private final String variableFqn;
-
-  private final NameDecorator nameDecorator;
+  private final String qualifiedName;
 
   /** The lazily constructed value of this variable. */
   private final JsValueImpl value;
 
   /** Variable name. */
-  private final String rawName;
+  private final Object rawName;
+
+  /** Variable name. */
+  private final String decoratedName;
 
   /**
    * Constructs a variable contained in the given context with the given
@@ -41,7 +42,7 @@
    * @param valueData value data for this variable
    */
   JsVariableImpl(InternalContext context, ValueMirror valueData, String name) {
-    this(context, valueData, name, null, NameDecorator.NOOP);
+    this(context, valueData, name, name, name);
   }
 
   /**
@@ -50,27 +51,27 @@
    *
    * @param context that owns this variable
    * @param valueData for this variable
-   * @param variableFqn the fully qualified name of this variable
+   * @param qualifiedName the fully qualified name of this variable
    */
-  JsVariableImpl(InternalContext context, ValueMirror valueData, String name, String variableFqn,
-      NameDecorator nameDecorator) {
+  JsVariableImpl(InternalContext context, ValueMirror valueData, Object rawName,
+      String decoratedName, String qualifiedName) {
     this.context = context;
     this.valueData = valueData;
-    this.rawName = name;
-    this.variableFqn = variableFqn;
-    this.nameDecorator = nameDecorator;
+    this.rawName = rawName;
+    this.decoratedName = decoratedName;
+    this.qualifiedName = qualifiedName;
 
     Type type = this.valueData.getType();
     switch (type) {
       case TYPE_FUNCTION:
-        this.value = new JsFunctionImpl(context, this.variableFqn, this.valueData);
+        this.value = new JsFunctionImpl(context, this.qualifiedName, this.valueData);
         break;
       case TYPE_ERROR:
       case TYPE_OBJECT:
-        this.value = new JsObjectImpl(context, this.variableFqn, this.valueData);
+        this.value = new JsObjectImpl(context, this.qualifiedName, this.valueData);
         break;
       case TYPE_ARRAY:
-        this.value = new JsArrayImpl(context, this.variableFqn, this.valueData);
+        this.value = new JsArrayImpl(context, this.qualifiedName, this.valueData);
         break;
       default:
         this.value = new JsValueImpl(this.valueData);
@@ -86,10 +87,14 @@
   }
 
   public String getName() {
-    return nameDecorator.decorateVarName(rawName);
+    return decoratedName;
   }
 
   public String getRawName() {
+    return this.rawName.toString();
+  }
+
+  Object getRawNameAsObject() {
     return this.rawName;
   }
 
@@ -132,23 +137,27 @@
   }
 
   public String getFullyQualifiedName() {
-    return variableFqn != null
-        ? variableFqn
+    return qualifiedName != null
+        ? qualifiedName
         : getName();
   }
 
-  static abstract class NameDecorator {
-    static final NameDecorator NOOP = new NameDecorator() {
-      @Override
-      String decorateVarName(String rawName) {
-        return rawName;
+  static class NameDecorator {
+    static String decorateVarName(Object rawName) {
+      if (rawName instanceof Number) {
+        return OPEN_BRACKET + rawName + CLOSE_BRACKET;
+      } else {
+        return rawName.toString();
       }
-      @Override
-      String buildAccessSuffix(String rawName) {
+    }
+    static String buildAccessSuffix(Object rawName) {
+      if (rawName instanceof Number) {
+        return OPEN_BRACKET + rawName + CLOSE_BRACKET;
+      } else {
         return "." + rawName;
       }
-    };
-    abstract String decorateVarName(String rawName);
-    abstract String buildAccessSuffix(String rawName);
+    }
+    private static final String OPEN_BRACKET = "[";
+    private static final String CLOSE_BRACKET = "]";
   }
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/PropertyReference.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/PropertyReference.java	Thu Mar 18 11:56:59 2010 -0700
@@ -9,7 +9,7 @@
  * A named property reference.
  */
 public class PropertyReference {
-  private final String name;
+  private final Object name;
 
   private final DataWithRef smthWithRef;
 
@@ -17,7 +17,7 @@
    * @param propertyName the name of the property
    * @param valueObject a JSON descriptor of the property
    */
-  public PropertyReference(String propertyName, DataWithRef smthWithRef) {
+  public PropertyReference(Object propertyName, DataWithRef smthWithRef) {
     this.name = propertyName;
     this.smthWithRef = smthWithRef;
   }
@@ -26,7 +26,7 @@
     return smthWithRef.ref();
   }
 
-  public String getName() {
+  public Object getName() {
     return name;
   }
 
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/ScriptImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/ScriptImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -90,7 +90,7 @@
 
   private final Descriptor descriptor;
 
-  private String source;
+  private volatile String source = null;
 
   /**
    * @param descriptor of the script retrieved from a "scripts" response
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/ScriptManager.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/ScriptManager.java	Thu Mar 18 11:56:59 2010 -0700
@@ -76,10 +76,10 @@
    * Associates a source received in a "source" V8 response with the given
    * script.
    *
-   * @param scriptBody the JSON response body
+   * @param body the JSON response body
    * @param script the script to associate the source with
    */
-  public void setSourceCode(ScriptHandle body, ScriptImpl script) {
+  private void setSourceCode(ScriptHandle body, ScriptImpl script) {
     String src = body.source();
     if (src == null) {
       return;
@@ -130,8 +130,8 @@
   }
 
   /**
-   * This method allows running the same code for all scripts in the manager.
-   *
+   * This method allows running the same code for all scripts in the manager. All modifications
+   * are blocked for this period of time.
    * @param callback to invoke for every script, until
    *        {@link Callback#process(Script)} returns {@code false}.
    */
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/StandaloneVmImpl.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/StandaloneVmImpl.java	Thu Mar 18 11:56:59 2010 -0700
@@ -12,7 +12,6 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.chromium.sdk.ChromiumIOException;
 import org.chromium.sdk.DebugEventListener;
 import org.chromium.sdk.StandaloneVm;
 import org.chromium.sdk.UnsupportedVersionException;
@@ -122,9 +121,9 @@
     } catch (InterruptedException e) {
       throw new RuntimeException(e);
     } catch (ExecutionException e) {
-      throw new ChromiumIOException("Failed to get version", e);
+      throw newIOException("Failed to get version", e);
     } catch (TimeoutException e) {
-      throw new ChromiumIOException("Timed out waiting for version", e);
+      throw newIOException("Timed out waiting for version", e);
     }
 
     String versionString = remoteInfo.getProtocolVersion();
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/protocol/data/PropertyWithValue.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/protocol/data/PropertyWithValue.java	Thu Mar 18 11:56:59 2010 -0700
@@ -13,5 +13,5 @@
 public interface PropertyWithValue extends JsonSubtype<PropertyObject> {
   @JsonSubtypeCondition
   @JsonOptionalField
-  RefWithDisplayData getValue();
+  SomeRef getValue();
 }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/BreakpointManager.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/BreakpointManager.java	Thu Mar 18 11:56:59 2010 -0700
@@ -8,7 +8,6 @@
 import org.chromium.sdk.JavascriptVm.BreakpointCallback;
 import org.chromium.sdk.internal.DebugSession;
 import org.chromium.sdk.internal.protocol.BreakpointBody;
-import org.chromium.sdk.internal.protocol.CommandResponse;
 import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
 import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessageFactory;
@@ -35,28 +34,25 @@
         true,
         callback == null
             ? null
-            : new V8CommandProcessor.V8HandlerCallback() {
-              public void messageReceived(CommandResponse response) {
-                SuccessCommandResponse successResponse = response.asSuccess();
-                if (successResponse != null) {
-                  BreakpointBody body;
-                  try {
-                    body = successResponse.getBody().asBreakpointBody();
-                  } catch (JsonProtocolParseException e) {
-                    throw new RuntimeException(e);
-                  }
-                  long id = body.getBreakpoint();
+            : new V8CommandCallbackBase() {
+              @Override
+              public void success(SuccessCommandResponse successResponse) {
+                BreakpointBody body;
+                try {
+                  body = successResponse.getBody().asBreakpointBody();
+                } catch (JsonProtocolParseException e) {
+                  throw new RuntimeException(e);
+                }
+                long id = body.getBreakpoint();
 
-                  final BreakpointImpl breakpoint =
-                      new BreakpointImpl(type, id, enabled, ignoreCount,
-                          condition, BreakpointManager.this);
+                final BreakpointImpl breakpoint =
+                    new BreakpointImpl(type, id, enabled, ignoreCount,
+                        condition, BreakpointManager.this);
 
-                  callback.success(breakpoint);
-                  idToBreakpoint.put(breakpoint.getId(), breakpoint);
-                } else {
-                  callback.failure(response.asFailure().getMessage());
-                }
+                callback.success(breakpoint);
+                idToBreakpoint.put(breakpoint.getId(), breakpoint);
               }
+              @Override
               public void failure(String message) {
                 if (callback != null) {
                   callback.failure(message);
@@ -80,19 +76,14 @@
     debugSession.sendMessageAsync(
         DebuggerMessageFactory.clearBreakpoint(breakpointImpl),
         true,
-        new V8CommandProcessor.V8HandlerCallback() {
-          public void messageReceived(CommandResponse response) {
-            SuccessCommandResponse successResponse = response.asSuccess();
-            if (successResponse != null) {
-              if (callback != null) {
-                callback.success(null);
-              }
-            } else {
-              if (callback != null) {
-                callback.failure(response.asFailure().getMessage());
-              }
+        new V8CommandCallbackBase() {
+          @Override
+          public void success(SuccessCommandResponse successResponse) {
+            if (callback != null) {
+              callback.success(null);
             }
           }
+          @Override
           public void failure(String message) {
             if (callback != null) {
               callback.failure(message);
@@ -107,17 +98,14 @@
     debugSession.sendMessageAsync(
         DebuggerMessageFactory.changeBreakpoint(breakpointImpl),
         true,
-        new V8CommandProcessor.V8HandlerCallback() {
-          public void messageReceived(CommandResponse response) {
+        new V8CommandCallbackBase() {
+          @Override
+          public void success(SuccessCommandResponse successResponse) {
             if (callback != null) {
-              SuccessCommandResponse successResponse = response.asSuccess();
-              if (successResponse != null) {
-                callback.success(breakpointImpl);
-              } else {
-                callback.failure(response.asFailure().getMessage());
-              }
+              callback.success(breakpointImpl);
             }
           }
+          @Override
           public void failure(String message) {
             if (callback != null) {
               callback.failure(message);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8CommandCallbackBase.java	Thu Mar 18 11:56:59 2010 -0700
@@ -0,0 +1,28 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.sdk.internal.tools.v8;
+
+import org.chromium.sdk.internal.protocol.CommandResponse;
+import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
+
+/**
+ * A basic implementation of {@link V8CommandProcessor.V8HandlerCallback} that introduces
+ * command success and failure handlers and dispatches the V8 response accordingly.
+ */
+public abstract class V8CommandCallbackBase implements V8CommandProcessor.V8HandlerCallback {
+  public abstract void success(SuccessCommandResponse successResponse);
+
+  public abstract void failure(String message);
+
+  public void messageReceived(CommandResponse response) {
+    SuccessCommandResponse successResponse = response.asSuccess();
+    if (successResponse == null) {
+      this.failure(response.asFailure().getMessage());
+      return;
+    } else {
+      success(successResponse);
+    }
+  }
+}
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8Helper.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8Helper.java	Thu Mar 18 11:56:59 2010 -0700
@@ -7,7 +7,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
 import org.chromium.sdk.CallbackSemaphore;
@@ -48,44 +47,33 @@
    */
   private final DebugSession debugSession;
 
-  /**
-   * A semaphore that prevents concurrent script reloading (which may effectively
-   * double the efforts.)
-   */
-  private final Semaphore scriptsReloadSemaphore = new Semaphore(1);
-
   public V8Helper(DebugSession debugSession) {
     this.debugSession = debugSession;
   }
 
+  public interface ScriptLoadCallback {
+    void success();
+    void failure(String message);
+  }
+
   /**
-   * Reloads all normal scripts found in the page. First, all scripts without
-   * their sources are retrieved to save bandwidth (script list change during a
-   * page lifetime is a relatively rare event.) If at least one script has been
-   * added, the script cache is dropped and re-populated with new scripts that
-   * are re-requested together with their sources.
-   *
+   * Loads all scripts and stores them in ScriptManager.
    * @param callback to invoke when the script reloading has completed
+   * @param syncCallback to invoke after callback whether it normally returned or threw an exception
    */
-  public void reloadAllScriptsAsync(V8CommandProcessor.V8HandlerCallback callback,
-      SyncCallback syncCallback) {
-    final V8CommandProcessor.V8HandlerCallback finalCallback = callback != null
-        ? callback
-        : V8CommandProcessor.V8HandlerCallback.NULL_CALLBACK;
-    lock();
+  public static void reloadAllScriptsAsync(final DebugSession debugSession,
+      final ScriptLoadCallback callback, SyncCallback syncCallback) {
     debugSession.sendMessageAsync(
         DebuggerMessageFactory.scripts(ScriptsMessage.SCRIPTS_NORMAL, true),
         true,
-        new V8CommandProcessor.V8HandlerCallback() {
+        new V8CommandCallbackBase() {
+          @Override
           public void failure(String message) {
-            unlock();
-            finalCallback.failure(message);
+            callback.failure(message);
           }
 
-          public void messageReceived(CommandResponse response) {
-            SuccessCommandResponse successResponse = response.asSuccess();
-
-            // TODO(peter.rybin): add try/finally for unlock, with some error reporting probably.
+          @Override
+          public void success(SuccessCommandResponse successResponse) {
             List<ScriptHandle> body;
             try {
               body = successResponse.getBody().asScripts();
@@ -98,30 +86,15 @@
               Long id = V8ProtocolUtil.getScriptIdFromResponse(scriptHandle);
               if (scriptManager.findById(id) == null &&
                   !ChromeDevToolSessionManager.JAVASCRIPT_VOID.equals(scriptHandle.source())) {
-                scriptManager.addScript(
-                    scriptHandle,
-                    successResponse.getRefs());
+                scriptManager.addScript(scriptHandle, successResponse.getRefs());
               }
             }
-            unlock();
-            finalCallback.messageReceived(response);
+            callback.success();
           }
         },
         syncCallback);
   }
 
-  protected void lock() {
-    try {
-      scriptsReloadSemaphore.acquire();
-    } catch (InterruptedException e) {
-      // consider it a successful acquisition
-    }
-  }
-
-  protected void unlock() {
-    scriptsReloadSemaphore.release();
-  }
-
   /**
    * Gets all resolved locals for the call frame, caches scripts and objects in
    * the scriptManager and handleManager.
@@ -222,7 +195,7 @@
     String className = valueHandle.className();
     Type type = JsDataTypeUtil.fromJsonTypeAndClassName(valueHandle.type(), className);
     if (type == null) {
-      throw new ValueLoadException("Bad value object");
+      type = Type.TYPE_OBJECT;
     }
     String text = valueHandle.text();
     return createMirrorFromLookup(valueHandle, type).getValueMirror();
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8ProtocolUtil.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/V8ProtocolUtil.java	Thu Mar 18 11:56:59 2010 -0700
@@ -146,7 +146,7 @@
    */
   public static <OBJ> PropertyReference extractProperty(OBJ prop,
       PropertyNameGetter<OBJ> nameGetter) {
-    String name = nameGetter.getName(prop);
+    Object name = nameGetter.getName(prop);
     if (name == null) {
       return null;
     }
@@ -193,8 +193,8 @@
 
     static final PropertyNameGetter<PropertyObject> LOCAL = new SubpropertyNameGetter() {
       @Override
-      String getName(PropertyObject ref) {
-        String name = super.getName(ref);
+      Object getName(PropertyObject ref) {
+        Object name = super.getName(ref);
         if (V8ProtocolUtil.isInternalProperty(name)) {
           return null;
         }
@@ -211,15 +211,14 @@
     static final PropertyNameGetter<PropertyObject> SUBPROPERTY = new SubpropertyNameGetter();
     static class SubpropertyNameGetter extends PropertyNameGetter<PropertyObject> {
       @Override
-      String getName(PropertyObject ref) {
-        Object nameObject = ref.name();
-        return nameObject.toString();
+      Object getName(PropertyObject ref) {
+        return ref.name();
       }
       @Override
       DataWithRef getRef(PropertyObject prop) {
         PropertyWithValue asPropertyWithValue = prop.asPropertyWithValue();
         if (asPropertyWithValue != null) {
-          return DataWithRef.fromSomeRef(asPropertyWithValue.getValue().getSuper());
+          return DataWithRef.fromSomeRef(asPropertyWithValue.getValue());
         } else {
           return DataWithRef.fromLong(prop.asPropertyWithRef().ref());
         }
@@ -239,7 +238,7 @@
     /**
      * @return property name or null if we should skip this property
      */
-    abstract String getName(OBJ ref);
+    abstract Object getName(OBJ ref);
     abstract Long getPropertyType(OBJ prop);
   }
 
@@ -248,9 +247,13 @@
    * @return whether the given property name corresponds to an internal V8
    *         property
    */
-  public static boolean isInternalProperty(String propertyName) {
+  public static boolean isInternalProperty(Object propertyName) {
+    if (propertyName instanceof String == false) {
+      return false;
+    }
+    String propertyNameStr = (String) propertyName;
     // Chrome can return properties like ".arguments". They should be ignored.
-    return propertyName.length() == 0 || propertyName.startsWith(".");
+    return propertyNameStr.length() == 0 || propertyNameStr.startsWith(".");
   }
 
   /**
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/AfterCompileProcessor.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/AfterCompileProcessor.java	Thu Mar 18 11:56:59 2010 -0700
@@ -11,13 +11,12 @@
 import org.chromium.sdk.internal.DebugSession;
 import org.chromium.sdk.internal.V8ContextFilter;
 import org.chromium.sdk.internal.protocol.AfterCompileBody;
-import org.chromium.sdk.internal.protocol.CommandResponse;
 import org.chromium.sdk.internal.protocol.EventNotification;
 import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
 import org.chromium.sdk.internal.protocol.data.ScriptHandle;
 import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
 import org.chromium.sdk.internal.tools.v8.ChromeDevToolSessionManager;
-import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
+import org.chromium.sdk.internal.tools.v8.V8CommandCallbackBase;
 import org.chromium.sdk.internal.tools.v8.V8ProtocolUtil;
 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessageFactory;
 
@@ -43,12 +42,9 @@
         DebuggerMessageFactory.scripts(
             Collections.singletonList(V8ProtocolUtil.getScriptIdFromResponse(script)), true),
         true,
-        new V8CommandProcessor.V8HandlerCallback(){
-          public void messageReceived(CommandResponse response) {
-            SuccessCommandResponse successResponse = response.asSuccess();
-            if (successResponse == null) {
-              return;
-            }
+        new V8CommandCallbackBase() {
+          @Override
+          public void success(SuccessCommandResponse successResponse) {
             List<ScriptHandle> body;
             try {
               body = successResponse.getBody().asScripts();
@@ -67,6 +63,7 @@
             }
           }
 
+          @Override
           public void failure(String message) {
             // The script is now missing.
           }
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/BacktraceProcessor.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/BacktraceProcessor.java	Thu Mar 18 11:56:59 2010 -0700
@@ -25,13 +25,14 @@
 import org.chromium.sdk.internal.protocol.data.SomeHandle;
 import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException;
 import org.chromium.sdk.internal.tools.v8.DebuggerCommand;
+import org.chromium.sdk.internal.tools.v8.V8CommandProcessor;
 import org.chromium.sdk.internal.tools.v8.V8ProtocolUtil;
 import org.json.simple.JSONObject;
 
 /**
  * Handles the "backtrace" V8 command replies.
  */
-class BacktraceProcessor implements org.chromium.sdk.internal.tools.v8.V8CommandProcessor.V8HandlerCallback {
+class BacktraceProcessor implements V8CommandProcessor.V8HandlerCallback {
 
   private final ContextBuilder.ExpectingBacktraceStep step2;
 
--- a/org.chromium.sdk/src/org/chromium/sdk/internal/transport/Handshaker.java	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/transport/Handshaker.java	Thu Mar 18 11:56:59 2010 -0700
@@ -11,8 +11,8 @@
 import java.util.concurrent.Future;
 import java.util.concurrent.FutureTask;
 
-import org.chromium.sdk.ChromiumIOException;
 import org.chromium.sdk.LineReader;
+import org.chromium.sdk.internal.JavascriptVmImpl;
 import org.chromium.sdk.internal.transport.Message.MalformedMessageException;
 
 /**
@@ -100,7 +100,7 @@
       } catch (InterruptedException e) {
         throw new RuntimeException(e);
       } catch (ExecutionException e) {
-        throw new ChromiumIOException("Failed to perform handshake", e);
+        throw JavascriptVmImpl.newIOException("Failed to perform handshake", e);
       }
 
     }
@@ -111,7 +111,7 @@
         try {
           message = Message.fromBufferedReader(input);
         } catch (MalformedMessageException e) {
-          throw new ChromiumIOException("Unrecognized handshake message from remote", e);
+          throw JavascriptVmImpl.newIOException("Unrecognized handshake message from remote", e);
         }
         if (message == null) {
           throw new IOException("End of stream");
--- a/org.symbian.tools.wrttools.previewer/preview/wrt_preview.html	Thu Mar 18 11:10:35 2010 -0700
+++ b/org.symbian.tools.wrttools.previewer/preview/wrt_preview.html	Thu Mar 18 11:56:59 2010 -0700
@@ -210,7 +210,7 @@
 	</div>
 </div>
 	<div id="InspectorTab" class="hide">
-		<div>To open Google Chrome Developer Tolls you need to:
+		<div>To open Web Inspector you need to:
 			<ol>
 				<li>Disconnect debugger from Chrome browser.</li>
 				<li>Press Ctrl+Shift+I to open inspector.</li>