Socket
Socket
Sign inDemoInstall

eslint

Package Overview
Dependencies
101
Maintainers
4
Versions
357
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 8.26.0 to 8.27.0

lib/rules/no-empty-static-block.js

127

lib/cli-engine/formatters/html.js

@@ -46,81 +46,106 @@ /**

body {
font-family:Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size:16px;
font-weight:normal;
margin:0;
padding:0;
color:#333
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
font-size: 16px;
font-weight: normal;
margin: 0;
padding: 0;
color: #333;
}
#overview {
padding:20px 30px
padding: 20px 30px;
}
td, th {
padding:5px 10px
td,
th {
padding: 5px 10px;
}
h1 {
margin:0
margin: 0;
}
table {
margin:30px;
width:calc(100% - 60px);
max-width:1000px;
border-radius:5px;
border:1px solid #ddd;
border-spacing:0px;
margin: 30px;
width: calc(100% - 60px);
max-width: 1000px;
border-radius: 5px;
border: 1px solid #ddd;
border-spacing: 0;
}
th {
font-weight:400;
font-size:medium;
text-align:left;
cursor:pointer
font-weight: 400;
font-size: medium;
text-align: left;
cursor: pointer;
}
td.clr-1, td.clr-2, th span {
font-weight:700
td.clr-1,
td.clr-2,
th span {
font-weight: 700;
}
th span {
float:right;
margin-left:20px
float: right;
margin-left: 20px;
}
th span:after {
content:"";
clear:both;
display:block
th span::after {
content: "";
clear: both;
display: block;
}
tr:last-child td {
border-bottom:none
border-bottom: none;
}
tr td:first-child, tr td:last-child {
color:#9da0a4
tr td:first-child,
tr td:last-child {
color: #9da0a4;
}
#overview.bg-0, tr.bg-0 th {
color:#468847;
background:#dff0d8;
border-bottom:1px solid #d6e9c6
#overview.bg-0,
tr.bg-0 th {
color: #468847;
background: #dff0d8;
border-bottom: 1px solid #d6e9c6;
}
#overview.bg-1, tr.bg-1 th {
color:#f0ad4e;
background:#fcf8e3;
border-bottom:1px solid #fbeed5
#overview.bg-1,
tr.bg-1 th {
color: #f0ad4e;
background: #fcf8e3;
border-bottom: 1px solid #fbeed5;
}
#overview.bg-2, tr.bg-2 th {
color:#b94a48;
background:#f2dede;
border-bottom:1px solid #eed3d7
#overview.bg-2,
tr.bg-2 th {
color: #b94a48;
background: #f2dede;
border-bottom: 1px solid #eed3d7;
}
td {
border-bottom:1px solid #ddd
border-bottom: 1px solid #ddd;
}
td.clr-1 {
color:#f0ad4e
color: #f0ad4e;
}
td.clr-2 {
color:#b94a48
color: #b94a48;
}
td a {
color:#3a33d1;
text-decoration:none
color: #3a33d1;
text-decoration: none;
}
td a:hover {
color:#272296;
text-decoration:underline
color: #272296;
text-decoration: underline;
}

@@ -218,3 +243,3 @@ </style>

return `
<tr style="display:none" class="f-${parentIndex}">
<tr style="display: none;" class="f-${parentIndex}">
<td>${lineNumber}:${columnNumber}</td>

@@ -221,0 +246,0 @@ <td class="clr-${severityNumber}">${severityName}</td>

@@ -31,2 +31,13 @@ /**

//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
/**
* @typedef {Object} GlobSearch
* @property {Array<string>} patterns The normalized patterns to use for a search.
* @property {Array<string>} rawPatterns The patterns as entered by the user
* before doing any normalization.
*/
//-----------------------------------------------------------------------------
// Errors

@@ -52,2 +63,26 @@ //-----------------------------------------------------------------------------

/**
* The error type when a search fails to match multiple patterns.
*/
class UnmatchedSearchPatternsError extends Error {
/**
* @param {Object} options The options for the error.
* @param {string} options.basePath The directory that was searched.
* @param {Array<string>} options.unmatchedPatterns The glob patterns
* which were not found.
* @param {Array<string>} options.patterns The glob patterns that were
* searched.
* @param {Array<string>} options.rawPatterns The raw glob patterns that
* were searched.
*/
constructor({ basePath, unmatchedPatterns, patterns, rawPatterns }) {
super(`No files matching '${rawPatterns}' in '${basePath}' were found.`);
this.basePath = basePath;
this.patternsToCheck = unmatchedPatterns;
this.patterns = patterns;
this.rawPatterns = rawPatterns;
}
}
/**
* The error type when there are files matched by a glob, but all of them have been ignored.

@@ -112,3 +147,66 @@ */

