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; |
+}}); |