123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- var events = require('events'),
- async = require('async'),
- debug = require('debug')('node-inspector:ScriptManager'),
- convert = require('./convert.js');
- // see Blink inspector > ContentSearchUtils.cpp > findMagicComment()
- var SOURCE_MAP_URL_REGEX = /\/\/[@#][ \t]sourceMappingURL=[ \t]*([^\s'"]*)[ \t]*$/m;
- /**
- * @param {{hidden}} config
- * @param {FrontendClient} frontendClient
- * @param {DebuggerClient} debuggerClient
- * @constructor
- */
- function ScriptManager(config, frontendClient, debuggerClient) {
- config = config || {};
- var self = Object.create(ScriptManager.prototype, {
- _sources: { value: {}, writable: true },
- _hidden: { value: config.hidden || [] },
- _frontendClient: { value: frontendClient },
- _debuggerClient: { value: debuggerClient }
- });
- self._registerDebuggerEventHandlers();
- return self;
- }
- ScriptManager.prototype = Object.create(events.EventEmitter.prototype, {
- mainAppScript: { value: null, writable: true },
- _registerDebuggerEventHandlers: {
- value: function() {
- this._debuggerClient.on(
- 'afterCompile',
- this._onAfterCompile.bind(this)
- );
- }
- },
- _onAfterCompile: {
- value: function(event) {
- if (!event.script) {
- console.log(
- 'Unexpected error: debugger emitted afterCompile event' +
- 'with no script data.'
- );
- return;
- }
- this.addScript(event.script);
- }
- },
- _isNodeInternal: {
- value: function(scriptName) {
- // node.js internal scripts have no path, just a filename
- // regular scripts have always a full path
- // (i.e their name contains at least one path separator)
- var isFullPath = /[\/\\]/.test(scriptName);
- return !isFullPath;
- }
- },
- _listAllSources: {
- value: function() {
- var self = this;
- return Object.keys(this._sources).map(function fnSelectValue(key) {
- return self._sources[key];
- });
- }
- },
- isScriptHidden: {
- /**
- * @param {string} scriptPath.
- * @return {boolean}
- */
- value: function(scriptPath) {
- return this._hidden.some(function fnHiddenScriptMatchesPath(r) {
- return r.test(scriptPath);
- });
- }
- },
-
- findScriptByID: {
- /**
- * @param {string} id script id.
- * @return {{hidden: boolean, path: string, url: string}}
- */
- value: function(id) {
- return this._sources[id];
- }
- },
- addScript: {
- value: function(v8data) {
- var localPath = v8data.name;
- var hidden = this.isScriptHidden(localPath) && localPath != this.mainAppScript;
- var inspectorScriptData = this._doAddScript(v8data, hidden);
- debug('addScript id: %s localPath: %s hidden? %s source? %s',
- v8data.id, localPath, hidden, !!v8data.source);
- if (hidden || this._isNodeInternal(localPath)) {
- notifyFrontEnd.call(this);
- } else {
- this._getSourceMapUrl(
- v8data.id,
- v8data.source,
- function onGetSourceMapUrlReturn(err, sourceMapUrl) {
- if (err) {
- console.log(
- 'Warning: cannot parse SourceMap URL for script %s (id %d). %s',
- localPath,
- v8data.id,
- err);
- }
- debug('sourceMapUrl for script %s:%s is %s',
- v8data.id, localPath, sourceMapUrl);
- inspectorScriptData.sourceMapURL = sourceMapUrl;
- notifyFrontEnd.call(this);
- }.bind(this)
- );
- }
- function notifyFrontEnd() {
- if (hidden) return;
- this._frontendClient.sendEvent(
- 'Debugger.scriptParsed',
- inspectorScriptData
- );
- }
- }
- },
- _doAddScript: {
- value: function(v8data, hidden) {
- var inspectorUrl = convert.v8NameToInspectorUrl(v8data.name);
- var inspectorScriptData = {
- scriptId: String(v8data.id),
- url: inspectorUrl,
- startLine: v8data.lineOffset,
- startColumn: v8data.columnOffset
- /* Properties not set:
- endLine: undefined,
- endColumn: undefined,
- isContentScript: undefined,
- hasSourceURL: undefined,
- */
- };
- var item = {
- hidden: hidden,
- v8name: v8data.name,
- url: inspectorUrl
- };
- this._sources[inspectorScriptData.scriptId] = item;
- return inspectorScriptData;
- }
- },
- _getSourceMapUrl: {
- value: function(scriptId, scriptSource, callback) {
- var getSource;
- if (scriptSource == null) {
- debug('_getSourceMapUrl(%s) - fetching source from V8', scriptId);
- getSource = this._debuggerClient.getScriptSourceById
- .bind(this._debuggerClient, scriptId);
- } else {
- debug('_getSourceMapUrl(%s) - using the suplied source', scriptId);
- getSource = function(cb) { cb(null, scriptSource); };
- }
- async.waterfall(
- [
- getSource,
- this._parseSourceMapUrlFromScriptSource.bind(this)
- ],
- callback
- );
- }
- },
- _parseSourceMapUrlFromScriptSource: {
- value: function(source, callback) {
- var match = SOURCE_MAP_URL_REGEX.exec(source);
- callback(null, match ? match[1] : undefined);
- }
- },
- reset: {
- value: function() {
- this._sources = {};
- }
- }
- });
- exports.ScriptManager = ScriptManager;
|