OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 "use strict"; | 5 "use strict"; |
6 | 6 |
7 // If true, prints all messages sent and received by inspector. | 7 // If true, prints all messages sent and received by inspector. |
8 const printProtocolMessages = false; | 8 const printProtocolMessages = false; |
9 | 9 |
10 // The active wrapper instance. | 10 // The active wrapper instance. |
11 let activeWrapper = undefined; | 11 let activeWrapper = undefined; |
12 | 12 |
13 // Receiver function called by inspector, delegating to active wrapper. | 13 // Receiver function called by inspector, delegating to active wrapper. |
14 function receive(message) { | 14 function receive(message) { |
15 activeWrapper.receiveMessage(message); | 15 activeWrapper.receiveMessage(message); |
16 } | 16 } |
17 | 17 |
18 // TODO(jgruber): Determine which of these are still required and possible. | |
19 // Debug events which can occur in the V8 JavaScript engine. | |
20 const DebugEvent = { Break: 1, | |
21 Exception: 2, | |
22 NewFunction: 3, | |
23 BeforeCompile: 4, | |
24 AfterCompile: 5, | |
25 CompileError: 6, | |
26 AsyncTaskEvent: 7 }; | |
27 | |
28 class DebugWrapper { | 18 class DebugWrapper { |
29 constructor() { | 19 constructor() { |
30 // Message dictionary storing {id, message} pairs. | 20 // Message dictionary storing {id, message} pairs. |
31 this.receivedMessages = {}; | 21 this.receivedMessages = {}; |
32 | 22 |
33 // Each message dispatched by the Debug wrapper is assigned a unique number | 23 // Each message dispatched by the Debug wrapper is assigned a unique number |
34 // using nextMessageId. | 24 // using nextMessageId. |
35 this.nextMessageId = 0; | 25 this.nextMessageId = 0; |
36 | 26 |
37 // The listener method called on certain events. | 27 // The listener method called on certain events. |
38 this.listener = () => undefined; | 28 this.listener = undefined; |
| 29 |
| 30 // TODO(jgruber): Determine which of these are still required and possible. |
| 31 // Debug events which can occur in the V8 JavaScript engine. |
| 32 this.DebugEvent = { Break: 1 |
| 33 , Exception: 2 |
| 34 , NewFunction: 3 |
| 35 , BeforeCompile: 4 |
| 36 , AfterCompile: 5 |
| 37 , CompileError: 6 |
| 38 , AsyncTaskEvent: 7 |
| 39 }; |
39 | 40 |
40 // Register as the active wrapper. | 41 // Register as the active wrapper. |
41 assertTrue(activeWrapper === undefined); | 42 assertTrue(activeWrapper === undefined); |
42 activeWrapper = this; | 43 activeWrapper = this; |
43 } | 44 } |
44 | 45 |
45 enable() { | 46 enable() { this.sendMessageForMethodChecked("Debugger.enable"); } |
46 const {msgid, msg} = this.createMessage("Debugger.enable"); | 47 disable() { this.sendMessageForMethodChecked("Debugger.disable"); } |
| 48 |
| 49 setListener(listener) { this.listener = listener; } |
| 50 |
| 51 stepOver() { this.sendMessageForMethodChecked("Debugger.stepOver"); } |
| 52 stepInto() { this.sendMessageForMethodChecked("Debugger.stepInto"); } |
| 53 stepOut() { this.sendMessageForMethodChecked("Debugger.stepOut"); } |
| 54 |
| 55 // Returns the resulting breakpoint id. |
| 56 setBreakPoint(func, opt_line, opt_column, opt_condition) { |
| 57 assertTrue(%IsFunction(func)); |
| 58 assertFalse(%FunctionIsAPIFunction(func)); |
| 59 |
| 60 // TODO(jgruber): We handle only script breakpoints for now. |
| 61 // TODO(jgruber): Handle conditions. |
| 62 |
| 63 const scriptid = %FunctionGetScriptId(func); |
| 64 assertTrue(scriptid != -1); |
| 65 |
| 66 const offset = %FunctionGetScriptSourcePosition(func); |
| 67 const loc = |
| 68 %ScriptLocationFromLine2(scriptid, opt_line, opt_column, offset); |
| 69 |
| 70 const {msgid, msg} = this.createMessage( |
| 71 "Debugger.setBreakpoint", |
| 72 { location : { scriptId : scriptid.toString() |
| 73 , lineNumber : loc.line |
| 74 , columnNumber : loc.column |
| 75 } |
| 76 }); |
| 77 this.sendMessage(msg); |
| 78 |
| 79 const reply = this.receivedMessages[msgid]; |
| 80 const breakid = reply.result.breakpointId; |
| 81 assertTrue(breakid !== undefined); |
| 82 |
| 83 return breakid; |
| 84 } |
| 85 |
| 86 clearBreakPoint(breakid) { |
| 87 const {msgid, msg} = this.createMessage( |
| 88 "Debugger.removeBreakpoint", { breakpointId : breakid }); |
47 this.sendMessage(msg); | 89 this.sendMessage(msg); |
48 assertTrue(this.receivedMessages[msgid] !== undefined); | 90 assertTrue(this.receivedMessages[msgid] !== undefined); |
49 } | 91 } |
50 | 92 |
51 disable() { | 93 // Returns the serialized result of the given expression. For example: |
52 const {msgid, msg} = this.createMessage("Debugger.disable"); | 94 // {"type":"number", "value":33, "description":"33"}. |
| 95 evaluate(frameid, expression) { |
| 96 const {msgid, msg} = this.createMessage( |
| 97 "Debugger.evaluateOnCallFrame", |
| 98 { callFrameId : frameid |
| 99 , expression : expression |
| 100 }); |
53 this.sendMessage(msg); | 101 this.sendMessage(msg); |
54 assertTrue(this.receivedMessages[msgid] !== undefined); | |
55 } | |
56 | 102 |
57 setListener(listener) { | 103 const reply = this.receivedMessages[msgid]; |
58 this.listener = listener; | 104 return reply.result.result; |
59 } | 105 } |
60 | 106 |
61 // --- Internal methods. ----------------------------------------------------- | 107 // --- Internal methods. ----------------------------------------------------- |
62 | 108 |
63 getNextMessageId() { | 109 getNextMessageId() { |
64 return this.nextMessageId++; | 110 return this.nextMessageId++; |
65 } | 111 } |
66 | 112 |
67 createMessage(method, params) { | 113 createMessage(method, params) { |
68 const id = this.getNextMessageId(); | 114 const id = this.getNextMessageId(); |
(...skipping 14 matching lines...) Expand all Loading... |
83 } | 129 } |
84 | 130 |
85 this.dispatchMessage(parsedMessage); | 131 this.dispatchMessage(parsedMessage); |
86 } | 132 } |
87 | 133 |
88 sendMessage(message) { | 134 sendMessage(message) { |
89 if (printProtocolMessages) print(message); | 135 if (printProtocolMessages) print(message); |
90 send(message); | 136 send(message); |
91 } | 137 } |
92 | 138 |
| 139 sendMessageForMethodChecked(method) { |
| 140 const {msgid, msg} = this.createMessage(method); |
| 141 this.sendMessage(msg); |
| 142 assertTrue(this.receivedMessages[msgid] !== undefined); |
| 143 } |
| 144 |
93 // --- Message handlers. ----------------------------------------------------- | 145 // --- Message handlers. ----------------------------------------------------- |
94 | 146 |
95 dispatchMessage(message) { | 147 dispatchMessage(message) { |
96 const method = message.method; | 148 const method = message.method; |
97 if (method == "Debugger.scriptParsed") { | 149 if (method == "Debugger.paused") { |
| 150 this.handleDebuggerPaused(message); |
| 151 } else if (method == "Debugger.scriptParsed") { |
98 this.handleDebuggerScriptParsed(message); | 152 this.handleDebuggerScriptParsed(message); |
99 } | 153 } |
100 } | 154 } |
101 | 155 |
| 156 handleDebuggerPaused(message) { |
| 157 const params = message.params; |
| 158 |
| 159 // TODO(jgruber): Arguments as needed. |
| 160 let execState = { frames: params.callFrames }; |
| 161 this.invokeListener(this.DebugEvent.Break, execState); |
| 162 } |
| 163 |
102 handleDebuggerScriptParsed(message) { | 164 handleDebuggerScriptParsed(message) { |
103 const params = message.params; | 165 const params = message.params; |
104 let eventData = { scriptId : params.scriptId | 166 let eventData = { scriptId : params.scriptId |
105 , eventType : DebugEvent.AfterCompile | 167 , eventType : this.DebugEvent.AfterCompile |
106 } | 168 } |
107 | 169 |
108 // TODO(jgruber): Arguments as needed. Still completely missing exec_state, | 170 // TODO(jgruber): Arguments as needed. Still completely missing exec_state, |
109 // and eventData used to contain the script mirror instead of its id. | 171 // and eventData used to contain the script mirror instead of its id. |
110 this.listener(DebugEvent.AfterCompile, undefined, eventData, undefined); | 172 this.invokeListener(this.DebugEvent.AfterCompile, undefined, eventData, |
| 173 undefined); |
| 174 } |
| 175 |
| 176 invokeListener(event, exec_state, event_data, data) { |
| 177 if (this.listener) { |
| 178 this.listener(event, exec_state, event_data, data); |
| 179 } |
111 } | 180 } |
112 } | 181 } |
OLD | NEW |