Index: test/debugger/test-api.js |
diff --git a/test/debugger/test-api.js b/test/debugger/test-api.js |
index f9d22afd87cce1e1a60322743a0cac5a1fe9be35..3d9de1f0485e9d8e70d344b0640398660cc7cffa 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. |
@@ -29,15 +29,39 @@ class DebugWrapper { |
// TODO(jgruber): Determine which of these are still required and possible. |
// Debug events which can occur in the V8 JavaScript engine. |
- this.DebugEvent = { Break: 1 |
- , Exception: 2 |
- , NewFunction: 3 |
- , BeforeCompile: 4 |
- , AfterCompile: 5 |
- , CompileError: 6 |
- , AsyncTaskEvent: 7 |
+ this.DebugEvent = { Break: 1, |
+ Exception: 2, |
+ NewFunction: 3, |
+ BeforeCompile: 4, |
+ AfterCompile: 5, |
+ CompileError: 6, |
+ 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; |
@@ -69,14 +93,15 @@ class DebugWrapper { |
const {msgid, msg} = this.createMessage( |
"Debugger.setBreakpoint", |
- { location : { scriptId : scriptid.toString() |
- , lineNumber : loc.line |
- , columnNumber : loc.column |
+ { location : { scriptId : scriptid.toString(), |
+ lineNumber : loc.line, |
+ columnNumber : loc.column |
} |
}); |
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: |
@@ -95,12 +120,12 @@ class DebugWrapper { |
evaluate(frameid, expression) { |
const {msgid, msg} = this.createMessage( |
"Debugger.evaluateOnCallFrame", |
- { callFrameId : frameid |
- , expression : expression |
+ { callFrameId : frameid, |
+ expression : expression |
}); |
this.sendMessage(msg); |
- const reply = this.receivedMessages[msgid]; |
+ const reply = this.takeReplyChecked(msgid); |
return reply.result.result; |
} |
@@ -117,7 +142,7 @@ class DebugWrapper { |
method: method, |
params: params, |
}); |
- return {msgid: id, msg: msg}; |
+ return { msgid : id, msg: msg }; |
} |
receiveMessage(message) { |
@@ -125,7 +150,7 @@ class DebugWrapper { |
const parsedMessage = JSON.parse(message); |
if (parsedMessage.id !== undefined) { |
- this.receivedMessages[parsedMessage.id] = parsedMessage; |
+ this.receivedMessages.set(parsedMessage.id, parsedMessage); |
} |
this.dispatchMessage(parsedMessage); |
@@ -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.get(msgid); |
+ assertTrue(reply !== undefined); |
+ this.receivedMessages.delete(msgid); |
+ 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 |
+ }; |
+ } |
+ |
+ 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,15 +218,25 @@ 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 |
+ }; |
+ let eventData = this.execStateFrame(params.callFrames[0]); |
+ this.invokeListener(this.DebugEvent.Break, execState, eventData); |
} |
handleDebuggerScriptParsed(message) { |
const params = message.params; |
- let eventData = { scriptId : params.scriptId |
- , eventType : this.DebugEvent.AfterCompile |
+ let eventData = { scriptId : params.scriptId, |
+ eventType : this.DebugEvent.AfterCompile |
} |
// TODO(jgruber): Arguments as needed. Still completely missing exec_state, |
@@ -179,3 +251,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; |
+}}); |