Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jshint/jshint
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2.13.3
Choose a base ref
...
head repository: jshint/jshint
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2.13.4
Choose a head ref
  • 6 commits
  • 12 files changed
  • 1 contributor

Commits on Jan 18, 2022

  1. [[CHORE]] Update version of package manifest (#3602)

    This changeset was generated automatically by the npm utility via the
    following command:
    
        $ npm install
    jugglinmike authored Jan 18, 2022
    Copy the full SHA
    a53cc95 View commit details

Commits on Jan 19, 2022

  1. Copy the full SHA
    33cfc87 View commit details

Commits on Jan 24, 2022

  1. [[CHORE]] Use consistent interface for fs ops

    The CLI uses the build-in Node.js `fs` module to test for the presence
    of a directory in one case. In all other instances, the CLI used the
    "shelljs" package. Switch to using "shelljs" consistently to better
    facilitate a forthcoming removal of that package.
    jugglinmike authored and rwaldron committed Jan 24, 2022
    Copy the full SHA
    56d4a47 View commit details
  2. [[CHORE]] Remove shelljs from internal tooling

    The "shelljs" package upon which JSHint depends includes a security
    vulnerability [1]. Remove it from the project's internal tooling as part
    of a larger effort to remove it entirely.
    
    [1] #3599
    jugglinmike authored and rwaldron committed Jan 24, 2022
    Copy the full SHA
    b23e125 View commit details
  3. [[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
    jugglinmike committed Jan 24, 2022
    Copy the full SHA
    eb4609a View commit details
  4. v2.13.4

    jugglinmike committed Jan 24, 2022
    Copy the full SHA
    61c868c View commit details
Showing with 9,250 additions and 321 deletions.
  1. +102 −0 .circleci/config.yml
  2. +0 −43 .travis.yml
  3. +7 −0 CHANGELOG.md
  4. +6 −7 bin/build
  5. +2 −2 bin/land
  6. +58 −10 dist/jshint-rhino.js
  7. +58 −10 dist/jshint.js
  8. +8,759 −60 package-lock.json
  9. +1 −2 package.json
  10. +15 −16 src/cli.js
  11. +61 −0 src/fs-utils.js
  12. +181 −171 tests/cli.js
102 changes: 102 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1

jobs:
# This configuration caches the contents of the `node_modules` aggressively
# because not all npm dependencies can be successfully installed in all
# supported releases of Node.js (e.g. `puppeteer` and `cli-table`) and
# because older releases of Node.js do not support the latest version of the
# `package-lock.json` file.
install:
docker:
- image: node:10-stretch
steps:
- checkout
- run:
name: install packages
command: npm ci
- save_cache:
key: node-deps-v2-{{ .Branch }}-{{checksum "package-lock.json"}}
paths:
- node_modules
test-with-latest-nodejs:
parameters:
npm-run-script:
type: string
docker:
- image: node:10-stretch
steps:
- checkout
- restore_cache:
keys:
- node-deps-v2-{{ .Branch }}-{{checksum "package-lock.json"}}
- when:
condition:
equal: [<< parameters.npm-run-script >>, test-262]
steps:
- run: git submodule sync
- run: git submodule update --init
- run:
name: run tests
command: npm run << parameters.npm-run-script >>

test-with-legacy-nodejs:
parameters:
nodejs_version:
type: string
docker:
- image: node:<< parameters.nodejs_version >>
steps:
- checkout
- restore_cache:
keys:
- node-deps-v2-{{ .Branch }}-{{checksum "package-lock.json"}}
- run:
name: run tests
command: npm run test-node

workflows:
orb-free-workflow:
jobs:
- install
- test-with-latest-nodejs:
name: Unit tests in latest release of Node.js
requires: [install]
npm-run-script: test-node
- test-with-latest-nodejs:
name: Test262
requires: [install]
npm-run-script: test-262
- test-with-latest-nodejs:
name: Static analysis of source code
requires: [install]
npm-run-script: pretest
- test-with-latest-nodejs:
name: Unit tests in a web browser
requires: [install]
npm-run-script: test-browser
- test-with-latest-nodejs:
name: Tests for jshint.com website
requires: [install]
npm-run-script: test-website
- test-with-legacy-nodejs:
name: Unit tests in Node.js version 0.10
requires: [install]
nodejs_version: '0.10'
- test-with-legacy-nodejs:
name: Unit tests in Node.js version 0.12
requires: [install]
nodejs_version: 0.12.0
- test-with-legacy-nodejs:
name: Unit tests in Node.js version 4.0
requires: [install]
nodejs_version: 4.0.0
- test-with-legacy-nodejs:
name: Unit tests in Node.js version 6.0
requires: [install]
nodejs_version: 6.0.0
- test-with-legacy-nodejs:
name: Unit tests in Node.js version 8.0
requires: [install]
nodejs_version: 8.0.0
43 changes: 0 additions & 43 deletions .travis.yml

This file was deleted.

7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
<a name="2.13.4"></a>
## [2.13.4](https://github.com/jshint/jshint/compare/2.13.3...v2.13.4) (2022-01-24)

### Bug Fixes

* Remove shelljs ([eb4609a](https://github.com/jshint/jshint/commit/eb4609a))

<a name="2.13.3"></a>
## [2.13.3](https://github.com/jshint/jshint/compare/2.13.2...v2.13.3) (2022-01-05)

13 changes: 6 additions & 7 deletions bin/build
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
#!/usr/bin/env node
/*jshint shelljs:true */

"use strict";

var fs = require("fs");
var path = require("path");
var build = require("../scripts/build");
require("shelljs/make");

var distDir = path.join(__dirname, "../dist");

if (!test("-e", distDir))
mkdir(distDir);
if (!fs.existsSync(distDir))
fs.mkdirSync(distDir);

build("web", function(err, version, src) {
if (err) {
console.error(err);
process.exit(1);
}

src.to(distDir + "/jshint.js");
fs.writeFileSync(distDir + "/jshint.js", src, "utf8");
console.log("Built: " + version + " (web)");
});

@@ -31,8 +30,8 @@ build("rhino", function(err, version, src) {
}

dest = distDir + "/jshint-rhino.js";
chmod("+x", dest);

src.to(dest);
fs.writeFileSync(dest, src, "utf8");
fs.chmodSync(dest, "0775");
console.log("Built: " + version + " (Rhino)");
});
4 changes: 2 additions & 2 deletions bin/land
Original file line number Diff line number Diff line change
@@ -2,9 +2,9 @@

"use strict";

var child_process = require("child_process");
var url = "https://github.com/jshint/jshint/pull/" + process.argv[2] + ".patch";
var https = require("https");
var shjs = require("shelljs");
var opts = require("url").parse(url);
var msg = process.argv[3];

@@ -27,7 +27,7 @@ function succ(res) {
data = data[1].replace(/^From\:\s/, "");
data = data.replace(/"/g, "");

shjs.exec("git commit -s --author=\"" + data + "\" --message=\"" + msg + "\"");
child_process.execSync("git commit -s --author=\"" + data + "\" --message=\"" + msg + "\"");
});
}

68 changes: 58 additions & 10 deletions dist/jshint-rhino.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env rhino
var window = {};
/*! 2.13.3 */
/*! 2.13.4 */
var JSHINT;
if (typeof window === 'undefined') window = {};
(function () {
@@ -1442,14 +1442,15 @@ function isUndefined(arg) {
var undefined;

/** Used as the semantic version number. */
var VERSION = '4.17.20';
var VERSION = '4.17.21';

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Error message constants. */
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
FUNC_ERROR_TEXT = 'Expected a function';
FUNC_ERROR_TEXT = 'Expected a function',
INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';
@@ -1582,10 +1583,11 @@ function isUndefined(arg) {
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
reHasRegExpChar = RegExp(reRegExpChar.source);

/** Used to match leading and trailing whitespace. */
var reTrim = /^\s+|\s+$/g,
reTrimStart = /^\s+/,
reTrimEnd = /\s+$/;
/** Used to match leading whitespace. */
var reTrimStart = /^\s+/;

/** Used to match a single whitespace character. */
var reWhitespace = /\s/;

/** Used to match wrap detail comments. */
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
@@ -1595,6 +1597,18 @@ function isUndefined(arg) {
/** Used to match words composed of alphanumeric characters. */
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;

/**
* Used to validate the `validate` option in `_.template` variable.
*
* Forbids characters which could potentially change the meaning of the function argument definition:
* - "()," (modification of function parameters)
* - "=" (default value)
* - "[]{}" (destructuring of function parameters)
* - "/" (beginning of a comment)
* - whitespace
*/
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

@@ -2423,6 +2437,19 @@ function isUndefined(arg) {
});
}

/**
* The base implementation of `_.trim`.
*
* @private
* @param {string} string The string to trim.
* @returns {string} Returns the trimmed string.
*/
function baseTrim(string) {
return string
? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
: string;
}

/**
* The base implementation of `_.unary` without support for storing metadata.
*
@@ -2756,6 +2783,21 @@ function isUndefined(arg) {
: asciiToArray(string);
}

/**
* Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
* character of `string`.
*
* @private
* @param {string} string The string to inspect.
* @returns {number} Returns the index of the last non-whitespace character.
*/
function trimmedEndIndex(string) {
var index = string.length;

while (index-- && reWhitespace.test(string.charAt(index))) {}
return index;
}

/**
* Used by `_.unescape` to convert HTML entities to characters.
*
@@ -13924,7 +13966,7 @@ function isUndefined(arg) {
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
@@ -16296,6 +16338,12 @@ function isUndefined(arg) {
if (!variable) {
source = 'with (obj) {\n' + source + '\n}\n';
}
// Throw an error if a forbidden character was found in `variable`, to prevent
// potential command injection attacks.
else if (reForbiddenIdentifierChars.test(variable)) {
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
}

// Cleanup code by stripping empty strings.
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
.replace(reEmptyStringMiddle, '$1')
@@ -16409,7 +16457,7 @@ function isUndefined(arg) {
function trim(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
return string.replace(reTrim, '');
return baseTrim(string);
}
if (!string || !(chars = baseToString(chars))) {
return string;
@@ -16444,7 +16492,7 @@ function isUndefined(arg) {
function trimEnd(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
return string.replace(reTrimEnd, '');
return string.slice(0, trimmedEndIndex(string) + 1);
}
if (!string || !(chars = baseToString(chars))) {
return string;
68 changes: 58 additions & 10 deletions dist/jshint.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! 2.13.3 */
/*! 2.13.4 */
var JSHINT;
if (typeof window === 'undefined') window = {};
(function () {
@@ -1440,14 +1440,15 @@ function isUndefined(arg) {
var undefined;

/** Used as the semantic version number. */
var VERSION = '4.17.20';
var VERSION = '4.17.21';

/** Used as the size to enable large array optimizations. */
var LARGE_ARRAY_SIZE = 200;

/** Error message constants. */
var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
FUNC_ERROR_TEXT = 'Expected a function';
FUNC_ERROR_TEXT = 'Expected a function',
INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';

/** Used to stand-in for `undefined` hash values. */
var HASH_UNDEFINED = '__lodash_hash_undefined__';
@@ -1580,10 +1581,11 @@ function isUndefined(arg) {
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
reHasRegExpChar = RegExp(reRegExpChar.source);

/** Used to match leading and trailing whitespace. */
var reTrim = /^\s+|\s+$/g,
reTrimStart = /^\s+/,
reTrimEnd = /\s+$/;
/** Used to match leading whitespace. */
var reTrimStart = /^\s+/;

/** Used to match a single whitespace character. */
var reWhitespace = /\s/;

/** Used to match wrap detail comments. */
var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
@@ -1593,6 +1595,18 @@ function isUndefined(arg) {
/** Used to match words composed of alphanumeric characters. */
var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;

/**
* Used to validate the `validate` option in `_.template` variable.
*
* Forbids characters which could potentially change the meaning of the function argument definition:
* - "()," (modification of function parameters)
* - "=" (default value)
* - "[]{}" (destructuring of function parameters)
* - "/" (beginning of a comment)
* - whitespace
*/
var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;

/** Used to match backslashes in property paths. */
var reEscapeChar = /\\(\\)?/g;

@@ -2421,6 +2435,19 @@ function isUndefined(arg) {
});
}

/**
* The base implementation of `_.trim`.
*
* @private
* @param {string} string The string to trim.
* @returns {string} Returns the trimmed string.
*/
function baseTrim(string) {
return string
? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '')
: string;
}

/**
* The base implementation of `_.unary` without support for storing metadata.
*
@@ -2754,6 +2781,21 @@ function isUndefined(arg) {
: asciiToArray(string);
}

/**
* Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
* character of `string`.
*
* @private
* @param {string} string The string to inspect.
* @returns {number} Returns the index of the last non-whitespace character.
*/
function trimmedEndIndex(string) {
var index = string.length;

while (index-- && reWhitespace.test(string.charAt(index))) {}
return index;
}

/**
* Used by `_.unescape` to convert HTML entities to characters.
*
@@ -13922,7 +13964,7 @@ function isUndefined(arg) {
if (typeof value != 'string') {
return value === 0 ? value : +value;
}
value = value.replace(reTrim, '');
value = baseTrim(value);
var isBinary = reIsBinary.test(value);
return (isBinary || reIsOctal.test(value))
? freeParseInt(value.slice(2), isBinary ? 2 : 8)
@@ -16294,6 +16336,12 @@ function isUndefined(arg) {
if (!variable) {
source = 'with (obj) {\n' + source + '\n}\n';
}
// Throw an error if a forbidden character was found in `variable`, to prevent
// potential command injection attacks.
else if (reForbiddenIdentifierChars.test(variable)) {
throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
}

// Cleanup code by stripping empty strings.
source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
.replace(reEmptyStringMiddle, '$1')
@@ -16407,7 +16455,7 @@ function isUndefined(arg) {
function trim(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
return string.replace(reTrim, '');
return baseTrim(string);
}
if (!string || !(chars = baseToString(chars))) {
return string;
@@ -16442,7 +16490,7 @@ function isUndefined(arg) {
function trimEnd(string, chars, guard) {
string = toString(string);
if (string && (guard || chars === undefined)) {
return string.replace(reTrimEnd, '');
return string.slice(0, trimmedEndIndex(string) + 1);
}
if (!string || !(chars = baseToString(chars))) {
return string;
8,819 changes: 8,759 additions & 60 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jshint",
"version": "2.13.3",
"version": "2.13.4",
"homepage": "http://jshint.com/",
"description": "Static analysis tool for JavaScript",
"author": {
@@ -46,7 +46,6 @@
"htmlparser2": "3.8.x",
"lodash": "~4.17.21",
"minimatch": "~3.0.2",
"shelljs": "0.3.x",
"strip-json-comments": "1.0.x"
},
"devDependencies": {
31 changes: 15 additions & 16 deletions src/cli.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
"use strict";

var _ = require("lodash");
var fs = require("fs");
var cli = require("cli");
var path = require("path");
var shjs = require("shelljs");
var minimatch = require("minimatch");
var htmlparser = require("htmlparser2");
var exit = require("exit");
var stripJsonComments = require("strip-json-comments");
var JSHINT = require("./jshint.js").JSHINT;
var defReporter = require("./reporters/default").reporter;
var fsUtils = require("./fs-utils");

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

if (shjs.test("-e", home))
if (fsUtils.exists(home))
return home;
}

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

while (paths.length) {
homePath = paths.shift();
if (fs.existsSync(homePath)) {
if (fsUtils.exists(homePath)) {
return homePath;
}
}
@@ -178,7 +177,7 @@ function findFile(name, cwd) {

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

if (shjs.test("-e", filename)) {
if (fsUtils.exists(filename)) {
findFileResults[filename] = filename;
return filename;
}
@@ -204,7 +203,7 @@ function loadIgnores(params) {
return [];
}

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

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

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

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

if (shjs.test("-d", fp)) {
shjs.ls(fp).forEach(function(item) {
if (fsUtils.isDirectory(fp)) {
fsUtils.readDirectory(fp).forEach(function(item) {
var itempath = path.join(fp, item);
if (shjs.test("-d", itempath) || item.match(ext)) {
if (fsUtils.isDirectory(itempath) || item.match(ext)) {
collect(itempath, files, ignores, ext);
}
});
@@ -459,8 +458,8 @@ function lint(code, results, config, data, file) {
if (config.prereq) {
config.prereq.forEach(function(fp) {
fp = path.join(config.dirname, fp);
if (shjs.test("-e", fp))
buffer.push(shjs.cat(fp));
if (fsUtils.exists(fp))
buffer.push(fsUtils.readFile(fp));
});
delete config.prereq;
}
@@ -530,13 +529,13 @@ var exports = {
return {};
}

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

try {
var config = JSON.parse(stripJsonComments(shjs.cat(fp)));
var config = JSON.parse(stripJsonComments(fsUtils.readFile(fp)));
config.dirname = path.dirname(fp);

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

try {
code = shjs.cat(file);
code = fsUtils.readFile(file);
} catch (err) {
cli.error("Can't open " + file);
exports.exit(1);
61 changes: 61 additions & 0 deletions src/fs-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use strict";

var fs = require("fs");

/**
* Determine if a file or directory is present at the given filesystem path.
*
* @param {string} name
*
* @returns {boolean}
*/
exports.exists = function(name) {
return fs.existsSync(name);
};

/**
* Determine if a directory is present at the given filesystem path.
*
* @param {string} name
*
* @returns {boolean}
*/
exports.isDirectory = function(name) {
var stat;
try {
stat = fs.statSync(name);
} catch (error) {
if (error.code === "ENOENT") {
return false;
}

throw error;
}

return stat.isDirectory();
};

/**
* Read a UTF-8-encoded file.
*
* @param {string} name
*
* @returns {string}
*/
exports.readFile = function(name) {
return fs.readFileSync(name, "utf8");
};

/**
* Retrieve the name of the files and directories within a given directory.
*
* @param {string} name
*
* @returns {string[]}
*/
exports.readDirectory = function(name) {
return fs.readdirSync(name)
.filter(function(name) {
return name[0] !== ".";
});
};
352 changes: 181 additions & 171 deletions tests/cli.js

Large diffs are not rendered by default.