|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style license that can be |
|
3 // found in the LICENSE file. |
|
4 |
|
5 package org.chromium.sdk.internal.tools.v8.processor; |
|
6 |
|
7 import java.util.ArrayList; |
|
8 import java.util.Collection; |
|
9 import java.util.Collections; |
|
10 import java.util.List; |
|
11 |
|
12 import org.chromium.sdk.Breakpoint; |
|
13 import org.chromium.sdk.ExceptionData; |
|
14 import org.chromium.sdk.internal.ContextBuilder; |
|
15 import org.chromium.sdk.internal.DebugSession; |
|
16 import org.chromium.sdk.internal.ExceptionDataImpl; |
|
17 import org.chromium.sdk.internal.InternalContext; |
|
18 import org.chromium.sdk.internal.InternalContext.ContextDismissedCheckedException; |
|
19 import org.chromium.sdk.internal.protocol.BreakEventBody; |
|
20 import org.chromium.sdk.internal.protocol.EventNotification; |
|
21 import org.chromium.sdk.internal.protocol.data.SomeHandle; |
|
22 import org.chromium.sdk.internal.protocol.data.ValueHandle; |
|
23 import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException; |
|
24 import org.chromium.sdk.internal.tools.v8.BreakpointManager; |
|
25 import org.chromium.sdk.internal.tools.v8.V8Helper; |
|
26 import org.chromium.sdk.internal.tools.v8.V8Protocol; |
|
27 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessage; |
|
28 import org.chromium.sdk.internal.tools.v8.request.DebuggerMessageFactory; |
|
29 |
|
30 /** |
|
31 * Handles the suspension-related V8 command replies and events. |
|
32 */ |
|
33 public class BreakpointProcessor extends V8EventProcessor { |
|
34 |
|
35 /** The name of the "exception" object to report as a variable name. */ |
|
36 private static final String EXCEPTION_NAME = "exception"; |
|
37 |
|
38 public BreakpointProcessor(DebugSession debugSession) { |
|
39 super(debugSession); |
|
40 } |
|
41 |
|
42 @Override |
|
43 public void messageReceived(EventNotification eventMessage) { |
|
44 final boolean isEvent = true; |
|
45 if (isEvent) { |
|
46 String event = eventMessage.getEvent(); |
|
47 DebugSession debugSession = getDebugSession(); |
|
48 |
|
49 ContextBuilder contextBuilder = debugSession.getContextBuilder(); |
|
50 |
|
51 ContextBuilder.ExpectingBreakEventStep step1 = contextBuilder.buildNewContext(); |
|
52 |
|
53 InternalContext internalContext = step1.getInternalContext(); |
|
54 |
|
55 BreakEventBody breakEventBody; |
|
56 try { |
|
57 breakEventBody = eventMessage.getBody().asBreakEventBody(); |
|
58 } catch (JsonProtocolParseException e) { |
|
59 throw new RuntimeException(e); |
|
60 } |
|
61 |
|
62 ContextBuilder.ExpectingBacktraceStep step2; |
|
63 if (V8Protocol.EVENT_BREAK.key.equals(event)) { |
|
64 Collection<Breakpoint> breakpointsHit = getBreakpointsHit(eventMessage, breakEventBody); |
|
65 step2 = step1.setContextState(breakpointsHit, null); |
|
66 } else if (V8Protocol.EVENT_EXCEPTION.key.equals(event)) { |
|
67 ExceptionData exception = createException(eventMessage, breakEventBody, |
|
68 internalContext); |
|
69 step2 = step1.setContextState(Collections.<Breakpoint> emptySet(), exception); |
|
70 } else { |
|
71 contextBuilder.buildSequenceFailure(); |
|
72 throw new RuntimeException(); |
|
73 } |
|
74 |
|
75 processNextStep(step2); |
|
76 } |
|
77 } |
|
78 |
|
79 public void processNextStep(ContextBuilder.ExpectingBacktraceStep step2) { |
|
80 BacktraceProcessor backtraceProcessor = new BacktraceProcessor(step2); |
|
81 InternalContext internalContext = step2.getInternalContext(); |
|
82 |
|
83 DebuggerMessage message = DebuggerMessageFactory.backtrace(null, null, true); |
|
84 try { |
|
85 // Command is not immediate because we are supposed to be suspended. |
|
86 internalContext.sendV8CommandAsync(message, false, backtraceProcessor, null); |
|
87 } catch (ContextDismissedCheckedException e) { |
|
88 // Can't happen -- we are just creating context, it couldn't have become invalid |
|
89 throw new RuntimeException(e); |
|
90 } |
|
91 } |
|
92 |
|
93 private Collection<Breakpoint> getBreakpointsHit(EventNotification response, |
|
94 BreakEventBody breakEventBody) { |
|
95 List<Long> breakpointIdsArray = breakEventBody.getBreakpoints(); |
|
96 BreakpointManager breakpointManager = getDebugSession().getBreakpointManager(); |
|
97 if (breakpointIdsArray == null) { |
|
98 // Suspended on step end. |
|
99 return Collections.<Breakpoint> emptySet(); |
|
100 } |
|
101 Collection<Breakpoint> breakpointsHit = new ArrayList<Breakpoint>(breakpointIdsArray.size()); |
|
102 for (int i = 0, size = breakpointIdsArray.size(); i < size; ++i) { |
|
103 Breakpoint existingBp = breakpointManager.getBreakpoint(breakpointIdsArray.get(i)); |
|
104 if (existingBp != null) { |
|
105 breakpointsHit.add(existingBp); |
|
106 } |
|
107 } |
|
108 return breakpointsHit; |
|
109 } |
|
110 |
|
111 private ExceptionData createException(EventNotification response, BreakEventBody body, |
|
112 InternalContext internalContext) { |
|
113 List<SomeHandle> refs = response.getRefs(); |
|
114 ValueHandle exception = body.getException(); |
|
115 List<SomeHandle> handles = new ArrayList<SomeHandle>(refs.size() + 1); |
|
116 handles.addAll(refs); |
|
117 handles.add(exception.getSuper()); |
|
118 internalContext.getHandleManager().putAll(handles); |
|
119 |
|
120 // source column is not exposed ("sourceColumn" in "body") |
|
121 String sourceText = body.getSourceLineText(); |
|
122 |
|
123 return new ExceptionDataImpl(internalContext, |
|
124 V8Helper.createMirrorFromLookup(exception).getValueMirror(), |
|
125 EXCEPTION_NAME, |
|
126 body.isUncaught(), |
|
127 sourceText, |
|
128 exception.text()); |
|
129 } |
|
130 |
|
131 } |