| 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 fs = require('fs');
var path = require('path');
var async = require('async');
var debug = require('debug')('node-inspector:ScriptFileStorage');
var MODULE_HEADER = '(function (exports, require, module, __filename, __dirname) { ';
var MODULE_TRAILER = '\n});';
var MODULE_WRAP_REGEX = new RegExp(
'^' + escapeRegex(MODULE_HEADER) +
'([\\s\\S]*)' +
escapeRegex(MODULE_TRAILER) + '$'
);
var CONVENTIONAL_DIRS_PATTERN = [
/^[^\/]*\.js$/,
/^lib\/[\s\S]*\.js$/,
/^test\/[\s\S]*\.js$/,
/^node_modules\/[\s\S]*\.js$/
];
var ALL_JS_PATTERN = [
/^[\s\S]*\.js$/
];
function escapeRegex(str) {
return str.replace(/([/\\.?*()^${}|[\]])/g, '\\$1');
}
/**
* @param {{preload}} config
* @param {ScriptManager} scriptManager
* @constructor
*/
function ScriptFileStorage(config, session) {
config = config || {};
this._hidden = config.hidden;
this._scriptManager = session.scriptManager;
this._noPreload = config.preload === false;
}
var $class = ScriptFileStorage.prototype;
$class.save = function(path, content, callback) {
var match = MODULE_WRAP_REGEX.exec(content);
if (!match) {
callback(new Error('The new content is not a valid node.js script.'));
return;
}
var newSource = match[1];
async.waterfall([
fs.readFile.bind(fs, path, 'utf-8'),
function(oldContent, cb) {
var match = /^(\#\!.*)/.exec(oldContent);
if (match)
newSource = match[1] + newSource;
fs.writeFile(path, newSource, cb);
}
],
callback);
};
/**
* @param {string} path
* @param {function(Object, string)} callback
*/
$class.load = function(path, callback) {
var scriptId = this._scriptManager.findScriptIdByPath(path);
// If requested source was loaded in app (scriptId != null), we can't expect that it is equal
// to the file with requested name stored in fs.
// So, if requested source was loaded in app, we need to require it from app.
if (scriptId != null) {
this._scriptManager.getScriptSourceById(scriptId, callback);
} else {
fs.readFile(
path,
'utf-8',
function(err, content) {
if (err) return callback(err);
// remove shebang
content = content.replace(/^\#\!.*/, '');
var source = MODULE_HEADER + content + MODULE_TRAILER;
return callback(null, source);
}
);
}
};
/**
* @param {string} mainScriptFile
* @param {function(Object, string)} callback
* @this {ScriptFileStorage}
*/
$class.findApplicationRoot = function(mainScriptFile, callback) {
fs.realpath(mainScriptFile, function(err, realPath) {
if (err) {
console.log('Cannot resolve real path of %s: %s', mainScriptFile, err);
realPath = mainScriptFile;
}
this._findApplicationRootForRealFile(realPath, callback);
}.bind(this));
};
/**
* For a given script file, find the root directory containing all application
* source files.
*
* Example:
* file = ~/work/app/bin/cli.js
* root = ~/work/app
*
* The algorithm:
*
* By default, we assume that the source file is in the root directory
* (~/work/app/bin in the example above).
*
* If this directory does not contain 'package.json' and the parent directory
* contains 'package.json', then we assume the parent directory is
* the application root (~/work/app in the example above).
*
* @param {string} file
* @param {function(Object, string)} callback
* @this {ScriptFileStorage}
*/
$class._findApplicationRootForRealFile = function(file, callback) {
var mainDir = path.dirname(file);
var parentDir = path.dirname(mainDir);
async.detect(
[mainDir, parentDir],
this._isApplicationRoot.bind(this),
function(result) {
callback(null, result || mainDir, !!result);
}
);
};
/**
* @param {string} folder
* @param {function(boolean)} callback
*/
$class._isApplicationRoot = function(folder, callback) {
fs.exists(path.join(folder, 'package.json'), callback);
};
/**
* @param {string} rootFolder
* @param {string} include
* @param {function(Object, Array.<string>?)} callback
*/
$class.listScripts = function(rootFolder, include, callback) {
// This simpler solution unfortunately does not work on windows
// see https://github.com/isaacs/node-glob/pull/68
// glob(
// '**/*.js',
// { root: rootFolder },
// callback
// );
debug('glob %s on %s', include, rootFolder);
var exclude = this._hidden;
list(rootFolder, include, exclude, function(error, result) {
if (result) {
result = result.map(function(unixPath) {
return unixPath.split('/').join(path.sep);
});
}
debug('glob returned %s files', error || result.length);
callback(error, result);
});
};
$class._findScriptsOfRunningApp = function(mainScriptFile, callback) {
if (!mainScriptFile) {
// mainScriptFile is null when running in the REPL mode
return process.nextTick(callback.bind(null, null, []));
}
async.waterfall(
[
this.findApplicationRoot.bind(this, mainScriptFile),
function(dir, isRoot, cb) {
var include = isRoot ? ALL_JS_PATTERN : CONVENTIONAL_DIRS_PATTERN;
this.listScripts(dir, include, cb);
}.bind(this)
],
callback
);
};
$class._findScriptsOfStartDirectoryApp = function(startDirectory, callback) {
this._isApplicationRoot(
startDirectory,
function handleIsStartDirectoryApplicationRoot(result) {
if (!result) {
callback(null, []);
} else {
this.listScripts(startDirectory, ALL_JS_PATTERN, callback);
}
}.bind(this)
);
};
/**
* @param {string} startDirectory
* @param {string} mainScriptFile
* @param {function(Object, Array.<string>)} callback
* @this {ScriptFileStorage}
*/
$class.findAllApplicationScripts = function(startDirectory, mainScriptFile, callback) {
if (this._noPreload) {
return process.nextTick(function() { callback(null, []); });
}
async.series(
[
this._findScriptsOfRunningApp.bind(this, mainScriptFile),
this._findScriptsOfStartDirectoryApp.bind(this, startDirectory)
],
function(err, results) {
if (err) return callback(err);
var files = results[0].concat(results[1]);
debug('findAllApplicationScripts returned %s files', files.length);
return callback(null, files);
}.bind(this)
);
};
var list = function(root, include, exclude, cb) {
include = include || [];
exclude = exclude || [];
var folders = [root];
var cache = {};
var list = [];
var node = null;
var realpaths = {};
iterator();
function iterator(error) {
if (error) console.warn('Access to ' + node + ' from ResourceTree denied. (' + error + ')');
if (folders.length) return iterate(node = folders.pop());
return cb(null, list);
}
function iterate(node) {
async.waterfall([
fs.readdir.bind(fs, node),
function(paths, cb) {
async.each(paths, function(child, cb) {
var apath = path.join(node, child);
var rpath = relative(apath);
fs.realpath(apath, realpaths, function(err, realpath) {
if (err) { return cb(err); }
if (cache[realpath] || excluded(rpath)) return cb();
cache[realpath] = true;
fs.stat(realpath, function(error, pstat) {
if (error) return cb(error);
if (pstat.isDirectory()) folders.push(realpath);
if (pstat.isFile() && included(rpath)) list.push(realpath);
cb();
});
});
}, cb);
}
], iterator);
}
function included(rpath) {
return include.some(function(rx) { return rx.test(rpath); });
}
function excluded(rpath) {
return exclude.some(function(rx) { return rx.test(rpath); });
}
function relative(apath) {
return path.relative(root, apath);
}
};
exports.ScriptFileStorage = ScriptFileStorage;