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.25.0 to 8.26.0

37

lib/cli.js

@@ -146,8 +146,2 @@ /**

if (ignorePattern) {
overrideConfig.push({
ignores: ignorePattern
});
}
} else {

@@ -191,3 +185,5 @@ overrideConfigFile = config;

if (configType !== "flat") {
if (configType === "flat") {
options.ignorePatterns = ignorePattern;
} else {
options.resolvePluginsRelativeTo = resolvePluginsRelativeTo;

@@ -284,2 +280,27 @@ options.rulePaths = rulesdir;

/**
* Returns whether flat config should be used.
* @param {boolean} [allowFlatConfig] Whether or not to allow flat config.
* @returns {Promise<boolean>} Where flat config should be used.
*/
async function shouldUseFlatConfig(allowFlatConfig) {
if (!allowFlatConfig) {
return false;
}
switch (process.env.ESLINT_USE_FLAT_CONFIG) {
case "true":
return true;
case "false":
return false;
default:
/*
* If neither explicitly enabled nor disabled, then use the presence
* of a flat config file to determine enablement.
*/
return !!(await findFlatConfigFile(process.cwd()));
}
}
//------------------------------------------------------------------------------

@@ -314,3 +335,3 @@ // Public Interface

const usingFlatConfig = allowFlatConfig && !!(await findFlatConfigFile(process.cwd()));
const usingFlatConfig = await shouldUseFlatConfig(allowFlatConfig);

@@ -317,0 +338,0 @@ debug("Using flat config?", usingFlatConfig);

