| Server IP : 68.183.124.220 / Your IP : 216.73.217.137 Web Server : Apache/2.4.18 (Ubuntu) System : Linux Sandbox-A 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 User : gavin ( 1000) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /home/gavin/workspace/happymandarin/node_modules/node-inspector/lib/ |
Upload File : |
var convert = require('./convert'),
async = require('async'),
CallFramesProvider = require('./CallFramesProvider').CallFramesProvider;
/**
* @param {Object} config
* @param {FrontendClient} frontendClient
* @param {DebuggerClient} debuggerClient
* @param {ScriptManager} scriptManager
* @param {InjectorClient} injectorClient
* @constructor
*/
function BreakEventHandler(config, session) {
this._config = config;
this._session = session;
this._frontendClient = session.frontendClient;
this._debuggerClient = session.debuggerClient;
this._injectorClient = session.injectorClient;
this._scriptManager = session.scriptManager;
this._callFramesProvider = new CallFramesProvider(config, session);
this._debuggerClient.on('break', this._onBreak.bind(this));
this._debuggerClient.on('exception', this._onBreak.bind(this));
}
var callbackForNextBreak;
Object.defineProperties(BreakEventHandler.prototype, {
/** @type {Number} */
continueToLocationBreakpointId: {
writable: true,
value: null
},
/** @type {function(eventData)} */
callbackForNextBreak: {
get: function() { return callbackForNextBreak; },
set: function(value) {
if (value && callbackForNextBreak)
throw new Error('Cannot set multiple callbacks for the next break.');
callbackForNextBreak = value;
}
}
});
BreakEventHandler.prototype._onBreak = function(obj) {
async.waterfall([
this._handleInjectorClientBreak.bind(this, obj),
this._resolveScriptSource.bind(this, obj),
this._handleIgnoreBreakpoint.bind(this, obj),
this._handleCallbackForNextBreak.bind(this, obj),
this._handleContinueToLocation.bind(this, obj),
this.sendBacktraceToFrontend.bind(this, obj)
], function(err) {
if (err && err !== true) {
this._frontendClient.sendLogToConsole('error', err);
}
}.bind(this));
};
BreakEventHandler.prototype._handleInjectorClientBreak = function(obj, cb) {
this._injectorClient.tryHandleDebuggerBreak(obj.invocationText, cb);
};
BreakEventHandler.prototype._resolveScriptSource = function(obj, cb) {
this._scriptManager.resolveScriptById(obj.script.id, cb);
};
BreakEventHandler.prototype._handleIgnoreBreakpoint = function(obj, source, cb) {
var ignore = false;
// Source is undefined when the breakpoint was in code eval()-ed via
// console or eval()-ed internally by node inspector.
// We could send backtrace in such case, but that isn't working well now.
// V8 is reusing the same scriptId for multiple eval() calls and DevTools
// front-end does not update the displayed source code when a content
// of a script changes.
// The following solution - ignore the breakpoint and resume the
// execution - should be good enough in most cases.
if (!source || source.hidden) {
ignore = true;
}
// In the case of "break on uncaught exception" triggered by
// "TypeError: undefined is not a function", the exception is
// thrown by a V8 builtin CALL_NON_FUNCTION defined in
// v8/src/runtime.js. Thus, the script id of the event is not know
// by Node Inspector, but the break even must not be ignored.
// See https://github.com/node-inspector/node-inspector/issues/344
if (obj.exception) {
ignore = false;
}
if (ignore) {
this._debuggerClient.request('continue', { stepaction: 'out' });
}
cb(ignore);
};
BreakEventHandler.prototype._handleCallbackForNextBreak = function(obj, cb) {
if (!this.callbackForNextBreak) return cb(null);
var callbackForNextBreak = this.callbackForNextBreak;
this.callbackForNextBreak = null;
callbackForNextBreak(obj);
cb(true);
};
BreakEventHandler.prototype._handleContinueToLocation = function(obj, cb) {
if (this.continueToLocationBreakpointId == null) return cb(null);
this._debuggerClient.clearBreakpoint(
this.continueToLocationBreakpointId,
function(err, result) {
if (err)
this._frontendClient.sendLogToConsole('warning', err);
else
this.continueToLocationBreakpointId = null;
cb(true);
}.bind(this)
);
};
/**
* @param {function(error, response)} callback
*/
BreakEventHandler.prototype.fetchCallFrames = function(callback) {
this._callFramesProvider.fetchCallFrames(callback);
};
/**
* @param {Object} exception
* @param {Array.<number>} hitBreakpoints
*/
BreakEventHandler.prototype.sendBacktraceToFrontend = function(obj, cb) {
obj = obj || {
exception: false,
hitBreakpoints: false
};
cb = cb || function() {};
var exception = obj.exception,
hitBreakpoints = obj.hitBreakpoints;
this.fetchCallFrames(function(error, result) {
if (error) return cb(error);
this._frontendClient.sendEvent(
'Debugger.paused',
{
callFrames: result,
reason: exception ? 'exception' : 'other',
data: exception ? convert.v8RefToInspectorObject(exception) : null,
hitBreakpoints: hitBreakpoints
});
cb(null);
}.bind(this));
};
exports.BreakEventHandler = BreakEventHandler;