Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Side by Side Diff: test/debugger/test-api.js

Issue 2466273005: [debugger] Further stepping support in test wrapper (Closed)
Patch Set: Move more tests Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/debugger/debugger/debug-step-4.js ('k') | test/mjsunit/debug-break-inline.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 class DebugWrapper { 18 class DebugWrapper {
19 constructor() { 19 constructor() {
20 // Message dictionary storing {id, message} pairs. 20 // Message dictionary storing {id, message} pairs.
21 this.receivedMessages = {}; 21 this.receivedMessages = new Map();
22 22
23 // 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
24 // using nextMessageId. 24 // using nextMessageId.
25 this.nextMessageId = 0; 25 this.nextMessageId = 0;
26 26
27 // The listener method called on certain events. 27 // The listener method called on certain events.
28 this.listener = undefined; 28 this.listener = undefined;
29 29
30 // TODO(jgruber): Determine which of these are still required and possible. 30 // TODO(jgruber): Determine which of these are still required and possible.
31 // Debug events which can occur in the V8 JavaScript engine. 31 // Debug events which can occur in the V8 JavaScript engine.
32 this.DebugEvent = { Break: 1 32 this.DebugEvent = { Break: 1,
33 , Exception: 2 33 Exception: 2,
34 , NewFunction: 3 34 NewFunction: 3,
35 , BeforeCompile: 4 35 BeforeCompile: 4,
36 , AfterCompile: 5 36 AfterCompile: 5,
37 , CompileError: 6 37 CompileError: 6,
38 , AsyncTaskEvent: 7 38 AsyncTaskEvent: 7
39 }; 39 };
40 40
41 // The different types of steps.
42 this.StepAction = { StepOut: 0,
43 StepNext: 1,
44 StepIn: 2,
45 StepFrame: 3,
46 };
47
48 // A copy of the scope types from runtime-debug.cc.
49 // NOTE: these constants should be backward-compatible, so
50 // add new ones to the end of this list.
51 this.ScopeType = { Global: 0,
52 Local: 1,
53 With: 2,
54 Closure: 3,
55 Catch: 4,
56 Block: 5,
57 Script: 6,
58 Eval: 7,
59 Module: 8
60 };
61
62 // Store the current script id so we can skip corresponding break events.
63 this.thisScriptId = %FunctionGetScriptId(receive);
64
41 // Register as the active wrapper. 65 // Register as the active wrapper.
42 assertTrue(activeWrapper === undefined); 66 assertTrue(activeWrapper === undefined);
43 activeWrapper = this; 67 activeWrapper = this;
44 } 68 }
45 69
46 enable() { this.sendMessageForMethodChecked("Debugger.enable"); } 70 enable() { this.sendMessageForMethodChecked("Debugger.enable"); }
47 disable() { this.sendMessageForMethodChecked("Debugger.disable"); } 71 disable() { this.sendMessageForMethodChecked("Debugger.disable"); }
48 72
49 setListener(listener) { this.listener = listener; } 73 setListener(listener) { this.listener = listener; }
50 74
(...skipping 11 matching lines...) Expand all
62 86
63 const scriptid = %FunctionGetScriptId(func); 87 const scriptid = %FunctionGetScriptId(func);
64 assertTrue(scriptid != -1); 88 assertTrue(scriptid != -1);
65 89
66 const offset = %FunctionGetScriptSourcePosition(func); 90 const offset = %FunctionGetScriptSourcePosition(func);
67 const loc = 91 const loc =
68 %ScriptLocationFromLine2(scriptid, opt_line, opt_column, offset); 92 %ScriptLocationFromLine2(scriptid, opt_line, opt_column, offset);
69 93
70 const {msgid, msg} = this.createMessage( 94 const {msgid, msg} = this.createMessage(
71 "Debugger.setBreakpoint", 95 "Debugger.setBreakpoint",
72 { location : { scriptId : scriptid.toString() 96 { location : { scriptId : scriptid.toString(),
73 , lineNumber : loc.line 97 lineNumber : loc.line,
74 , columnNumber : loc.column 98 columnNumber : loc.column
75 } 99 }
76 }); 100 });
77 this.sendMessage(msg); 101 this.sendMessage(msg);
78 102
79 const reply = this.receivedMessages[msgid]; 103 const reply = this.takeReplyChecked(msgid);
104 assertTrue(reply.result !== undefined);
80 const breakid = reply.result.breakpointId; 105 const breakid = reply.result.breakpointId;
81 assertTrue(breakid !== undefined); 106 assertTrue(breakid !== undefined);
82 107
83 return breakid; 108 return breakid;
84 } 109 }
85 110
86 clearBreakPoint(breakid) { 111 clearBreakPoint(breakid) {
87 const {msgid, msg} = this.createMessage( 112 const {msgid, msg} = this.createMessage(
88 "Debugger.removeBreakpoint", { breakpointId : breakid }); 113 "Debugger.removeBreakpoint", { breakpointId : breakid });
89 this.sendMessage(msg); 114 this.sendMessage(msg);
90 assertTrue(this.receivedMessages[msgid] !== undefined); 115 this.takeReplyChecked(msgid);
91 } 116 }
92 117
93 // Returns the serialized result of the given expression. For example: 118 // Returns the serialized result of the given expression. For example:
94 // {"type":"number", "value":33, "description":"33"}. 119 // {"type":"number", "value":33, "description":"33"}.
95 evaluate(frameid, expression) { 120 evaluate(frameid, expression) {
96 const {msgid, msg} = this.createMessage( 121 const {msgid, msg} = this.createMessage(
97 "Debugger.evaluateOnCallFrame", 122 "Debugger.evaluateOnCallFrame",
98 { callFrameId : frameid 123 { callFrameId : frameid,
99 , expression : expression 124 expression : expression
100 }); 125 });
101 this.sendMessage(msg); 126 this.sendMessage(msg);
102 127
103 const reply = this.receivedMessages[msgid]; 128 const reply = this.takeReplyChecked(msgid);
104 return reply.result.result; 129 return reply.result.result;
105 } 130 }
106 131
107 // --- Internal methods. ----------------------------------------------------- 132 // --- Internal methods. -----------------------------------------------------
108 133
109 getNextMessageId() { 134 getNextMessageId() {
110 return this.nextMessageId++; 135 return this.nextMessageId++;
111 } 136 }
112 137
113 createMessage(method, params) { 138 createMessage(method, params) {
114 const id = this.getNextMessageId(); 139 const id = this.getNextMessageId();
115 const msg = JSON.stringify({ 140 const msg = JSON.stringify({
116 id: id, 141 id: id,
117 method: method, 142 method: method,
118 params: params, 143 params: params,
119 }); 144 });
120 return {msgid: id, msg: msg}; 145 return { msgid : id, msg: msg };
121 } 146 }
122 147
123 receiveMessage(message) { 148 receiveMessage(message) {
124 if (printProtocolMessages) print(message); 149 if (printProtocolMessages) print(message);
125 150
126 const parsedMessage = JSON.parse(message); 151 const parsedMessage = JSON.parse(message);
127 if (parsedMessage.id !== undefined) { 152 if (parsedMessage.id !== undefined) {
128 this.receivedMessages[parsedMessage.id] = parsedMessage; 153 this.receivedMessages.set(parsedMessage.id, parsedMessage);
129 } 154 }
130 155
131 this.dispatchMessage(parsedMessage); 156 this.dispatchMessage(parsedMessage);
132 } 157 }
133 158
134 sendMessage(message) { 159 sendMessage(message) {
135 if (printProtocolMessages) print(message); 160 if (printProtocolMessages) print(message);
136 send(message); 161 send(message);
137 } 162 }
138 163
139 sendMessageForMethodChecked(method) { 164 sendMessageForMethodChecked(method) {
140 const {msgid, msg} = this.createMessage(method); 165 const {msgid, msg} = this.createMessage(method);
141 this.sendMessage(msg); 166 this.sendMessage(msg);
142 assertTrue(this.receivedMessages[msgid] !== undefined); 167 this.takeReplyChecked(msgid);
168 }
169
170 takeReplyChecked(msgid) {
171 const reply = this.receivedMessages.get(msgid);
172 assertTrue(reply !== undefined);
173 this.receivedMessages.delete(msgid);
174 return reply;
175 }
176
177 execStatePrepareStep(action) {
178 switch(action) {
179 case this.StepAction.StepOut: this.stepOut(); break;
180 case this.StepAction.StepNext: this.stepOver(); break;
181 case this.StepAction.StepIn: this.stepInto(); break;
182 default: %AbortJS("Unsupported StepAction"); break;
183 }
184 }
185
186 execStateScope(scope) {
187 // TODO(jgruber): Mapping
188 return { scopeType: () => scope.type,
189 scopeObject: () => scope.object
190 };
191 }
192
193 execStateFrame(frame) {
194 const scriptid = parseInt(frame.location.scriptId);
195 const line = frame.location.lineNumber;
196 const column = frame.location.columnNumber;
197 const loc = %ScriptLocationFromLine2(scriptid, line, column, 0);
198 const func = { name : () => frame.functionName };
199 return { sourceLineText : () => loc.sourceText,
200 functionName : () => frame.functionName,
201 func : () => func,
202 scopeCount : () => frame.scopeChain.length,
203 scope : (index) => this.execStateScope(frame.scopeChain[index])
204 };
143 } 205 }
144 206
145 // --- Message handlers. ----------------------------------------------------- 207 // --- Message handlers. -----------------------------------------------------
146 208
147 dispatchMessage(message) { 209 dispatchMessage(message) {
148 const method = message.method; 210 const method = message.method;
149 if (method == "Debugger.paused") { 211 if (method == "Debugger.paused") {
150 this.handleDebuggerPaused(message); 212 this.handleDebuggerPaused(message);
151 } else if (method == "Debugger.scriptParsed") { 213 } else if (method == "Debugger.scriptParsed") {
152 this.handleDebuggerScriptParsed(message); 214 this.handleDebuggerScriptParsed(message);
153 } 215 }
154 } 216 }
155 217
156 handleDebuggerPaused(message) { 218 handleDebuggerPaused(message) {
157 const params = message.params; 219 const params = message.params;
158 220
221 // Skip break events in this file.
222 if (params.callFrames[0].location.scriptId == this.thisScriptId) return;
223
159 // TODO(jgruber): Arguments as needed. 224 // TODO(jgruber): Arguments as needed.
160 let execState = { frames: params.callFrames }; 225 let execState = { frames : params.callFrames,
161 this.invokeListener(this.DebugEvent.Break, execState); 226 prepareStep : this.execStatePrepareStep.bind(this),
227 frame : (index) => this.execStateFrame(
228 index ? params.callFrames[index]
229 : params.callFrames[0]),
230 frameCount : () => params.callFrames.length
231 };
232 let eventData = this.execStateFrame(params.callFrames[0]);
233 this.invokeListener(this.DebugEvent.Break, execState, eventData);
162 } 234 }
163 235
164 handleDebuggerScriptParsed(message) { 236 handleDebuggerScriptParsed(message) {
165 const params = message.params; 237 const params = message.params;
166 let eventData = { scriptId : params.scriptId 238 let eventData = { scriptId : params.scriptId,
167 , eventType : this.DebugEvent.AfterCompile 239 eventType : this.DebugEvent.AfterCompile
168 } 240 }
169 241
170 // TODO(jgruber): Arguments as needed. Still completely missing exec_state, 242 // TODO(jgruber): Arguments as needed. Still completely missing exec_state,
171 // and eventData used to contain the script mirror instead of its id. 243 // and eventData used to contain the script mirror instead of its id.
172 this.invokeListener(this.DebugEvent.AfterCompile, undefined, eventData, 244 this.invokeListener(this.DebugEvent.AfterCompile, undefined, eventData,
173 undefined); 245 undefined);
174 } 246 }
175 247
176 invokeListener(event, exec_state, event_data, data) { 248 invokeListener(event, exec_state, event_data, data) {
177 if (this.listener) { 249 if (this.listener) {
178 this.listener(event, exec_state, event_data, data); 250 this.listener(event, exec_state, event_data, data);
179 } 251 }
180 } 252 }
181 } 253 }
254
255 // Simulate the debug object generated by --expose-debug-as debug.
256 var debug = { instance : undefined };
257 Object.defineProperty(debug, 'Debug', { get: function() {
258 if (!debug.instance) {
259 debug.instance = new DebugWrapper();
260 debug.instance.enable();
261 }
262 return debug.instance;
263 }});
OLDNEW
« no previous file with comments | « test/debugger/debugger/debug-step-4.js ('k') | test/mjsunit/debug-break-inline.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698