2013-05-14 22:32:10 +04:00
|
|
|
var async = require('async'),
|
|
|
|
convert = require('./convert.js');
|
|
|
|
|
2013-05-27 21:04:46 +04:00
|
|
|
var SCOPE_ID_MATCHER = /^scope:(\d+):(\d+)$/;
|
|
|
|
|
2013-09-24 09:21:24 +04:00
|
|
|
/**
|
|
|
|
* @param {Object} config
|
|
|
|
* @param {DebuggerClient} debuggerClient
|
|
|
|
*/
|
|
|
|
function CallFramesProvider(config, debuggerClient) {
|
|
|
|
this._config = config;
|
2013-05-14 22:32:10 +04:00
|
|
|
this._debuggerClient = debuggerClient;
|
|
|
|
}
|
|
|
|
|
|
|
|
CallFramesProvider.prototype = {
|
|
|
|
|
|
|
|
fetchCallFrames: function(handleResponse) {
|
2013-05-27 21:04:46 +04:00
|
|
|
this._debuggerClient.request(
|
|
|
|
'backtrace',
|
|
|
|
{
|
2013-09-24 09:21:24 +04:00
|
|
|
inlineRefs: true,
|
|
|
|
fromFrame: 0,
|
|
|
|
toFrame: this._config.stackTraceLimit
|
2013-05-27 21:04:46 +04:00
|
|
|
},
|
2013-05-14 22:32:10 +04:00
|
|
|
function(err, responseBody, responseRefs) {
|
|
|
|
if (err) {
|
|
|
|
handleResponse(err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._convertBacktraceToCallFrames(responseBody, responseRefs, handleResponse);
|
|
|
|
}.bind(this));
|
|
|
|
},
|
|
|
|
|
|
|
|
_convertBacktraceToCallFrames: function(backtraceResponseBody, backtrackResponseRefs, handleResponse) {
|
|
|
|
var debuggerFrames = backtraceResponseBody.frames || [];
|
|
|
|
|
|
|
|
async.map(
|
|
|
|
debuggerFrames,
|
|
|
|
this._convertDebuggerFrameToInspectorFrame.bind(this, backtrackResponseRefs),
|
|
|
|
handleResponse);
|
|
|
|
},
|
|
|
|
|
|
|
|
_convertDebuggerFrameToInspectorFrame: function(backtrackResponseRefs, frame, done) {
|
2013-05-27 21:04:46 +04:00
|
|
|
var scopeChain = frame.scopes.map(function(scope) {
|
2014-03-14 11:32:36 +04:00
|
|
|
return {
|
|
|
|
object: {
|
|
|
|
type: 'object',
|
|
|
|
objectId: 'scope:' + frame.index + ':' + scope.index,
|
|
|
|
className: 'Object',
|
|
|
|
description: 'Object'
|
|
|
|
},
|
|
|
|
type: convert.v8ScopeTypeToString(scope.type)
|
|
|
|
};
|
2013-05-27 21:04:46 +04:00
|
|
|
});
|
|
|
|
|
|
|
|
done(null, {
|
|
|
|
callFrameId: frame.index.toString(),
|
|
|
|
functionName: frame.func.inferredName || frame.func.name,
|
|
|
|
location: {
|
|
|
|
scriptId: convert.v8ScriptIdToInspectorId(frame.func.scriptId),
|
|
|
|
lineNumber: frame.line,
|
|
|
|
columnNumber: frame.column
|
|
|
|
},
|
|
|
|
scopeChain: scopeChain,
|
|
|
|
this: convert.v8RefToInspectorObject(frame.receiver)
|
2013-05-14 22:32:10 +04:00
|
|
|
});
|
|
|
|
},
|
|
|
|
|
2013-05-27 21:04:46 +04:00
|
|
|
isScopeId: function(objectId) {
|
|
|
|
return SCOPE_ID_MATCHER.test(objectId);
|
|
|
|
},
|
|
|
|
|
2013-06-05 13:29:28 +04:00
|
|
|
resolveScopeId: function(objectId, callback) {
|
2013-05-27 21:04:46 +04:00
|
|
|
var scopeIdMatch = SCOPE_ID_MATCHER.exec(objectId);
|
|
|
|
if (!scopeIdMatch) throw new Error('Invalid scope id "' + objectId + '"');
|
2013-05-30 14:50:01 +04:00
|
|
|
this._debuggerClient.request(
|
2013-05-27 21:04:46 +04:00
|
|
|
'scope',
|
2013-05-29 11:00:59 +04:00
|
|
|
{
|
2013-05-27 21:04:46 +04:00
|
|
|
number: Number(scopeIdMatch[2]),
|
2013-06-05 13:29:28 +04:00
|
|
|
frameNumber: Number(scopeIdMatch[1])
|
2013-05-29 11:00:59 +04:00
|
|
|
},
|
2013-06-05 13:29:28 +04:00
|
|
|
function(err, result) {
|
|
|
|
if (err)
|
|
|
|
callback(err);
|
|
|
|
else
|
|
|
|
callback(null, result.object.ref);
|
2013-05-27 21:04:46 +04:00
|
|
|
});
|
2013-05-29 11:00:59 +04:00
|
|
|
}
|
2013-05-14 22:32:10 +04:00
|
|
|
};
|
|
|
|
|
2013-05-29 11:00:59 +04:00
|
|
|
exports.CallFramesProvider = CallFramesProvider;
|