Update list of scripts on afterCompile event.
Added afterCompile listener that registers newly parsed/loaded script. Includes - refactoring of script registration (extracted class ScriptManager). - fix of script path shortening, where windows paths containing '\' instead of '/' were not shortened at all.
This commit is contained in:
Родитель
87c71616ff
Коммит
de14ca3951
|
@ -0,0 +1,91 @@
|
|||
var events = require('events');
|
||||
|
||||
/**
|
||||
* @param hiddenScripts List of scripts that are not displayed to the user.
|
||||
* @returns {ScriptManager}
|
||||
* @constructor
|
||||
*/
|
||||
function ScriptManager(hiddenScripts) {
|
||||
hiddenScripts = hiddenScripts || [];
|
||||
return Object.create(ScriptManager.prototype, {
|
||||
_sources: { value: {} },
|
||||
_hiddenScripts: { value: hiddenScripts }
|
||||
});
|
||||
}
|
||||
|
||||
ScriptManager.prototype = Object.create(events.EventEmitter.prototype, {
|
||||
_isHidden: {
|
||||
value: function(scriptUrl) {
|
||||
return this._hiddenScripts.some(function fnHiddenScriptMatchesUrl(r) {
|
||||
return r.test(scriptUrl);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_listAllSources: {
|
||||
value: function() {
|
||||
var self = this;
|
||||
return Object.keys(this._sources).map(function fnSelectValue(key) {
|
||||
return self._sources[key];
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
findScriptByID: {
|
||||
/**
|
||||
* @param id script id
|
||||
* @returns {{hidden: boolean, path: string, url: string}}
|
||||
*/
|
||||
value: function(id) {
|
||||
return this._sources[id];
|
||||
}
|
||||
},
|
||||
|
||||
_shortenPath: {
|
||||
value: function(pathArray) {
|
||||
var p;
|
||||
var scripts = this._listAllSources();
|
||||
|
||||
for (var i = pathArray.length - 1; i > 0; i--) {
|
||||
p = pathArray.slice(i).join('/');
|
||||
if (!scripts.some(function fnScriptUrlMatchesP(s) {
|
||||
return s.url === p;
|
||||
})) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return pathArray.join('/');
|
||||
}
|
||||
},
|
||||
|
||||
addScript: {
|
||||
value: function(v8data) {
|
||||
var script = {
|
||||
sourceID: String(v8data.id),
|
||||
url: v8data.name,
|
||||
data: v8data.source,
|
||||
firstLine: v8data.lineOffset,
|
||||
scriptWorldType: 0,
|
||||
},
|
||||
path = String(v8data.name).split(/[\/\\]/);
|
||||
|
||||
var hidden = this._isHidden(script.url),
|
||||
item = {
|
||||
hidden: hidden,
|
||||
path: script.url,
|
||||
url: script.url,
|
||||
};
|
||||
|
||||
if (path.length > 1) {
|
||||
item.url = script.url = this._shortenPath(path);
|
||||
}
|
||||
|
||||
this._sources[script.sourceID] = item;
|
||||
if (!hidden) {
|
||||
this.emit('scriptLoaded', script);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
exports.ScriptManager = ScriptManager;
|
|
@ -1,5 +1,6 @@
|
|||
var events = require('events'),
|
||||
debugr = require('./debugger'),
|
||||
ScriptManager = require('./ScriptManager').ScriptManager;
|
||||
Breakpoint = require('./Breakpoint').Breakpoint;
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
@ -11,8 +12,7 @@ exports.create = function(debuggerPort, config) {
|
|||
attachedToDebugger = false,
|
||||
//map from sourceID:lineNumber to breakpoint
|
||||
breakpoints = {},
|
||||
//map from sourceID to filename
|
||||
sourceIDs = {},
|
||||
scriptManager = new ScriptManager(config.hidden),
|
||||
//milliseconds to wait for a lookup
|
||||
LOOKUP_TIMEOUT = 2500,
|
||||
//node function wrapper
|
||||
|
@ -20,6 +20,10 @@ exports.create = function(debuggerPort, config) {
|
|||
//
|
||||
cpuProfileCount = 0;
|
||||
|
||||
scriptManager.on('scriptLoaded', function onScriptLoaded(script) {
|
||||
sendEvent('parsedScriptSource', script);
|
||||
});
|
||||
|
||||
function wrapperObject(type, description, hasChildren, frame, scope, ref) {
|
||||
return {
|
||||
type: type,
|
||||
|
@ -147,7 +151,7 @@ exports.create = function(debuggerPort, config) {
|
|||
|
||||
function breakEvent(obj) {
|
||||
var data = {},
|
||||
source = sourceIDs[obj.body.script.id],
|
||||
source = scriptManager.findScriptByID(obj.body.script.id),
|
||||
args;
|
||||
if (!source) {
|
||||
args = {
|
||||
|
@ -165,43 +169,14 @@ exports.create = function(debuggerPort, config) {
|
|||
sendBacktrace();
|
||||
}
|
||||
|
||||
function onAfterCompile(event) {
|
||||
if (!event.success) return;
|
||||
scriptManager.addScript(event.body.script);
|
||||
}
|
||||
|
||||
function parsedScripts(msg) {
|
||||
var scripts = msg.body.map(function(s) {
|
||||
return {
|
||||
sourceID: String(s.id),
|
||||
url: s.name,
|
||||
data: s.source,
|
||||
firstLine: s.lineOffset,
|
||||
scriptWorldType: 0,
|
||||
path: String(s.name).split('/')
|
||||
};
|
||||
});
|
||||
scripts.sort(function(a, b) {
|
||||
return a.path.length - b.path.length;
|
||||
});
|
||||
var paths = [];
|
||||
function shorten(s) {
|
||||
var p;
|
||||
for (var i = s.length - 1; i > 0; i--) {
|
||||
p = s.slice(i).join('/');
|
||||
if (paths.indexOf(p) === -1) {
|
||||
paths.push(p);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return s.join('/');
|
||||
}
|
||||
scripts.forEach(function(s) {
|
||||
var hidden = config.hidden &&
|
||||
config.hidden.some(function(r) { return r.test(s.url); }),
|
||||
item = { hidden: hidden, path: s.url };
|
||||
if (s.path.length > 1) s.url = shorten(s.path);
|
||||
item.url = s.url;
|
||||
sourceIDs[s.sourceID] = item;
|
||||
delete s.path;
|
||||
if (!hidden) {
|
||||
sendEvent('parsedScriptSource', s);
|
||||
}
|
||||
msg.body.forEach(function(s) {
|
||||
scriptManager.addScript(s);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -263,7 +238,7 @@ exports.create = function(debuggerPort, config) {
|
|||
|
||||
if (bp.type === 'scriptId') {
|
||||
data.sourceID = bp.script_id;
|
||||
data.url = sourceIDs[bp.script_id].url;
|
||||
data.url = scriptManager.findScriptByID(bp.script_id).url;
|
||||
} else if (bp.type == 'scriptName') {
|
||||
data.url = bp.script_name;
|
||||
if (bp.actual_locations && bp.actual_locations.length > 0)
|
||||
|
@ -331,6 +306,7 @@ exports.create = function(debuggerPort, config) {
|
|||
var self = this;
|
||||
debug = debugr.attachDebugger(debuggerPort);
|
||||
debug.on('break', breakEvent);
|
||||
debug.on('afterCompile', onAfterCompile)
|
||||
debug.on('close', function() {
|
||||
//TODO determine proper close behavior
|
||||
debug = {
|
||||
|
@ -626,7 +602,7 @@ exports.create = function(debuggerPort, config) {
|
|||
var b = msg.body;
|
||||
var breakpoint = new Breakpoint({
|
||||
sourceID: b.script_id,
|
||||
url: sourceIDs[b.script_id].url,
|
||||
url: scriptManager.findScriptByID(b.script_id).url,
|
||||
line: b.line + 1,
|
||||
enabled: enabled,
|
||||
condition: condition,
|
||||
|
@ -799,9 +775,10 @@ exports.create = function(debuggerPort, config) {
|
|||
var fs = require('fs'),
|
||||
match = FUNC_WRAP.exec(newContent),
|
||||
newSource;
|
||||
if (match && sourceIDs[sourceID] && sourceIDs[sourceID].path) {
|
||||
var source = scriptManager.findScriptByID(sourceID);
|
||||
if (match && source && source.path) {
|
||||
newSource = match[1];
|
||||
fs.writeFile(sourceIDs[sourceID].path, newSource, function(e) {
|
||||
fs.writeFile(source.path, newSource, function(e) {
|
||||
if (e) {
|
||||
var err = e.toString(),
|
||||
data = {
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
var expect = require('chai').expect,
|
||||
ScriptManager = require('../lib/ScriptManager').ScriptManager;
|
||||
|
||||
describe('ScriptManager', function() {
|
||||
|
||||
describe('findSourceByID()', function() {
|
||||
var manager;
|
||||
|
||||
beforeEach(function() {
|
||||
manager = new ScriptManager();
|
||||
});
|
||||
|
||||
it('returns stored source', function() {
|
||||
manager._sources['id'] = 'a-source';
|
||||
expect(manager.findScriptByID('id')).to.equal('a-source');
|
||||
});
|
||||
|
||||
it('returns undefined for unknown id', function() {
|
||||
expect(manager.findScriptByID('unknown-id')).to.be.undefined;
|
||||
});
|
||||
});
|
||||
});
|
Загрузка…
Ссылка в новой задаче