Chromium Code Reviews| Index: test/debugger/test-api.js |
| diff --git a/test/debugger/test-api.js b/test/debugger/test-api.js |
| index f9d22afd87cce1e1a60322743a0cac5a1fe9be35..e5d0316e1e848ada9e69be35f2970bc65a5c8296 100644 |
| --- a/test/debugger/test-api.js |
| +++ b/test/debugger/test-api.js |
| @@ -18,7 +18,7 @@ function receive(message) { |
| class DebugWrapper { |
| constructor() { |
| // Message dictionary storing {id, message} pairs. |
| - this.receivedMessages = {}; |
| + this.receivedMessages = new Map(); |
| // Each message dispatched by the Debug wrapper is assigned a unique number |
| // using nextMessageId. |
| @@ -38,6 +38,30 @@ class DebugWrapper { |
| , AsyncTaskEvent: 7 |
| }; |
| + // The different types of steps. |
| + this.StepAction = { StepOut: 0 |
| + , StepNext: 1 |
| + , StepIn: 2 |
| + , StepFrame: 3 |
| + }; |
| + |
| + // A copy of the scope types from runtime-debug.cc. |
| + // NOTE: these constants should be backward-compatible, so |
| + // add new ones to the end of this list. |
| + this.ScopeType = { Global: 0 |
| + , Local: 1 |
| + , With: 2 |
| + , Closure: 3 |
| + , Catch: 4 |
| + , Block: 5 |
| + , Script: 6 |
| + , Eval: 7 |
| + , Module: 8 |
| + }; |
| + |
| + // Store the current script id so we can skip corresponding break events. |
| + this.thisScriptId = %FunctionGetScriptId(receive); |
| + |
| // Register as the active wrapper. |
| assertTrue(activeWrapper === undefined); |
| activeWrapper = this; |
| @@ -76,7 +100,8 @@ class DebugWrapper { |
| }); |
| this.sendMessage(msg); |
| - const reply = this.receivedMessages[msgid]; |
| + const reply = this.takeReplyChecked(msgid); |
| + assertTrue(reply.result !== undefined); |
| const breakid = reply.result.breakpointId; |
| assertTrue(breakid !== undefined); |
| @@ -87,7 +112,7 @@ class DebugWrapper { |
| const {msgid, msg} = this.createMessage( |
| "Debugger.removeBreakpoint", { breakpointId : breakid }); |
| this.sendMessage(msg); |
| - assertTrue(this.receivedMessages[msgid] !== undefined); |
| + this.takeReplyChecked(msgid); |
| } |
| // Returns the serialized result of the given expression. For example: |
| @@ -100,7 +125,7 @@ class DebugWrapper { |
| }); |
| this.sendMessage(msg); |
| - const reply = this.receivedMessages[msgid]; |
| + const reply = this.takeReplyChecked(msgid); |
| return reply.result.result; |
| } |
| @@ -139,7 +164,44 @@ class DebugWrapper { |
| sendMessageForMethodChecked(method) { |
| const {msgid, msg} = this.createMessage(method); |
| this.sendMessage(msg); |
| - assertTrue(this.receivedMessages[msgid] !== undefined); |
| + this.takeReplyChecked(msgid); |
| + } |
| + |
| + takeReplyChecked(msgid) { |
| + const reply = this.receivedMessages[msgid]; |
| + assertTrue(reply !== undefined); |
| + delete this.receivedMessages[msgid]; |
|
Yang
2016/11/02 10:36:04
I don't think this is how to use a Map. You would
jgruber
2016/11/07 11:35:11
Done.
|
| + return reply; |
| + } |
| + |
| + execStatePrepareStep(action) { |
| + switch(action) { |
| + case this.StepAction.StepOut: this.stepOut(); break; |
| + case this.StepAction.StepNext: this.stepOver(); break; |
| + case this.StepAction.StepIn: this.stepInto(); break; |
| + default: %AbortJS("Unsupported StepAction"); break; |
| + } |
| + } |
| + |
| + execStateScope(scope) { |
| + // TODO(jgruber): Mapping |
| + return { scopeType: () => scope.type |
| + , scopeObject: () => scope.object |
|
Yang
2016/11/02 10:36:04
Can we have the comma on the previous line? Elsewh
jgruber
2016/11/07 11:35:11
Dang, thought I could sneak some nice haskell-styl
|
| + }; |
| + } |
| + |
| + execStateFrame(frame) { |
| + const scriptid = parseInt(frame.location.scriptId); |
| + const line = frame.location.lineNumber; |
| + const column = frame.location.columnNumber; |
| + const loc = %ScriptLocationFromLine2(scriptid, line, column, 0); |
| + const func = { name : () => frame.functionName }; |
| + return { sourceLineText : () => loc.sourceText |
| + , functionName : () => frame.functionName |
| + , func : () => func |
| + , scopeCount : () => frame.scopeChain.length |
| + , scope : (index) => this.execStateScope(frame.scopeChain[index]) |
| + }; |
| } |
| // --- Message handlers. ----------------------------------------------------- |
| @@ -156,9 +218,17 @@ class DebugWrapper { |
| handleDebuggerPaused(message) { |
| const params = message.params; |
| + // Skip break events in this file. |
| + if (params.callFrames[0].location.scriptId == this.thisScriptId) return; |
| + |
| // TODO(jgruber): Arguments as needed. |
| - let execState = { frames: params.callFrames }; |
| - this.invokeListener(this.DebugEvent.Break, execState); |
| + let execState = { frames : params.callFrames |
| + , prepareStep : this.execStatePrepareStep.bind(this) |
| + , frame : (index) => this.execStateFrame(index ? params.callFrames[index] : params.callFrames[0]) |
| + , frameCount : () => params.callFrames.length |
|
Yang
2016/11/02 10:36:04
80-char limit.
jgruber
2016/11/07 11:35:11
Done.
|
| + }; |
| + let eventData = this.execStateFrame(params.callFrames[0]); |
| + this.invokeListener(this.DebugEvent.Break, execState, eventData); |
| } |
| handleDebuggerScriptParsed(message) { |
| @@ -179,3 +249,13 @@ class DebugWrapper { |
| } |
| } |
| } |
| + |
| +// Simulate the debug object generated by --expose-debug-as debug. |
| +var debug = { instance : undefined }; |
| +Object.defineProperty(debug, 'Debug', { get: function() { |
| + if (!debug.instance) { |
| + debug.instance = new DebugWrapper(); |
| + debug.instance.enable(); |
| + } |
| + return debug.instance; |
| +}}); |