@@ -55,3 +55,3 @@ /**

"**/node_modules/**",
".git/**"
".git/"
]

@@ -58,0 +58,0 @@ },

@@ -16,7 +16,17 @@ /**

const isGlob = require("is-glob");
const globby = require("globby");
const hash = require("../cli-engine/hash");
const minimatch = require("minimatch");
const util = require("util");
const fswalk = require("@nodelib/fs.walk");
const globParent = require("glob-parent");
const isPathInside = require("is-path-inside");
//-----------------------------------------------------------------------------
// Fixup references
//-----------------------------------------------------------------------------
const doFsWalk = util.promisify(fswalk.walk);
const Minimatch = minimatch.Minimatch;
//-----------------------------------------------------------------------------
// Errors

@@ -102,2 +112,137 @@ //-----------------------------------------------------------------------------

/**
* Searches a directory looking for matching glob patterns. This uses
* the config array's logic to determine if a directory or file should
* be ignored, so it is consistent with how ignoring works throughout
* ESLint.
* @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
* to match.
* @param {FlatConfigArray} options.configs The config array to use for
* determining what to ignore.
* @returns {Promise<Array<string>>} An array of matching file paths
* or an empty array if there are no matches.
*/
async function globSearch({ basePath, patterns, configs }) {
if (patterns.length === 0) {
return [];
}
const matchers = patterns.map(pattern => {
const patternToUse = path.isAbsolute(pattern)
? normalizeToPosix(path.relative(basePath, pattern))
: pattern;
return new minimatch.Minimatch(patternToUse);
});
return (await doFsWalk(basePath, {
deepFilter(entry) {
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
const matchesPattern = matchers.some(matcher => matcher.match(relativePath, true));
return matchesPattern && !configs.isDirectoryIgnored(entry.path);
},
entryFilter(entry) {
const relativePath = normalizeToPosix(path.relative(basePath, entry.path));
// entries may be directories or files so filter out directories
if (entry.dirent.isDirectory()) {
return false;
}
const matchesPattern = matchers.some(matcher => matcher.match(relativePath));
return matchesPattern && !configs.isFileIgnored(entry.path);
}
})).map(entry => entry.path);
}
/**
* Performs multiple glob searches in parallel.
* @param {Object} options The options for this function.
* @param {Array<{patterns:Array<string>,rawPatterns:Array<string>}>} options.searches
* An array of glob patterns to match.
* @param {FlatConfigArray} options.configs The config array to use for
* determining what to ignore.
* @returns {Promise<Array<string>>} An array of matching file paths
* or an empty array if there are no matches.
*/
async function globMultiSearch({ searches, configs }) {
const results = await Promise.all(
[...searches].map(
([basePath, { patterns }]) => globSearch({ basePath, patterns, configs })
)
);
return [...new Set(results.flat())];
}
/**
* 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();
});
}
/**
* Finds all files matching the options specified.

@@ -125,4 +270,6 @@ * @param {Object} args The arguments objects.

const results = [];
const globbyPatterns = [];
const missingPatterns = [];
let globbyPatterns = [];
let rawPatterns = [];
const searches = new Map([[cwd, { patterns: globbyPatterns, rawPatterns: [] }]]);

@@ -148,3 +295,3 @@ // check to see if we have explicit files and directories

filePath,
ignored: configs.isIgnored(filePath)
ignored: configs.isFileIgnored(filePath)
});

@@ -156,65 +303,14 @@ }

// filePatterns are all relative to cwd
const filePatterns = configs.files
.filter(filePattern => {
// can only do this for strings, not functions
if (typeof filePattern !== "string") {
return false;
}
// patterns starting with ** always apply
if (filePattern.startsWith("**")) {
return true;
}
// patterns ending with * are not used for file search
if (filePattern.endsWith("*")) {
return false;
}
// not sure how to handle negated patterns yet
if (filePattern.startsWith("!")) {
return false;
}
// check if the pattern would be inside the config base path or not
const fullFilePattern = path.join(cwd, filePattern);
const patternRelativeToConfigBasePath = path.relative(configs.basePath, fullFilePattern);
if (patternRelativeToConfigBasePath.startsWith("..")) {
return false;
}
// check if the pattern matches
if (minimatch(filePath, path.dirname(fullFilePattern), { partial: true })) {
return true;
}
// check if the pattern is inside the directory or not
const patternRelativeToFilePath = path.relative(filePath, fullFilePattern);
if (patternRelativeToFilePath.startsWith("..")) {
return false;
}
return true;
})
.map(filePattern => {
if (filePattern.startsWith("**")) {
return path.join(pattern, filePattern);
}
// adjust the path to be relative to the cwd
return path.relative(
cwd,
path.join(configs.basePath, filePattern)
);
})
.map(normalizeToPosix);
if (filePatterns.length) {
globbyPatterns.push(...filePatterns);
// group everything in cwd together and split out others
if (isPathInside(filePath, cwd)) {
({ patterns: globbyPatterns, rawPatterns } = searches.get(cwd));
} else {
if (!searches.has(filePath)) {
searches.set(filePath, { patterns: [], rawPatterns: [] });
}
({ patterns: globbyPatterns, rawPatterns } = searches.get(filePath));
}
globbyPatterns.push(`${normalizeToPosix(filePath)}/**`);
rawPatterns.push(pattern);
}

@@ -227,3 +323,17 @@

if (globInputPaths && isGlobPattern(filePath)) {
globbyPatterns.push(pattern);
const basePath = globParent(filePath);
// group in cwd if possible and split out others
if (isPathInside(basePath, cwd)) {
({ patterns: globbyPatterns, rawPatterns } = searches.get(cwd));
} else {
if (!searches.has(basePath)) {
searches.set(basePath, { patterns: [], rawPatterns: [] });
}
({ patterns: globbyPatterns, rawPatterns } = searches.get(basePath));
}
globbyPatterns.push(filePath);
rawPatterns.push(pattern);
} else {

@@ -234,8 +344,6 @@ missingPatterns.push(pattern);

// note: globbyPatterns can be an empty array
const globbyResults = (await globby(globbyPatterns, {
cwd,
absolute: true,
ignore: configs.ignores.filter(matcher => typeof matcher === "string")
}));
const globbyResults = await globMultiSearch({
searches,
configs
});

@@ -245,19 +353,27 @@ // if there are no results, tell the user why

// try globby without ignoring anything
/* eslint-disable no-unreachable-loop -- We want to exit early. */
for (const globbyPattern of globbyPatterns) {
for (const [basePath, { patterns: patternsToCheck, rawPatterns: patternsToReport }] of searches) {
/* eslint-disable-next-line no-unused-vars -- Want to exit early. */
for await (const filePath of globby.stream(globbyPattern, { cwd, absolute: true })) {
let index = 0;
// files were found but ignored
throw new AllFilesIgnoredError(globbyPattern);
}
// try globby without ignoring anything
for (const patternToCheck of patternsToCheck) {
// no files were found
if (errorOnUnmatchedPattern) {
throw new NoFilesFoundError(globbyPattern, globInputPaths);
// 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++;
}
}
/* eslint-enable no-unreachable-loop -- Go back to normal. */

@@ -264,0 +380,0 @@ }

@@ -265,8 +265,5 @@ /**

* @param {string} filePath The filename to load from.
* @param {Object} options Options to help load the config file.
* @param {string} options.basePath The base path for the config array.
* @param {boolean} options.shouldIgnore Whether to honor ignore patterns.
* @returns {Promise<FlatConfigArray>} The config array loaded from the config file.
* @returns {Promise<any>} The config loaded from the config file.
*/
async function loadFlatConfigFile(filePath, { basePath, shouldIgnore }) {
async function loadFlatConfigFile(filePath) {
debug(`Loading config from ${filePath}`);

@@ -278,8 +275,3 @@

const module = await import(fileURL);
return new FlatConfigArray(module.default, {
basePath,
shouldIgnore
});
return (await import(fileURL)).default;
}

@@ -295,2 +287,3 @@

cwd,
baseConfig,
overrideConfig,

@@ -327,12 +320,14 @@ configFile,

// load config array
let configs;
const configs = new FlatConfigArray(baseConfig || [], { basePath, shouldIgnore });
// load config file
if (configFilePath) {
configs = await loadFlatConfigFile(configFilePath, {
basePath,
shouldIgnore
});
} else {
configs = new FlatConfigArray([], { basePath, shouldIgnore });
const fileConfig = await loadFlatConfigFile(configFilePath);
if (Array.isArray(fileConfig)) {
configs.push(...fileConfig);
} else {
configs.push(fileConfig);
}
}

@@ -369,13 +364,2 @@

/*
* Ignore patterns are considered relative to a directory
* when the pattern contains a slash in a position other
* than the last character. If that's the case, we need to
* add the relative ignore path to the current pattern to
* get the correct behavior. Otherwise, no change is needed.
*/
if (!basePattern.includes("/") || basePattern.endsWith("/")) {
return pattern;
}
return (negated ? "!" : "") +

@@ -673,9 +657,8 @@ path.posix.join(relativeIgnorePath, basePattern);

const resultRules = new Map();
// short-circuit simple case
if (results.length === 0) {
return resultRules;
return {};
}
const resultRules = new Map();
const { configs } = privateMembers.get(this);

@@ -709,2 +692,6 @@

for (const { ruleId } of allMessages) {
if (!ruleId) {
continue;
}
const rule = getRuleFromConfig(ruleId, config);

@@ -711,0 +698,0 @@

@@ -115,14 +115,20 @@ /**

// Object.defineProperty()
if (parent.parent.parent.type === "CallExpression" &&
astUtils.getStaticPropertyName(parent.parent.parent.callee) === "defineProperty") {
return true;
// Object.defineProperty() or Reflect.defineProperty()
if (parent.parent.parent.type === "CallExpression") {
const callNode = parent.parent.parent.callee;
if (astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperty") ||
astUtils.isSpecificMemberAccess(callNode, "Reflect", "defineProperty")) {
return true;
}
}
// Object.defineProperties()
// Object.defineProperties() or Object.create()
if (parent.parent.parent.type === "Property" &&
parent.parent.parent.parent.type === "ObjectExpression" &&
parent.parent.parent.parent.parent.type === "CallExpression" &&
astUtils.getStaticPropertyName(parent.parent.parent.parent.parent.callee) === "defineProperties") {
return true;
parent.parent.parent.parent.parent.type === "CallExpression") {
const callNode = parent.parent.parent.parent.parent.callee;
return astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperties") ||
astUtils.isSpecificMemberAccess(callNode, "Object", "create");
}

@@ -129,0 +135,0 @@ }

@@ -80,2 +80,7 @@ /**

// Variables exported by "exported" block comments
if (variable.eslintExported) {
return;
}
variable.defs.forEach(def => {

@@ -82,0 +87,0 @@ const defNode = def.node;

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

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

"@eslint/eslintrc": "^1.3.3",
"@humanwhocodes/config-array": "^0.10.5",
"@humanwhocodes/config-array": "^0.11.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
"ajv": "^6.10.0",

@@ -77,5 +78,4 @@ "chalk": "^4.0.0",

"find-up": "^5.0.0",
"glob-parent": "^6.0.1",
"glob-parent": "^6.0.2",
"globals": "^13.15.0",
"globby": "^11.1.0",
"grapheme-splitter": "^1.0.4",

@@ -86,2 +86,3 @@ "ignore": "^5.2.0",

"is-glob": "^4.0.0",
"is-path-inside": "^3.0.3",
"js-sdsl": "^4.1.4",

@@ -88,0 +89,0 @@ "js-yaml": "^4.1.0",

Sorry, the diff of this file is too big to display

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