kopia lustrzana https://github.com/c9/core
797 wiersze
31 KiB
JavaScript
797 wiersze
31 KiB
JavaScript
/**
|
|
* This file is part of IKPdb Cloud9 debugger plugin.
|
|
* Copyright (c) 2016 by Cyril MORISSE, Audaxis
|
|
* Licence MIT. See LICENCE at repository root
|
|
*/
|
|
|
|
define(function(require, exports, module) {
|
|
main.consumes = [
|
|
"Plugin", "c9", "util", "debugger", "dialog.error",
|
|
"notification.bubble"
|
|
];
|
|
main.provides = ["ikpdb"];
|
|
return main;
|
|
|
|
function main(options, imports, register) {
|
|
/****( IDE connection )*****/
|
|
var Plugin = imports.Plugin;
|
|
var util = imports.util;
|
|
|
|
var debug = imports["debugger"];
|
|
var showError = imports["dialog.error"].show;
|
|
var bubble = imports["notification.bubble"];
|
|
|
|
var panels = imports.panels;
|
|
var settings = imports.settings;
|
|
|
|
var Frame = debug.Frame;
|
|
var Source = debug.Source;
|
|
var Breakpoint = debug.Breakpoint;
|
|
var Variable = debug.Variable;
|
|
var Scope = debug.Scope;
|
|
|
|
/***** Other dependencies *****/
|
|
var IKPdbService = require("./lib/IKPdbService");
|
|
|
|
|
|
/***** Initialization *****/
|
|
var TYPE = "pythondebug";
|
|
var PROXY = require("text!./netproxy.js");
|
|
|
|
var plugin = new Plugin("Cyril Morisse,Audaxis", main.consumes);
|
|
var emit = plugin.getEmitter();
|
|
// TODO: emit.setMaxListeners(1000);
|
|
|
|
/**
|
|
* State variables
|
|
*/
|
|
var attached = false,
|
|
state = null,
|
|
stack = null,
|
|
ikpdbs = null;
|
|
|
|
var debugger_socket = null;
|
|
var SCOPES = ["Parameters", "Locals"];
|
|
|
|
/***** Lifecycle *****/
|
|
plugin.on("load", function() {
|
|
debug.registerDebugger(TYPE, plugin);
|
|
});
|
|
plugin.on("unload", function() {
|
|
debug.unregisterDebugger(TYPE, plugin);
|
|
attached = false;
|
|
stack = null;
|
|
ikpdbs = null;
|
|
state = null;
|
|
debugger_socket = null;
|
|
});
|
|
|
|
|
|
/*****(Event handlers and Methods )*****/
|
|
|
|
function sendCommand(command, args, callback) {
|
|
ikpdbs.sendCommand(command, args, function(err, reply) {
|
|
/*****
|
|
* Process the messages IKPdb could send
|
|
* Note that error messages ar only displayed if IKPdb returned
|
|
* an error.
|
|
*/
|
|
if (reply) {
|
|
// Display info and warning messages
|
|
reply.info_messages.forEach(function (iMessage) {
|
|
console.log(iMessage);
|
|
});
|
|
reply.warning_messages.forEach(function (wMessage) {
|
|
bubble.popup(wMessage, false);
|
|
});
|
|
}
|
|
|
|
if (err) {
|
|
// Display errors
|
|
var errMessage;
|
|
if (reply) {
|
|
errMessage = reply.error_messages.join(" ");
|
|
showError(errMessage, 10000);
|
|
}
|
|
return callback && callback(err);
|
|
}
|
|
|
|
if (reply.result.executionStatus)
|
|
setState(reply.result.executionStatus);
|
|
|
|
callback && callback(err, reply);
|
|
});
|
|
}
|
|
|
|
/* Called by Cloud9 when user start execution */
|
|
function runScript(callback) {
|
|
sendCommand("runScript", {}, callback);
|
|
}
|
|
/* Called by Cloud9 when user clic on the Step over / F10 button */
|
|
function stepOver(callback) {
|
|
sendCommand("stepOver", {}, callback);
|
|
}
|
|
/* Called by Cloud9 when user clic on the Step over / F10 button */
|
|
function stepInto(callback) {
|
|
sendCommand("stepInto", {}, callback);
|
|
}
|
|
/* Called by Cloud9 when user clic on the Step over / F10 button */
|
|
function stepOut(callback) {
|
|
sendCommand("stepOut", {}, callback);
|
|
}
|
|
|
|
/* Called by Cloud9 when user clic on the Resume / F8 button */
|
|
function resume(callback) {
|
|
sendCommand("resume", {}, callback);
|
|
}
|
|
|
|
/* Called by Cloud9 when user clic on Suspend */
|
|
function suspend(callback) {
|
|
sendCommand("suspend", {}, callback);
|
|
}
|
|
|
|
/**
|
|
* Build individual variable objects from IKPdb output
|
|
*/
|
|
function buildVariable(variable, scope) {
|
|
if (variable == null) return;
|
|
|
|
return new Variable({
|
|
// ref: (variable.objname) ? variable.objname : variable.name,
|
|
ref: variable.id,
|
|
// name: (variable.exp) ? variable.exp : variable.name,
|
|
name: variable.name,
|
|
value: variable.value,
|
|
type: variable.type,
|
|
//children: (variable.numchild && variable.numchild > 0),
|
|
children: variable.children_count,
|
|
properties: null,
|
|
scope: scope
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Create a scope and variables from data received from IKPdb
|
|
*/
|
|
function buildScopeVariables(frame_vars, scope_index, frame_index, vars) {
|
|
var scope = new Scope({
|
|
index: scope_index,
|
|
type: SCOPES[scope_index],
|
|
frameIndex: frame_index
|
|
});
|
|
|
|
for (var i = 0, j = vars.length; i < j; i++) {
|
|
frame_vars.push(buildVariable(vars[i], scope));
|
|
}
|
|
}
|
|
|
|
function buildFrame(thread_id, frame, i) {
|
|
var variables = [];
|
|
|
|
// build scopes and variables for this frame
|
|
/*
|
|
* Right now Cloud9 does not allow to diplay parameter appart from
|
|
* local vars
|
|
* TODO: Discuss with Cloud9 how to render parameters appart from locals in Debugger panels
|
|
*/
|
|
//buildScopeVariables(variables, 0, i, frame.f_locals);
|
|
if (typeof frame.f_locals !== "undefined") {
|
|
buildScopeVariables(variables, 1, i, frame.f_locals);
|
|
}
|
|
|
|
// parse file from path
|
|
return new Frame({
|
|
index: i,
|
|
name: frame.name,
|
|
column: 0,
|
|
id: frame.id,
|
|
line: parseInt(frame.line_number, 10) - 1, // IKPdb lines are 1 based
|
|
path: util.normalizePath("/" + frame.file_path),
|
|
sourceId: frame.file_path,
|
|
thread: thread_id,
|
|
istop: (i === 0),
|
|
variables: variables
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Process asynchonous messags received from remote debugger
|
|
* like breakpoint hit or program termination
|
|
*/
|
|
function programBreak(message) {
|
|
if (message.command === 'programEnd') {
|
|
return detach(); // detach() update state
|
|
}
|
|
|
|
// no error, only frames
|
|
stack = [];
|
|
|
|
// process frames
|
|
var frames = message.frames;
|
|
for (var i = 0, j = frames.length; i < j; i++) {
|
|
stack.push(buildFrame(frames[i].thread, frames[i], i));
|
|
}
|
|
|
|
setState("stopped");
|
|
emit("frameActivate", { frame: stack[0] });
|
|
|
|
/*****
|
|
* Process the 3 levels of messags IKPdb can send.
|
|
*/
|
|
message.info_messages.forEach(function (iMessage) {
|
|
console.log(iMessage);
|
|
});
|
|
message.warning_messages.forEach(function (wMessage) {
|
|
bubble.popup(wMessage, false);
|
|
});
|
|
message.error_messages.forEach(function (eMessage) {
|
|
showError(eMessage, 10000);
|
|
});
|
|
|
|
/**
|
|
* Exceptions handling
|
|
* We build a variable describing the exception
|
|
* that c9 will inject into "Watch Expressions".
|
|
*/
|
|
if (message.exception) {
|
|
showError("IKpdb has detected an unmanaged exception \"" +
|
|
message.exception.type + "\":" + message.exception.info +
|
|
". Execution has stopped!",
|
|
10000);
|
|
var exception = new Variable({
|
|
ref: null,
|
|
name: message.exception.type,
|
|
value: message.exception.info,
|
|
type: "Exception",
|
|
children: false,
|
|
properties: null,
|
|
scope: "Locals"
|
|
});
|
|
|
|
emit("exception", { frame: stack[0], frames: stack, exception: exception });
|
|
debug.getElement("btnSuspend").setAttribute("disabled", true);
|
|
debug.getElement("btnStepOut").setAttribute("disabled", true);
|
|
debug.getElement("btnStepInto").setAttribute("disabled", true);
|
|
debug.getElement("btnStepOver").setAttribute("disabled", true);
|
|
} else {
|
|
emit("break", { frame: stack[0], frames: stack });
|
|
if (stack.length == 1)
|
|
debug.getElement("btnStepOut").setAttribute("disabled", true);
|
|
}
|
|
}
|
|
|
|
/*****
|
|
* Set the debugger state and emit state change
|
|
*/
|
|
function setState(_state) {
|
|
if (state === _state) return;
|
|
state = _state;
|
|
emit("stateChange", { state: state });
|
|
}
|
|
|
|
/*****
|
|
* we can't use this since breakpoints function are called by cloud9
|
|
* not by user
|
|
* TODO: check with cloud9 a way to intercept user actions
|
|
*/
|
|
function breakpointManagementWarning(commandSpecificMessage) {
|
|
return;
|
|
if (state == "running") {
|
|
var msg = "IKPdpb Error: You can't manage breakpoints while" +
|
|
" program is running. Breakpoints can be manipulated " +
|
|
"before debugger launch or when program is stopped. " +
|
|
commandSpecificMessage;
|
|
showError(msg, 10000);
|
|
bubble.popup(commandSpecificMessage, false);
|
|
}
|
|
}
|
|
|
|
function setBreakpoint(bp, callback) {
|
|
// TODO: Check with c9 how we can prevent user to set breakpoint
|
|
breakpointManagementWarning("Breakpoint creation request will be send to debugger at next programm break !.");
|
|
|
|
bp.data.file_name = bp.data.path.substring(1); // IKPdb expects a filename so we remove leading /
|
|
bp.data.line_number = bp.data.line + 1; // IKPdb expects 1 based lines
|
|
sendCommand("setBreakpoint", bp.data, function(err, reply) {
|
|
if (err)
|
|
return callback && callback(err);
|
|
if (reply.commandExecStatus == "error")
|
|
return callback && callback(new Error("Can't set breakpoint"));
|
|
bp.id = reply.result.breakpoint_number;
|
|
callback && callback(null, bp, {});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Called by c9 when user clic on enable / disable breakpoints
|
|
*/
|
|
function changeBreakpoint(bp, callback) {
|
|
// TODO: Check with c9 how we can prevent user to set breakpoint
|
|
breakpointManagementWarning("Breakpoint modification request will be send to debugger at next programm break !.");
|
|
|
|
if (!bp.data) {
|
|
console.error("Missing bp.data in changeBreakpoint(", bp, ") ");
|
|
}
|
|
|
|
bp.data.breakpoint_number = bp.id;
|
|
sendCommand("changeBreakpointState", bp.data, function(err) {
|
|
callback && callback(err, bp);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Called by c9 when user remove an existing breakpoint.
|
|
*/
|
|
function clearBreakpoint(bp, callback) {
|
|
// TODO: Check with c9 how we can prevent user to set breakpoint
|
|
breakpointManagementWarning("Breakpoint removal request will be send to debugger at next programm break !.");
|
|
|
|
bp.data.breakpoint_number = bp.id;
|
|
sendCommand("clearBreakpoint", bp.data, function(err) {
|
|
callback && callback(err, bp);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* send breakpoints to debugger and attach when done
|
|
*/
|
|
function manyBreakpoints(breakpoints, command, callback) {
|
|
function _setBPs(breakpoints, failed, callback, i) {
|
|
// run callback once we've exhausted setting breakpoints
|
|
if (i == breakpoints.length) {
|
|
callback(breakpoints, failed);
|
|
return;
|
|
}
|
|
|
|
command(breakpoints[i], function(err, bp) {
|
|
if (err) {
|
|
// breakpoint failure, remove it before going on
|
|
failed.push(breakpoints.splice(i, 1));
|
|
_setBPs(breakpoints, failed, callback, i);
|
|
}
|
|
else {
|
|
breakpoints[i].id = bp.id;
|
|
_setBPs(breakpoints, failed, callback, i + 1);
|
|
}
|
|
});
|
|
}
|
|
|
|
_setBPs(breakpoints, [], callback, 0);
|
|
}
|
|
|
|
function sync(begin, callback) {
|
|
// send breakpoints to ikpdb and attach when done
|
|
var localBkpts = emit("getBreakpoints");
|
|
|
|
listBreakpoints(function(err, remoteBkpts) {
|
|
if (err) return callback(err);
|
|
|
|
/* There exist two sets of breakpoints. One local as shown
|
|
* in the GUI, L, and one "remote" that already exists in
|
|
* IKPdb's state, R.
|
|
* Syncing L and R must prioritize L's elements. We'll
|
|
* create three sets:
|
|
* to_remove = R\L (or {x∈R|x∉L})
|
|
* BPs present in R but not in L, must be removed from R
|
|
* to_add = L/R (or {x∈L|x∉R})
|
|
* BPs present in L but not in R, must be added to R
|
|
* synced = L∩R
|
|
* BPs already in both.
|
|
*/
|
|
|
|
var to_add = [];
|
|
var synced = [];
|
|
|
|
// compare the GUI breakpoints to those already created
|
|
for (var i = 0, j = localBkpts.length; i < j; i++) {
|
|
var bp = localBkpts[i];
|
|
var missing = true;
|
|
|
|
// test for membership of bp in remoteBkpts
|
|
for (var x = 0, y = remoteBkpts.length; x < y; x++) {
|
|
var rbp = remoteBkpts[x];
|
|
if (bp.path == rbp.path && bp.line == rbp.line &&
|
|
bp.condition == rbp.condition) {
|
|
// make sure synced BP has correct id
|
|
bp.id = rbp.id;
|
|
|
|
// track necessary removals by removing used BPs
|
|
remoteBkpts.splice(x, 1);
|
|
missing = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (missing)
|
|
to_add.push(bp);
|
|
else
|
|
synced.push(bp);
|
|
}
|
|
|
|
// notify IKPDb of new breakpoints
|
|
manyBreakpoints(to_add, setBreakpoint, function(added, fail) {
|
|
// successfully created BPs are now synced
|
|
synced = synced.concat(added);
|
|
|
|
// now remove extraneous BPs
|
|
manyBreakpoints(remoteBkpts, clearBreakpoint, function(cleared, clrfail) {
|
|
// BPs that failed to remove need to be present locally
|
|
synced = synced.concat(clrfail);
|
|
|
|
attached = true;
|
|
emit("attach", { breakpoints: synced });
|
|
|
|
if (begin)
|
|
runScript(callback);
|
|
else
|
|
sendCommand("getStatus", {}, callback);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
/*
|
|
* Called by Cloud9 to retreive value of "Watch Expressions" and
|
|
* results of expressions types in "Immediate (Debuger)"" panel
|
|
* WARNING: Right now only expressions are supported ; user
|
|
* can't type a statement in immediate panel
|
|
*/
|
|
function evaluate(expression, frame, global, disableBreak, callback) {
|
|
var args = {
|
|
"expression": expression,
|
|
"frame": (frame && frame.id) || null,
|
|
"thread": (frame && frame.thread) || null,
|
|
"global": global,
|
|
"disableBreak": disableBreak
|
|
};
|
|
sendCommand("evaluate", args, function(err, reply) {
|
|
if (err) {
|
|
return callback(new Error("No value"));
|
|
}
|
|
/* TODO: remove if unneeded
|
|
else if (reply.commandExecutionStatus == "error")
|
|
return callback(new Error(reply.messages.msg));
|
|
*/
|
|
callback(null, new Variable({
|
|
name: expression,
|
|
value: reply.result.value,
|
|
type: reply.result.type,
|
|
children: false
|
|
}));
|
|
});
|
|
}
|
|
|
|
function setVariable(variable, value, frame, callback) {
|
|
var args = {
|
|
"frame": frame.id,
|
|
"name": variable.name,
|
|
"value": value
|
|
};
|
|
sendCommand("setVariable", args, function(err, reply) {
|
|
if (err)
|
|
return callback && callback(err);
|
|
callback && callback(null, variable);
|
|
});
|
|
}
|
|
|
|
|
|
/**
|
|
* properly handle reconnect
|
|
*/
|
|
function reconnectSync(callback) {
|
|
if (!callback)
|
|
callback = function() {};
|
|
|
|
sendCommand("reconnect", {}, function(err, reply) {
|
|
var restart = !err && reply.executionStatus == "running";
|
|
sync(restart, callback);
|
|
});
|
|
}
|
|
|
|
|
|
function attach(_socket, reconnect, callback) {
|
|
//console.debug("Entering IKPdb Plugin attach(_socket", _socket, "reconnect=", reconnect," ,callback=", callback,")");
|
|
|
|
debugger_socket = _socket;
|
|
|
|
// The back event is fired when the socket reconnects
|
|
debugger_socket.on("back", function() {
|
|
reconnectSync();
|
|
}, plugin);
|
|
|
|
// The error event is fired when the socket fails to connect
|
|
debugger_socket.on("error", function(err) {
|
|
console.error("IKPb debugger socket error !", err);
|
|
emit("error", err);
|
|
}, plugin);
|
|
|
|
ikpdbs = new IKPdbService(debugger_socket, programBreak);
|
|
|
|
ikpdbs.attach(function() {
|
|
emit("connect");
|
|
|
|
// if we're reconnecting, check IKPdb's state
|
|
if (reconnect)
|
|
reconnectSync(callback);
|
|
else
|
|
sync(true, callback);
|
|
});
|
|
|
|
// Update GUI
|
|
emit("frameActivate", { frame: null });
|
|
}
|
|
|
|
/*
|
|
* Clean up the debugger connection
|
|
*/
|
|
function detach() {
|
|
// console.log("entering detach()");
|
|
if (ikpdbs)
|
|
ikpdbs.detach();
|
|
|
|
emit("frameActivate", { frame: null });
|
|
setState(null);
|
|
|
|
debugger_socket = null;
|
|
attached = false;
|
|
ikpdbs = null;
|
|
|
|
emit("detach");
|
|
}
|
|
|
|
function getProxySource(process) {
|
|
return PROXY.replace(/\/\/.*/g, "")
|
|
.replace(/[\n\r]/g, "")
|
|
.replace(/\{DEBUGGED_PROCESS_PORT\}/, process.runner.debugport)
|
|
.replace(/\{DEBUGGED_PROCESS_HOST\}/, process.runner.debughost || "127.0.0.1");
|
|
}
|
|
|
|
|
|
/* Not applicable */
|
|
function getSources(callback) {
|
|
var sources = [new Source()];
|
|
callback(null, sources);
|
|
emit("sources", { sources: sources });
|
|
}
|
|
|
|
/* Not applicable */
|
|
function getSource(source, callback) {
|
|
callback(null, new Source());
|
|
}
|
|
|
|
function getFrames(callback, silent) {
|
|
var frames = [];
|
|
emit("getFrames", { frames: frames });
|
|
callback(null, frames);
|
|
}
|
|
|
|
function getScope(frame, scope, callback) {
|
|
callback(null, scope.variables, scope, frame);
|
|
}
|
|
|
|
/* called by cloud9 when user request to expand variable's children */
|
|
function getProperties(variable, callback) {
|
|
// request children of a variable
|
|
var args = { id: variable.ref, name: variable.name };
|
|
sendCommand("getProperties", args, function(err, reply) {
|
|
if (err)
|
|
return callback && callback(err);
|
|
else if (reply.result.properties.length === 0)
|
|
return callback && callback(new Error("No children"));
|
|
|
|
var children = [];
|
|
reply.result.properties.forEach(function (child) {
|
|
children.push(buildVariable(child, variable.scope));
|
|
});
|
|
variable.properties = children;
|
|
callback && callback(null, children, variable);
|
|
});
|
|
}
|
|
|
|
/***
|
|
* Retrieves a list of all the breakpoints that are set in the debugger.
|
|
*/
|
|
function listBreakpoints(callback) {
|
|
sendCommand("getBreakpoints", {}, function(err, reply) {
|
|
if (err) {
|
|
console.error("getBreakpoints() error with response=", reply);
|
|
return callback && callback(err, reply);
|
|
}
|
|
// we reprocess breakpoints list to adjust line numbers and file paths
|
|
reply.result.forEach(function(bp) {
|
|
bp.line = bp.line_number - 1;
|
|
bp.id = bp.breakpoint_number;
|
|
bp.path = util.normalizePath(bp.file_name);
|
|
});
|
|
var breakpointList = reply.result;
|
|
callback(null, breakpointList);
|
|
});
|
|
}
|
|
|
|
/***** Register and define API *****/
|
|
|
|
/**
|
|
* TODO: comment
|
|
* @singleton
|
|
*/
|
|
plugin.freezePublicAPI({
|
|
/**
|
|
* Specifies the features that this debugger implementation supports
|
|
* @property {Object} features
|
|
* @property {Boolean} features.scripts Able to download code (disable the scripts button)
|
|
* @property {Boolean} features.conditionalBreakpoints Able to have conditional breakpoints (disable menu item)
|
|
* @property {Boolean} features.liveUpdate Able to update code live (don't do anything when saving)
|
|
* @property {Boolean} features.updateWatchedVariables Able to edit variables in watches (don't show editor)
|
|
* @property {Boolean} features.updateScopeVariables Able to edit variables in variables panel (don't show editor)
|
|
* @property {Boolean} features.setBreakBehavior Able to configure break behavior (disable break behavior button)
|
|
* @property {Boolean} features.executeCode Able to execute code (disable REPL)
|
|
*/
|
|
features: {
|
|
scripts: false,
|
|
conditionalBreakpoints: true,
|
|
liveUpdate: false,
|
|
updateWatchedVariables: false,
|
|
updateScopeVariables: true,
|
|
setBreakBehavior: false,
|
|
executeCode: true
|
|
},
|
|
/**
|
|
* The type of the debugger implementation. This is the identifier
|
|
* with which the runner selects the debugger implementation.
|
|
* @property {String} type
|
|
* @readonly
|
|
*/
|
|
type: TYPE,
|
|
|
|
|
|
/**
|
|
* Besides features and type, there are only four properties for
|
|
* which we should define property getters.
|
|
* These are state, attached, breakOnExceptions
|
|
* and breakOnUncaughtExceptions.
|
|
|
|
/**
|
|
* @property {null|"running"|"stopped"} state The state of the debugger process
|
|
* <table>
|
|
* <tr><td>Value</td><td> Description</td></tr>
|
|
* <tr><td>null</td><td> process doesn't exist</td></tr>
|
|
* <tr><td>"stopped"</td><td> paused on breakpoint</td></tr>
|
|
* <tr><td>"running"</td><td> process is running</td></tr>
|
|
* </table>
|
|
* @readonly
|
|
*/
|
|
get state() { return state; },
|
|
|
|
/**
|
|
*
|
|
*/
|
|
get attached() { return attached; },
|
|
|
|
/**
|
|
* Whether the debugger will break when it encounters any exception.
|
|
* This includes exceptions in try/catch blocks.
|
|
* @property {Boolean} breakOnExceptions
|
|
* @readonly
|
|
*/
|
|
get breakOnExceptions() { return false; },
|
|
|
|
/**
|
|
* Whether the debugger will break when it encounters an uncaught
|
|
* exception.
|
|
* @property {Boolean} breakOnUncaughtExceptions
|
|
* @readonly
|
|
*/
|
|
get breakOnUncaughtExceptions() { return true; },
|
|
|
|
_events: [
|
|
"attach",
|
|
"detach",
|
|
/**
|
|
* Fires when the current list of breakpoints is needed
|
|
* @event getBreakpoints
|
|
*/
|
|
"getBreakpoints",
|
|
],
|
|
|
|
/**
|
|
* Attaches the debugger to the started process.
|
|
* @param {Object} runner A runner as specified by {@link run#run}.
|
|
* @param {debugger.Breakpoint[]} breakpoints The set of breakpoints that should be set from the start
|
|
*/
|
|
attach: attach,
|
|
detach: detach,
|
|
resume: resume,
|
|
suspend: suspend,
|
|
stepOver: stepOver,
|
|
|
|
/**
|
|
* Retrieves and sets the properties of a variable.
|
|
* @param {debugger.Variable} variable The variable for which to retrieve the properties.
|
|
* @param {Function} callback Called when the properties are loaded
|
|
* @param {Error} callback.err The error object if an error occured.
|
|
* @param {debugger.Variable[]} callback.properties A list of properties of the variable.
|
|
* @param {debugger.Variable} callback.variable The variable to which the properties belong.
|
|
*/
|
|
getProperties: getProperties,
|
|
|
|
stepInto: stepInto,
|
|
stepOut: stepOut,
|
|
getProxySource: getProxySource,
|
|
|
|
/**
|
|
* Adds a breakpoint to a line in a source file.
|
|
* @param {debugger.Breakpoint} breakpoint The breakpoint to add.
|
|
* @param {Function} callback Called after the expression has executed.
|
|
* @param {Error} callback.err The error if any error occured.
|
|
* @param {debugger.Breakpoint} callback.breakpoint The added breakpoint
|
|
* @param {Object} callback.data Additional debugger specific information.
|
|
*/
|
|
setBreakpoint: setBreakpoint,
|
|
|
|
|
|
|
|
clearBreakpoint: clearBreakpoint,
|
|
|
|
/**
|
|
* Evaluates an expression in a frame or in global space.
|
|
* @param {String} expression The expression.
|
|
* @param {debugger.Frame} frame The stack frame which serves as the contenxt of the expression.
|
|
* @param {Boolean} global Specifies whether to execute the expression in global space.
|
|
* @param {Boolean} disableBreak Specifies whether to disabled breaking when executing this expression.
|
|
* @param {Function} callback Called after the expression has executed.
|
|
* @param {Error} callback.err The error if any error occured.
|
|
* @param {debugger.Variable} callback.variable The result of the expression.
|
|
*/
|
|
evaluate: evaluate,
|
|
|
|
|
|
/**
|
|
* Defines how the debugger deals with exceptions.
|
|
* @param {"all"/"uncaught"} type Specifies which errors to break on.
|
|
* @param {Boolean} enabled Specifies whether to enable breaking on exceptions.
|
|
* @param {Function} callback Called after the setting is changed.
|
|
* @param {Error} callback.err The error if any error occured.
|
|
*/
|
|
setBreakBehavior: function() {},
|
|
|
|
/**
|
|
* Updates properties of a breakpoint
|
|
* @param {debugger.Breakpoint} breakpoint The breakpoint to update.
|
|
* @param {Function} callback Called after the expression has executed.
|
|
* @param {Error} callback.err The error if any error occured.
|
|
* @param {debugger.Breakpoint} callback.breakpoint The updated breakpoint
|
|
*/
|
|
changeBreakpoint: changeBreakpoint,
|
|
|
|
/*
|
|
* Retrieves a list of all the breakpoints that are set in the
|
|
* debugger.
|
|
* @param {Function} callback Called when the breakpoints are retrieved.
|
|
* @param {Error} callback.err The error if any error occured.
|
|
* @param {debugger.Breakpoint[]} callback.breakpoints A list of breakpoints
|
|
*/
|
|
listBreakpoints: listBreakpoints,
|
|
|
|
/**
|
|
* Sets the value of a variable.
|
|
* @param {debugger.Variable} variable The variable to set the value of.
|
|
* @param {Mixed} value The new value of the variable.
|
|
* @param {debugger.Frame} frame The frame to which the variable belongs.
|
|
* @param {Function} callback
|
|
* @param {Function} callback Called when the breakpoints are retrieved.
|
|
* @param {Error} callback.err The error if any error occured.
|
|
* @param {Object} callback.data Additional debugger specific information.
|
|
*/
|
|
setVariable: setVariable,
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
register(null, {
|
|
"ikpdb": plugin
|
|
});
|
|
}
|
|
}); |