diff --git a/tools/node_modules/eslint/README.md b/tools/node_modules/eslint/README.md
index 0cde09fc602b17..65c57271956185 100644
--- a/tools/node_modules/eslint/README.md
+++ b/tools/node_modules/eslint/README.md
@@ -39,7 +39,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
## Installation and Usage
-Prerequisites: [Node.js](https://nodejs.org/) (`^8.10.0`, `^10.13.0`, or `>=11.10.1`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
+Prerequisites: [Node.js](https://nodejs.org/) (`^10.12.0`, or `>=12.0.0`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
You can install ESLint using npm:
@@ -264,7 +264,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
Gold Sponsors
Silver Sponsors
Bronze Sponsors
-
+
## Technology Sponsors
diff --git a/tools/node_modules/eslint/conf/default-cli-options.js b/tools/node_modules/eslint/conf/default-cli-options.js
index 0f7b377fb362ec..e09a829d17cee2 100644
--- a/tools/node_modules/eslint/conf/default-cli-options.js
+++ b/tools/node_modules/eslint/conf/default-cli-options.js
@@ -12,7 +12,7 @@ module.exports = {
useEslintrc: true,
envs: [],
globals: [],
- extensions: [".js"],
+ extensions: null,
ignore: true,
ignorePath: void 0,
cache: false,
diff --git a/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js b/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js
index 52703a873bb67e..f91dea4c448276 100644
--- a/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js
+++ b/tools/node_modules/eslint/lib/cli-engine/cascading-config-array-factory.js
@@ -26,6 +26,7 @@
const os = require("os");
const path = require("path");
const { validateConfigArray } = require("../shared/config-validator");
+const { emitDeprecationWarning } = require("../shared/deprecation-warnings");
const { ConfigArrayFactory } = require("./config-array-factory");
const { ConfigArray, ConfigDependency, IgnorePattern } = require("./config-array");
const loadRules = require("./load-rules");
@@ -105,6 +106,7 @@ function createBaseConfigArray({
*/
if (rulePaths && rulePaths.length > 0) {
baseConfigArray.push({
+ type: "config",
name: "--rulesdir",
filePath: "",
plugins: {
@@ -290,10 +292,11 @@ class CascadingConfigArrayFactory {
/**
* Load and normalize config files from the ancestor directories.
* @param {string} directoryPath The path to a leaf directory.
+ * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
* @returns {ConfigArray} The loaded config.
* @private
*/
- _loadConfigInAncestors(directoryPath) {
+ _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
const {
baseConfigArray,
configArrayFactory,
@@ -320,6 +323,16 @@ class CascadingConfigArrayFactory {
// Consider this is root.
if (directoryPath === homePath && cwd !== homePath) {
debug("Stop traversing because of considered root.");
+ if (configsExistInSubdirs) {
+ const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
+
+ if (filePath) {
+ emitDeprecationWarning(
+ filePath,
+ "ESLINT_PERSONAL_CONFIG_SUPPRESS"
+ );
+ }
+ }
return this._cacheConfig(directoryPath, baseConfigArray);
}
@@ -344,7 +357,10 @@ class CascadingConfigArrayFactory {
// Load from the ancestors and merge it.
const parentPath = path.dirname(directoryPath);
const parentConfigArray = parentPath && parentPath !== directoryPath
- ? this._loadConfigInAncestors(parentPath)
+ ? this._loadConfigInAncestors(
+ parentPath,
+ configsExistInSubdirs || configArray.length > 0
+ )
: baseConfigArray;
if (configArray.length > 0) {
@@ -400,12 +416,29 @@ class CascadingConfigArrayFactory {
configArray.every(c => !c.filePath) &&
cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
) {
- debug("Loading the config file of the home directory.");
+ const homePath = os.homedir();
+
+ debug("Loading the config file of the home directory:", homePath);
- finalConfigArray = configArrayFactory.loadInDirectory(
- os.homedir(),
- { name: "PersonalConfig", parent: finalConfigArray }
+ const personalConfigArray = configArrayFactory.loadInDirectory(
+ homePath,
+ { name: "PersonalConfig" }
);
+
+ if (
+ personalConfigArray.length > 0 &&
+ !directoryPath.startsWith(homePath)
+ ) {
+ const lastElement =
+ personalConfigArray[personalConfigArray.length - 1];
+
+ emitDeprecationWarning(
+ lastElement.filePath,
+ "ESLINT_PERSONAL_CONFIG_LOAD"
+ );
+ }
+
+ finalConfigArray = finalConfigArray.concat(personalConfigArray);
}
// Apply CLI options.
diff --git a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js
index 22336a91de2909..6a0352399b7738 100644
--- a/tools/node_modules/eslint/lib/cli-engine/cli-engine.js
+++ b/tools/node_modules/eslint/lib/cli-engine/cli-engine.js
@@ -57,7 +57,7 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
* @property {string} configFile The configuration file to use.
* @property {string} cwd The value to use for the current working directory.
* @property {string[]} envs An array of environments to load.
- * @property {string[]} extensions An array of file extensions to check.
+ * @property {string[]|null} extensions An array of file extensions to check.
* @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean.
* @property {string[]} fixTypes Array of rule types to apply fixes for.
* @property {string[]} globals An array of global variables to declare.
@@ -201,7 +201,7 @@ function calculateStatsPerRun(results) {
* @param {boolean} config.fix If `true` then it does fix.
* @param {boolean} config.allowInlineConfig If `true` then it uses directive comments.
* @param {boolean} config.reportUnusedDisableDirectives If `true` then it reports unused `eslint-disable` comments.
- * @param {RegExp} config.extensionRegExp The `RegExp` object that tests if a file path has the allowed file extensions.
+ * @param {FileEnumerator} config.fileEnumerator The file enumerator to check if a path is a target or not.
* @param {Linter} config.linter The linter instance to verify.
* @returns {LintResult} The result of linting.
* @private
@@ -214,7 +214,7 @@ function verifyText({
fix,
allowInlineConfig,
reportUnusedDisableDirectives,
- extensionRegExp,
+ fileEnumerator,
linter
}) {
const filePath = providedFilePath || "";
@@ -238,13 +238,11 @@ function verifyText({
/**
* Check if the linter should adopt a given code block or not.
- * Currently, the linter adopts code blocks if the name matches `--ext` option.
- * In the future, `overrides` in the configuration would affect the adoption (https://github.com/eslint/rfcs/pull/20).
* @param {string} blockFilename The virtual filename of a code block.
* @returns {boolean} `true` if the linter should adopt the code block.
*/
filterCodeBlock(blockFilename) {
- return extensionRegExp.test(blockFilename);
+ return fileEnumerator.isTargetPath(blockFilename);
}
}
);
@@ -704,7 +702,7 @@ class CLIEngine {
return patterns.filter(Boolean);
}
- const extensions = options.extensions.map(ext => ext.replace(/^\./u, ""));
+ const extensions = (options.extensions || [".js"]).map(ext => ext.replace(/^\./u, ""));
const dirSuffix = `/**/*.{${extensions.join(",")}}`;
return patterns.filter(Boolean).map(pathname => {
@@ -803,7 +801,7 @@ class CLIEngine {
fix,
allowInlineConfig,
reportUnusedDisableDirectives,
- extensionRegExp: fileEnumerator.extensionRegExp,
+ fileEnumerator,
linter
});
@@ -891,7 +889,7 @@ class CLIEngine {
fix,
allowInlineConfig,
reportUnusedDisableDirectives,
- extensionRegExp: fileEnumerator.extensionRegExp,
+ fileEnumerator,
linter
}));
}
diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js
index 76c4ccd70212cd..997a7e15318dfd 100644
--- a/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js
+++ b/tools/node_modules/eslint/lib/cli-engine/config-array-factory.js
@@ -436,6 +436,29 @@ class ConfigArrayFactory {
);
}
+ /**
+ * Check if a config file on a given directory exists or not.
+ * @param {string} directoryPath The path to a directory.
+ * @returns {string | null} The path to the found config file. If not found then null.
+ */
+ static getPathToConfigFileInDirectory(directoryPath) {
+ for (const filename of configFilenames) {
+ const filePath = path.join(directoryPath, filename);
+
+ if (fs.existsSync(filePath)) {
+ if (filename === "package.json") {
+ try {
+ loadPackageJSONConfigFile(filePath);
+ return filePath;
+ } catch (error) { /* ignore */ }
+ } else {
+ return filePath;
+ }
+ }
+ }
+ return null;
+ }
+
/**
* Load `.eslintignore` file.
* @param {string} filePath The path to a `.eslintignore` file to load.
@@ -542,7 +565,7 @@ class ConfigArrayFactory {
*/
*_normalizeESLintIgnoreData(ignorePatterns, filePath, name) {
const elements = this._normalizeObjectConfigData(
- { ignorePatterns },
+ { type: "ignore", ignorePatterns },
filePath,
name
);
@@ -644,6 +667,7 @@ class ConfigArrayFactory {
root,
rules,
settings,
+ type = "config",
overrides: overrideList = []
},
filePath,
@@ -675,6 +699,7 @@ class ConfigArrayFactory {
yield {
// Debug information.
+ type,
name,
filePath,
@@ -1024,6 +1049,7 @@ class ConfigArrayFactory {
if (processorId.startsWith(".")) {
yield* this._normalizeObjectConfigData(
{
+ type: "implicit-processor",
files: [`*${processorId}`],
processor: `${pluginId}/${processorId}`
},
diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js b/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js
index 4fae8deaca1b69..02f73b43e65438 100644
--- a/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js
+++ b/tools/node_modules/eslint/lib/cli-engine/config-array/config-array.js
@@ -454,6 +454,25 @@ class ConfigArray extends Array {
return cache.get(cacheKey);
}
+
+ /**
+ * Check if a given path is an additional lint target.
+ * @param {string} filePath The absolute path to the target file.
+ * @returns {boolean} `true` if the file is an additional lint target.
+ */
+ isAdditionalTargetPath(filePath) {
+ for (const { criteria, type } of this) {
+ if (
+ type === "config" &&
+ criteria &&
+ !criteria.endsWithWildcard &&
+ criteria.test(filePath)
+ ) {
+ return true;
+ }
+ }
+ return false;
+ }
}
const exportObject = {
diff --git a/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js b/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js
index 67c8a6ed8a0cbb..e7ba1202f1cb08 100644
--- a/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js
+++ b/tools/node_modules/eslint/lib/cli-engine/config-array/override-tester.js
@@ -96,14 +96,22 @@ class OverrideTester {
static create(files, excludedFiles, basePath) {
const includePatterns = normalizePatterns(files);
const excludePatterns = normalizePatterns(excludedFiles);
- const allPatterns = includePatterns.concat(excludePatterns);
+ let endsWithWildcard = false;
- if (allPatterns.length === 0) {
+ if (includePatterns.length === 0) {
return null;
}
// Rejects absolute paths or relative paths to parents.
- for (const pattern of allPatterns) {
+ for (const pattern of includePatterns) {
+ if (path.isAbsolute(pattern) || pattern.includes("..")) {
+ throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
+ }
+ if (pattern.endsWith("*")) {
+ endsWithWildcard = true;
+ }
+ }
+ for (const pattern of excludePatterns) {
if (path.isAbsolute(pattern) || pattern.includes("..")) {
throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
}
@@ -112,7 +120,11 @@ class OverrideTester {
const includes = toMatcher(includePatterns);
const excludes = toMatcher(excludePatterns);
- return new OverrideTester([{ includes, excludes }], basePath);
+ return new OverrideTester(
+ [{ includes, excludes }],
+ basePath,
+ endsWithWildcard
+ );
}
/**
@@ -125,28 +137,44 @@ class OverrideTester {
*/
static and(a, b) {
if (!b) {
- return a && new OverrideTester(a.patterns, a.basePath);
+ return a && new OverrideTester(
+ a.patterns,
+ a.basePath,
+ a.endsWithWildcard
+ );
}
if (!a) {
- return new OverrideTester(b.patterns, b.basePath);
+ return new OverrideTester(
+ b.patterns,
+ b.basePath,
+ b.endsWithWildcard
+ );
}
assert.strictEqual(a.basePath, b.basePath);
- return new OverrideTester(a.patterns.concat(b.patterns), a.basePath);
+ return new OverrideTester(
+ a.patterns.concat(b.patterns),
+ a.basePath,
+ a.endsWithWildcard || b.endsWithWildcard
+ );
}
/**
* Initialize this instance.
* @param {Pattern[]} patterns The matchers.
* @param {string} basePath The base path.
+ * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
*/
- constructor(patterns, basePath) {
+ constructor(patterns, basePath, endsWithWildcard = false) {
/** @type {Pattern[]} */
this.patterns = patterns;
/** @type {string} */
this.basePath = basePath;
+
+ /** @type {boolean} */
+ this.endsWithWildcard = endsWithWildcard;
}
/**
diff --git a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js
index c67e01aef9b1c8..16e5182ad8a450 100644
--- a/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js
+++ b/tools/node_modules/eslint/lib/cli-engine/file-enumerator.js
@@ -88,7 +88,7 @@ const IGNORED = 2;
* @typedef {Object} FileEnumeratorInternalSlots
* @property {CascadingConfigArrayFactory} configArrayFactory The factory for config arrays.
* @property {string} cwd The base directory to start lookup.
- * @property {RegExp} extensionRegExp The RegExp to test if a string ends with specific file extensions.
+ * @property {RegExp|null} extensionRegExp The RegExp to test if a string ends with specific file extensions.
* @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
* @property {boolean} ignoreFlag The flag to check ignored files.
* @property {(filePath:string, dot:boolean) => boolean} defaultIgnores The default predicate function to ignore files.
@@ -127,12 +127,12 @@ function statSafeSync(filePath) {
/**
* Get filenames in a given path to a directory.
* @param {string} directoryPath The path to target directory.
- * @returns {string[]} The filenames.
+ * @returns {import("fs").Dirent[]} The filenames.
* @private
*/
function readdirSafeSync(directoryPath) {
try {
- return fs.readdirSync(directoryPath);
+ return fs.readdirSync(directoryPath, { withFileTypes: true });
} catch (error) {
/* istanbul ignore next */
if (error.code !== "ENOENT") {
@@ -142,6 +142,27 @@ function readdirSafeSync(directoryPath) {
}
}
+/**
+ * Create a `RegExp` object to detect extensions.
+ * @param {string[] | null} extensions The extensions to create.
+ * @returns {RegExp | null} The created `RegExp` object or null.
+ */
+function createExtensionRegExp(extensions) {
+ if (extensions) {
+ const normalizedExts = extensions.map(ext => escapeRegExp(
+ ext.startsWith(".")
+ ? ext.slice(1)
+ : ext
+ ));
+
+ return new RegExp(
+ `.\\.(?:${normalizedExts.join("|")})$`,
+ "u"
+ );
+ }
+ return null;
+}
+
/**
* The error type when no files match a glob.
*/
@@ -188,7 +209,7 @@ class FileEnumerator {
constructor({
cwd = process.cwd(),
configArrayFactory = new CascadingConfigArrayFactory({ cwd }),
- extensions = [".js"],
+ extensions = null,
globInputPaths = true,
errorOnUnmatchedPattern = true,
ignore = true
@@ -197,17 +218,7 @@ class FileEnumerator {
configArrayFactory,
cwd,
defaultIgnores: IgnorePattern.createDefaultIgnore(cwd),
- extensionRegExp: new RegExp(
- `.\\.(?:${extensions
- .map(ext => escapeRegExp(
- ext.startsWith(".")
- ? ext.slice(1)
- : ext
- ))
- .join("|")
- })$`,
- "u"
- ),
+ extensionRegExp: createExtensionRegExp(extensions),
globInputPaths,
errorOnUnmatchedPattern,
ignoreFlag: ignore
@@ -215,11 +226,36 @@ class FileEnumerator {
}
/**
- * The `RegExp` object that tests if a file path has the allowed file extensions.
- * @type {RegExp}
+ * Check if a given file is target or not.
+ * @param {string} filePath The path to a candidate file.
+ * @param {ConfigArray} [providedConfig] Optional. The configuration for the file.
+ * @returns {boolean} `true` if the file is a target.
*/
- get extensionRegExp() {
- return internalSlotsMap.get(this).extensionRegExp;
+ isTargetPath(filePath, providedConfig) {
+ const {
+ configArrayFactory,
+ extensionRegExp
+ } = internalSlotsMap.get(this);
+
+ // If `--ext` option is present, use it.
+ if (extensionRegExp) {
+ return extensionRegExp.test(filePath);
+ }
+
+ // `.js` file is target by default.
+ if (filePath.endsWith(".js")) {
+ return true;
+ }
+
+ // use `overrides[].files` to check additional targets.
+ const config =
+ providedConfig ||
+ configArrayFactory.getConfigArrayForFile(
+ filePath,
+ { ignoreNotFoundError: true }
+ );
+
+ return config.isAdditionalTargetPath(filePath);
}
/**
@@ -380,18 +416,17 @@ class FileEnumerator {
*/
*_iterateFilesRecursive(directoryPath, options) {
debug(`Enter the directory: ${directoryPath}`);
- const { configArrayFactory, extensionRegExp } = internalSlotsMap.get(this);
+ const { configArrayFactory } = internalSlotsMap.get(this);
/** @type {ConfigArray|null} */
let config = null;
// Enumerate the files of this directory.
- for (const filename of readdirSafeSync(directoryPath)) {
- const filePath = path.join(directoryPath, filename);
- const stat = statSafeSync(filePath); // TODO: Use `withFileTypes` in the future.
+ for (const entry of readdirSafeSync(directoryPath)) {
+ const filePath = path.join(directoryPath, entry.name);
// Check if the file is matched.
- if (stat && stat.isFile()) {
+ if (entry.isFile()) {
if (!config) {
config = configArrayFactory.getConfigArrayForFile(
filePath,
@@ -404,29 +439,30 @@ class FileEnumerator {
{ ignoreNotFoundError: true }
);
}
- const ignored = this._isIgnoredFile(filePath, { ...options, config });
- const flag = ignored ? IGNORED_SILENTLY : NONE;
const matched = options.selector
// Started with a glob pattern; choose by the pattern.
? options.selector.match(filePath)
// Started with a directory path; choose by file extensions.
- : extensionRegExp.test(filePath);
+ : this.isTargetPath(filePath, config);
if (matched) {
- debug(`Yield: ${filename}${ignored ? " but ignored" : ""}`);
+ const ignored = this._isIgnoredFile(filePath, { ...options, config });
+ const flag = ignored ? IGNORED_SILENTLY : NONE;
+
+ debug(`Yield: ${entry.name}${ignored ? " but ignored" : ""}`);
yield {
config: configArrayFactory.getConfigArrayForFile(filePath),
filePath,
flag
};
} else {
- debug(`Didn't match: ${filename}`);
+ debug(`Didn't match: ${entry.name}`);
}
// Dive into the sub directory.
- } else if (options.recursive && stat && stat.isDirectory()) {
+ } else if (options.recursive && entry.isDirectory()) {
if (!config) {
config = configArrayFactory.getConfigArrayForFile(
filePath,
diff --git a/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js b/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js
index c32425883f7cac..a994b4b1980eea 100644
--- a/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js
+++ b/tools/node_modules/eslint/lib/cli-engine/formatters/junit.js
@@ -32,7 +32,7 @@ function getMessageType(message) {
* @private
*/
function pathWithoutExt(filePath) {
- return path.posix.join(path.posix.dirname(filePath), path.basename(filePath, path.extname(filePath)));
+ return path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath)));
}
//------------------------------------------------------------------------------
diff --git a/tools/node_modules/eslint/lib/cli.js b/tools/node_modules/eslint/lib/cli.js
index 944b4b79353b3d..815ce68c22fe2e 100644
--- a/tools/node_modules/eslint/lib/cli.js
+++ b/tools/node_modules/eslint/lib/cli.js
@@ -17,7 +17,6 @@
const fs = require("fs"),
path = require("path"),
- mkdirp = require("mkdirp"),
{ CLIEngine } = require("./cli-engine"),
options = require("./options"),
log = require("./shared/logging"),
@@ -115,7 +114,7 @@ function printResults(engine, results, format, outputFile) {
}
try {
- mkdirp.sync(path.dirname(filePath));
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, output);
} catch (ex) {
log.error("There was a problem writing the output file:\n%s", ex);
diff --git a/tools/node_modules/eslint/lib/linter/linter.js b/tools/node_modules/eslint/lib/linter/linter.js
index 6d88cb5aa1245f..76d35b49eefb55 100644
--- a/tools/node_modules/eslint/lib/linter/linter.js
+++ b/tools/node_modules/eslint/lib/linter/linter.js
@@ -267,6 +267,15 @@ function createDisableDirectives(options) {
return result;
}
+/**
+ * Remove the ignored part from a given directive comment and trim it.
+ * @param {string} value The comment text to strip.
+ * @returns {string} The stripped text.
+ */
+function stripDirectiveComment(value) {
+ return value.split(/\s-{2,}\s/u)[0].trim();
+}
+
/**
* Parses comments in file to extract file-specific config of rules, globals
* and environments and merges them with global config; also code blocks
@@ -286,7 +295,7 @@ function getDirectiveComments(filename, ast, ruleMapper, warnInlineConfig) {
const disableDirectives = [];
ast.comments.filter(token => token.type !== "Shebang").forEach(comment => {
- const trimmedCommentText = comment.value.trim();
+ const trimmedCommentText = stripDirectiveComment(comment.value);
const match = /^(eslint(?:-env|-enable|-disable(?:(?:-next)?-line)?)?|exported|globals?)(?:\s|$)/u.exec(trimmedCommentText);
if (!match) {
@@ -444,8 +453,11 @@ function findEslintEnv(text) {
eslintEnvPattern.lastIndex = 0;
- while ((match = eslintEnvPattern.exec(text))) {
- retv = Object.assign(retv || {}, commentParser.parseListConfig(match[1]));
+ while ((match = eslintEnvPattern.exec(text)) !== null) {
+ retv = Object.assign(
+ retv || {},
+ commentParser.parseListConfig(stripDirectiveComment(match[1]))
+ );
}
return retv;
diff --git a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js
index 44e01dadf09b5d..2ac26534fcc0ea 100644
--- a/tools/node_modules/eslint/lib/rule-tester/rule-tester.js
+++ b/tools/node_modules/eslint/lib/rule-tester/rule-tester.js
@@ -50,6 +50,52 @@ const
const ajv = require("../shared/ajv")({ strictDefaults: true });
+
+//------------------------------------------------------------------------------
+// Typedefs
+//------------------------------------------------------------------------------
+
+/**
+ * A test case that is expected to pass lint.
+ * @typedef {Object} ValidTestCase
+ * @property {string} code Code for the test case.
+ * @property {any[]} [options] Options for the test case.
+ * @property {{ [name: string]: any }} [settings] Settings for the test case.
+ * @property {string} [filename] The fake filename for the test case. Useful for rules that make assertion about filenames.
+ * @property {string} [parser] The absolute path for the parser.
+ * @property {{ [name: string]: any }} [parserOptions] Options for the parser.
+ * @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables.
+ * @property {{ [name: string]: boolean }} [env] Environments for the test case.
+ */
+
+/**
+ * A test case that is expected to fail lint.
+ * @typedef {Object} InvalidTestCase
+ * @property {string} code Code for the test case.
+ * @property {number | Array} errors Expected errors.
+ * @property {string | null} [output] The expected code after autofixes are applied. If set to `null`, the test runner will assert that no autofix is suggested.
+ * @property {any[]} [options] Options for the test case.
+ * @property {{ [name: string]: any }} [settings] Settings for the test case.
+ * @property {string} [filename] The fake filename for the test case. Useful for rules that make assertion about filenames.
+ * @property {string} [parser] The absolute path for the parser.
+ * @property {{ [name: string]: any }} [parserOptions] Options for the parser.
+ * @property {{ [name: string]: "readonly" | "writable" | "off" }} [globals] The additional global variables.
+ * @property {{ [name: string]: boolean }} [env] Environments for the test case.
+ */
+
+/**
+ * A description of a reported error used in a rule tester test.
+ * @typedef {Object} TestCaseError
+ * @property {string | RegExp} [message] Message.
+ * @property {string} [messageId] Message ID.
+ * @property {string} [type] The type of the reported AST node.
+ * @property {{ [name: string]: string }} [data] The data used to fill the message template.
+ * @property {number} [line] The 1-based line number of the reported start location.
+ * @property {number} [column] The 1-based column number of the reported start location.
+ * @property {number} [endLine] The 1-based line number of the reported end location.
+ * @property {number} [endColumn] The 1-based column number of the reported end location.
+ */
+
//------------------------------------------------------------------------------
// Private Members
//------------------------------------------------------------------------------
@@ -128,7 +174,7 @@ function freezeDeeply(x) {
*/
function sanitize(text) {
return text.replace(
- /[\u0000-\u0009|\u000b-\u001a]/gu, // eslint-disable-line no-control-regex
+ /[\u0000-\u0009\u000b-\u001a]/gu, // eslint-disable-line no-control-regex
c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`
);
}
@@ -273,7 +319,10 @@ class RuleTester {
* Adds a new rule test to execute.
* @param {string} ruleName The name of the rule to run.
* @param {Function} rule The rule to test.
- * @param {Object} test The collection of tests to run.
+ * @param {{
+ * valid: (ValidTestCase | string)[],
+ * invalid: InvalidTestCase[]
+ * }} test The collection of tests to run.
* @returns {void}
*/
run(ruleName, rule, test) {
diff --git a/tools/node_modules/eslint/lib/rules/array-callback-return.js b/tools/node_modules/eslint/lib/rules/array-callback-return.js
index d632a3f30c28a3..6e425dcdcb89da 100644
--- a/tools/node_modules/eslint/lib/rules/array-callback-return.js
+++ b/tools/node_modules/eslint/lib/rules/array-callback-return.js
@@ -18,7 +18,7 @@ const astUtils = require("./utils/ast-utils");
//------------------------------------------------------------------------------
const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
-const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/u;
+const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|flatMap|map|reduce(?:Right)?|some|sort)$/u;
/**
* Checks a given code path segment is reachable.
diff --git a/tools/node_modules/eslint/lib/rules/array-element-newline.js b/tools/node_modules/eslint/lib/rules/array-element-newline.js
index 1da67667bee849..b7a967865b92a1 100644
--- a/tools/node_modules/eslint/lib/rules/array-element-newline.js
+++ b/tools/node_modules/eslint/lib/rules/array-element-newline.js
@@ -24,28 +24,52 @@ module.exports = {
fixable: "whitespace",
- schema: [
- {
- oneOf: [
- {
- enum: ["always", "never", "consistent"]
- },
- {
- type: "object",
- properties: {
- multiline: {
- type: "boolean"
+ schema: {
+ definitions: {
+ basicConfig: {
+ oneOf: [
+ {
+ enum: ["always", "never", "consistent"]
+ },
+ {
+ type: "object",
+ properties: {
+ multiline: {
+ type: "boolean"
+ },
+ minItems: {
+ type: ["integer", "null"],
+ minimum: 0
+ }
},
- minItems: {
- type: ["integer", "null"],
- minimum: 0
- }
+ additionalProperties: false
+ }
+ ]
+ }
+ },
+ items: [
+ {
+ oneOf: [
+ {
+ $ref: "#/definitions/basicConfig"
},
- additionalProperties: false
- }
- ]
- }
- ],
+ {
+ type: "object",
+ properties: {
+ ArrayExpression: {
+ $ref: "#/definitions/basicConfig"
+ },
+ ArrayPattern: {
+ $ref: "#/definitions/basicConfig"
+ }
+ },
+ additionalProperties: false,
+ minProperties: 1
+ }
+ ]
+ }
+ ]
+ },
messages: {
unexpectedLineBreak: "There should be no linebreak here.",
@@ -93,6 +117,20 @@ module.exports = {
* @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object.
*/
function normalizeOptions(options) {
+ if (options && (options.ArrayExpression || options.ArrayPattern)) {
+ let expressionOptions, patternOptions;
+
+ if (options.ArrayExpression) {
+ expressionOptions = normalizeOptionValue(options.ArrayExpression);
+ }
+
+ if (options.ArrayPattern) {
+ patternOptions = normalizeOptionValue(options.ArrayPattern);
+ }
+
+ return { ArrayExpression: expressionOptions, ArrayPattern: patternOptions };
+ }
+
const value = normalizeOptionValue(options);
return { ArrayExpression: value, ArrayPattern: value };
@@ -177,6 +215,10 @@ module.exports = {
const normalizedOptions = normalizeOptions(context.options[0]);
const options = normalizedOptions[node.type];
+ if (!options) {
+ return;
+ }
+
let elementBreak = false;
/*
diff --git a/tools/node_modules/eslint/lib/rules/computed-property-spacing.js b/tools/node_modules/eslint/lib/rules/computed-property-spacing.js
index a0bd7f48ced66b..48bea6a6fdc8f4 100644
--- a/tools/node_modules/eslint/lib/rules/computed-property-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/computed-property-spacing.js
@@ -67,7 +67,7 @@ module.exports = {
function reportNoBeginningSpace(node, token, tokenAfter) {
context.report({
node,
- loc: token.loc.start,
+ loc: { start: token.loc.end, end: tokenAfter.loc.start },
messageId: "unexpectedSpaceAfter",
data: {
tokenValue: token.value
@@ -88,7 +88,7 @@ module.exports = {
function reportNoEndingSpace(node, token, tokenBefore) {
context.report({
node,
- loc: token.loc.start,
+ loc: { start: tokenBefore.loc.end, end: token.loc.start },
messageId: "unexpectedSpaceBefore",
data: {
tokenValue: token.value
@@ -108,7 +108,7 @@ module.exports = {
function reportRequiredBeginningSpace(node, token) {
context.report({
node,
- loc: token.loc.start,
+ loc: token.loc,
messageId: "missingSpaceAfter",
data: {
tokenValue: token.value
@@ -128,7 +128,7 @@ module.exports = {
function reportRequiredEndingSpace(node, token) {
context.report({
node,
- loc: token.loc.start,
+ loc: token.loc,
messageId: "missingSpaceBefore",
data: {
tokenValue: token.value
diff --git a/tools/node_modules/eslint/lib/rules/default-case-last.js b/tools/node_modules/eslint/lib/rules/default-case-last.js
new file mode 100644
index 00000000000000..80c5d6bda73958
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/default-case-last.js
@@ -0,0 +1,44 @@
+/**
+ * @fileoverview Rule to enforce default clauses in switch statements to be last
+ * @author Milos Djermanovic
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ type: "suggestion",
+
+ docs: {
+ description: "enforce default clauses in switch statements to be last",
+ category: "Best Practices",
+ recommended: false,
+ url: "https://eslint.org/docs/rules/default-case-last"
+ },
+
+ schema: [],
+
+ messages: {
+ notLast: "Default clause should be the last clause."
+ }
+ },
+
+ create(context) {
+ return {
+ SwitchStatement(node) {
+ const cases = node.cases,
+ indexOfDefault = cases.findIndex(c => c.test === null);
+
+ if (indexOfDefault !== -1 && indexOfDefault !== cases.length - 1) {
+ const defaultClause = cases[indexOfDefault];
+
+ context.report({ node: defaultClause, messageId: "notLast" });
+ }
+ }
+ };
+ }
+};
diff --git a/tools/node_modules/eslint/lib/rules/id-blacklist.js b/tools/node_modules/eslint/lib/rules/id-blacklist.js
index 53be62e68a3626..e5dcdc63091568 100644
--- a/tools/node_modules/eslint/lib/rules/id-blacklist.js
+++ b/tools/node_modules/eslint/lib/rules/id-blacklist.js
@@ -61,9 +61,12 @@ module.exports = {
* @returns {boolean} whether an error should be reported or not
*/
function shouldReport(effectiveParent, name) {
- return effectiveParent.type !== "CallExpression" &&
+ return (
+ effectiveParent.type !== "CallExpression" &&
effectiveParent.type !== "NewExpression" &&
- isInvalid(name);
+ effectiveParent.parent.type !== "ObjectPattern" &&
+ isInvalid(name)
+ );
}
/**
@@ -98,11 +101,11 @@ module.exports = {
report(node);
}
- // Report AssignmentExpressions only if they are the left side of the assignment
+ // Report AssignmentExpressions only if they are the left side of the assignment
} else if (effectiveParent.type === "AssignmentExpression" &&
(effectiveParent.right.type !== "MemberExpression" ||
- effectiveParent.left.type === "MemberExpression" &&
- effectiveParent.left.property.name === node.name)) {
+ effectiveParent.left.type === "MemberExpression" &&
+ effectiveParent.left.property.name === node.name)) {
if (isInvalid(name)) {
report(node);
}
@@ -115,7 +118,7 @@ module.exports = {
report(node);
}
- // Report anything that is a match and not a CallExpression
+ // Report anything that is a match and not a CallExpression
} else if (shouldReport(effectiveParent, name)) {
report(node);
}
diff --git a/tools/node_modules/eslint/lib/rules/indent.js b/tools/node_modules/eslint/lib/rules/indent.js
index 694cf7d9e6ed4f..d576fde0382461 100644
--- a/tools/node_modules/eslint/lib/rules/indent.js
+++ b/tools/node_modules/eslint/lib/rules/indent.js
@@ -540,8 +540,15 @@ module.exports = {
]
},
outerIIFEBody: {
- type: "integer",
- minimum: 0
+ oneOf: [
+ {
+ type: "integer",
+ minimum: 0
+ },
+ {
+ enum: ["off"]
+ }
+ ]
},
MemberExpression: {
oneOf: [
@@ -590,6 +597,10 @@ module.exports = {
type: "boolean",
default: false
},
+ offsetTernaryExpressions: {
+ type: "boolean",
+ default: false
+ },
ignoredNodes: {
type: "array",
items: {
@@ -922,7 +933,11 @@ module.exports = {
parameterParens.add(openingParen);
parameterParens.add(closingParen);
- offsets.setDesiredOffset(openingParen, sourceCode.getTokenBefore(openingParen), 0);
+
+ const offsetAfterToken = node.callee.type === "TaggedTemplateExpression" ? sourceCode.getFirstToken(node.callee.quasi) : openingParen;
+ const offsetToken = sourceCode.getTokenBefore(offsetAfterToken);
+
+ offsets.setDesiredOffset(openingParen, offsetToken, 0);
addElementListIndent(node.arguments, openingParen, closingParen, options.CallExpression.arguments);
}
@@ -1088,7 +1103,6 @@ module.exports = {
},
"BlockStatement, ClassBody"(node) {
-
let blockIndentLevel;
if (node.parent && isOuterIIFE(node.parent)) {
@@ -1108,6 +1122,7 @@ module.exports = {
if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
offsets.setDesiredOffset(sourceCode.getFirstToken(node), sourceCode.getFirstToken(node.parent), 0);
}
+
addElementListIndent(node.body, sourceCode.getFirstToken(node), sourceCode.getLastToken(node), blockIndentLevel);
},
@@ -1142,7 +1157,8 @@ module.exports = {
offsets.setDesiredOffset(questionMarkToken, firstToken, 1);
offsets.setDesiredOffset(colonToken, firstToken, 1);
- offsets.setDesiredOffset(firstConsequentToken, firstToken, 1);
+ offsets.setDesiredOffset(firstConsequentToken, firstToken,
+ options.offsetTernaryExpressions ? 2 : 1);
/*
* The alternate and the consequent should usually have the same indentation.
@@ -1167,7 +1183,9 @@ module.exports = {
* If `baz` were aligned with `bar` rather than being offset by 1 from `foo`, `baz` would end up
* having no expected indentation.
*/
- offsets.setDesiredOffset(firstAlternateToken, firstToken, 1);
+ offsets.setDesiredOffset(firstAlternateToken, firstToken,
+ firstAlternateToken.type === "Punctuator" &&
+ options.offsetTernaryExpressions ? 2 : 1);
}
}
},
diff --git a/tools/node_modules/eslint/lib/rules/index.js b/tools/node_modules/eslint/lib/rules/index.js
index d3fbe412080360..7f563eb2ebfb96 100644
--- a/tools/node_modules/eslint/lib/rules/index.js
+++ b/tools/node_modules/eslint/lib/rules/index.js
@@ -37,6 +37,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
"constructor-super": () => require("./constructor-super"),
curly: () => require("./curly"),
"default-case": () => require("./default-case"),
+ "default-case-last": () => require("./default-case-last"),
"default-param-last": () => require("./default-param-last"),
"dot-location": () => require("./dot-location"),
"dot-notation": () => require("./dot-notation"),
@@ -178,6 +179,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
"no-prototype-builtins": () => require("./no-prototype-builtins"),
"no-redeclare": () => require("./no-redeclare"),
"no-regex-spaces": () => require("./no-regex-spaces"),
+ "no-restricted-exports": () => require("./no-restricted-exports"),
"no-restricted-globals": () => require("./no-restricted-globals"),
"no-restricted-imports": () => require("./no-restricted-imports"),
"no-restricted-modules": () => require("./no-restricted-modules"),
@@ -215,6 +217,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
"no-unused-labels": () => require("./no-unused-labels"),
"no-unused-vars": () => require("./no-unused-vars"),
"no-use-before-define": () => require("./no-use-before-define"),
+ "no-useless-backreference": () => require("./no-useless-backreference"),
"no-useless-call": () => require("./no-useless-call"),
"no-useless-catch": () => require("./no-useless-catch"),
"no-useless-computed-key": () => require("./no-useless-computed-key"),
diff --git a/tools/node_modules/eslint/lib/rules/key-spacing.js b/tools/node_modules/eslint/lib/rules/key-spacing.js
index 6d1b9121c78c5f..c405043794c7d1 100644
--- a/tools/node_modules/eslint/lib/rules/key-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/key-spacing.js
@@ -414,8 +414,7 @@ module.exports = {
if (property.computed) {
return sourceCode.getText().slice(key.range[0], key.range[1]);
}
-
- return property.key.name || property.key.value;
+ return astUtils.getStaticPropertyName(property);
}
/**
diff --git a/tools/node_modules/eslint/lib/rules/max-len.js b/tools/node_modules/eslint/lib/rules/max-len.js
index b29099ed4c4f09..82229c3be4894a 100644
--- a/tools/node_modules/eslint/lib/rules/max-len.js
+++ b/tools/node_modules/eslint/lib/rules/max-len.js
@@ -183,6 +183,21 @@ module.exports = {
(end.line > lineNumber || (end.line === lineNumber && end.column === line.length));
}
+ /**
+ * Check if a node is a JSXEmptyExpression contained in a single line JSXExpressionContainer.
+ * @param {ASTNode} node A node to check.
+ * @returns {boolean} True if the node is a JSXEmptyExpression contained in a single line JSXExpressionContainer.
+ */
+ function isJSXEmptyExpressionInSingleLineContainer(node) {
+ if (!node || !node.parent || node.type !== "JSXEmptyExpression" || node.parent.type !== "JSXExpressionContainer") {
+ return false;
+ }
+
+ const parent = node.parent;
+
+ return parent.loc.start.line === parent.loc.end.line;
+ }
+
/**
* Gets the line after the comment and any remaining trailing whitespace is
* stripped.
@@ -252,6 +267,33 @@ module.exports = {
return acc;
}
+ /**
+ * Returns an array of all comments in the source code.
+ * If the element in the array is a JSXEmptyExpression contained with a single line JSXExpressionContainer,
+ * the element is changed with JSXExpressionContainer node.
+ * @returns {ASTNode[]} An array of comment nodes
+ */
+ function getAllComments() {
+ const comments = [];
+
+ sourceCode.getAllComments()
+ .forEach(commentNode => {
+ const containingNode = sourceCode.getNodeByRangeIndex(commentNode.range[0]);
+
+ if (isJSXEmptyExpressionInSingleLineContainer(containingNode)) {
+
+ // push a unique node only
+ if (comments[comments.length - 1] !== containingNode.parent) {
+ comments.push(containingNode.parent);
+ }
+ } else {
+ comments.push(commentNode);
+ }
+ });
+
+ return comments;
+ }
+
/**
* Check the program for max length
* @param {ASTNode} node Node to examine
@@ -264,7 +306,7 @@ module.exports = {
const lines = sourceCode.lines,
// list of comments to ignore
- comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? sourceCode.getAllComments() : [];
+ comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? getAllComments() : [];
// we iterate over comments in parallel with the lines
let commentsIndex = 0;
diff --git a/tools/node_modules/eslint/lib/rules/max-lines-per-function.js b/tools/node_modules/eslint/lib/rules/max-lines-per-function.js
index 0cfc1f8da9e65e..03539fae470078 100644
--- a/tools/node_modules/eslint/lib/rules/max-lines-per-function.js
+++ b/tools/node_modules/eslint/lib/rules/max-lines-per-function.js
@@ -54,9 +54,6 @@ const OPTIONS_OR_INTEGER_SCHEMA = {
function getCommentLineNumbers(comments) {
const map = new Map();
- if (!comments) {
- return map;
- }
comments.forEach(comment => {
for (let i = comment.loc.start.line; i <= comment.loc.end.line; i++) {
map.set(i, comment);
diff --git a/tools/node_modules/eslint/lib/rules/new-cap.js b/tools/node_modules/eslint/lib/rules/new-cap.js
index cee979310ea7cc..7cce968c5aed0e 100644
--- a/tools/node_modules/eslint/lib/rules/new-cap.js
+++ b/tools/node_modules/eslint/lib/rules/new-cap.js
@@ -9,6 +9,8 @@
// Requirements
//------------------------------------------------------------------------------
+const astUtils = require("./utils/ast-utils");
+
//------------------------------------------------------------------------------
// Helpers
//------------------------------------------------------------------------------
@@ -160,13 +162,7 @@ module.exports = {
let name = "";
if (node.callee.type === "MemberExpression") {
- const property = node.callee.property;
-
- if (property.type === "Literal" && (typeof property.value === "string")) {
- name = property.value;
- } else if (property.type === "Identifier" && !node.callee.computed) {
- name = property.name;
- }
+ name = astUtils.getStaticPropertyName(node.callee) || "";
} else {
name = node.callee.name;
}
diff --git a/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js b/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js
index 6041e9e371ce5e..55639746b27590 100644
--- a/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js
+++ b/tools/node_modules/eslint/lib/rules/no-dupe-class-members.js
@@ -5,6 +5,8 @@
"use strict";
+const astUtils = require("./utils/ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -53,21 +55,6 @@ module.exports = {
return stateMap[key][isStatic ? "static" : "nonStatic"];
}
- /**
- * Gets the name text of a given node.
- * @param {ASTNode} node A node to get the name.
- * @returns {string} The name text of the node.
- */
- function getName(node) {
- switch (node.type) {
- case "Identifier": return node.name;
- case "Literal": return String(node.value);
-
- /* istanbul ignore next: syntax error */
- default: return "";
- }
- }
-
return {
// Initializes the stack of state of member declarations.
@@ -91,7 +78,7 @@ module.exports = {
return;
}
- const name = getName(node.key);
+ const name = astUtils.getStaticPropertyName(node) || "";
const state = getState(name, node.static);
let isDuplicate = false;
diff --git a/tools/node_modules/eslint/lib/rules/no-extra-parens.js b/tools/node_modules/eslint/lib/rules/no-extra-parens.js
index f96e572bfeef54..e70353576bb950 100644
--- a/tools/node_modules/eslint/lib/rules/no-extra-parens.js
+++ b/tools/node_modules/eslint/lib/rules/no-extra-parens.js
@@ -169,6 +169,28 @@ module.exports = {
return ruleApplies(node) && isParenthesisedTwice(node);
}
+ /**
+ * Determines if a node that is expected to be parenthesised is surrounded by
+ * (potentially) invalid extra parentheses with considering precedence level of the node.
+ * If the preference level of the node is not higher or equal to precedence lower limit, it also checks
+ * whether the node is surrounded by parentheses twice or not.
+ * @param {ASTNode} node The node to be checked.
+ * @param {number} precedenceLowerLimit The lower limit of precedence.
+ * @returns {boolean} True if the node is has an unexpected extra pair of parentheses.
+ * @private
+ */
+ function hasExcessParensWithPrecedence(node, precedenceLowerLimit) {
+ if (ruleApplies(node) && isParenthesised(node)) {
+ if (
+ precedence(node) >= precedenceLowerLimit ||
+ isParenthesisedTwice(node)
+ ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Determines if a node test expression is allowed to have a parenthesised assignment
* @param {ASTNode} node The node to be checked.
@@ -320,6 +342,17 @@ module.exports = {
return node.type === "CallExpression" && node.callee.type === "FunctionExpression";
}
+ /**
+ * Determines if the given node can be the assignment target in destructuring or the LHS of an assignment.
+ * This is to avoid an autofix that could change behavior because parsers mistakenly allow invalid syntax,
+ * such as `(a = b) = c` and `[(a = b) = c] = []`. Ideally, this function shouldn't be necessary.
+ * @param {ASTNode} [node] The node to check
+ * @returns {boolean} `true` if the given node can be a valid assignment target
+ */
+ function canBeAssignmentTarget(node) {
+ return node && (node.type === "Identifier" || node.type === "MemberExpression");
+ }
+
/**
* Report the node
* @param {ASTNode} node node to evaluate
@@ -370,17 +403,13 @@ module.exports = {
}
/**
- * Evaluate Unary update
+ * Evaluate a argument of the node.
* @param {ASTNode} node node to evaluate
* @returns {void}
* @private
*/
- function checkUnaryUpdate(node) {
- if (node.type === "UnaryExpression" && node.argument.type === "BinaryExpression" && node.argument.operator === "**") {
- return;
- }
-
- if (hasExcessParens(node.argument) && precedence(node.argument) >= precedence(node)) {
+ function checkArgumentWithPrecedence(node) {
+ if (hasExcessParensWithPrecedence(node.argument, precedence(node))) {
report(node.argument);
}
}
@@ -411,25 +440,24 @@ module.exports = {
function checkCallNew(node) {
const callee = node.callee;
- if (hasExcessParens(callee) && precedence(callee) >= precedence(node)) {
+ if (hasExcessParensWithPrecedence(callee, precedence(node))) {
const hasNewParensException = callee.type === "NewExpression" && !isNewExpressionWithParens(callee);
if (
hasDoubleExcessParens(callee) ||
!isIIFE(node) && !hasNewParensException && !(
- /*
- * Allow extra parens around a new expression if
- * there are intervening parentheses.
- */
- (callee.type === "MemberExpression" && doesMemberExpressionContainCallExpression(callee))
+ // Allow extra parens around a new expression if they are intervening parentheses.
+ node.type === "NewExpression" &&
+ callee.type === "MemberExpression" &&
+ doesMemberExpressionContainCallExpression(callee)
)
) {
report(node.callee);
}
}
node.arguments
- .filter(arg => hasExcessParens(arg) && precedence(arg) >= PRECEDENCE_OF_ASSIGNMENT_EXPR)
+ .filter(arg => hasExcessParensWithPrecedence(arg, PRECEDENCE_OF_ASSIGNMENT_EXPR))
.forEach(report);
}
@@ -444,15 +472,26 @@ module.exports = {
const leftPrecedence = precedence(node.left);
const rightPrecedence = precedence(node.right);
const isExponentiation = node.operator === "**";
- const shouldSkipLeft = (NESTED_BINARY && (node.left.type === "BinaryExpression" || node.left.type === "LogicalExpression")) ||
- node.left.type === "UnaryExpression" && isExponentiation;
+ const shouldSkipLeft = NESTED_BINARY && (node.left.type === "BinaryExpression" || node.left.type === "LogicalExpression");
const shouldSkipRight = NESTED_BINARY && (node.right.type === "BinaryExpression" || node.right.type === "LogicalExpression");
- if (!shouldSkipLeft && hasExcessParens(node.left) && (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation))) {
- report(node.left);
+ if (!shouldSkipLeft && hasExcessParens(node.left)) {
+ if (
+ !(node.left.type === "UnaryExpression" && isExponentiation) &&
+ (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation)) ||
+ isParenthesisedTwice(node.left)
+ ) {
+ report(node.left);
+ }
}
- if (!shouldSkipRight && hasExcessParens(node.right) && (rightPrecedence > prec || (rightPrecedence === prec && isExponentiation))) {
- report(node.right);
+
+ if (!shouldSkipRight && hasExcessParens(node.right)) {
+ if (
+ (rightPrecedence > prec || (rightPrecedence === prec && isExponentiation)) ||
+ isParenthesisedTwice(node.right)
+ ) {
+ report(node.right);
+ }
}
}
@@ -485,11 +524,7 @@ module.exports = {
* @returns {void}
*/
function checkSpreadOperator(node) {
- const hasExtraParens = precedence(node.argument) >= PRECEDENCE_OF_ASSIGNMENT_EXPR
- ? hasExcessParens(node.argument)
- : hasDoubleExcessParens(node.argument);
-
- if (hasExtraParens) {
+ if (hasExcessParensWithPrecedence(node.argument, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
report(node.argument);
}
}
@@ -651,7 +686,13 @@ module.exports = {
return {
ArrayExpression(node) {
node.elements
- .filter(e => e && hasExcessParens(e) && precedence(e) >= PRECEDENCE_OF_ASSIGNMENT_EXPR)
+ .filter(e => e && hasExcessParensWithPrecedence(e, PRECEDENCE_OF_ASSIGNMENT_EXPR))
+ .forEach(report);
+ },
+
+ ArrayPattern(node) {
+ node.elements
+ .filter(e => canBeAssignmentTarget(e) && hasExcessParens(e))
.forEach(report);
},
@@ -674,18 +715,18 @@ module.exports = {
if (astUtils.isOpeningParenToken(tokenBeforeFirst) && astUtils.isOpeningBraceToken(firstBodyToken)) {
tokensToIgnore.add(firstBodyToken);
}
- if (hasExcessParens(node.body) && precedence(node.body) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
+ if (hasExcessParensWithPrecedence(node.body, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
report(node.body);
}
}
},
AssignmentExpression(node) {
- if (isReturnAssignException(node)) {
- return;
+ if (canBeAssignmentTarget(node.left) && hasExcessParens(node.left)) {
+ report(node.left);
}
- if (hasExcessParens(node.right) && precedence(node.right) >= precedence(node)) {
+ if (!isReturnAssignException(node) && hasExcessParensWithPrecedence(node.right, precedence(node))) {
report(node.right);
}
},
@@ -702,8 +743,8 @@ module.exports = {
ClassBody(node) {
node.body
- .filter(member => member.type === "MethodDefinition" && member.computed &&
- member.key && hasExcessParens(member.key) && precedence(member.key) >= PRECEDENCE_OF_ASSIGNMENT_EXPR)
+ .filter(member => member.type === "MethodDefinition" && member.computed && member.key)
+ .filter(member => hasExcessParensWithPrecedence(member.key, PRECEDENCE_OF_ASSIGNMENT_EXPR))
.forEach(member => report(member.key));
},
@@ -711,16 +752,18 @@ module.exports = {
if (isReturnAssignException(node)) {
return;
}
-
- if (hasExcessParens(node.test) && precedence(node.test) >= precedence({ type: "LogicalExpression", operator: "||" })) {
+ if (
+ !isCondAssignException(node) &&
+ hasExcessParensWithPrecedence(node.test, precedence({ type: "LogicalExpression", operator: "||" }))
+ ) {
report(node.test);
}
- if (hasExcessParens(node.consequent) && precedence(node.consequent) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
+ if (hasExcessParensWithPrecedence(node.consequent, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
report(node.consequent);
}
- if (hasExcessParens(node.alternate) && precedence(node.alternate) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
+ if (hasExcessParensWithPrecedence(node.alternate, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
report(node.alternate);
}
},
@@ -757,9 +800,19 @@ module.exports = {
tokensToIgnore.add(firstLeftToken);
}
}
- if (!(node.type === "ForOfStatement" && node.right.type === "SequenceExpression") && hasExcessParens(node.right)) {
+
+ if (node.type === "ForOfStatement") {
+ const hasExtraParens = node.right.type === "SequenceExpression"
+ ? hasDoubleExcessParens(node.right)
+ : hasExcessParens(node.right);
+
+ if (hasExtraParens) {
+ report(node.right);
+ }
+ } else if (hasExcessParens(node.right)) {
report(node.right);
}
+
if (hasExcessParens(node.left)) {
report(node.left);
}
@@ -910,11 +963,17 @@ module.exports = {
NewExpression: checkCallNew,
ObjectExpression(node) {
+ node.properties
+ .filter(property => property.value && hasExcessParensWithPrecedence(property.value, PRECEDENCE_OF_ASSIGNMENT_EXPR))
+ .forEach(property => report(property.value));
+ },
+
+ ObjectPattern(node) {
node.properties
.filter(property => {
const value = property.value;
- return value && hasExcessParens(value) && precedence(value) >= PRECEDENCE_OF_ASSIGNMENT_EXPR;
+ return canBeAssignmentTarget(value) && hasExcessParens(value);
}).forEach(property => report(property.value));
},
@@ -922,12 +981,20 @@ module.exports = {
if (node.computed) {
const { key } = node;
- if (key && hasExcessParens(key) && precedence(key) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
+ if (key && hasExcessParensWithPrecedence(key, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
report(key);
}
}
},
+ RestElement(node) {
+ const argument = node.argument;
+
+ if (canBeAssignmentTarget(argument) && hasExcessParens(argument)) {
+ report(argument);
+ }
+ },
+
ReturnStatement(node) {
const returnToken = sourceCode.getFirstToken(node);
@@ -945,8 +1012,10 @@ module.exports = {
},
SequenceExpression(node) {
+ const precedenceOfNode = precedence(node);
+
node.expressions
- .filter(e => hasExcessParens(e) && precedence(e) >= precedence(node))
+ .filter(e => hasExcessParensWithPrecedence(e, precedenceOfNode))
.forEach(report);
},
@@ -970,16 +1039,17 @@ module.exports = {
}
},
- UnaryExpression: checkUnaryUpdate,
- UpdateExpression: checkUnaryUpdate,
- AwaitExpression: checkUnaryUpdate,
+ UnaryExpression: checkArgumentWithPrecedence,
+ UpdateExpression: checkArgumentWithPrecedence,
+ AwaitExpression: checkArgumentWithPrecedence,
VariableDeclarator(node) {
- if (node.init && hasExcessParens(node.init) &&
- precedence(node.init) >= PRECEDENCE_OF_ASSIGNMENT_EXPR &&
+ if (
+ node.init && hasExcessParensWithPrecedence(node.init, PRECEDENCE_OF_ASSIGNMENT_EXPR) &&
- // RegExp literal is allowed to have parens (#1589)
- !(node.init.type === "Literal" && node.init.regex)) {
+ // RegExp literal is allowed to have parens (#1589)
+ !(node.init.type === "Literal" && node.init.regex)
+ ) {
report(node.init);
}
},
@@ -1022,9 +1092,13 @@ module.exports = {
},
AssignmentPattern(node) {
- const { right } = node;
+ const { left, right } = node;
+
+ if (canBeAssignmentTarget(left) && hasExcessParens(left)) {
+ report(left);
+ }
- if (right && hasExcessParens(right) && precedence(right) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
+ if (right && hasExcessParensWithPrecedence(right, PRECEDENCE_OF_ASSIGNMENT_EXPR)) {
report(right);
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-func-assign.js b/tools/node_modules/eslint/lib/rules/no-func-assign.js
index 66756e62bef5b2..33d0ad9ecd1433 100644
--- a/tools/node_modules/eslint/lib/rules/no-func-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-func-assign.js
@@ -22,7 +22,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-func-assign"
},
- schema: []
+ schema: [],
+
+ messages: {
+ isAFunction: "'{{name}}' is a function."
+ }
},
create(context) {
@@ -34,7 +38,13 @@ module.exports = {
*/
function checkReference(references) {
astUtils.getModifyingReferences(references).forEach(reference => {
- context.report({ node: reference.identifier, message: "'{{name}}' is a function.", data: { name: reference.identifier.name } });
+ context.report({
+ node: reference.identifier,
+ messageId: "isAFunction",
+ data: {
+ name: reference.identifier.name
+ }
+ });
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-global-assign.js b/tools/node_modules/eslint/lib/rules/no-global-assign.js
index 4ab0c706446256..ea854c4aa8cd9b 100644
--- a/tools/node_modules/eslint/lib/rules/no-global-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-global-assign.js
@@ -32,7 +32,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ globalShouldNotBeModified: "Read-only global '{{name}}' should not be modified."
+ }
},
create(context) {
@@ -60,8 +64,10 @@ module.exports = {
) {
context.report({
node: identifier,
- message: "Read-only global '{{name}}' should not be modified.",
- data: identifier
+ messageId: "globalShouldNotBeModified",
+ data: {
+ name: identifier.name
+ }
});
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js b/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js
index c80f9813020be5..6d5ee61e96bd5b 100644
--- a/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js
+++ b/tools/node_modules/eslint/lib/rules/no-implicit-coercion.js
@@ -187,7 +187,11 @@ module.exports = {
}
},
additionalProperties: false
- }]
+ }],
+
+ messages: {
+ useRecommendation: "use `{{recommendation}}` instead."
+ }
},
create(context) {
@@ -204,7 +208,7 @@ module.exports = {
function report(node, recommendation, shouldFix) {
context.report({
node,
- message: "use `{{recommendation}}` instead.",
+ messageId: "useRecommendation",
data: {
recommendation
},
diff --git a/tools/node_modules/eslint/lib/rules/no-implied-eval.js b/tools/node_modules/eslint/lib/rules/no-implied-eval.js
index e0764d8223db0a..46bb5d4f76e5f7 100644
--- a/tools/node_modules/eslint/lib/rules/no-implied-eval.js
+++ b/tools/node_modules/eslint/lib/rules/no-implied-eval.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-implied-eval"
},
- schema: []
+ schema: [],
+
+ messages: {
+ impliedEval: "Implied eval. Consider passing a function instead of a string."
+ }
},
create(context) {
@@ -107,7 +111,10 @@ module.exports = {
// remove the entire substack, to avoid duplicate reports
const substack = impliedEvalAncestorsStack.pop();
- context.report({ node: substack[0], message: "Implied eval. Consider passing a function instead of a string." });
+ context.report({
+ node: substack[0],
+ messageId: "impliedEval"
+ });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-inline-comments.js b/tools/node_modules/eslint/lib/rules/no-inline-comments.js
index bd226ecc35fde1..41b0f1e664c776 100644
--- a/tools/node_modules/eslint/lib/rules/no-inline-comments.js
+++ b/tools/node_modules/eslint/lib/rules/no-inline-comments.js
@@ -21,7 +21,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-inline-comments"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpectedInlineComment: "Unexpected comment inline with code."
+ }
},
create(context) {
@@ -64,7 +68,10 @@ module.exports = {
return;
}
- context.report({ node, message: "Unexpected comment inline with code." });
+ context.report({
+ node,
+ messageId: "unexpectedInlineComment"
+ });
}
//--------------------------------------------------------------------------
diff --git a/tools/node_modules/eslint/lib/rules/no-inner-declarations.js b/tools/node_modules/eslint/lib/rules/no-inner-declarations.js
index 60508d3e864eda..e1c29e0a3b4f3f 100644
--- a/tools/node_modules/eslint/lib/rules/no-inner-declarations.js
+++ b/tools/node_modules/eslint/lib/rules/no-inner-declarations.js
@@ -24,7 +24,11 @@ module.exports = {
{
enum: ["functions", "both"]
}
- ]
+ ],
+
+ messages: {
+ moveDeclToRoot: "Move {{type}} declaration to {{body}} root."
+ }
},
create(context) {
@@ -68,7 +72,7 @@ module.exports = {
if (!valid) {
context.report({
node,
- message: "Move {{type}} declaration to {{body}} root.",
+ messageId: "moveDeclToRoot",
data: {
type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
body: (body.type === "Program" ? "program" : "function body")
diff --git a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js
index 852efbbb935b90..4ede995891bbca 100644
--- a/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js
+++ b/tools/node_modules/eslint/lib/rules/no-invalid-regexp.js
@@ -40,6 +40,8 @@ module.exports = {
},
additionalProperties: false
}]
+
+ // no messages, because the error text comes directly from the regexpp module
},
create(context) {
diff --git a/tools/node_modules/eslint/lib/rules/no-invalid-this.js b/tools/node_modules/eslint/lib/rules/no-invalid-this.js
index 5398fc3b5f842c..a79c586d719852 100644
--- a/tools/node_modules/eslint/lib/rules/no-invalid-this.js
+++ b/tools/node_modules/eslint/lib/rules/no-invalid-this.js
@@ -37,7 +37,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpectedThis: "Unexpected 'this'."
+ }
},
create(context) {
@@ -130,7 +134,10 @@ module.exports = {
const current = stack.getCurrent();
if (current && !current.valid) {
- context.report({ node, message: "Unexpected 'this'." });
+ context.report({
+ node,
+ messageId: "unexpectedThis"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js b/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js
index f339fa6c8f34c9..fa72c3ee72fcdc 100644
--- a/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js
+++ b/tools/node_modules/eslint/lib/rules/no-irregular-whitespace.js
@@ -59,7 +59,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ noIrregularWhitespace: "Irregular whitespace not allowed."
+ }
},
create(context) {
@@ -161,7 +165,11 @@ module.exports = {
column: match.index
};
- errors.push({ node, message: "Irregular whitespace not allowed.", loc: location });
+ errors.push({
+ node,
+ messageId: "noIrregularWhitespace",
+ loc: location
+ });
}
});
}
@@ -186,7 +194,11 @@ module.exports = {
column: sourceLines[lineIndex].length
};
- errors.push({ node, message: "Irregular whitespace not allowed.", loc: location });
+ errors.push({
+ node,
+ messageId: "noIrregularWhitespace",
+ loc: location
+ });
lastLineIndex = lineIndex;
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-iterator.js b/tools/node_modules/eslint/lib/rules/no-iterator.js
index 82319a3fb1dfb6..0b01d3533d9db1 100644
--- a/tools/node_modules/eslint/lib/rules/no-iterator.js
+++ b/tools/node_modules/eslint/lib/rules/no-iterator.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-iterator"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noIterator: "Reserved name '__iterator__'."
+ }
},
create(context) {
@@ -32,7 +36,10 @@ module.exports = {
if (node.property &&
(node.property.type === "Identifier" && node.property.name === "__iterator__" && !node.computed) ||
(node.property.type === "Literal" && node.property.value === "__iterator__")) {
- context.report({ node, message: "Reserved name '__iterator__'." });
+ context.report({
+ node,
+ messageId: "noIterator"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-label-var.js b/tools/node_modules/eslint/lib/rules/no-label-var.js
index a9fd042a390225..570db03285cf97 100644
--- a/tools/node_modules/eslint/lib/rules/no-label-var.js
+++ b/tools/node_modules/eslint/lib/rules/no-label-var.js
@@ -26,7 +26,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-label-var"
},
- schema: []
+ schema: [],
+
+ messages: {
+ identifierClashWithLabel: "Found identifier with same name as label."
+ }
},
create(context) {
@@ -62,7 +66,10 @@ module.exports = {
* with the innermost scope.
*/
if (findIdentifier(scope, node.label.name)) {
- context.report({ node, message: "Found identifier with same name as label." });
+ context.report({
+ node,
+ messageId: "identifierClashWithLabel"
+ });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-labels.js b/tools/node_modules/eslint/lib/rules/no-labels.js
index 52f4b0f5168b71..85760d80dbedd7 100644
--- a/tools/node_modules/eslint/lib/rules/no-labels.js
+++ b/tools/node_modules/eslint/lib/rules/no-labels.js
@@ -40,7 +40,13 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpectedLabel: "Unexpected labeled statement.",
+ unexpectedLabelInBreak: "Unexpected label in break statement.",
+ unexpectedLabelInContinue: "Unexpected label in continue statement."
+ }
},
create(context) {
@@ -113,7 +119,7 @@ module.exports = {
if (!isAllowed(scopeInfo.kind)) {
context.report({
node,
- message: "Unexpected labeled statement."
+ messageId: "unexpectedLabel"
});
}
@@ -124,7 +130,7 @@ module.exports = {
if (node.label && !isAllowed(getKind(node.label.name))) {
context.report({
node,
- message: "Unexpected label in break statement."
+ messageId: "unexpectedLabelInBreak"
});
}
},
@@ -133,7 +139,7 @@ module.exports = {
if (node.label && !isAllowed(getKind(node.label.name))) {
context.report({
node,
- message: "Unexpected label in continue statement."
+ messageId: "unexpectedLabelInContinue"
});
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-lone-blocks.js b/tools/node_modules/eslint/lib/rules/no-lone-blocks.js
index 37561b0f9a3055..d7069887b8e460 100644
--- a/tools/node_modules/eslint/lib/rules/no-lone-blocks.js
+++ b/tools/node_modules/eslint/lib/rules/no-lone-blocks.js
@@ -20,7 +20,12 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-lone-blocks"
},
- schema: []
+ schema: [],
+
+ messages: {
+ redundantBlock: "Block is redundant.",
+ redundantNestedBlock: "Nested block is redundant."
+ }
},
create(context) {
@@ -35,9 +40,12 @@ module.exports = {
* @returns {void}
*/
function report(node) {
- const message = node.parent.type === "BlockStatement" ? "Nested block is redundant." : "Block is redundant.";
+ const messageId = node.parent.type === "BlockStatement" ? "redundantNestedBlock" : "redundantBlock";
- context.report({ node, message });
+ context.report({
+ node,
+ messageId
+ });
}
/**
diff --git a/tools/node_modules/eslint/lib/rules/no-lonely-if.js b/tools/node_modules/eslint/lib/rules/no-lonely-if.js
index b62d176a264210..53f9445f835ec5 100644
--- a/tools/node_modules/eslint/lib/rules/no-lonely-if.js
+++ b/tools/node_modules/eslint/lib/rules/no-lonely-if.js
@@ -20,7 +20,11 @@ module.exports = {
},
schema: [],
- fixable: "code"
+ fixable: "code",
+
+ messages: {
+ unexpectedLonelyIf: "Unexpected if as the only statement in an else block."
+ }
},
create(context) {
@@ -38,7 +42,7 @@ module.exports = {
parent === grandparent.alternate) {
context.report({
node,
- message: "Unexpected if as the only statement in an else block.",
+ messageId: "unexpectedLonelyIf",
fix(fixer) {
const openingElseCurly = sourceCode.getFirstToken(parent);
const closingElseCurly = sourceCode.getLastToken(parent);
diff --git a/tools/node_modules/eslint/lib/rules/no-magic-numbers.js b/tools/node_modules/eslint/lib/rules/no-magic-numbers.js
index 0909e3166d952e..4bf24996cb8f20 100644
--- a/tools/node_modules/eslint/lib/rules/no-magic-numbers.js
+++ b/tools/node_modules/eslint/lib/rules/no-magic-numbers.js
@@ -5,10 +5,24 @@
"use strict";
+const { isNumericLiteral } = require("./utils/ast-utils");
+
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
+/**
+ * Convert the value to bigint if it's a string. Otherwise return the value as-is.
+ * @param {bigint|number|string} x The value to normalize.
+ * @returns {bigint|number} The normalized value.
+ */
+function normalizeIgnoreValue(x) {
+ if (typeof x === "string") {
+ return BigInt(x.slice(0, -1));
+ }
+ return x;
+}
+
module.exports = {
meta: {
type: "suggestion",
@@ -34,7 +48,10 @@ module.exports = {
ignore: {
type: "array",
items: {
- type: "number"
+ anyOf: [
+ { type: "number" },
+ { type: "string", pattern: "^[+-]?(?:0|[1-9][0-9]*)n$" }
+ ]
},
uniqueItems: true
},
@@ -56,18 +73,9 @@ module.exports = {
const config = context.options[0] || {},
detectObjects = !!config.detectObjects,
enforceConst = !!config.enforceConst,
- ignore = config.ignore || [],
+ ignore = (config.ignore || []).map(normalizeIgnoreValue),
ignoreArrayIndexes = !!config.ignoreArrayIndexes;
- /**
- * Returns whether the node is number literal
- * @param {Node} node the node literal being evaluated
- * @returns {boolean} true if the node is a number literal
- */
- function isNumber(node) {
- return typeof node.value === "number";
- }
-
/**
* Returns whether the number should be ignored
* @param {number} num the number
@@ -113,7 +121,7 @@ module.exports = {
Literal(node) {
const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"];
- if (!isNumber(node)) {
+ if (!isNumericLiteral(node)) {
return;
}
diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-operators.js b/tools/node_modules/eslint/lib/rules/no-mixed-operators.js
index 80fac79affdb0e..37e8906e827a4c 100644
--- a/tools/node_modules/eslint/lib/rules/no-mixed-operators.js
+++ b/tools/node_modules/eslint/lib/rules/no-mixed-operators.js
@@ -112,7 +112,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpectedMixedOperator: "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'."
+ }
},
create(context) {
@@ -188,8 +192,6 @@ module.exports = {
const parent = node.parent;
const left = (getChildNode(parent) === node) ? node : parent;
const right = (getChildNode(parent) !== node) ? node : parent;
- const message =
- "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'.";
const data = {
leftOperator: left.operator || "?:",
rightOperator: right.operator || "?:"
@@ -198,13 +200,13 @@ module.exports = {
context.report({
node: left,
loc: getOperatorToken(left).loc,
- message,
+ messageId: "unexpectedMixedOperator",
data
});
context.report({
node: right,
loc: getOperatorToken(right).loc,
- message,
+ messageId: "unexpectedMixedOperator",
data
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-requires.js b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js
index fda8a11d9e2e74..8e988e32c24f84 100644
--- a/tools/node_modules/eslint/lib/rules/no-mixed-requires.js
+++ b/tools/node_modules/eslint/lib/rules/no-mixed-requires.js
@@ -40,7 +40,12 @@ module.exports = {
}
]
}
- ]
+ ],
+
+ messages: {
+ noMixRequire: "Do not mix 'require' and other declarations.",
+ noMixCoreModuleFileComputed: "Do not mix core, module, file and computed requires."
+ }
},
create(context) {
@@ -211,9 +216,15 @@ module.exports = {
VariableDeclaration(node) {
if (isMixed(node.declarations)) {
- context.report({ node, message: "Do not mix 'require' and other declarations." });
+ context.report({
+ node,
+ messageId: "noMixRequire"
+ });
} else if (grouping && !isGrouped(node.declarations)) {
- context.report({ node, message: "Do not mix core, module, file and computed requires." });
+ context.report({
+ node,
+ messageId: "noMixCoreModuleFileComputed"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js b/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js
index 7b1e2c4a2a760c..16c2bd4122e851 100644
--- a/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js
+++ b/tools/node_modules/eslint/lib/rules/no-mixed-spaces-and-tabs.js
@@ -23,14 +23,17 @@ module.exports = {
{
enum: ["smart-tabs", true, false]
}
- ]
+ ],
+
+ messages: {
+ mixedSpacesAndTabs: "Mixed spaces and tabs."
+ }
},
create(context) {
const sourceCode = context.getSourceCode();
let smartTabs;
- const ignoredLocs = [];
switch (context.options[0]) {
case true: // Support old syntax, maybe add deprecation warning here
@@ -41,47 +44,23 @@ module.exports = {
smartTabs = false;
}
- /**
- * Determines if a given line and column are before a location.
- * @param {Location} loc The location object from an AST node.
- * @param {int} line The line to check.
- * @param {int} column The column to check.
- * @returns {boolean} True if the line and column are before the location, false if not.
- * @private
- */
- function beforeLoc(loc, line, column) {
- if (line < loc.start.line) {
- return true;
- }
- return line === loc.start.line && column < loc.start.column;
- }
-
- /**
- * Determines if a given line and column are after a location.
- * @param {Location} loc The location object from an AST node.
- * @param {int} line The line to check.
- * @param {int} column The column to check.
- * @returns {boolean} True if the line and column are after the location, false if not.
- * @private
- */
- function afterLoc(loc, line, column) {
- if (line > loc.end.line) {
- return true;
- }
- return line === loc.end.line && column > loc.end.column;
- }
-
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
- TemplateElement(node) {
- ignoredLocs.push(node.loc);
- },
-
"Program:exit"(node) {
+ const lines = sourceCode.lines,
+ comments = sourceCode.getAllComments(),
+ ignoredCommentLines = new Set();
+
+ // Add all lines except the first ones.
+ comments.forEach(comment => {
+ for (let i = comment.loc.start.line + 1; i <= comment.loc.end.line; i++) {
+ ignoredCommentLines.add(i);
+ }
+ });
/*
* At least one space followed by a tab
@@ -89,24 +68,6 @@ module.exports = {
* characters begin.
*/
let regex = /^(?=[\t ]*(\t | \t))/u;
- const lines = sourceCode.lines,
- comments = sourceCode.getAllComments();
-
- comments.forEach(comment => {
- ignoredLocs.push(comment.loc);
- });
-
- ignoredLocs.sort((first, second) => {
- if (beforeLoc(first, second.start.line, second.start.column)) {
- return 1;
- }
-
- if (beforeLoc(second, first.start.line, second.start.column)) {
- return -1;
- }
-
- return 0;
- });
if (smartTabs) {
@@ -122,25 +83,23 @@ module.exports = {
if (match) {
const lineNumber = i + 1,
- column = match.index + 1;
-
- for (let j = 0; j < ignoredLocs.length; j++) {
- if (beforeLoc(ignoredLocs[j], lineNumber, column)) {
- continue;
+ column = match.index + 1,
+ loc = { line: lineNumber, column };
+
+ if (!ignoredCommentLines.has(lineNumber)) {
+ const containingNode = sourceCode.getNodeByRangeIndex(sourceCode.getIndexFromLoc(loc));
+
+ if (!(containingNode && ["Literal", "TemplateElement"].includes(containingNode.type))) {
+ context.report({
+ node,
+ loc,
+ messageId: "mixedSpacesAndTabs"
+ });
}
- if (afterLoc(ignoredLocs[j], lineNumber, column)) {
- continue;
- }
-
- return;
}
-
- context.report({ node, loc: { line: lineNumber, column }, message: "Mixed spaces and tabs." });
}
});
}
-
};
-
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-multi-assign.js b/tools/node_modules/eslint/lib/rules/no-multi-assign.js
index 8524a1a571ef9e..ab6430c19ef070 100644
--- a/tools/node_modules/eslint/lib/rules/no-multi-assign.js
+++ b/tools/node_modules/eslint/lib/rules/no-multi-assign.js
@@ -21,7 +21,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-multi-assign"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpectedChain: "Unexpected chained assignment."
+ }
},
create(context) {
@@ -35,7 +39,7 @@ module.exports = {
if (["AssignmentExpression", "VariableDeclarator"].indexOf(node.parent.type) !== -1) {
context.report({
node,
- message: "Unexpected chained assignment."
+ messageId: "unexpectedChain"
});
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-multi-spaces.js b/tools/node_modules/eslint/lib/rules/no-multi-spaces.js
index 403d04da9dd9ec..d43ed736337945 100644
--- a/tools/node_modules/eslint/lib/rules/no-multi-spaces.js
+++ b/tools/node_modules/eslint/lib/rules/no-multi-spaces.js
@@ -44,7 +44,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ multipleSpaces: "Multiple spaces found before '{{displayValue}}'."
+ }
},
create(context) {
@@ -122,7 +126,7 @@ module.exports = {
context.report({
node: rightToken,
loc: { start: leftToken.loc.end, end: rightToken.loc.start },
- message: "Multiple spaces found before '{{displayValue}}'.",
+ messageId: "multipleSpaces",
data: { displayValue },
fix: fixer => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ")
});
diff --git a/tools/node_modules/eslint/lib/rules/no-multi-str.js b/tools/node_modules/eslint/lib/rules/no-multi-str.js
index f6832f3341777f..7cf1ae367942fe 100644
--- a/tools/node_modules/eslint/lib/rules/no-multi-str.js
+++ b/tools/node_modules/eslint/lib/rules/no-multi-str.js
@@ -26,7 +26,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-multi-str"
},
- schema: []
+ schema: [],
+
+ messages: {
+ multilineString: "Multiline support is limited to browsers supporting ES5 only."
+ }
},
create(context) {
@@ -49,7 +53,10 @@ module.exports = {
Literal(node) {
if (astUtils.LINEBREAK_MATCHER.test(node.raw) && !isJSXElement(node.parent)) {
- context.report({ node, message: "Multiline support is limited to browsers supporting ES5 only." });
+ context.report({
+ node,
+ messageId: "multilineString"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js b/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js
index 41e6be3a289584..9cccef3088a56e 100644
--- a/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js
+++ b/tools/node_modules/eslint/lib/rules/no-multiple-empty-lines.js
@@ -42,7 +42,13 @@ module.exports = {
required: ["max"],
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ blankBeginningOfFile: "Too many blank lines at the beginning of file. Max of {{max}} allowed.",
+ blankEndOfFile: "Too many blank lines at the end of file. Max of {{max}} allowed.",
+ consecutiveBlank: "More than {{max}} blank {{pluralizedLines}} not allowed."
+ }
},
create(context) {
@@ -94,25 +100,31 @@ module.exports = {
// Given two line numbers of non-empty lines, report the lines between if the difference is too large.
.reduce((lastLineNumber, lineNumber) => {
- let message, maxAllowed;
+ let messageId, maxAllowed;
if (lastLineNumber === 0) {
- message = "Too many blank lines at the beginning of file. Max of {{max}} allowed.";
+ messageId = "blankBeginningOfFile";
maxAllowed = maxBOF;
} else if (lineNumber === allLines.length + 1) {
- message = "Too many blank lines at the end of file. Max of {{max}} allowed.";
+ messageId = "blankEndOfFile";
maxAllowed = maxEOF;
} else {
- message = "More than {{max}} blank {{pluralizedLines}} not allowed.";
+ messageId = "consecutiveBlank";
maxAllowed = max;
}
if (lineNumber - lastLineNumber - 1 > maxAllowed) {
context.report({
node,
- loc: { start: { line: lastLineNumber + maxAllowed + 1, column: 0 }, end: { line: lineNumber, column: 0 } },
- message,
- data: { max: maxAllowed, pluralizedLines: maxAllowed === 1 ? "line" : "lines" },
+ loc: {
+ start: { line: lastLineNumber + maxAllowed + 1, column: 0 },
+ end: { line: lineNumber, column: 0 }
+ },
+ messageId,
+ data: {
+ max: maxAllowed,
+ pluralizedLines: maxAllowed === 1 ? "line" : "lines"
+ },
fix(fixer) {
const rangeStart = sourceCode.getIndexFromLoc({ line: lastLineNumber + 1, column: 0 });
diff --git a/tools/node_modules/eslint/lib/rules/no-negated-condition.js b/tools/node_modules/eslint/lib/rules/no-negated-condition.js
index e55a8287487de3..8a9eba881df04c 100644
--- a/tools/node_modules/eslint/lib/rules/no-negated-condition.js
+++ b/tools/node_modules/eslint/lib/rules/no-negated-condition.js
@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-negated-condition"
},
- schema: []
+ schema: [],
+
+ messages: {
+ unexpectedNegated: "Unexpected negated condition."
+ }
},
create(context) {
@@ -72,12 +76,18 @@ module.exports = {
}
if (isNegatedIf(node)) {
- context.report({ node, message: "Unexpected negated condition." });
+ context.report({
+ node,
+ messageId: "unexpectedNegated"
+ });
}
},
ConditionalExpression(node) {
if (isNegatedIf(node)) {
- context.report({ node, message: "Unexpected negated condition." });
+ context.report({
+ node,
+ messageId: "unexpectedNegated"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-nested-ternary.js b/tools/node_modules/eslint/lib/rules/no-nested-ternary.js
index 87a11e87962a8f..383bb238887d2a 100644
--- a/tools/node_modules/eslint/lib/rules/no-nested-ternary.js
+++ b/tools/node_modules/eslint/lib/rules/no-nested-ternary.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-nested-ternary"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noNestedTernary: "Do not nest ternary expressions."
+ }
},
create(context) {
@@ -29,7 +33,10 @@ module.exports = {
ConditionalExpression(node) {
if (node.alternate.type === "ConditionalExpression" ||
node.consequent.type === "ConditionalExpression") {
- context.report({ node, message: "Do not nest ternary expressions." });
+ context.report({
+ node,
+ messageId: "noNestedTernary"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-new-func.js b/tools/node_modules/eslint/lib/rules/no-new-func.js
index 23e92f7bf3030c..d1360e9dee036d 100644
--- a/tools/node_modules/eslint/lib/rules/no-new-func.js
+++ b/tools/node_modules/eslint/lib/rules/no-new-func.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-new-func"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noFunctionConstructor: "The Function constructor is eval."
+ }
},
create(context) {
@@ -36,7 +40,10 @@ module.exports = {
* @private
*/
function report(node) {
- context.report({ node, message: "The Function constructor is eval." });
+ context.report({
+ node,
+ messageId: "noFunctionConstructor"
+ });
}
return {
diff --git a/tools/node_modules/eslint/lib/rules/no-new-object.js b/tools/node_modules/eslint/lib/rules/no-new-object.js
index f5cc28664f4e1c..f3e99c9bd13502 100644
--- a/tools/node_modules/eslint/lib/rules/no-new-object.js
+++ b/tools/node_modules/eslint/lib/rules/no-new-object.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-new-object"
},
- schema: []
+ schema: [],
+
+ messages: {
+ preferLiteral: "The object literal notation {} is preferrable."
+ }
},
create(context) {
@@ -29,7 +33,10 @@ module.exports = {
NewExpression(node) {
if (node.callee.name === "Object") {
- context.report({ node, message: "The object literal notation {} is preferrable." });
+ context.report({
+ node,
+ messageId: "preferLiteral"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-new-require.js b/tools/node_modules/eslint/lib/rules/no-new-require.js
index 1eae0659430fbd..df12a424e3527e 100644
--- a/tools/node_modules/eslint/lib/rules/no-new-require.js
+++ b/tools/node_modules/eslint/lib/rules/no-new-require.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-new-require"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noNewRequire: "Unexpected use of new with require."
+ }
},
create(context) {
@@ -29,7 +33,10 @@ module.exports = {
NewExpression(node) {
if (node.callee.type === "Identifier" && node.callee.name === "require") {
- context.report({ node, message: "Unexpected use of new with require." });
+ context.report({
+ node,
+ messageId: "noNewRequire"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-new-symbol.js b/tools/node_modules/eslint/lib/rules/no-new-symbol.js
index ccf757ed6a0cee..cb7e4f0fc88d69 100644
--- a/tools/node_modules/eslint/lib/rules/no-new-symbol.js
+++ b/tools/node_modules/eslint/lib/rules/no-new-symbol.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-new-symbol"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noNewSymbol: "`Symbol` cannot be called as a constructor."
+ }
},
create(context) {
@@ -35,7 +39,10 @@ module.exports = {
const node = ref.identifier;
if (node.parent && node.parent.type === "NewExpression") {
- context.report({ node, message: "`Symbol` cannot be called as a constructor." });
+ context.report({
+ node,
+ messageId: "noNewSymbol"
+ });
}
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-new-wrappers.js b/tools/node_modules/eslint/lib/rules/no-new-wrappers.js
index ae2aeec0341243..0a2861fa5f7799 100644
--- a/tools/node_modules/eslint/lib/rules/no-new-wrappers.js
+++ b/tools/node_modules/eslint/lib/rules/no-new-wrappers.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-new-wrappers"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noConstructor: "Do not use {{fn}} as a constructor."
+ }
},
create(context) {
@@ -31,7 +35,11 @@ module.exports = {
const wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"];
if (wrapperObjects.indexOf(node.callee.name) > -1) {
- context.report({ node, message: "Do not use {{fn}} as a constructor.", data: { fn: node.callee.name } });
+ context.report({
+ node,
+ messageId: "noConstructor",
+ data: { fn: node.callee.name }
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-new.js b/tools/node_modules/eslint/lib/rules/no-new.js
index 2e0702597eade3..aa8a4e26876609 100644
--- a/tools/node_modules/eslint/lib/rules/no-new.js
+++ b/tools/node_modules/eslint/lib/rules/no-new.js
@@ -21,14 +21,21 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-new"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noNewStatement: "Do not use 'new' for side effects."
+ }
},
create(context) {
return {
"ExpressionStatement > NewExpression"(node) {
- context.report({ node: node.parent, message: "Do not use 'new' for side effects." });
+ context.report({
+ node: node.parent,
+ messageId: "noNewStatement"
+ });
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-octal.js b/tools/node_modules/eslint/lib/rules/no-octal.js
index 5ee69f0309ee03..e9940befafa889 100644
--- a/tools/node_modules/eslint/lib/rules/no-octal.js
+++ b/tools/node_modules/eslint/lib/rules/no-octal.js
@@ -20,7 +20,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-octal"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noOcatal: "Octal literals should not be used."
+ }
},
create(context) {
@@ -29,7 +33,10 @@ module.exports = {
Literal(node) {
if (typeof node.value === "number" && /^0[0-9]/u.test(node.raw)) {
- context.report({ node, message: "Octal literals should not be used." });
+ context.report({
+ node,
+ messageId: "noOcatal"
+ });
}
}
};
diff --git a/tools/node_modules/eslint/lib/rules/no-param-reassign.js b/tools/node_modules/eslint/lib/rules/no-param-reassign.js
index d65eb34762aaf2..6874af44f389b7 100644
--- a/tools/node_modules/eslint/lib/rules/no-param-reassign.js
+++ b/tools/node_modules/eslint/lib/rules/no-param-reassign.js
@@ -58,7 +58,12 @@ module.exports = {
}
]
}
- ]
+ ],
+
+ messages: {
+ assignmentToFunctionParam: "Assignment to function parameter '{{name}}'.",
+ assignmentToFunctionParamProp: "Assignment to property of function parameter '{{name}}'."
+ }
},
create(context) {
@@ -177,9 +182,17 @@ module.exports = {
(index === 0 || references[index - 1].identifier !== identifier)
) {
if (reference.isWrite()) {
- context.report({ node: identifier, message: "Assignment to function parameter '{{name}}'.", data: { name: identifier.name } });
+ context.report({
+ node: identifier,
+ messageId: "assignmentToFunctionParam",
+ data: { name: identifier.name }
+ });
} else if (props && isModifyingProp(reference) && !isIgnoredPropertyAssignment(identifier.name)) {
- context.report({ node: identifier, message: "Assignment to property of function parameter '{{name}}'.", data: { name: identifier.name } });
+ context.report({
+ node: identifier,
+ messageId: "assignmentToFunctionParamProp",
+ data: { name: identifier.name }
+ });
}
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-path-concat.js b/tools/node_modules/eslint/lib/rules/no-path-concat.js
index abe0d5247db719..9fa8b852fe8358 100644
--- a/tools/node_modules/eslint/lib/rules/no-path-concat.js
+++ b/tools/node_modules/eslint/lib/rules/no-path-concat.js
@@ -19,7 +19,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-path-concat"
},
- schema: []
+ schema: [],
+
+ messages: {
+ usePathFunctions: "Use path.join() or path.resolve() instead of + to create paths."
+ }
},
create(context) {
@@ -42,7 +46,10 @@ module.exports = {
(right.type === "Identifier" && MATCHER.test(right.name)))
) {
- context.report({ node, message: "Use path.join() or path.resolve() instead of + to create paths." });
+ context.report({
+ node,
+ messageId: "usePathFunctions"
+ });
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-plusplus.js b/tools/node_modules/eslint/lib/rules/no-plusplus.js
index 1d122dcd31f086..f55303863d25ca 100644
--- a/tools/node_modules/eslint/lib/rules/no-plusplus.js
+++ b/tools/node_modules/eslint/lib/rules/no-plusplus.js
@@ -32,7 +32,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ unexpectedUnaryOp: "Unary operator '{{operator}}' used."
+ }
},
create(context) {
@@ -52,7 +56,7 @@ module.exports = {
}
context.report({
node,
- message: "Unary operator '{{operator}}' used.",
+ messageId: "unexpectedUnaryOp",
data: {
operator: node.operator
}
diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-exports.js b/tools/node_modules/eslint/lib/rules/no-restricted-exports.js
new file mode 100644
index 00000000000000..5b5c7d9bffb99c
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/no-restricted-exports.js
@@ -0,0 +1,84 @@
+/**
+ * @fileoverview Rule to disallow specified names in exports
+ * @author Milos Djermanovic
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ type: "suggestion",
+
+ docs: {
+ description: "disallow specified names in exports",
+ category: "ECMAScript 6",
+ recommended: false,
+ url: "https://eslint.org/docs/rules/no-restricted-exports"
+ },
+
+ schema: [{
+ type: "object",
+ properties: {
+ restrictedNamedExports: {
+ type: "array",
+ items: {
+ type: "string"
+ },
+ uniqueItems: true
+ }
+ },
+ additionalProperties: false
+ }],
+
+ messages: {
+ restrictedNamed: "'{{name}}' is restricted from being used as an exported name."
+ }
+ },
+
+ create(context) {
+
+ const restrictedNames = new Set(context.options[0] && context.options[0].restrictedNamedExports);
+
+ /**
+ * Checks and reports given exported identifier.
+ * @param {ASTNode} node exported `Identifer` node to check.
+ * @returns {void}
+ */
+ function checkExportedName(node) {
+ const name = node.name;
+
+ if (restrictedNames.has(name)) {
+ context.report({
+ node,
+ messageId: "restrictedNamed",
+ data: { name }
+ });
+ }
+ }
+
+ return {
+ ExportNamedDeclaration(node) {
+ const declaration = node.declaration;
+
+ if (declaration) {
+ if (declaration.type === "FunctionDeclaration" || declaration.type === "ClassDeclaration") {
+ checkExportedName(declaration.id);
+ } else if (declaration.type === "VariableDeclaration") {
+ context.getDeclaredVariables(declaration)
+ .map(v => v.defs.find(d => d.parent === declaration))
+ .map(d => d.name) // Identifier nodes
+ .forEach(checkExportedName);
+ }
+ } else {
+ node.specifiers
+ .map(s => s.exported)
+ .forEach(checkExportedName);
+ }
+ }
+ };
+ }
+};
diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-globals.js b/tools/node_modules/eslint/lib/rules/no-restricted-globals.js
index 1a2629a8ec95e8..2c932a7307c0b2 100644
--- a/tools/node_modules/eslint/lib/rules/no-restricted-globals.js
+++ b/tools/node_modules/eslint/lib/rules/no-restricted-globals.js
@@ -4,13 +4,6 @@
*/
"use strict";
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-const DEFAULT_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'.",
- CUSTOM_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'. {{customMessage}}";
-
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
@@ -46,6 +39,12 @@ module.exports = {
},
uniqueItems: true,
minItems: 0
+ },
+
+ messages: {
+ defaultMessage: "Unexpected use of '{{name}}'.",
+ // eslint-disable-next-line eslint-plugin/report-message-format
+ customMessage: "Unexpected use of '{{name}}'. {{customMessage}}"
}
},
@@ -75,13 +74,13 @@ module.exports = {
function reportReference(reference) {
const name = reference.identifier.name,
customMessage = restrictedGlobalMessages[name],
- message = customMessage
- ? CUSTOM_MESSAGE_TEMPLATE
- : DEFAULT_MESSAGE_TEMPLATE;
+ messageId = customMessage
+ ? "customMessage"
+ : "defaultMessage";
context.report({
node: reference.identifier,
- message,
+ messageId,
data: {
name,
customMessage
diff --git a/tools/node_modules/eslint/lib/rules/no-restricted-imports.js b/tools/node_modules/eslint/lib/rules/no-restricted-imports.js
index ec0696f99a2de0..c205dad8bdb79d 100644
--- a/tools/node_modules/eslint/lib/rules/no-restricted-imports.js
+++ b/tools/node_modules/eslint/lib/rules/no-restricted-imports.js
@@ -64,7 +64,11 @@ module.exports = {
everything: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted.",
// eslint-disable-next-line eslint-plugin/report-message-format
- everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}"
+ everythingWithCustomMessage: "* import is invalid because '{{importNames}}' from '{{importSource}}' is restricted. {{customMessage}}",
+
+ importName: "'{{importName}}' import from '{{importSource}}' is restricted.",
+ // eslint-disable-next-line eslint-plugin/report-message-format
+ importNameWithCustomMessage: "'{{importName}}' import from '{{importSource}}' is restricted. {{customMessage}}"
},
schema: {
@@ -87,6 +91,7 @@ module.exports = {
},
create(context) {
+ const sourceCode = context.getSourceCode();
const options = Array.isArray(context.options) ? context.options : [];
const isPathAndPatternsObject =
typeof options[0] === "object" &&
@@ -95,6 +100,11 @@ module.exports = {
const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
+ // if no imports are restricted we don"t need to check
+ if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
+ return {};
+ }
+
const restrictedPathMessages = restrictedPaths.reduce((memo, importSource) => {
if (typeof importSource === "string") {
memo[importSource] = { message: null };
@@ -107,40 +117,68 @@ module.exports = {
return memo;
}, {});
- // if no imports are restricted we don"t need to check
- if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
- return {};
- }
-
const restrictedPatternsMatcher = ignore().add(restrictedPatterns);
- /**
- * Checks to see if "*" is being used to import everything.
- * @param {Set.} importNames Set of import names that are being imported
- * @returns {boolean} whether everything is imported or not
- */
- function isEverythingImported(importNames) {
- return importNames.has("*");
- }
-
/**
* Report a restricted path.
+ * @param {string} importSource path of the import
+ * @param {Map} importNames Map of import names that are being imported
* @param {node} node representing the restricted path reference
* @returns {void}
* @private
*/
- function reportPath(node) {
- const importSource = node.source.value.trim();
- const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
+ function checkRestrictedPathAndReport(importSource, importNames, node) {
+ if (!Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
+ return;
+ }
- context.report({
- node,
- messageId: customMessage ? "pathWithCustomMessage" : "path",
- data: {
- importSource,
- customMessage
+ const customMessage = restrictedPathMessages[importSource].message;
+ const restrictedImportNames = restrictedPathMessages[importSource].importNames;
+
+ if (restrictedImportNames) {
+ if (importNames.has("*")) {
+ const specifierData = importNames.get("*")[0];
+
+ context.report({
+ node,
+ messageId: customMessage ? "everythingWithCustomMessage" : "everything",
+ loc: specifierData.loc,
+ data: {
+ importSource,
+ importNames: restrictedImportNames,
+ customMessage
+ }
+ });
}
- });
+
+ restrictedImportNames.forEach(importName => {
+ if (importNames.has(importName)) {
+ const specifiers = importNames.get(importName);
+
+ specifiers.forEach(specifier => {
+ context.report({
+ node,
+ messageId: customMessage ? "importNameWithCustomMessage" : "importName",
+ loc: specifier.loc,
+ data: {
+ importSource,
+ customMessage,
+ importName
+ }
+ });
+ });
+ }
+ });
+ } else {
+ context.report({
+ node,
+ messageId: customMessage ? "pathWithCustomMessage" : "path",
+ data: {
+ importSource,
+ customMessage
+ }
+ });
+ }
}
/**
@@ -161,75 +199,6 @@ module.exports = {
});
}
- /**
- * Report a restricted path specifically when using the '*' import.
- * @param {string} importSource path of the import
- * @param {node} node representing the restricted path reference
- * @returns {void}
- * @private
- */
- function reportPathForEverythingImported(importSource, node) {
- const importNames = restrictedPathMessages[importSource].importNames;
- const customMessage = restrictedPathMessages[importSource] && restrictedPathMessages[importSource].message;
-
- context.report({
- node,
- messageId: customMessage ? "everythingWithCustomMessage" : "everything",
- data: {
- importSource,
- importNames,
- customMessage
- }
- });
- }
-
- /**
- * Check if the given importSource is restricted because '*' is being imported.
- * @param {string} importSource path of the import
- * @param {Set.} importNames Set of import names that are being imported
- * @returns {boolean} whether the path is restricted
- * @private
- */
- function isRestrictedForEverythingImported(importSource, importNames) {
- return Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource) &&
- restrictedPathMessages[importSource].importNames &&
- isEverythingImported(importNames);
- }
-
- /**
- * Check if the given importNames are restricted given a list of restrictedImportNames.
- * @param {Set.} importNames Set of import names that are being imported
- * @param {string[]} restrictedImportNames array of import names that are restricted for this import
- * @returns {boolean} whether the objectName is restricted
- * @private
- */
- function isRestrictedObject(importNames, restrictedImportNames) {
- return restrictedImportNames.some(restrictedObjectName => (
- importNames.has(restrictedObjectName)
- ));
- }
-
- /**
- * Check if the given importSource is a restricted path.
- * @param {string} importSource path of the import
- * @param {Set.} importNames Set of import names that are being imported
- * @returns {boolean} whether the variable is a restricted path or not
- * @private
- */
- function isRestrictedPath(importSource, importNames) {
- let isRestricted = false;
-
- if (Object.prototype.hasOwnProperty.call(restrictedPathMessages, importSource)) {
- if (restrictedPathMessages[importSource].importNames) {
- isRestricted = isRestrictedObject(importNames, restrictedPathMessages[importSource].importNames);
- } else {
- isRestricted = true;
- }
- }
-
- return isRestricted;
- }
-
/**
* Check if the given importSource is restricted by a pattern.
* @param {string} importSource path of the import
@@ -248,26 +217,39 @@ module.exports = {
*/
function checkNode(node) {
const importSource = node.source.value.trim();
- const importNames = node.specifiers ? node.specifiers.reduce((set, specifier) => {
- if (specifier.type === "ImportDefaultSpecifier") {
- set.add("default");
- } else if (specifier.type === "ImportNamespaceSpecifier") {
- set.add("*");
- } else if (specifier.imported) {
- set.add(specifier.imported.name);
- } else if (specifier.local) {
- set.add(specifier.local.name);
- }
- return set;
- }, new Set()) : new Set();
+ const importNames = new Map();
+
+ if (node.type === "ExportAllDeclaration") {
+ const starToken = sourceCode.getFirstToken(node, 1);
+
+ importNames.set("*", [{ loc: starToken.loc }]);
+ } else if (node.specifiers) {
+ for (const specifier of node.specifiers) {
+ let name;
+ const specifierData = { loc: specifier.loc };
+
+ if (specifier.type === "ImportDefaultSpecifier") {
+ name = "default";
+ } else if (specifier.type === "ImportNamespaceSpecifier") {
+ name = "*";
+ } else if (specifier.imported) {
+ name = specifier.imported.name;
+ } else if (specifier.local) {
+ name = specifier.local.name;
+ }
- if (isRestrictedForEverythingImported(importSource, importNames)) {
- reportPathForEverythingImported(importSource, node);
+ if (name) {
+ if (importNames.has(name)) {
+ importNames.get(name).push(specifierData);
+ } else {
+ importNames.set(name, [specifierData]);
+ }
+ }
+ }
}
- if (isRestrictedPath(importSource, importNames)) {
- reportPath(node);
- }
+ checkRestrictedPathAndReport(importSource, importNames, node);
+
if (isRestrictedPattern(importSource)) {
reportPathForPatterns(node);
}
diff --git a/tools/node_modules/eslint/lib/rules/no-shadow.js b/tools/node_modules/eslint/lib/rules/no-shadow.js
index bad6cb5f3094cc..1be8590e47abcb 100644
--- a/tools/node_modules/eslint/lib/rules/no-shadow.js
+++ b/tools/node_modules/eslint/lib/rules/no-shadow.js
@@ -41,7 +41,11 @@ module.exports = {
},
additionalProperties: false
}
- ]
+ ],
+
+ messages: {
+ noShadow: "'{{name}}' is already declared in the upper scope."
+ }
},
create(context) {
@@ -163,7 +167,7 @@ module.exports = {
) {
context.report({
node: variable.identifiers[0],
- message: "'{{name}}' is already declared in the upper scope.",
+ messageId: "noShadow",
data: variable
});
}
diff --git a/tools/node_modules/eslint/lib/rules/no-use-before-define.js b/tools/node_modules/eslint/lib/rules/no-use-before-define.js
index ed3540532f9095..c7300567ede0b7 100644
--- a/tools/node_modules/eslint/lib/rules/no-use-before-define.js
+++ b/tools/node_modules/eslint/lib/rules/no-use-before-define.js
@@ -157,7 +157,11 @@ module.exports = {
}
]
}
- ]
+ ],
+
+ messages: {
+ usedBeforeDefined: "'{{name}}' was used before it was defined."
+ }
},
create(context) {
@@ -212,7 +216,7 @@ module.exports = {
// Reports.
context.report({
node: reference.identifier,
- message: "'{{name}}' was used before it was defined.",
+ messageId: "usedBeforeDefined",
data: reference.identifier
});
});
diff --git a/tools/node_modules/eslint/lib/rules/no-useless-backreference.js b/tools/node_modules/eslint/lib/rules/no-useless-backreference.js
new file mode 100644
index 00000000000000..8a6fbe14daafe6
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/no-useless-backreference.js
@@ -0,0 +1,193 @@
+/**
+ * @fileoverview Rule to disallow useless backreferences in regular expressions
+ * @author Milos Djermanovic
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const { CALL, CONSTRUCT, ReferenceTracker, getStringIfConstant } = require("eslint-utils");
+const { RegExpParser, visitRegExpAST } = require("regexpp");
+const lodash = require("lodash");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const parser = new RegExpParser();
+
+/**
+ * Finds the path from the given `regexpp` AST node to the root node.
+ * @param {regexpp.Node} node Node.
+ * @returns {regexpp.Node[]} Array that starts with the given node and ends with the root node.
+ */
+function getPathToRoot(node) {
+ const path = [];
+ let current = node;
+
+ do {
+ path.push(current);
+ current = current.parent;
+ } while (current);
+
+ return path;
+}
+
+/**
+ * Determines whether the given `regexpp` AST node is a lookaround node.
+ * @param {regexpp.Node} node Node.
+ * @returns {boolean} `true` if it is a lookaround node.
+ */
+function isLookaround(node) {
+ return node.type === "Assertion" &&
+ (node.kind === "lookahead" || node.kind === "lookbehind");
+}
+
+/**
+ * Determines whether the given `regexpp` AST node is a negative lookaround node.
+ * @param {regexpp.Node} node Node.
+ * @returns {boolean} `true` if it is a negative lookaround node.
+ */
+function isNegativeLookaround(node) {
+ return isLookaround(node) && node.negate;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+ meta: {
+ type: "problem",
+
+ docs: {
+ description: "disallow useless backreferences in regular expressions",
+ category: "Possible Errors",
+ recommended: false,
+ url: "https://eslint.org/docs/rules/no-useless-backreference"
+ },
+
+ schema: [],
+
+ messages: {
+ nested: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' from within that group.",
+ forward: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which appears later in the pattern.",
+ backward: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which appears before in the same lookbehind.",
+ disjunctive: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which is in another alternative.",
+ intoNegativeLookaround: "Backreference '{{ bref }}' will be ignored. It references group '{{ group }}' which is in a negative lookaround."
+ }
+ },
+
+ create(context) {
+
+ /**
+ * Checks and reports useless backreferences in the given regular expression.
+ * @param {ASTNode} node Node that represents regular expression. A regex literal or RegExp constructor call.
+ * @param {string} pattern Regular expression pattern.
+ * @param {string} flags Regular expression flags.
+ * @returns {void}
+ */
+ function checkRegex(node, pattern, flags) {
+ let regExpAST;
+
+ try {
+ regExpAST = parser.parsePattern(pattern, 0, pattern.length, flags.includes("u"));
+ } catch (e) {
+
+ // Ignore regular expressions with syntax errors
+ return;
+ }
+
+ visitRegExpAST(regExpAST, {
+ onBackreferenceEnter(bref) {
+ const group = bref.resolved,
+ brefPath = getPathToRoot(bref),
+ groupPath = getPathToRoot(group);
+ let messageId = null;
+
+ if (brefPath.includes(group)) {
+
+ // group is bref's ancestor => bref is nested ('nested reference') => group hasn't matched yet when bref starts to match.
+ messageId = "nested";
+ } else {
+
+ // Start from the root to find the lowest common ancestor.
+ let i = brefPath.length - 1,
+ j = groupPath.length - 1;
+
+ do {
+ i--;
+ j--;
+ } while (brefPath[i] === groupPath[j]);
+
+ const indexOfLowestCommonAncestor = j + 1,
+ groupCut = groupPath.slice(0, indexOfLowestCommonAncestor),
+ commonPath = groupPath.slice(indexOfLowestCommonAncestor),
+ lowestCommonLookaround = commonPath.find(isLookaround),
+ isMatchingBackward = lowestCommonLookaround && lowestCommonLookaround.kind === "lookbehind";
+
+ if (!isMatchingBackward && bref.end <= group.start) {
+
+ // bref is left, group is right ('forward reference') => group hasn't matched yet when bref starts to match.
+ messageId = "forward";
+ } else if (isMatchingBackward && group.end <= bref.start) {
+
+ // the opposite of the previous when the regex is matching backward in a lookbehind context.
+ messageId = "backward";
+ } else if (lodash.last(groupCut).type === "Alternative") {
+
+ // group's and bref's ancestor nodes below the lowest common ancestor are sibling alternatives => they're disjunctive.
+ messageId = "disjunctive";
+ } else if (groupCut.some(isNegativeLookaround)) {
+
+ // group is in a negative lookaround which isn't bref's ancestor => group has already failed when bref starts to match.
+ messageId = "intoNegativeLookaround";
+ }
+ }
+
+ if (messageId) {
+ context.report({
+ node,
+ messageId,
+ data: {
+ bref: bref.raw,
+ group: group.raw
+ }
+ });
+ }
+ }
+ });
+ }
+
+ return {
+ "Literal[regex]"(node) {
+ const { pattern, flags } = node.regex;
+
+ checkRegex(node, pattern, flags);
+ },
+ Program() {
+ const scope = context.getScope(),
+ tracker = new ReferenceTracker(scope),
+ traceMap = {
+ RegExp: {
+ [CALL]: true,
+ [CONSTRUCT]: true
+ }
+ };
+
+ for (const { node } of tracker.iterateGlobalReferences(traceMap)) {
+ const [patternNode, flagsNode] = node.arguments,
+ pattern = getStringIfConstant(patternNode, scope),
+ flags = getStringIfConstant(flagsNode, scope);
+
+ if (typeof pattern === "string") {
+ checkRegex(node, pattern, flags || "");
+ }
+ }
+ }
+ };
+ }
+};
diff --git a/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js b/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js
index b5e53174e42be7..0e0acbea7c381c 100644
--- a/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js
+++ b/tools/node_modules/eslint/lib/rules/no-useless-computed-key.js
@@ -71,14 +71,11 @@ module.exports = {
message: MESSAGE_UNNECESSARY_COMPUTED,
data: { property: sourceCode.getText(key) },
fix(fixer) {
- const leftSquareBracket = sourceCode.getFirstToken(node, astUtils.isOpeningBracketToken);
- const rightSquareBracket = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken);
- const tokensBetween = sourceCode.getTokensBetween(leftSquareBracket, rightSquareBracket, 1);
+ const leftSquareBracket = sourceCode.getTokenBefore(key, astUtils.isOpeningBracketToken);
+ const rightSquareBracket = sourceCode.getTokenAfter(key, astUtils.isClosingBracketToken);
- if (tokensBetween.slice(0, -1).some((token, index) =>
- sourceCode.getText().slice(token.range[1], tokensBetween[index + 1].range[0]).trim())) {
-
- // If there are comments between the brackets and the property name, don't do a fix.
+ // If there are comments between the brackets and the property name, don't do a fix.
+ if (sourceCode.commentsExistBetween(leftSquareBracket, rightSquareBracket)) {
return null;
}
diff --git a/tools/node_modules/eslint/lib/rules/no-useless-constructor.js b/tools/node_modules/eslint/lib/rules/no-useless-constructor.js
index 7cf033805f99d9..2920328c6f39c0 100644
--- a/tools/node_modules/eslint/lib/rules/no-useless-constructor.js
+++ b/tools/node_modules/eslint/lib/rules/no-useless-constructor.js
@@ -143,7 +143,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-useless-constructor"
},
- schema: []
+ schema: [],
+
+ messages: {
+ noUselessConstructor: "Useless constructor."
+ }
},
create(context) {
@@ -165,7 +169,7 @@ module.exports = {
if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) {
context.report({
node,
- message: "Useless constructor."
+ messageId: "noUselessConstructor"
});
}
}
diff --git a/tools/node_modules/eslint/lib/rules/no-void.js b/tools/node_modules/eslint/lib/rules/no-void.js
index d2b5d2f9631dff..99c83785552ab8 100644
--- a/tools/node_modules/eslint/lib/rules/no-void.js
+++ b/tools/node_modules/eslint/lib/rules/no-void.js
@@ -19,22 +19,46 @@ module.exports = {
url: "https://eslint.org/docs/rules/no-void"
},
- schema: []
+ messages: {
+ noVoid: "Expected 'undefined' and instead saw 'void'."
+ },
+
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allowAsStatement: {
+ type: "boolean",
+ default: false
+ }
+ },
+ additionalProperties: false
+ }
+ ]
},
create(context) {
+ const allowAsStatement =
+ context.options[0] && context.options[0].allowAsStatement;
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
return {
- UnaryExpression(node) {
- if (node.operator === "void") {
- context.report({ node, message: "Expected 'undefined' and instead saw 'void'." });
+ 'UnaryExpression[operator="void"]'(node) {
+ if (
+ allowAsStatement &&
+ node.parent &&
+ node.parent.type === "ExpressionStatement"
+ ) {
+ return;
}
+ context.report({
+ node,
+ messageId: "noVoid"
+ });
}
};
-
}
};
diff --git a/tools/node_modules/eslint/lib/rules/prefer-object-spread.js b/tools/node_modules/eslint/lib/rules/prefer-object-spread.js
index bbcd88bee3d071..00f5fb6d4c8991 100644
--- a/tools/node_modules/eslint/lib/rules/prefer-object-spread.js
+++ b/tools/node_modules/eslint/lib/rules/prefer-object-spread.js
@@ -25,6 +25,36 @@ function hasArraySpread(node) {
return node.arguments.some(arg => arg.type === "SpreadElement");
}
+/**
+ * Determines whether the given node is an accessor property (getter/setter).
+ * @param {ASTNode} node Node to check.
+ * @returns {boolean} `true` if the node is a getter or a setter.
+ */
+function isAccessorProperty(node) {
+ return node.type === "Property" &&
+ (node.kind === "get" || node.kind === "set");
+}
+
+/**
+ * Determines whether the given object expression node has accessor properties (getters/setters).
+ * @param {ASTNode} node `ObjectExpression` node to check.
+ * @returns {boolean} `true` if the node has at least one getter/setter.
+ */
+function hasAccessors(node) {
+ return node.properties.some(isAccessorProperty);
+}
+
+/**
+ * Determines whether the given call expression node has object expression arguments with accessor properties (getters/setters).
+ * @param {ASTNode} node `CallExpression` node to check.
+ * @returns {boolean} `true` if the node has at least one argument that is an object expression with at least one getter/setter.
+ */
+function hasArgumentsWithAccessors(node) {
+ return node.arguments
+ .filter(arg => arg.type === "ObjectExpression")
+ .some(hasAccessors);
+}
+
/**
* Helper that checks if the node needs parentheses to be valid JS.
* The default is to wrap the node in parentheses to avoid parsing errors.
@@ -249,7 +279,11 @@ module.exports = {
if (
node.arguments.length >= 1 &&
node.arguments[0].type === "ObjectExpression" &&
- !hasArraySpread(node)
+ !hasArraySpread(node) &&
+ !(
+ node.arguments.length > 1 &&
+ hasArgumentsWithAccessors(node)
+ )
) {
const messageId = node.arguments.length === 1
? "useLiteralMessage"
diff --git a/tools/node_modules/eslint/lib/rules/quote-props.js b/tools/node_modules/eslint/lib/rules/quote-props.js
index ab09b8fa938e63..4cc53b988f634d 100644
--- a/tools/node_modules/eslint/lib/rules/quote-props.js
+++ b/tools/node_modules/eslint/lib/rules/quote-props.js
@@ -8,8 +8,9 @@
// Requirements
//------------------------------------------------------------------------------
-const espree = require("espree"),
- keywords = require("./utils/keywords");
+const espree = require("espree");
+const astUtils = require("./utils/ast-utils");
+const keywords = require("./utils/keywords");
//------------------------------------------------------------------------------
// Rule Definition
@@ -177,7 +178,7 @@ module.exports = {
data: { property: key.name },
fix: fixer => fixer.replaceText(key, getQuotedKey(key))
});
- } else if (NUMBERS && key.type === "Literal" && typeof key.value === "number") {
+ } else if (NUMBERS && key.type === "Literal" && astUtils.isNumericLiteral(key)) {
context.report({
node,
message: MESSAGE_NUMERIC,
diff --git a/tools/node_modules/eslint/lib/rules/quotes.js b/tools/node_modules/eslint/lib/rules/quotes.js
index f78d1129425633..d1f4443b9033c9 100644
--- a/tools/node_modules/eslint/lib/rules/quotes.js
+++ b/tools/node_modules/eslint/lib/rules/quotes.js
@@ -110,7 +110,11 @@ module.exports = {
}
]
}
- ]
+ ],
+
+ messages: {
+ wrongQuotes: "Strings must use {{description}}."
+ }
},
create(context) {
@@ -273,7 +277,7 @@ module.exports = {
if (!isValid) {
context.report({
node,
- message: "Strings must use {{description}}.",
+ messageId: "wrongQuotes",
data: {
description: settings.description
},
@@ -304,7 +308,7 @@ module.exports = {
context.report({
node,
- message: "Strings must use {{description}}.",
+ messageId: "wrongQuotes",
data: {
description: settings.description
},
diff --git a/tools/node_modules/eslint/lib/rules/require-await.js b/tools/node_modules/eslint/lib/rules/require-await.js
index 22c111b6dc852e..274e241cfc7d5b 100644
--- a/tools/node_modules/eslint/lib/rules/require-await.js
+++ b/tools/node_modules/eslint/lib/rules/require-await.js
@@ -39,7 +39,11 @@ module.exports = {
url: "https://eslint.org/docs/rules/require-await"
},
- schema: []
+ schema: [],
+
+ messages: {
+ missingAwait: "{{name}} has no 'await' expression."
+ }
},
create(context) {
@@ -68,7 +72,7 @@ module.exports = {
context.report({
node,
loc: astUtils.getFunctionHeadLoc(node, sourceCode),
- message: "{{name}} has no 'await' expression.",
+ messageId: "missingAwait",
data: {
name: capitalizeFirstLetter(
astUtils.getFunctionNameWithKind(node)
diff --git a/tools/node_modules/eslint/lib/rules/semi.js b/tools/node_modules/eslint/lib/rules/semi.js
index 22e299efe72e49..3491f4765c77a2 100644
--- a/tools/node_modules/eslint/lib/rules/semi.js
+++ b/tools/node_modules/eslint/lib/rules/semi.js
@@ -67,6 +67,11 @@ module.exports = {
maxItems: 2
}
]
+ },
+
+ messages: {
+ missingSemi: "Missing semicolon.",
+ extraSemi: "Extra semicolon."
}
},
@@ -91,12 +96,12 @@ module.exports = {
*/
function report(node, missing) {
const lastToken = sourceCode.getLastToken(node);
- let message,
+ let messageId,
fix,
loc;
if (!missing) {
- message = "Missing semicolon.";
+ messageId = "missingSemi";
loc = {
start: lastToken.loc.end,
end: astUtils.getNextLocation(sourceCode, lastToken.loc.end)
@@ -105,7 +110,7 @@ module.exports = {
return fixer.insertTextAfter(lastToken, ";");
};
} else {
- message = "Extra semicolon.";
+ messageId = "extraSemi";
loc = lastToken.loc;
fix = function(fixer) {
@@ -123,7 +128,7 @@ module.exports = {
context.report({
node,
loc,
- message,
+ messageId,
fix
});
diff --git a/tools/node_modules/eslint/lib/rules/template-curly-spacing.js b/tools/node_modules/eslint/lib/rules/template-curly-spacing.js
index 07da6a39b0e9bb..a16c0732df7b50 100644
--- a/tools/node_modules/eslint/lib/rules/template-curly-spacing.js
+++ b/tools/node_modules/eslint/lib/rules/template-curly-spacing.js
@@ -57,7 +57,7 @@ module.exports = {
* @returns {void}
*/
function checkSpacingBefore(token) {
- const prevToken = sourceCode.getTokenBefore(token);
+ const prevToken = sourceCode.getTokenBefore(token, { includeComments: true });
if (prevToken &&
CLOSE_PAREN.test(token.value) &&
@@ -86,7 +86,7 @@ module.exports = {
* @returns {void}
*/
function checkSpacingAfter(token) {
- const nextToken = sourceCode.getTokenAfter(token);
+ const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
if (nextToken &&
OPEN_PAREN.test(token.value) &&
diff --git a/tools/node_modules/eslint/lib/rules/utils/ast-utils.js b/tools/node_modules/eslint/lib/rules/utils/ast-utils.js
index 01c6b47b82eefc..e10544dd61e9ca 100644
--- a/tools/node_modules/eslint/lib/rules/utils/ast-utils.js
+++ b/tools/node_modules/eslint/lib/rules/utils/ast-utils.js
@@ -865,6 +865,47 @@ module.exports = {
return isFunction(node) && module.exports.isEmptyBlock(node.body);
},
+ /**
+ * Returns the result of the string conversion applied to the evaluated value of the given expression node,
+ * if it can be determined statically.
+ *
+ * This function returns a `string` value for all `Literal` nodes and simple `TemplateLiteral` nodes only.
+ * In all other cases, this function returns `null`.
+ * @param {ASTNode} node Expression node.
+ * @returns {string|null} String value if it can be determined. Otherwise, `null`.
+ */
+ getStaticStringValue(node) {
+ switch (node.type) {
+ case "Literal":
+ if (node.value === null) {
+ if (module.exports.isNullLiteral(node)) {
+ return String(node.value); // "null"
+ }
+ if (node.regex) {
+ return `/${node.regex.pattern}/${node.regex.flags}`;
+ }
+ if (node.bigint) {
+ return node.bigint;
+ }
+
+ // Otherwise, this is an unknown literal. The function will return null.
+
+ } else {
+ return String(node.value);
+ }
+ break;
+ case "TemplateLiteral":
+ if (node.expressions.length === 0 && node.quasis.length === 1) {
+ return node.quasis[0].value.cooked;
+ }
+ break;
+
+ // no default
+ }
+
+ return null;
+ },
+
/**
* Gets the property name of a given node.
* The node can be a MemberExpression, a Property, or a MethodDefinition.
@@ -911,23 +952,12 @@ module.exports = {
// no default
}
- switch (prop && prop.type) {
- case "Literal":
- return String(prop.value);
-
- case "TemplateLiteral":
- if (prop.expressions.length === 0 && prop.quasis.length === 1) {
- return prop.quasis[0].value.cooked;
- }
- break;
-
- case "Identifier":
- if (!node.computed) {
- return prop.name;
- }
- break;
+ if (prop) {
+ if (prop.type === "Identifier" && !node.computed) {
+ return prop.name;
+ }
- // no default
+ return module.exports.getStaticStringValue(prop);
}
return null;
@@ -987,6 +1017,7 @@ module.exports = {
* 0o5 // false
* 5e0 // false
* '5' // false
+ * 5n // false
*/
isDecimalInteger(node) {
return node.type === "Literal" && typeof node.value === "number" &&
@@ -1306,6 +1337,18 @@ module.exports = {
return node.type === "Literal" && node.value === null && !node.regex && !node.bigint;
},
+ /**
+ * Check if a given node is a numeric literal or not.
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} `true` if the node is a number or bigint literal.
+ */
+ isNumericLiteral(node) {
+ return (
+ node.type === "Literal" &&
+ (typeof node.value === "number" || Boolean(node.bigint))
+ );
+ },
+
/**
* Determines whether two tokens can safely be placed next to each other without merging into a single token
* @param {Token|string} leftValue The left token. If this is a string, it will be tokenized and the last token will be used.
diff --git a/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js b/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js
index 0fa40ee4ae8630..0498b99a21ed45 100644
--- a/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js
+++ b/tools/node_modules/eslint/lib/rules/utils/unicode/is-combining-character.js
@@ -1,13 +1,13 @@
-// THIS FILE WAS GENERATED BY 'tools/update-unicode-utils.js'
+/**
+ * @author Toru Nagashima
+ */
"use strict";
-const combiningChars = new Set([768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802,803,804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,1155,1156,1157,1158,1159,1160,1161,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1471,1473,1474,1476,1477,1479,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1648,1750,1751,1752,1753,1754,1755,1756,1759,1760,1761,1762,1763,1764,1767,1768,1770,1771,1772,1773,1809,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,2027,2028,2029,2030,2031,2032,2033,2034,2035,2070,2071,2072,2073,2075,2076,2077,2078,2079,2080,2081,2082,2083,2085,2086,2087,2089,2090,2091,2092,2093,2137,2138,2139,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2362,2363,2364,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2385,2386,2387,2388,2389,2390,2391,2402,2403,2433,2434,2435,2492,2494,2495,2496,2497,2498,2499,2500,2503,2504,2507,2508,2509,2519,2530,2531,2561,2562,2563,2620,2622,2623,2624,2625,2626,2631,2632,2635,2636,2637,2641,2672,2673,2677,2689,2690,2691,2748,2750,2751,2752,2753,2754,2755,2756,2757,2759,2760,2761,2763,2764,2765,2786,2787,2810,2811,2812,2813,2814,2815,2817,2818,2819,2876,2878,2879,2880,2881,2882,2883,2884,2887,2888,2891,2892,2893,2902,2903,2914,2915,2946,3006,3007,3008,3009,3010,3014,3015,3016,3018,3019,3020,3021,3031,3072,3073,3074,3075,3134,3135,3136,3137,3138,3139,3140,3142,3143,3144,3146,3147,3148,3149,3157,3158,3170,3171,3201,3202,3203,3260,3262,3263,3264,3265,3266,3267,3268,3270,3271,3272,3274,3275,3276,3277,3285,3286,3298,3299,3328,3329,3330,3331,3387,3388,3390,3391,3392,3393,3394,3395,3396,3398,3399,3400,3402,3403,3404,3405,3415,3426,3427,3458,3459,3530,3535,3536,3537,3538,3539,3540,3542,3544,3545,3546,3547,3548,3549,3550,3551,3570,3571,3633,3636,3637,3638,3639,3640,3641,3642,3655,3656,3657,3658,3659,3660,3661,3662,3761,3764,3765,3766,3767,3768,3769,3771,3772,3784,3785,3786,3787,3788,3789,3864,3865,3893,3895,3897,3902,3903,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3974,3975,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4038,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4182,4183,4184,4185,4190,4191,4192,4194,4195,4196,4199,4200,4201,4202,4203,4204,4205,4209,4210,4211,4212,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4239,4250,4251,4252,4253,4957,4958,4959,5906,5907,5908,5938,5939,5940,5970,5971,6002,6003,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6109,6155,6156,6157,6277,6278,6313,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6679,6680,6681,6682,6683,6741,6742,6743,6744,6745,6746,6747,6748,6749,6750,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6783,6832,6833,6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6912,6913,6914,6915,6916,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,6974,6975,6976,6977,6978,6979,6980,7019,7020,7021,7022,7023,7024,7025,7026,7027,7040,7041,7042,7073,7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,7155,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7376,7377,7378,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7405,7410,7411,7412,7415,7416,7417,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7675,7676,7677,7678,7679,8400,8401,8402,8403,8404,8405,8406,8407,8408,8409,8410,8411,8412,8413,8414,8415,8416,8417,8418,8419,8420,8421,8422,8423,8424,8425,8426,8427,8428,8429,8430,8431,8432,11503,11504,11505,11647,11744,11745,11746,11747,11748,11749,11750,11751,11752,11753,11754,11755,11756,11757,11758,11759,11760,11761,11762,11763,11764,11765,11766,11767,11768,11769,11770,11771,11772,11773,11774,11775,12330,12331,12332,12333,12334,12335,12441,12442,42607,42608,42609,42610,42612,42613,42614,42615,42616,42617,42618,42619,42620,42621,42654,42655,42736,42737,43010,43014,43019,43043,43044,43045,43046,43047,43136,43137,43188,43189,43190,43191,43192,43193,43194,43195,43196,43197,43198,43199,43200,43201,43202,43203,43204,43205,43232,43233,43234,43235,43236,43237,43238,43239,43240,43241,43242,43243,43244,43245,43246,43247,43248,43249,43302,43303,43304,43305,43306,43307,43308,43309,43335,43336,43337,43338,43339,43340,43341,43342,43343,43344,43345,43346,43347,43392,43393,43394,43395,43443,43444,43445,43446,43447,43448,43449,43450,43451,43452,43453,43454,43455,43456,43493,43561,43562,43563,43564,43565,43566,43567,43568,43569,43570,43571,43572,43573,43574,43587,43596,43597,43643,43644,43645,43696,43698,43699,43700,43703,43704,43710,43711,43713,43755,43756,43757,43758,43759,43765,43766,44003,44004,44005,44006,44007,44008,44009,44010,44012,44013,64286,65024,65025,65026,65027,65028,65029,65030,65031,65032,65033,65034,65035,65036,65037,65038,65039,65056,65057,65058,65059,65060,65061,65062,65063,65064,65065,65066,65067,65068,65069,65070,65071,66045,66272,66422,66423,66424,66425,66426,68097,68098,68099,68101,68102,68108,68109,68110,68111,68152,68153,68154,68159,68325,68326,69632,69633,69634,69688,69689,69690,69691,69692,69693,69694,69695,69696,69697,69698,69699,69700,69701,69702,69759,69760,69761,69762,69808,69809,69810,69811,69812,69813,69814,69815,69816,69817,69818,69888,69889,69890,69927,69928,69929,69930,69931,69932,69933,69934,69935,69936,69937,69938,69939,69940,70003,70016,70017,70018,70067,70068,70069,70070,70071,70072,70073,70074,70075,70076,70077,70078,70079,70080,70090,70091,70092,70188,70189,70190,70191,70192,70193,70194,70195,70196,70197,70198,70199,70206,70367,70368,70369,70370,70371,70372,70373,70374,70375,70376,70377,70378,70400,70401,70402,70403,70460,70462,70463,70464,70465,70466,70467,70468,70471,70472,70475,70476,70477,70487,70498,70499,70502,70503,70504,70505,70506,70507,70508,70512,70513,70514,70515,70516,70709,70710,70711,70712,70713,70714,70715,70716,70717,70718,70719,70720,70721,70722,70723,70724,70725,70726,70832,70833,70834,70835,70836,70837,70838,70839,70840,70841,70842,70843,70844,70845,70846,70847,70848,70849,70850,70851,71087,71088,71089,71090,71091,71092,71093,71096,71097,71098,71099,71100,71101,71102,71103,71104,71132,71133,71216,71217,71218,71219,71220,71221,71222,71223,71224,71225,71226,71227,71228,71229,71230,71231,71232,71339,71340,71341,71342,71343,71344,71345,71346,71347,71348,71349,71350,71351,71453,71454,71455,71456,71457,71458,71459,71460,71461,71462,71463,71464,71465,71466,71467,72193,72194,72195,72196,72197,72198,72199,72200,72201,72202,72243,72244,72245,72246,72247,72248,72249,72251,72252,72253,72254,72263,72273,72274,72275,72276,72277,72278,72279,72280,72281,72282,72283,72330,72331,72332,72333,72334,72335,72336,72337,72338,72339,72340,72341,72342,72343,72344,72345,72751,72752,72753,72754,72755,72756,72757,72758,72760,72761,72762,72763,72764,72765,72766,72767,72850,72851,72852,72853,72854,72855,72856,72857,72858,72859,72860,72861,72862,72863,72864,72865,72866,72867,72868,72869,72870,72871,72873,72874,72875,72876,72877,72878,72879,72880,72881,72882,72883,72884,72885,72886,73009,73010,73011,73012,73013,73014,73018,73020,73021,73023,73024,73025,73026,73027,73028,73029,73031,92912,92913,92914,92915,92916,92976,92977,92978,92979,92980,92981,92982,94033,94034,94035,94036,94037,94038,94039,94040,94041,94042,94043,94044,94045,94046,94047,94048,94049,94050,94051,94052,94053,94054,94055,94056,94057,94058,94059,94060,94061,94062,94063,94064,94065,94066,94067,94068,94069,94070,94071,94072,94073,94074,94075,94076,94077,94078,94095,94096,94097,94098,113821,113822,119141,119142,119143,119144,119145,119149,119150,119151,119152,119153,119154,119163,119164,119165,119166,119167,119168,119169,119170,119173,119174,119175,119176,119177,119178,119179,119210,119211,119212,119213,119362,119363,119364,121344,121345,121346,121347,121348,121349,121350,121351,121352,121353,121354,121355,121356,121357,121358,121359,121360,121361,121362,121363,121364,121365,121366,121367,121368,121369,121370,121371,121372,121373,121374,121375,121376,121377,121378,121379,121380,121381,121382,121383,121384,121385,121386,121387,121388,121389,121390,121391,121392,121393,121394,121395,121396,121397,121398,121403,121404,121405,121406,121407,121408,121409,121410,121411,121412,121413,121414,121415,121416,121417,121418,121419,121420,121421,121422,121423,121424,121425,121426,121427,121428,121429,121430,121431,121432,121433,121434,121435,121436,121437,121438,121439,121440,121441,121442,121443,121444,121445,121446,121447,121448,121449,121450,121451,121452,121461,121476,121499,121500,121501,121502,121503,121505,121506,121507,121508,121509,121510,121511,121512,121513,121514,121515,121516,121517,121518,121519,122880,122881,122882,122883,122884,122885,122886,122888,122889,122890,122891,122892,122893,122894,122895,122896,122897,122898,122899,122900,122901,122902,122903,122904,122907,122908,122909,122910,122911,122912,122913,122915,122916,122918,122919,122920,122921,122922,125136,125137,125138,125139,125140,125141,125142,125252,125253,125254,125255,125256,125257,125258,917760,917761,917762,917763,917764,917765,917766,917767,917768,917769,917770,917771,917772,917773,917774,917775,917776,917777,917778,917779,917780,917781,917782,917783,917784,917785,917786,917787,917788,917789,917790,917791,917792,917793,917794,917795,917796,917797,917798,917799,917800,917801,917802,917803,917804,917805,917806,917807,917808,917809,917810,917811,917812,917813,917814,917815,917816,917817,917818,917819,917820,917821,917822,917823,917824,917825,917826,917827,917828,917829,917830,917831,917832,917833,917834,917835,917836,917837,917838,917839,917840,917841,917842,917843,917844,917845,917846,917847,917848,917849,917850,917851,917852,917853,917854,917855,917856,917857,917858,917859,917860,917861,917862,917863,917864,917865,917866,917867,917868,917869,917870,917871,917872,917873,917874,917875,917876,917877,917878,917879,917880,917881,917882,917883,917884,917885,917886,917887,917888,917889,917890,917891,917892,917893,917894,917895,917896,917897,917898,917899,917900,917901,917902,917903,917904,917905,917906,917907,917908,917909,917910,917911,917912,917913,917914,917915,917916,917917,917918,917919,917920,917921,917922,917923,917924,917925,917926,917927,917928,917929,917930,917931,917932,917933,917934,917935,917936,917937,917938,917939,917940,917941,917942,917943,917944,917945,917946,917947,917948,917949,917950,917951,917952,917953,917954,917955,917956,917957,917958,917959,917960,917961,917962,917963,917964,917965,917966,917967,917968,917969,917970,917971,917972,917973,917974,917975,917976,917977,917978,917979,917980,917981,917982,917983,917984,917985,917986,917987,917988,917989,917990,917991,917992,917993,917994,917995,917996,917997,917998,917999])
-
/**
* Check whether a given character is a combining mark or not.
- * @param {number} c The character code to check.
- * @returns {boolean} `true` if the character belongs to the category, one of `Mc`, `Me`, and `Mn`.
+ * @param {number} codePoint The character code to check.
+ * @returns {boolean} `true` if the character belongs to the category, any of `Mc`, `Me`, and `Mn`.
*/
-module.exports = function isCombiningCharacter(c) {
- return combiningChars.has(c);
+module.exports = function isCombiningCharacter(codePoint) {
+ return /^[\p{Mc}\p{Me}\p{Mn}]$/u.test(String.fromCodePoint(codePoint));
};
diff --git a/tools/node_modules/eslint/lib/rules/yoda.js b/tools/node_modules/eslint/lib/rules/yoda.js
index b00acf82c702b0..be5c59ce072269 100644
--- a/tools/node_modules/eslint/lib/rules/yoda.js
+++ b/tools/node_modules/eslint/lib/rules/yoda.js
@@ -53,8 +53,7 @@ function looksLikeLiteral(node) {
return (node.type === "UnaryExpression" &&
node.operator === "-" &&
node.prefix &&
- node.argument.type === "Literal" &&
- typeof node.argument.value === "number");
+ astUtils.isNumericLiteral(node.argument));
}
/**
diff --git a/tools/node_modules/eslint/lib/shared/config-validator.js b/tools/node_modules/eslint/lib/shared/config-validator.js
index aca6e1fb274fdb..70eaf0a9670514 100644
--- a/tools/node_modules/eslint/lib/shared/config-validator.js
+++ b/tools/node_modules/eslint/lib/shared/config-validator.js
@@ -10,13 +10,12 @@
//------------------------------------------------------------------------------
const
- path = require("path"),
util = require("util"),
- lodash = require("lodash"),
configSchema = require("../../conf/config-schema"),
BuiltInEnvironments = require("../../conf/environments"),
BuiltInRules = require("../rules"),
- ConfigOps = require("./config-ops");
+ ConfigOps = require("./config-ops"),
+ { emitDeprecationWarning } = require("./deprecation-warnings");
const ajv = require("./ajv")();
const ruleValidators = new WeakMap();
@@ -26,11 +25,6 @@ const noop = Function.prototype;
// Private
//------------------------------------------------------------------------------
let validateSchema;
-
-// Defitions for deprecation warnings.
-const deprecationWarningMessages = {
- ESLINT_LEGACY_ECMAFEATURES: "The 'ecmaFeatures' config file property is deprecated, and has no effect."
-};
const severityMap = {
error: 2,
warn: 1,
@@ -254,25 +248,6 @@ function formatErrors(errors) {
}).map(message => `\t- ${message}.\n`).join("");
}
-/**
- * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
- * for each unique file path, but repeated invocations with the same file path have no effect.
- * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
- * @param {string} source The name of the configuration source to report the warning for.
- * @param {string} errorCode The warning message to show.
- * @returns {void}
- */
-const emitDeprecationWarning = lodash.memoize((source, errorCode) => {
- const rel = path.relative(process.cwd(), source);
- const message = deprecationWarningMessages[errorCode];
-
- process.emitWarning(
- `${message} (found in "${rel}")`,
- "DeprecationWarning",
- errorCode
- );
-});
-
/**
* Validates the top level properties of the config object.
* @param {Object} config The config object to validate.
diff --git a/tools/node_modules/eslint/lib/shared/deprecation-warnings.js b/tools/node_modules/eslint/lib/shared/deprecation-warnings.js
new file mode 100644
index 00000000000000..e1481a2e9aa0b8
--- /dev/null
+++ b/tools/node_modules/eslint/lib/shared/deprecation-warnings.js
@@ -0,0 +1,56 @@
+/**
+ * @fileoverview Provide the function that emits deprecation warnings.
+ * @author Toru Nagashima
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const path = require("path");
+const lodash = require("lodash");
+
+//------------------------------------------------------------------------------
+// Private
+//------------------------------------------------------------------------------
+
+// Defitions for deprecation warnings.
+const deprecationWarningMessages = {
+ ESLINT_LEGACY_ECMAFEATURES:
+ "The 'ecmaFeatures' config file property is deprecated and has no effect.",
+ ESLINT_PERSONAL_CONFIG_LOAD:
+ "'~/.eslintrc.*' config files have been deprecated. " +
+ "Please use a config file per project or the '--config' option.",
+ ESLINT_PERSONAL_CONFIG_SUPPRESS:
+ "'~/.eslintrc.*' config files have been deprecated. " +
+ "Please remove it or add 'root:true' to the config files in your " +
+ "projects in order to avoid loading '~/.eslintrc.*' accidentally."
+};
+
+/**
+ * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
+ * for each unique file path, but repeated invocations with the same file path have no effect.
+ * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
+ * @param {string} source The name of the configuration source to report the warning for.
+ * @param {string} errorCode The warning message to show.
+ * @returns {void}
+ */
+const emitDeprecationWarning = lodash.memoize((source, errorCode) => {
+ const rel = path.relative(process.cwd(), source);
+ const message = deprecationWarningMessages[errorCode];
+
+ process.emitWarning(
+ `${message} (found in "${rel}")`,
+ "DeprecationWarning",
+ errorCode
+ );
+}, (...args) => JSON.stringify(args));
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+module.exports = {
+ emitDeprecationWarning
+};
diff --git a/tools/node_modules/eslint/lib/shared/relative-module-resolver.js b/tools/node_modules/eslint/lib/shared/relative-module-resolver.js
index 5b25fa111214ed..fa6cca72361df5 100644
--- a/tools/node_modules/eslint/lib/shared/relative-module-resolver.js
+++ b/tools/node_modules/eslint/lib/shared/relative-module-resolver.js
@@ -6,35 +6,18 @@
"use strict";
const Module = require("module");
-const path = require("path");
-// Polyfill Node's `Module.createRequire` if not present. We only support the case where the argument is a filepath, not a URL.
-const createRequire = (
-
- // Added in v12.2.0
- Module.createRequire ||
-
- // Added in v10.12.0, but deprecated in v12.2.0.
- Module.createRequireFromPath ||
-
- // Polyfill - This is not executed on the tests on node@>=10.
- /* istanbul ignore next */
- (filename => {
- const mod = new Module(filename, null);
-
- mod.filename = filename;
- mod.paths = Module._nodeModulePaths(path.dirname(filename)); // eslint-disable-line no-underscore-dangle
- mod._compile("module.exports = require;", filename); // eslint-disable-line no-underscore-dangle
- return mod.exports;
- })
-);
+/*
+ * `Module.createRequire` is added in v12.2.0. It supports URL as well.
+ * We only support the case where the argument is a filepath, not a URL.
+ */
+const createRequire = Module.createRequire || Module.createRequireFromPath;
module.exports = {
/**
* Resolves a Node module relative to another module
* @param {string} moduleName The name of a Node module, or a path to a Node module.
- *
* @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be
* a file rather than a directory, but the file need not actually exist.
* @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`
@@ -43,6 +26,8 @@ module.exports = {
try {
return createRequire(relativeToPath).resolve(moduleName);
} catch (error) {
+
+ // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.
if (
typeof error === "object" &&
error !== null &&
diff --git a/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js b/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js
index 35176fbc0682ca..62945f7782a774 100644
--- a/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js
+++ b/tools/node_modules/eslint/node_modules/@babel/code-frame/lib/index.js
@@ -6,17 +6,11 @@ Object.defineProperty(exports, "__esModule", {
exports.codeFrameColumns = codeFrameColumns;
exports.default = _default;
-function _highlight() {
- const data = _interopRequireWildcard(require("@babel/highlight"));
+var _highlight = _interopRequireWildcard(require("@babel/highlight"));
- _highlight = function () {
- return data;
- };
-
- return data;
-}
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
-function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
let deprecationWarningShown = false;
@@ -35,7 +29,7 @@ function getMarkerLines(loc, source, opts) {
column: 0,
line: -1
}, loc.start);
- const endLoc = Object.assign({}, startLoc, loc.end);
+ const endLoc = Object.assign({}, startLoc, {}, loc.end);
const {
linesAbove = 2,
linesBelow = 3
@@ -94,8 +88,8 @@ function getMarkerLines(loc, source, opts) {
}
function codeFrameColumns(rawLines, loc, opts = {}) {
- const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight().shouldHighlight)(opts);
- const chalk = (0, _highlight().getChalk)(opts);
+ const highlighted = (opts.highlightCode || opts.forceColor) && (0, _highlight.shouldHighlight)(opts);
+ const chalk = (0, _highlight.getChalk)(opts);
const defs = getDefs(chalk);
const maybeHighlight = (chalkFn, string) => {
@@ -110,7 +104,7 @@ function codeFrameColumns(rawLines, loc, opts = {}) {
} = getMarkerLines(loc, lines, opts);
const hasColumns = loc.start && typeof loc.start.column === "number";
const numberMaxWidth = String(end).length;
- const highlightedLines = highlighted ? (0, _highlight().default)(rawLines, opts) : rawLines;
+ const highlightedLines = highlighted ? (0, _highlight.default)(rawLines, opts) : rawLines;
let frame = highlightedLines.split(NEWLINE).slice(start, end).map((line, index) => {
const number = start + 1 + index;
const paddedNumber = ` ${number}`.slice(-numberMaxWidth);
diff --git a/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json b/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json
index d619d9a8f53194..7508b5b1402c94 100644
--- a/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json
+++ b/tools/node_modules/eslint/node_modules/@babel/code-frame/package.json
@@ -5,7 +5,7 @@
},
"bundleDependencies": false,
"dependencies": {
- "@babel/highlight": "^7.0.0"
+ "@babel/highlight": "^7.8.3"
},
"deprecated": false,
"description": "Generate errors that contain a code frame that point to source locations.",
@@ -13,7 +13,7 @@
"chalk": "^2.0.0",
"strip-ansi": "^4.0.0"
},
- "gitHead": "0407f034f09381b95e9cabefbf6b176c76485a43",
+ "gitHead": "a7620bd266ae1345975767bbc7abf09034437017",
"homepage": "https://babeljs.io/",
"license": "MIT",
"main": "lib/index.js",
@@ -25,5 +25,5 @@
"type": "git",
"url": "https://github.com/babel/babel/tree/master/packages/babel-code-frame"
},
- "version": "7.5.5"
+ "version": "7.8.3"
}
\ No newline at end of file
diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js b/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js
index 6ac5b4a350b8e6..bf275748784b50 100644
--- a/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js
+++ b/tools/node_modules/eslint/node_modules/@babel/highlight/lib/index.js
@@ -7,39 +7,17 @@ exports.shouldHighlight = shouldHighlight;
exports.getChalk = getChalk;
exports.default = highlight;
-function _jsTokens() {
- const data = _interopRequireWildcard(require("js-tokens"));
+var _jsTokens = _interopRequireWildcard(require("js-tokens"));
- _jsTokens = function () {
- return data;
- };
-
- return data;
-}
-
-function _esutils() {
- const data = _interopRequireDefault(require("esutils"));
+var _esutils = _interopRequireDefault(require("esutils"));
- _esutils = function () {
- return data;
- };
-
- return data;
-}
-
-function _chalk() {
- const data = _interopRequireDefault(require("chalk"));
-
- _chalk = function () {
- return data;
- };
-
- return data;
-}
+var _chalk = _interopRequireDefault(require("chalk"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
-function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
+function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
+
+function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
function getDefs(chalk) {
return {
@@ -61,10 +39,10 @@ const BRACKET = /^[()[\]{}]$/;
function getTokenType(match) {
const [offset, text] = match.slice(-2);
- const token = (0, _jsTokens().matchToToken)(match);
+ const token = (0, _jsTokens.matchToToken)(match);
if (token.type === "name") {
- if (_esutils().default.keyword.isReservedWordES6(token.value)) {
+ if (_esutils.default.keyword.isReservedWordES6(token.value)) {
return "keyword";
}
@@ -89,7 +67,7 @@ function getTokenType(match) {
}
function highlightTokens(defs, text) {
- return text.replace(_jsTokens().default, function (...args) {
+ return text.replace(_jsTokens.default, function (...args) {
const type = getTokenType(args);
const colorize = defs[type];
@@ -102,14 +80,14 @@ function highlightTokens(defs, text) {
}
function shouldHighlight(options) {
- return _chalk().default.supportsColor || options.forceColor;
+ return _chalk.default.supportsColor || options.forceColor;
}
function getChalk(options) {
- let chalk = _chalk().default;
+ let chalk = _chalk.default;
if (options.forceColor) {
- chalk = new (_chalk().default.constructor)({
+ chalk = new _chalk.default.constructor({
enabled: true,
level: 1
});
diff --git a/tools/node_modules/eslint/node_modules/chalk/index.js b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js
similarity index 100%
rename from tools/node_modules/eslint/node_modules/chalk/index.js
rename to tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js
diff --git a/tools/node_modules/eslint/node_modules/chalk/index.js.flow b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js.flow
similarity index 100%
rename from tools/node_modules/eslint/node_modules/chalk/index.js.flow
rename to tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/index.js.flow
diff --git a/tools/node_modules/eslint/node_modules/string-width/node_modules/strip-ansi/license b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/license
similarity index 100%
rename from tools/node_modules/eslint/node_modules/string-width/node_modules/strip-ansi/license
rename to tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/license
diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/package.json b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/package.json
new file mode 100644
index 00000000000000..270fecdc347d42
--- /dev/null
+++ b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/package.json
@@ -0,0 +1,80 @@
+{
+ "bugs": {
+ "url": "https://github.com/chalk/chalk/issues"
+ },
+ "bundleDependencies": false,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "deprecated": false,
+ "description": "Terminal string styling done right",
+ "devDependencies": {
+ "ava": "*",
+ "coveralls": "^3.0.0",
+ "execa": "^0.9.0",
+ "flow-bin": "^0.68.0",
+ "import-fresh": "^2.0.0",
+ "matcha": "^0.7.0",
+ "nyc": "^11.0.2",
+ "resolve-from": "^4.0.0",
+ "typescript": "^2.5.3",
+ "xo": "*"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "files": [
+ "index.js",
+ "templates.js",
+ "types/index.d.ts",
+ "index.js.flow"
+ ],
+ "homepage": "https://github.com/chalk/chalk#readme",
+ "keywords": [
+ "color",
+ "colour",
+ "colors",
+ "terminal",
+ "console",
+ "cli",
+ "string",
+ "str",
+ "ansi",
+ "style",
+ "styles",
+ "tty",
+ "formatting",
+ "rgb",
+ "256",
+ "shell",
+ "xterm",
+ "log",
+ "logging",
+ "command-line",
+ "text"
+ ],
+ "license": "MIT",
+ "name": "chalk",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/chalk/chalk.git"
+ },
+ "scripts": {
+ "bench": "matcha benchmark.js",
+ "coveralls": "nyc report --reporter=text-lcov | coveralls",
+ "test": "xo && tsc --project types && flow --max-warnings=0 && nyc ava"
+ },
+ "types": "types/index.d.ts",
+ "version": "2.4.2",
+ "xo": {
+ "envs": [
+ "node",
+ "mocha"
+ ],
+ "ignores": [
+ "test/_flow.js"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/readme.md b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/readme.md
new file mode 100644
index 00000000000000..d298e2c48d64a0
--- /dev/null
+++ b/tools/node_modules/eslint/node_modules/@babel/highlight/node_modules/chalk/readme.md
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+> Terminal string styling done right
+
+[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) [![Mentioned in Awesome Node.js](https://awesome.re/mentioned-badge.svg)](https://github.com/sindresorhus/awesome-nodejs)
+
+### [See what's new in Chalk 2](https://github.com/chalk/chalk/releases/tag/v2.0.0)
+
+
+
+
+## Highlights
+
+- Expressive API
+- Highly performant
+- Ability to nest styles
+- [256/Truecolor color support](#256-and-truecolor-color-support)
+- Auto-detects color support
+- Doesn't extend `String.prototype`
+- Clean and focused
+- Actively maintained
+- [Used by ~23,000 packages](https://www.npmjs.com/browse/depended/chalk) as of December 31, 2017
+
+
+## Install
+
+```console
+$ npm install chalk
+```
+
+
+
+
+
+
+## Usage
+
+```js
+const chalk = require('chalk');
+
+console.log(chalk.blue('Hello world!'));
+```
+
+Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
+
+```js
+const chalk = require('chalk');
+const log = console.log;
+
+// Combine styled and normal strings
+log(chalk.blue('Hello') + ' World' + chalk.red('!'));
+
+// Compose multiple styles using the chainable API
+log(chalk.blue.bgRed.bold('Hello world!'));
+
+// Pass in multiple arguments
+log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
+
+// Nest styles
+log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
+
+// Nest styles of the same type even (color, underline, background)
+log(chalk.green(
+ 'I am a green line ' +
+ chalk.blue.underline.bold('with a blue substring') +
+ ' that becomes green again!'
+));
+
+// ES2015 template literal
+log(`
+CPU: ${chalk.red('90%')}
+RAM: ${chalk.green('40%')}
+DISK: ${chalk.yellow('70%')}
+`);
+
+// ES2015 tagged template literal
+log(chalk`
+CPU: {red ${cpu.totalPercent}%}
+RAM: {green ${ram.used / ram.total * 100}%}
+DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
+`);
+
+// Use RGB colors in terminal emulators that support it.
+log(chalk.keyword('orange')('Yay for orange colored text!'));
+log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
+log(chalk.hex('#DEADED').bold('Bold gray!'));
+```
+
+Easily define your own themes:
+
+```js
+const chalk = require('chalk');
+
+const error = chalk.bold.red;
+const warning = chalk.keyword('orange');
+
+console.log(error('Error!'));
+console.log(warning('Warning!'));
+```
+
+Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
+
+```js
+const name = 'Sindre';
+console.log(chalk.green('Hello %s'), name);
+//=> 'Hello Sindre'
+```
+
+
+## API
+
+### chalk.`