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