Skip to content

Commit eb4609a

Browse files
committed
[[FIX]] Remove shelljs
The "shelljs" package upon which JSHint depends includes a security vulnerability [1]. Futhermore, that package's coupling to Node.js runs contrary to JSHint's goal to support the Rhino runtime. Replace the package with a minimal implementation. This commit was forcibly pushed to the main development branch in order to correct a formatting error in the original version. [1] #3599
1 parent b23e125 commit eb4609a

File tree

5 files changed

+253
-204
lines changed

5 files changed

+253
-204
lines changed

package-lock.json

-17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
"htmlparser2": "3.8.x",
4747
"lodash": "~4.17.21",
4848
"minimatch": "~3.0.2",
49-
"shelljs": "0.3.x",
5049
"strip-json-comments": "1.0.x"
5150
},
5251
"devDependencies": {

src/cli.js

+15-15
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
var _ = require("lodash");
44
var cli = require("cli");
55
var path = require("path");
6-
var shjs = require("shelljs");
76
var minimatch = require("minimatch");
87
var htmlparser = require("htmlparser2");
98
var exit = require("exit");
109
var stripJsonComments = require("strip-json-comments");
1110
var JSHINT = require("./jshint.js").JSHINT;
1211
var defReporter = require("./reporters/default").reporter;
12+
var fsUtils = require("./fs-utils");
1313

1414
var OPTIONS = {
1515
"config": ["c", "Custom configuration file", "string", false ],
@@ -89,7 +89,7 @@ function findConfig(file) {
8989
else if (envs) {
9090
home = path.normalize(path.join(envs, ".jshintrc"));
9191

92-
if (shjs.test("-e", home))
92+
if (fsUtils.exists(home))
9393
return home;
9494
}
9595

@@ -108,7 +108,7 @@ function getHomeDir() {
108108

109109
while (paths.length) {
110110
homePath = paths.shift();
111-
if (homePath && shjs.test("-e", homePath)) {
111+
if (fsUtils.exists(homePath)) {
112112
return homePath;
113113
}
114114
}
@@ -177,7 +177,7 @@ function findFile(name, cwd) {
177177

178178
var parent = path.resolve(cwd, "../");
179179

180-
if (shjs.test("-e", filename)) {
180+
if (fsUtils.exists(filename)) {
181181
findFileResults[filename] = filename;
182182
return filename;
183183
}
@@ -203,7 +203,7 @@ function loadIgnores(params) {
203203
return [];
204204
}
205205

206-
var lines = (file ? shjs.cat(file) : "").split("\n");
206+
var lines = (file ? fsUtils.readFile(file) : "").split("\n");
207207
var exclude = params.exclude || "";
208208
lines.unshift.apply(lines, exclude.split(","));
209209

@@ -237,7 +237,7 @@ function isIgnored(fp, patterns) {
237237
return true;
238238
}
239239

240-
if (shjs.test("-d", fp) && ip.match(/^[^\/\\]*[\/\\]?$/) &&
240+
if (fsUtils.isDirectory(fp) && ip.match(/^[^\/\\]*[\/\\]?$/) &&
241241
fp.match(new RegExp("^" + ip + ".*"))) {
242242
return true;
243243
}
@@ -419,15 +419,15 @@ function collect(fp, files, ignores, ext) {
419419
return;
420420
}
421421

422-
if (!shjs.test("-e", fp)) {
422+
if (!fsUtils.exists(fp)) {
423423
cli.error("Can't open " + fp);
424424
return;
425425
}
426426

427-
if (shjs.test("-d", fp)) {
428-
shjs.ls(fp).forEach(function(item) {
427+
if (fsUtils.isDirectory(fp)) {
428+
fsUtils.readDirectory(fp).forEach(function(item) {
429429
var itempath = path.join(fp, item);
430-
if (shjs.test("-d", itempath) || item.match(ext)) {
430+
if (fsUtils.isDirectory(itempath) || item.match(ext)) {
431431
collect(itempath, files, ignores, ext);
432432
}
433433
});
@@ -458,8 +458,8 @@ function lint(code, results, config, data, file) {
458458
if (config.prereq) {
459459
config.prereq.forEach(function(fp) {
460460
fp = path.join(config.dirname, fp);
461-
if (shjs.test("-e", fp))
462-
buffer.push(shjs.cat(fp));
461+
if (fsUtils.exists(fp))
462+
buffer.push(fsUtils.readFile(fp));
463463
});
464464
delete config.prereq;
465465
}
@@ -529,13 +529,13 @@ var exports = {
529529
return {};
530530
}
531531

532-
if (!shjs.test("-e", fp)) {
532+
if (!fsUtils.exists(fp)) {
533533
cli.error("Can't find config file: " + fp);
534534
exports.exit(1);
535535
}
536536

537537
try {
538-
var config = JSON.parse(stripJsonComments(shjs.cat(fp)));
538+
var config = JSON.parse(stripJsonComments(fsUtils.readFile(fp)));
539539
config.dirname = path.dirname(fp);
540540

541541
if (config['extends']) {
@@ -653,7 +653,7 @@ var exports = {
653653
var errors = [];
654654

655655
try {
656-
code = shjs.cat(file);
656+
code = fsUtils.readFile(file);
657657
} catch (err) {
658658
cli.error("Can't open " + file);
659659
exports.exit(1);

src/fs-utils.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"use strict";
2+
3+
var fs = require("fs");
4+
5+
/**
6+
* Determine if a file or directory is present at the given filesystem path.
7+
*
8+
* @param {string} name
9+
*
10+
* @returns {boolean}
11+
*/
12+
exports.exists = function(name) {
13+
return fs.existsSync(name);
14+
};
15+
16+
/**
17+
* Determine if a directory is present at the given filesystem path.
18+
*
19+
* @param {string} name
20+
*
21+
* @returns {boolean}
22+
*/
23+
exports.isDirectory = function(name) {
24+
var stat;
25+
try {
26+
stat = fs.statSync(name);
27+
} catch (error) {
28+
if (error.code === "ENOENT") {
29+
return false;
30+
}
31+
32+
throw error;
33+
}
34+
35+
return stat.isDirectory();
36+
};
37+
38+
/**
39+
* Read a UTF-8-encoded file.
40+
*
41+
* @param {string} name
42+
*
43+
* @returns {string}
44+
*/
45+
exports.readFile = function(name) {
46+
return fs.readFileSync(name, "utf8");
47+
};
48+
49+
/**
50+
* Retrieve the name of the files and directories within a given directory.
51+
*
52+
* @param {string} name
53+
*
54+
* @returns {string[]}
55+
*/
56+
exports.readDirectory = function(name) {
57+
return fs.readdirSync(name)
58+
.filter(function(name) {
59+
return name[0] !== ".";
60+
});
61+
};

0 commit comments

Comments
 (0)