org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/BacktraceProcessor.java
changeset 2 e4420d2515f1
child 52 f577ea64429e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/tools/v8/processor/BacktraceProcessor.java	Wed Dec 23 17:13:18 2009 -0800
@@ -0,0 +1,148 @@
+// 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.processor;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.chromium.sdk.DebugContext;
+import org.chromium.sdk.JavascriptVm;
+import org.chromium.sdk.Script;
+import org.chromium.sdk.internal.ContextBuilder;
+import org.chromium.sdk.internal.DebugSession;
+import org.chromium.sdk.internal.FrameMirror;
+import org.chromium.sdk.internal.HandleManager;
+import org.chromium.sdk.internal.protocol.BacktraceCommandBody;
+import org.chromium.sdk.internal.protocol.CommandResponse;
+import org.chromium.sdk.internal.protocol.FrameObject;
+import org.chromium.sdk.internal.protocol.SuccessCommandResponse;
+import org.chromium.sdk.internal.protocol.data.ScriptHandle;
+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.V8ProtocolUtil;
+import org.json.simple.JSONObject;
+
+/**
+ * Handles the "backtrace" V8 command replies.
+ */
+class BacktraceProcessor implements org.chromium.sdk.internal.tools.v8.V8CommandProcessor.V8HandlerCallback {
+
+  private final ContextBuilder.ExpectingBacktraceStep step2;
+
+  BacktraceProcessor(ContextBuilder.ExpectingBacktraceStep step2) {
+    this.step2 = step2;
+ }
+
+  public void messageReceived(CommandResponse response) {
+    String commandString = response.getCommand();
+
+    DebuggerCommand command = DebuggerCommand.forString(commandString);
+    if (command != DebuggerCommand.BACKTRACE) {
+      handleWrongStacktrace();
+    }
+    SuccessCommandResponse successResponse = response.asSuccess();
+    if (successResponse == null) {
+      handleWrongStacktrace();
+    }
+
+    final DebugContext debugContext = setFrames(successResponse);
+    final DebugSession debugSession = step2.getInternalContext().getDebugSession();
+
+    JavascriptVm.ScriptsCallback afterScriptsAreLoaded = new JavascriptVm.ScriptsCallback() {
+      public void failure(String errorMessage) {
+        handleWrongStacktrace();
+      }
+
+      public void success(Collection<Script> scripts) {
+        debugSession.getDebugEventListener().suspended(debugContext);
+      }
+    };
+
+    debugSession.getScriptLoader().loadAllScripts(afterScriptsAreLoaded, null);
+  }
+
+  private DebugContext setFrames(SuccessCommandResponse response) {
+    BacktraceCommandBody body;
+    try {
+      body = response.getBody().asBacktraceCommandBody();
+    } catch (JsonProtocolParseException e) {
+      throw new RuntimeException(e);
+    }
+    List<FrameObject> jsonFrames = body.getFrames();
+    int frameCnt = jsonFrames.size();
+    FrameMirror[] frameMirrors = new FrameMirror[frameCnt];
+
+    HandleManager handleManager = step2.getInternalContext().getHandleManager();
+
+    List<SomeHandle> refs = response.getRefs();
+    handleManager.putAll(refs);
+    for (int frameIdx = 0; frameIdx < frameCnt; frameIdx++) {
+      FrameObject frameObject = jsonFrames.get(frameIdx);
+      int index = (int) frameObject.getIndex();
+      FrameObject frame = jsonFrames.get(frameIdx);
+      JSONObject func = frame.getFunc();
+
+      String text = frame.getText().replace('\r', ' ').replace('\n', ' ');
+      Matcher m = FRAME_TEXT_PATTERN.matcher(text);
+      m.matches();
+      String url = m.group(1);
+
+      int currentLine = (int) frame.getLine();
+
+      // If we stopped because of the debuggerword then we're on the next
+      // line.
+      // TODO(apavlov): Terry says: we need to use the [e.g. Rhino] AST to
+      // decide if line is debuggerword. If so, find the next sequential line.
+      // The below works for simple scripts but doesn't take into account
+      // comments, etc.
+      String srcLine = frame.getSourceLineText();
+      if (srcLine.trim().startsWith(DEBUGGER_RESERVED)) {
+        currentLine++;
+      }
+      Long scriptRef = V8ProtocolUtil.getObjectRef(frame.getScript());
+
+      Long scriptId = -1L;
+      if (scriptRef != null) {
+        SomeHandle handle = handleManager.getHandle(scriptRef);
+        ScriptHandle scriptHandle;
+        try {
+          scriptHandle = handle.asScriptHandle();
+        } catch (JsonProtocolParseException e) {
+          throw new RuntimeException(e);
+        }
+        if (handle != null) {
+          scriptId = scriptHandle.id();
+        }
+      }
+      frameMirrors[index] =
+          new FrameMirror(frameObject, url, currentLine, scriptId,
+              V8ProtocolUtil.getFunctionName(func));
+    }
+
+
+    return step2.setFrames(frameMirrors);
+  }
+
+  public void failure(String message) {
+    handleWrongStacktrace();
+  }
+
+  private void handleWrongStacktrace() {
+    step2.getInternalContext().getContextBuilder().buildSequenceFailure();
+  }
+
+  private static final String DEBUGGER_RESERVED = "debugger";
+
+  /** Regex for the "text" field of the "backtrace" element response. */
+  private static final String FRAME_TEXT_REGEX =
+      "^(?:.+) ([^\\s]+) line (.+) column (.+)" + " (?:\\(position (.+)\\))?";
+
+  /** A pattern for the frame "text" regex. */
+  private static final Pattern FRAME_TEXT_PATTERN = Pattern.compile(FRAME_TEXT_REGEX);
+
+}