Comparing version 9.8.0 to 9.9.0
@@ -343,5 +343,6 @@ /** | ||
* @param {string} configFile The path to the config file to inspect. | ||
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not. | ||
* @returns {Promise<string>} The command string to execute. | ||
*/ | ||
async calculateInspectConfigFlags(configFile) { | ||
async calculateInspectConfigFlags(configFile, hasUnstableTSConfigFlag) { | ||
@@ -353,3 +354,3 @@ // find the config file | ||
error | ||
} = await locateConfigFileToUse({ cwd: process.cwd(), configFile }); | ||
} = await locateConfigFileToUse({ cwd: process.cwd(), configFile }, hasUnstableTSConfigFlag); | ||
@@ -459,3 +460,3 @@ if (error) { | ||
const spawn = require("cross-spawn"); | ||
const flags = await cli.calculateInspectConfigFlags(flatOptions.overrideConfigFile); | ||
const flags = await cli.calculateInspectConfigFlags(flatOptions.overrideConfigFile, flatOptions.flags ? flatOptions.flags.includes("unstable_ts_config") : false); | ||
@@ -462,0 +463,0 @@ spawn.sync("npx", ["@eslint/config-inspector@latest", ...flags], { encoding: "utf8", stdio: "inherit" }); |
@@ -66,2 +66,4 @@ /** | ||
/** @typedef {ReturnType<ConfigArray.extractConfig>} ExtractedConfig */ | ||
/** @typedef {import('../cli-engine/cli-engine').CLIEngine} CLIEngine */ | ||
/** @typedef {import('./legacy-eslint').CLIEngineLintReport} CLIEngineLintReport */ | ||
@@ -90,3 +92,3 @@ /** | ||
* @property {boolean} [stats] True enables added statistics on lint results. | ||
* @property {boolean} warnIgnored Show warnings when the file list includes ignored files | ||
* @property {boolean} [warnIgnored] Show warnings when the file list includes ignored files | ||
* @property {boolean} [passOnNoPatterns=false] When set to true, missing patterns cause | ||
@@ -105,4 +107,14 @@ * the linting operation to short circuit and not report any failures. | ||
]; | ||
const FLAT_CONFIG_FILENAMES_WITH_TS = [ | ||
...FLAT_CONFIG_FILENAMES, | ||
"eslint.config.ts", | ||
"eslint.config.mts", | ||
"eslint.config.cts" | ||
]; | ||
const debug = require("debug")("eslint:eslint"); | ||
const privateMembers = new WeakMap(); | ||
/** | ||
* @type {Map<string, string>} | ||
*/ | ||
const importedConfigFileModificationTime = new Map(); | ||
@@ -268,7 +280,10 @@ const removedFormatters = new Set([ | ||
* @param {string} cwd The current working directory to search from. | ||
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not. | ||
* @returns {Promise<string|undefined>} The filename if found or `undefined` if not. | ||
*/ | ||
function findFlatConfigFile(cwd) { | ||
function findFlatConfigFile(cwd, hasUnstableTSConfigFlag) { | ||
const filenames = hasUnstableTSConfigFlag ? FLAT_CONFIG_FILENAMES_WITH_TS : FLAT_CONFIG_FILENAMES; | ||
return findUp( | ||
FLAT_CONFIG_FILENAMES, | ||
filenames, | ||
{ cwd } | ||
@@ -279,7 +294,35 @@ ); | ||
/** | ||
* Check if the file is a TypeScript file. | ||
* @param {string} filePath The file path to check. | ||
* @returns {boolean} `true` if the file is a TypeScript file, `false` if it's not. | ||
*/ | ||
function isFileTS(filePath) { | ||
const fileExtension = path.extname(filePath); | ||
return /^\.[mc]?ts$/u.test(fileExtension); | ||
} | ||
/** | ||
* Check if ESLint is running in Bun. | ||
* @returns {boolean} `true` if the ESLint is running Bun, `false` if it's not. | ||
*/ | ||
function isRunningInBun() { | ||
return !!globalThis.Bun; | ||
} | ||
/** | ||
* Check if ESLint is running in Deno. | ||
* @returns {boolean} `true` if the ESLint is running in Deno, `false` if it's not. | ||
*/ | ||
function isRunningInDeno() { | ||
return !!globalThis.Deno; | ||
} | ||
/** | ||
* Load the config array from the given filename. | ||
* @param {string} filePath The filename to load from. | ||
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not. | ||
* @returns {Promise<any>} The config loaded from the config file. | ||
*/ | ||
async function loadFlatConfigFile(filePath) { | ||
async function loadFlatConfigFile(filePath, hasUnstableTSConfigFlag) { | ||
debug(`Loading config from ${filePath}`); | ||
@@ -291,3 +334,3 @@ | ||
const mtime = (await fs.stat(filePath)).mtime.getTime(); | ||
const mtime = (await fs.stat(filePath)).mtime.getTime().toString(); | ||
@@ -323,4 +366,34 @@ /* | ||
const config = (await import(fileURL)).default; | ||
const isTS = isFileTS(filePath) && hasUnstableTSConfigFlag; | ||
const isBun = isRunningInBun(); | ||
const isDeno = isRunningInDeno(); | ||
if (isTS && !isDeno && !isBun) { | ||
const createJiti = await import("jiti").then(jitiModule => jitiModule.default, () => { | ||
throw new Error("The 'jiti' library is required for loading TypeScript configuration files. Make sure to install it."); | ||
}); | ||
/* | ||
* Disabling `moduleCache` allows us to reload a | ||
* config file when the last modified timestamp changes. | ||
*/ | ||
const jiti = createJiti(__filename, { moduleCache: false }); | ||
if (typeof jiti?.import !== "function") { | ||
throw new Error("You are using an outdated version of the 'jiti' library. Please update to the latest version of 'jiti' to ensure compatibility and access to the latest features."); | ||
} | ||
const config = await jiti.import(fileURL.href); | ||
importedConfigFileModificationTime.set(filePath, mtime); | ||
return config?.default ?? config; | ||
} | ||
const config = (await import(fileURL.href)).default; | ||
importedConfigFileModificationTime.set(filePath, mtime); | ||
@@ -336,7 +409,8 @@ | ||
* upwards from the cwd for a file named `eslint.config.js`. | ||
* @param {import("./eslint").ESLintOptions} options The ESLint instance options. | ||
* @returns {{configFilePath:string|undefined,basePath:string,error:Error|null}} Location information for | ||
* @param {ESLintOptions} options The ESLint instance options. | ||
* @param {boolean} hasUnstableTSConfigFlag `true` if the `unstable_ts_config` flag is enabled, `false` if it's not. | ||
* @returns {Promise<{configFilePath:string|undefined;basePath:string;error:Error|null}>} Location information for | ||
* the config file. | ||
*/ | ||
async function locateConfigFileToUse({ configFile, cwd }) { | ||
async function locateConfigFileToUse({ configFile, cwd }, hasUnstableTSConfigFlag) { | ||
@@ -353,3 +427,3 @@ // determine where to load config file from | ||
debug("Searching for eslint.config.js"); | ||
configFilePath = await findFlatConfigFile(cwd); | ||
configFilePath = await findFlatConfigFile(cwd, hasUnstableTSConfigFlag); | ||
@@ -376,4 +450,4 @@ if (configFilePath) { | ||
* @param {ESLint} eslint The instance to create the config array for. | ||
* @param {import("./eslint").ESLintOptions} options The ESLint instance options. | ||
* @returns {FlatConfigArray} The config array for `eslint``. | ||
* @param {ESLintOptions} options The ESLint instance options. | ||
* @returns {Promise<typeof FlatConfigArray>} The config array for `eslint``. | ||
*/ | ||
@@ -396,4 +470,6 @@ async function calculateConfigArray(eslint, { | ||
const { configFilePath, basePath, error } = await locateConfigFileToUse({ configFile, cwd }); | ||
const hasUnstableTSConfigFlag = eslint.hasFlag("unstable_ts_config"); | ||
const { configFilePath, basePath, error } = await locateConfigFileToUse({ configFile, cwd }, hasUnstableTSConfigFlag); | ||
// config file is required to calculate config | ||
@@ -408,3 +484,3 @@ if (error) { | ||
if (configFilePath) { | ||
const fileConfig = await loadFlatConfigFile(configFilePath); | ||
const fileConfig = await loadFlatConfigFile(configFilePath, hasUnstableTSConfigFlag); | ||
@@ -1159,3 +1235,3 @@ if (Array.isArray(fileConfig)) { | ||
* The main formatter method. | ||
* @param {LintResults[]} results The lint results to format. | ||
* @param {LintResult[]} results The lint results to format. | ||
* @param {ResultsMeta} resultsMeta Warning count and max threshold. | ||
@@ -1206,3 +1282,3 @@ * @returns {string} The formatted lint results. | ||
* passed to the constructor. | ||
* @returns {string|undefined} The path to the config file being used or | ||
* @returns {Promise<string|undefined>} The path to the config file being used or | ||
* `undefined` if no config file is being used. | ||
@@ -1212,3 +1288,3 @@ */ | ||
const options = privateMembers.get(this).options; | ||
const { configFilePath } = await locateConfigFileToUse(options); | ||
const { configFilePath } = await locateConfigFileToUse(options, this.hasFlag("unstable_ts_config")); | ||
@@ -1215,0 +1291,0 @@ return configFilePath; |
@@ -921,3 +921,3 @@ /** | ||
/** | ||
* Returns the locatin of the given node or token. | ||
* Returns the location of the given node or token. | ||
* @param {ASTNode|Token} nodeOrToken The node or token to get the location of. | ||
@@ -924,0 +924,0 @@ * @returns {SourceLocation} The location of the node or token. |
@@ -45,4 +45,7 @@ /** | ||
messages: { | ||
missingAwait: "{{name}} has no 'await' expression." | ||
} | ||
missingAwait: "{{name}} has no 'await' expression.", | ||
removeAsync: "Remove 'async'." | ||
}, | ||
hasSuggestions: true | ||
}, | ||
@@ -73,2 +76,29 @@ | ||
if (!node.generator && node.async && !scopeInfo.hasAwait && !astUtils.isEmptyFunction(node)) { | ||
/* | ||
* If the function belongs to a method definition or | ||
* property, then the function's range may not include the | ||
* `async` keyword and we should look at the parent instead. | ||
*/ | ||
const nodeWithAsyncKeyword = | ||
(node.parent.type === "MethodDefinition" && node.parent.value === node) || | ||
(node.parent.type === "Property" && node.parent.method && node.parent.value === node) | ||
? node.parent | ||
: node; | ||
const asyncToken = sourceCode.getFirstToken(nodeWithAsyncKeyword, token => token.value === "async"); | ||
const asyncRange = [asyncToken.range[0], sourceCode.getTokenAfter(asyncToken, { includeComments: true }).range[0]]; | ||
/* | ||
* Removing the `async` keyword can cause parsing errors if the current | ||
* statement is relying on automatic semicolon insertion. If ASI is currently | ||
* being used, then we should replace the `async` keyword with a semicolon. | ||
*/ | ||
const nextToken = sourceCode.getTokenAfter(asyncToken); | ||
const addSemiColon = | ||
nextToken.type === "Punctuator" && | ||
(nextToken.value === "[" || nextToken.value === "(") && | ||
(nodeWithAsyncKeyword.type === "MethodDefinition" || astUtils.isStartOfExpressionStatement(nodeWithAsyncKeyword)) && | ||
astUtils.needsPrecedingSemicolon(sourceCode, nodeWithAsyncKeyword); | ||
context.report({ | ||
@@ -82,3 +112,7 @@ node, | ||
) | ||
} | ||
}, | ||
suggest: [{ | ||
messageId: "removeAsync", | ||
fix: fixer => fixer.replaceTextRange(asyncRange, addSemiColon ? ";" : "") | ||
}] | ||
}); | ||
@@ -85,0 +119,0 @@ } |
@@ -12,3 +12,4 @@ /** | ||
const activeFlags = new Map([ | ||
["test_only", "Used only for testing."] | ||
["test_only", "Used only for testing."], | ||
["unstable_ts_config", "Enable TypeScript configuration files."] | ||
]); | ||
@@ -15,0 +16,0 @@ |
{ | ||
"name": "eslint", | ||
"version": "9.8.0", | ||
"version": "9.9.0", | ||
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>", | ||
@@ -73,3 +73,3 @@ "description": "An AST-based pattern checker for JavaScript.", | ||
"@eslint/eslintrc": "^3.1.0", | ||
"@eslint/js": "9.8.0", | ||
"@eslint/js": "9.9.0", | ||
"@humanwhocodes/module-importer": "^1.0.1", | ||
@@ -108,10 +108,10 @@ "@humanwhocodes/retry": "^0.3.0", | ||
"@babel/preset-env": "^7.4.3", | ||
"@eslint/core": "^0.2.0", | ||
"@eslint/json": "^0.2.0", | ||
"@eslint/core": "^0.3.0", | ||
"@eslint/json": "^0.3.0", | ||
"@types/estree": "^1.0.5", | ||
"@types/node": "^20.11.5", | ||
"@wdio/browser-runner": "^8.38.3", | ||
"@wdio/cli": "^8.38.2", | ||
"@wdio/concise-reporter": "^8.38.2", | ||
"@wdio/mocha-framework": "^8.38.2", | ||
"@wdio/browser-runner": "^8.40.1", | ||
"@wdio/cli": "^8.40.0", | ||
"@wdio/concise-reporter": "^8.39.0", | ||
"@wdio/mocha-framework": "^8.40.0", | ||
"babel-loader": "^8.0.5", | ||
@@ -137,2 +137,3 @@ "c8": "^7.12.0", | ||
"gray-matter": "^4.0.3", | ||
"jiti": "^1.21.6", | ||
"js-yaml": "^4.1.0", | ||
@@ -171,2 +172,10 @@ "knip": "^5.21.0", | ||
}, | ||
"peerDependencies": { | ||
"jiti": "*" | ||
}, | ||
"peerDependenciesMeta": { | ||
"jiti": { | ||
"optional": true | ||
} | ||
}, | ||
"keywords": [ | ||
@@ -173,0 +182,0 @@ "ast", |
@@ -298,3 +298,3 @@ [![npm version](https://img.shields.io/npm/v/eslint.svg)](https://www.npmjs.com/package/eslint) | ||
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3> | ||
<p><a href="#"><img src="https://images.opencollective.com/guest-bf377e88/avatar.png" alt="Eli Schleifer" height="96"></a> <a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a></p><h3>Silver Sponsors</h3> | ||
<p><a href="#"><img src="https://images.opencollective.com/guest-bf377e88/avatar.png" alt="Eli Schleifer" height="96"></a></p><h3>Silver Sponsors</h3> | ||
<p><a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a> <a href="https://www.workleap.com"><img src="https://avatars.githubusercontent.com/u/53535748?u=d1e55d7661d724bf2281c1bfd33cb8f99fe2465f&v=4" alt="Workleap" height="64"></a></p><h3>Bronze Sponsors</h3> | ||
@@ -301,0 +301,0 @@ <p><a href="https://www.notion.so"><img src="https://images.opencollective.com/notion/bf3b117/logo.png" alt="notion" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://usenextbase.com"><img src="https://avatars.githubusercontent.com/u/145838380?v=4" alt="Nextbase Starter Kit" height="32"></a></p> |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
3078278
72438
35
63
+ Added@eslint/js@9.9.0(transitive)
+ Addedjiti@1.21.6(transitive)
- Removed@eslint/js@9.8.0(transitive)
Updated@eslint/js@9.9.0