/**
* Determines if a given glob pattern will return any results.
* Used primarily to help with useful error messages.
* @param {Object} options The options for the function.
* @param {string} options.basePath The directory to search.
* @param {string} options.pattern A glob pattern to match.
* @returns {Promise<boolean>} True if there is a glob match, false if not.
*/
function globMatch({ basePath, pattern }) {
let found = false;
const patternToUse = path.isAbsolute(pattern)
? normalizeToPosix(path.relative(basePath, pattern))
: pattern;
const matcher = new Minimatch(patternToUse);
const fsWalkSettings = {
deepFilter(entry) {
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
return !found && matcher.match(relativePath, true);
},
entryFilter(entry) {
if (found || entry.dirent.isDirectory()) {
return false;
}
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
if (matcher.match(relativePath)) {
found = true;
return true;
}
return false;
}
};
return new Promise(resolve => {
// using a stream so we can exit early because we just need one match
const globStream = fswalk.walkStream(basePath, fsWalkSettings);
globStream.on("data", () => {
globStream.destroy();
resolve(true);
});
// swallow errors as they're not important here
globStream.on("error", () => { });
globStream.on("end", () => {
resolve(false);
});
globStream.read();
});
}
/**
* Searches a directory looking for matching glob patterns. This uses

@@ -122,8 +220,20 @@ * the config array's logic to determine if a directory or file should

* to match.
* @param {Array<string>} options.rawPatterns An array of glob patterns
* as the user inputted them. Used for errors.
* @param {FlatConfigArray} options.configs The config array to use for
* determining what to ignore.
* @param {boolean} options.errorOnUnmatchedPattern Determines if an error
* should be thrown when a pattern is unmatched.
* @returns {Promise<Array<string>>} An array of matching file paths
* or an empty array if there are no matches.
* @throws {UnmatchedSearchPatternsErrror} If there is a pattern that doesn't
* match any files.
*/
async function globSearch({ basePath, patterns, configs }) {
async function globSearch({
basePath,
patterns,
rawPatterns,
configs,
errorOnUnmatchedPattern
}) {

@@ -134,3 +244,16 @@ if (patterns.length === 0) {

const matchers = patterns.map(pattern => {
/*
* In this section we are converting the patterns into Minimatch
* instances for performance reasons. Because we are doing the same
* matches repeatedly, it's best to compile those patterns once and
* reuse them multiple times.
*
* To do that, we convert any patterns with an absolute path into a
* relative path and normalize it to Posix-style slashes. We also keep
* track of the relative patterns to map them back to the original
* patterns, which we need in order to throw an error if there are any
* unmatched patterns.
*/
const relativeToPatterns = new Map();
const matchers = patterns.map((pattern, i) => {
const patternToUse = path.isAbsolute(pattern)

@@ -140,7 +263,18 @@ ? normalizeToPosix(path.relative(basePath, pattern))

relativeToPatterns.set(patternToUse, patterns[i]);
return new minimatch.Minimatch(patternToUse);
});
return (await doFsWalk(basePath, {
/*
* We track unmatched patterns because we may want to throw an error when
* they occur. To start, this set is initialized with all of the patterns.
* Every time a match occurs, the pattern is removed from the set, making
* it easy to tell if we have any unmatched patterns left at the end of
* search.
*/
const unmatchedPatterns = new Set([...relativeToPatterns.keys()]);
const filePaths = (await doFsWalk(basePath, {
deepFilter(entry) {

@@ -160,90 +294,173 @@ const relativePath = normalizeToPosix(path.relative(basePath, entry.path));

const matchesPattern = matchers.some(matcher => matcher.match(relativePath));
/*
* Optimization: We need to track when patterns are left unmatched
* and so we use `unmatchedPatterns` to do that. There is a bit of
* complexity here because the same file can be matched by more than
* one pattern. So, when we start, we actually need to test every
* pattern against every file. Once we know there are no remaining
* unmatched patterns, then we can switch to just looking for the
* first matching pattern for improved speed.
*/
const matchesPattern = unmatchedPatterns.size > 0
? matchers.reduce((previousValue, matcher) => {
const pathMatches = matcher.match(relativePath);
/*
* We updated the unmatched patterns set only if the path
* matches and the file isn't ignored. If the file is
* ignored, that means there wasn't a match for the
* pattern so it should not be removed.
*
* Performance note: isFileIgnored() aggressively caches
* results so there is no performance penalty for calling
* it twice with the same argument.
*/
if (pathMatches && !configs.isFileIgnored(entry.path)) {
unmatchedPatterns.delete(matcher.pattern);
}
return pathMatches || previousValue;
}, false)
: matchers.some(matcher => matcher.match(relativePath));
return matchesPattern && !configs.isFileIgnored(entry.path);
}
})).map(entry => entry.path);
// now check to see if we have any unmatched patterns
if (errorOnUnmatchedPattern && unmatchedPatterns.size > 0) {
throw new UnmatchedSearchPatternsError({
basePath,
unmatchedPatterns: [...unmatchedPatterns].map(
pattern => relativeToPatterns.get(pattern)
),
patterns,
rawPatterns
});
}
return filePaths;
}
/**
* Checks to see if there are any ignored results for a given search. This
* happens either when there are unmatched patterns during a search or if
* a search returns no results.
* @param {Object} options The options for this function.
* @param {string} options.basePath The directory to search.
* @param {Array<string>} options.patterns An array of glob patterns
* that were used in the original search.
* @param {Array<string>} options.rawPatterns An array of glob patterns
* as the user inputted them. Used for errors.
* @param {Array<string>} options.patternsToCheck An array of glob patterns
* to use for this check.
* @returns {void}
* @throws {NoFilesFoundError} If there is a pattern that doesn't match
* any files and `errorOnUnmatchedPattern` is true.
* @throws {AllFilesIgnoredError} If there is a pattern that matches files
* when there are no ignores.
*/
async function checkForIgnoredResults({
basePath,
patterns,
rawPatterns,
patternsToCheck = patterns
}) {
for (const pattern of patternsToCheck) {
const patternHasMatch = await globMatch({
basePath,
pattern
});
if (patternHasMatch) {
throw new AllFilesIgnoredError(
rawPatterns[patterns.indexOf(pattern)]
);
}
}
// if we get here there are truly no matches
throw new NoFilesFoundError(
rawPatterns[patterns.indexOf(patternsToCheck[0])],
true
);
}
/**
* Performs multiple glob searches in parallel.
* @param {Object} options The options for this function.
* @param {Array<{patterns:Array<string>,rawPatterns:Array<string>}>} options.searches
* @param {Map<string,GlobSearch>} options.searches
* An array of glob patterns to match.
* @param {FlatConfigArray} options.configs The config array to use for
* determining what to ignore.
* @param {boolean} options.errorOnUnmatchedPattern Determines if an
* unmatched glob pattern should throw an error.
* @returns {Promise<Array<string>>} An array of matching file paths
* or an empty array if there are no matches.
*/
async function globMultiSearch({ searches, configs }) {
async function globMultiSearch({ searches, configs, errorOnUnmatchedPattern }) {
const results = await Promise.all(
[...searches].map(
([basePath, { patterns }]) => globSearch({ basePath, patterns, configs })
/*
* For convenience, we normalized the search map into an array of objects.
* Next, we filter out all searches that have no patterns. This happens
* primarily for the cwd, which is prepopulated in the searches map as an
* optimization. However, if it has no patterns, it means all patterns
* occur outside of the cwd and we can safely filter out that search.
*/
const normalizedSearches = [...searches].map(
([basePath, { patterns, rawPatterns }]) => ({ basePath, patterns, rawPatterns })
).filter(({ patterns }) => patterns.length > 0);
const results = await Promise.allSettled(
normalizedSearches.map(
({ basePath, patterns, rawPatterns }) => globSearch({
basePath,
patterns,
rawPatterns,
configs,
errorOnUnmatchedPattern
})
)
);
return [...new Set(results.flat())];
}
const filePaths = [];
/**
* Determines if a given glob pattern will return any results.
* Used primarily to help with useful error messages.
* @param {Object} options The options for the function.
* @param {string} options.basePath The directory to search.
* @param {string} options.pattern A glob pattern to match.
* @returns {Promise<boolean>} True if there is a glob match, false if not.
*/
function globMatch({ basePath, pattern }) {
for (let i = 0; i < results.length; i++) {
let found = false;
const patternToUse = path.isAbsolute(pattern)
? normalizeToPosix(path.relative(basePath, pattern))
: pattern;
const result = results[i];
const currentSearch = normalizedSearches[i];
const matcher = new Minimatch(patternToUse);
if (result.status === "fulfilled") {
const fsWalkSettings = {
deepFilter(entry) {
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
return !found && matcher.match(relativePath, true);
},
entryFilter(entry) {
if (found || entry.dirent.isDirectory()) {
return false;
// if the search was successful just add the results
if (result.value.length > 0) {
filePaths.push(...result.value);
}
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
continue;
}
if (matcher.match(relativePath)) {
found = true;
return true;
}
// if we make it here then there was an error
const error = result.reason;
return false;
// unexpected errors should be re-thrown
if (!error.basePath) {
throw error;
}
};
return new Promise(resolve => {
if (errorOnUnmatchedPattern) {
// using a stream so we can exit early because we just need one match
const globStream = fswalk.walkStream(basePath, fsWalkSettings);
await checkForIgnoredResults({
...currentSearch,
patternsToCheck: error.patternsToCheck
});
globStream.on("data", () => {
globStream.destroy();
resolve(true);
});
}
// swallow errors as they're not important here
globStream.on("error", () => {});
}
globStream.on("end", () => {
resolve(false);
});
globStream.read();
});
return [...new Set(filePaths)];

@@ -345,38 +562,2 @@ }

const globbyResults = await globMultiSearch({
searches,
configs
});
// if there are no results, tell the user why
if (!results.length && !globbyResults.length) {
for (const [basePath, { patterns: patternsToCheck, rawPatterns: patternsToReport }] of searches) {
let index = 0;
// try globby without ignoring anything
for (const patternToCheck of patternsToCheck) {
// check if there are any matches at all
const patternHasMatch = await globMatch({
basePath,
pattern: patternToCheck
});
if (patternHasMatch) {
throw new AllFilesIgnoredError(patternsToReport[index]);
}
// otherwise no files were found
if (errorOnUnmatchedPattern) {
throw new NoFilesFoundError(patternsToReport[index], globInputPaths);
}
index++;
}
}
}
// there were patterns that didn't match anything, tell the user

@@ -387,2 +568,8 @@ if (errorOnUnmatchedPattern && missingPatterns.length) {

// now we are safe to do the search
const globbyResults = await globMultiSearch({
searches,
configs,
errorOnUnmatchedPattern
});

@@ -389,0 +576,0 @@ return [

@@ -164,2 +164,12 @@ /**

/**
* Return the absolute path of a file named `"__placeholder__.js"` in a given directory.
* This is used as a replacement for a missing file path.
* @param {string} cwd An absolute directory path.
* @returns {string} The absolute path of a file named `"__placeholder__.js"` in the given directory.
*/
function getPlaceholderPath(cwd) {
return path.join(cwd, "__placeholder__.js");
}
/** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */

@@ -181,3 +191,3 @@ const usedDeprecatedRulesCache = new WeakMap();

? maybeFilePath
: path.join(cwd, "__placeholder__.js");
: getPlaceholderPath(cwd);
const config = configs.getConfig(filePath);

@@ -427,3 +437,3 @@

*/
const filePathToVerify = filePath === "<text>" ? path.join(cwd, "__placeholder__.js") : filePath;
const filePathToVerify = filePath === "<text>" ? getPlaceholderPath(cwd) : filePath;
const { fixed, messages, output } = linter.verifyAndFix(

@@ -525,2 +535,10 @@ text,

/**
* Creates an error to be thrown when an array of results passed to `getRulesMetaForResults` was not created by the current engine.
* @returns {TypeError} An error object.
*/
function createExtraneousResultsError() {
return new TypeError("Results object was not created from this ESLint instance.");
}
//-----------------------------------------------------------------------------

@@ -662,3 +680,6 @@ // Main API

const resultRules = new Map();
const { configs } = privateMembers.get(this);
const {
configs,
options: { cwd }
} = privateMembers.get(this);

@@ -672,3 +693,3 @@ /*

if (!configs) {
throw new TypeError("Results object was not created from this ESLint instance.");
throw createExtraneousResultsError();
}

@@ -682,9 +703,3 @@

const filePath = result.filePath === "<text>"
? "__placeholder__.js" : result.filePath;
/*
* All of the plugin and rule information is contained within the
* calculated config for the given file.
*/
const config = configs.getConfig(filePath);
? getPlaceholderPath(cwd) : result.filePath;
const allMessages = result.messages.concat(result.suppressedMessages);

@@ -697,2 +712,11 @@

/*
* All of the plugin and rule information is contained within the
* calculated config for the given file.
*/
const config = configs.getConfig(filePath);
if (!config) {
throw createExtraneousResultsError();
}
const rule = getRuleFromConfig(ruleId, config);

@@ -1035,3 +1059,3 @@

// TODO: This is pretty dirty...would be nice to clean up at some point.
formatterPath = ModuleResolver.resolve(npmFormat, path.join(cwd, "__placeholder__.js"));
formatterPath = ModuleResolver.resolve(npmFormat, getPlaceholderPath(cwd));
} catch {

@@ -1038,0 +1062,0 @@ formatterPath = path.resolve(__dirname, "../", "cli-engine", "formatters", `${normalizedFormatName}.js`);

@@ -53,3 +53,3 @@ /**

exports: optionValue,
functions: (!ecmaVersion || ecmaVersion < 8) ? "ignore" : optionValue
functions: ecmaVersion < 2017 ? "ignore" : optionValue
};

@@ -138,3 +138,3 @@ }

create(context) {
const options = normalizeOptions(context.options[0], context.parserOptions.ecmaVersion);
const options = normalizeOptions(context.options[0], context.languageOptions.ecmaVersion);

@@ -141,0 +141,0 @@ const sourceCode = context.getSourceCode();

@@ -47,3 +47,3 @@ /**

function isIdentifier(name, ecmaVersion) {
if (ecmaVersion >= 6) {
if (ecmaVersion >= 2015) {
return esutils.keyword.isIdentifierES6(name);

@@ -108,3 +108,3 @@ }

const includeModuleExports = options.includeCommonJSModuleExports;
const ecmaVersion = context.parserOptions && context.parserOptions.ecmaVersion ? context.parserOptions.ecmaVersion : 5;
const ecmaVersion = context.languageOptions.ecmaVersion;

@@ -111,0 +111,0 @@ /**

@@ -126,2 +126,3 @@ /**

"no-empty-pattern": () => require("./no-empty-pattern"),
"no-empty-static-block": () => require("./no-empty-static-block"),
"no-eq-null": () => require("./no-eq-null"),

@@ -171,2 +172,3 @@ "no-eval": () => require("./no-eval"),

"no-new-func": () => require("./no-new-func"),
"no-new-native-nonconstructor": () => require("./no-new-native-nonconstructor"),
"no-new-object": () => require("./no-new-object"),

@@ -173,0 +175,0 @@ "no-new-require": () => require("./no-new-require"),

@@ -20,2 +20,3 @@ /**

meta: {
hasSuggestions: true,
type: "suggestion",

@@ -43,3 +44,4 @@

messages: {
unexpected: "Empty {{type}} statement."
unexpected: "Empty {{type}} statement.",
suggestComment: "Add comment inside empty {{type}} statement."
}

@@ -76,3 +78,18 @@ },

context.report({ node, messageId: "unexpected", data: { type: "block" } });
context.report({
node,
messageId: "unexpected",
data: { type: "block" },
suggest: [
{
messageId: "suggestComment",
data: { type: "block" },
fix(fixer) {
const range = [node.range[0] + 1, node.range[1] - 1];
return fixer.replaceTextRange(range, " /* empty */ ");
}
}
]
});
},

@@ -79,0 +96,0 @@

@@ -196,6 +196,6 @@ /**

function isValidWithUnicodeFlag(pattern) {
const { ecmaVersion } = context.parserOptions;
const { ecmaVersion } = context.languageOptions;
// ecmaVersion is unknown or it doesn't support the 'u' flag
if (typeof ecmaVersion !== "number" || ecmaVersion <= 5) {
// ecmaVersion <= 5 doesn't support the 'u' flag
if (ecmaVersion <= 5) {
return false;

@@ -205,3 +205,3 @@ }

const validator = new RegExpValidator({
ecmaVersion: Math.min(ecmaVersion + 2009, REGEXPP_LATEST_ECMA_VERSION)
ecmaVersion: Math.min(ecmaVersion, REGEXPP_LATEST_ECMA_VERSION)
});

@@ -208,0 +208,0 @@

@@ -251,10 +251,10 @@ /**

* Returns a ecmaVersion compatible for regexpp.
* @param {any} ecmaVersion The ecmaVersion to convert.
* @param {number} ecmaVersion The ecmaVersion to convert.
* @returns {import("regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp.
*/
function getRegexppEcmaVersion(ecmaVersion) {
if (typeof ecmaVersion !== "number" || ecmaVersion <= 5) {
if (ecmaVersion <= 5) {
return 5;
}
return Math.min(ecmaVersion + 2009, REGEXPP_LATEST_ECMA_VERSION);
return Math.min(ecmaVersion, REGEXPP_LATEST_ECMA_VERSION);
}

@@ -324,3 +324,3 @@

const regexppEcmaVersion = getRegexppEcmaVersion(context.parserOptions.ecmaVersion);
const regexppEcmaVersion = getRegexppEcmaVersion(context.languageOptions.ecmaVersion);
const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: regexppEcmaVersion });

@@ -327,0 +327,0 @@

{
"name": "eslint",
"version": "8.26.0",
"version": "8.27.0",
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",

@@ -5,0 +5,0 @@ "description": "An AST-based pattern checker for JavaScript.",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc