diff options
author | Rich Trott <rtrott@gmail.com> | 2016-08-13 15:06:43 -0700 |
---|---|---|
committer | Evan Lucas <evanlucas@me.com> | 2016-08-20 10:00:31 -0500 |
commit | cdcf23ab7f111c4ae531192d2eaa6045778965bc (patch) | |
tree | 5782d53c16ead52396b58826afe340448fb6ca6b | |
parent | be41f584f3e6a5b7ec342984dc5152717b6eb600 (diff) | |
download | node-new-cdcf23ab7f111c4ae531192d2eaa6045778965bc.tar.gz |
tools: update ESLint to 3.3.0 and enable rules
Update ESLint 3.3.0 and update .eslintrc:
* replace deprecated no-negated-in-lhs rule with no-unsafe-negation
* http://eslint.org/docs/rules/no-negated-in-lhs
* http://eslint.org/docs/rules/no-unsafe-negation
* enable no-template-curly-in-string
* http://eslint.org/docs/rules/no-template-curly-in-string
* enable no-global-assign
* http://eslint.org/docs/rules/no-global-assign
* enable func-call-spacing
* http://eslint.org/docs/rules/func-call-spacing
PR-URL: https://github.com/nodejs/node/pull/8097
Reviewed-By: targos - Michaƫl Zasso <mic.besace@gmail.com>
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Reviewed-By: Roman Reiss <me@silverwind.io>
391 files changed, 4755 insertions, 5775 deletions
@@ -19,17 +19,19 @@ rules: no-func-assign: 2 no-invalid-regexp: 2 no-irregular-whitespace: 2 - no-negated-in-lhs: 2 no-obj-calls: 2 no-proto: 2 + no-template-curly-in-string: 2 no-unexpected-multiline: 2 no-unreachable: 2 + no-unsafe-negation: 2 use-isnan: 2 valid-typeof: 2 # Best Practices # http://eslint.org/docs/rules/#best-practices no-fallthrough: 2 + no-global-assign: 2 no-multi-spaces: 2 no-octal: 2 no-redeclare: 2 @@ -58,6 +60,7 @@ rules: brace-style: [2, 1tbs, {allowSingleLine: true}] comma-spacing: 2 eol-last: 2 + func-call-spacing: 2 indent: [2, 2, {SwitchCase: 1, MemberExpression: 1}] key-spacing: [2, {mode: minimum}] keyword-spacing: 2 diff --git a/tools/eslint/conf/category-list.json b/tools/eslint/conf/category-list.json index d7e84b6c15..b5020c1f00 100644 --- a/tools/eslint/conf/category-list.json +++ b/tools/eslint/conf/category-list.json @@ -8,6 +8,11 @@ { "name": "Stylistic Issues", "description": "These rules relate to style guidelines, and are therefore quite subjective:" }, { "name": "ECMAScript 6", "description": "These rules relate to ES6, also known as ES2015:" } ], + "deprecated": { + "name": "Deprecated", + "description": "These rules have been deprecated and replaced by newer rules:", + "rules": [] + }, "removed": { "name": "Removed", "description": "These rules from older versions of ESLint have been replaced by newer rules:", @@ -32,4 +37,4 @@ { "removed": "spaced-line-comment", "replacedBy": ["spaced-comment"] } ] } -}
\ No newline at end of file +} diff --git a/tools/eslint/conf/environments.js b/tools/eslint/conf/environments.js index d938a6cfaa..a11f2963dc 100644 --- a/tools/eslint/conf/environments.js +++ b/tools/eslint/conf/environments.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let globals = require("globals"); +const globals = require("globals"); //------------------------------------------------------------------------------ // Public Interface diff --git a/tools/eslint/conf/eslint-all.js b/tools/eslint/conf/eslint-all.js index 53d5cdb82d..28d745a921 100644 --- a/tools/eslint/conf/eslint-all.js +++ b/tools/eslint/conf/eslint-all.js @@ -9,17 +9,16 @@ // Requirements //------------------------------------------------------------------------------ -let fs = require("fs"), - path = require("path"); +const load = require("../lib/load-rules"), + rules = require("../lib/rules"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let ruleFiles = fs.readdirSync(path.resolve(__dirname, "../lib/rules")); -let enabledRules = ruleFiles.reduce(function(result, filename) { - if (path.extname(filename) === ".js") { - result[path.basename(filename, ".js")] = "error"; +const enabledRules = Object.keys(load()).reduce((result, ruleId) => { + if (!rules.get(ruleId).meta.deprecated) { + result[ruleId] = "error"; } return result; }, {}); diff --git a/tools/eslint/conf/eslint.json b/tools/eslint/conf/eslint.json index 53b2e75590..3d7779ea06 100644..100755 --- a/tools/eslint/conf/eslint.json +++ b/tools/eslint/conf/eslint.json @@ -41,6 +41,7 @@ "no-fallthrough": "error", "no-floating-decimal": "off", "no-func-assign": "error", + "no-global-assign": "off", "no-implicit-coercion": "off", "no-implicit-globals": "off", "no-implied-eval": "off", @@ -113,6 +114,7 @@ "no-unneeded-ternary": "off", "no-unreachable": "error", "no-unsafe-finally": "error", + "no-unsafe-negation": "off", "no-unused-expressions": "off", "no-unused-labels": "error", "no-unused-vars": "error", @@ -152,6 +154,7 @@ "dot-notation": "off", "eol-last": "off", "eqeqeq": "off", + "func-call-spacing": "off", "func-names": "off", "func-style": "off", "generator-star-spacing": "off", @@ -204,6 +207,7 @@ "rest-spread-spacing": "off", "semi": "off", "semi-spacing": "off", + "sort-keys": "off", "sort-imports": "off", "sort-vars": "off", "space-before-blocks": "off", @@ -221,6 +225,7 @@ "vars-on-top": "off", "wrap-iife": "off", "wrap-regex": "off", + "no-template-curly-in-string": "off", "yield-star-spacing": "off", "yoda": "off" } diff --git a/tools/eslint/lib/ast-utils.js b/tools/eslint/lib/ast-utils.js index 881cc26c5f..9fcab25b4a 100644 --- a/tools/eslint/lib/ast-utils.js +++ b/tools/eslint/lib/ast-utils.js @@ -9,19 +9,19 @@ // Requirements //------------------------------------------------------------------------------ -let esutils = require("esutils"); +const esutils = require("esutils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/; -let anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/; -let arrayOrTypedArrayPattern = /Array$/; -let arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/; -let bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/; -let breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/; -let thisTagPattern = /^[\s\*]*@this/m; +const anyFunctionPattern = /^(?:Function(?:Declaration|Expression)|ArrowFunctionExpression)$/; +const anyLoopPattern = /^(?:DoWhile|For|ForIn|ForOf|While)Statement$/; +const arrayOrTypedArrayPattern = /Array$/; +const arrayMethodPattern = /^(?:every|filter|find|findIndex|forEach|map|some)$/; +const bindOrCallOrApplyPattern = /^(?:bind|call|apply)$/; +const breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/; +const thisTagPattern = /^[\s\*]*@this/m; /** * Checks reference if is non initializer and writable. @@ -32,15 +32,14 @@ let thisTagPattern = /^[\s\*]*@this/m; * @private */ function isModifyingReference(reference, index, references) { - let identifier = reference.identifier, - modifyingDifferentIdentifier; + const identifier = reference.identifier; /* * Destructuring assignments can have multiple default value, so * possibly there are multiple writeable references for the same * identifier. */ - modifyingDifferentIdentifier = index === 0 || + const modifyingDifferentIdentifier = index === 0 || references[index - 1].identifier !== identifier; return (identifier && @@ -51,15 +50,22 @@ function isModifyingReference(reference, index, references) { } /** + * Checks whether the given string starts with uppercase or not. + * + * @param {string} s - The string to check. + * @returns {boolean} `true` if the string starts with uppercase. + */ +function startsWithUpperCase(s) { + return s[0] !== s[0].toLocaleLowerCase(); +} + +/** * Checks whether or not a node is a constructor. * @param {ASTNode} node - A function node to check. * @returns {boolean} Wehether or not a node is a constructor. */ function isES5Constructor(node) { - return ( - node.id && - node.id.name[0] !== node.id.name[0].toLocaleLowerCase() - ); + return (node.id && startsWithUpperCase(node.id.name)); } /** @@ -160,7 +166,7 @@ function isMethodWhichHasThisArg(node) { * @returns {boolean} Whether or not the node has a `@this` tag in its comments. */ function hasJSDocThisTag(node, sourceCode) { - let jsdocComment = sourceCode.getJSDocComment(node); + const jsdocComment = sourceCode.getJSDocComment(node); if (jsdocComment && thisTagPattern.test(jsdocComment.value)) { return true; @@ -183,7 +189,7 @@ function hasJSDocThisTag(node, sourceCode) { * @private */ function isParenthesised(sourceCode, node) { - let previousToken = sourceCode.getTokenBefore(node), + const previousToken = sourceCode.getTokenBefore(node), nextToken = sourceCode.getTokenAfter(node); return Boolean(previousToken && nextToken) && @@ -285,7 +291,7 @@ module.exports = { * @returns {boolean} `true` if the node is an ESLint directive comment */ isDirectiveComment: function(node) { - let comment = node.value.trim(); + const comment = node.value.trim(); return ( node.type === "Line" && comment.indexOf("eslint-") === 0 || @@ -321,7 +327,7 @@ module.exports = { let scope = initScope; while (scope) { - let variable = scope.set.get(name); + const variable = scope.set.get(name); if (variable) { return variable; @@ -345,9 +351,9 @@ module.exports = { * If the location is below, this judges `this` is valid. * * - The location is not on an object literal. - * - The location does not assign to a property. + * - The location is not assigned to a variable which starts with an uppercase letter. * - The location is not on an ES2015 class. - * - The location does not call its `bind`/`call`/`apply` method directly. + * - Its `bind`/`call`/`apply` method is not called directly. * - The function is not a callback of array methods (such as `.forEach()`) if `thisArg` is given. * * @param {ASTNode} node - A function node to check. @@ -358,9 +364,10 @@ module.exports = { if (isES5Constructor(node) || hasJSDocThisTag(node, sourceCode)) { return false; } + const isAnonymous = node.id === null; while (node) { - let parent = node.parent; + const parent = node.parent; switch (parent.type) { @@ -392,25 +399,44 @@ module.exports = { // e.g. // var obj = { foo() { ... } }; // var obj = { foo: function() { ... } }; - case "Property": - return false; - - // e.g. - // obj.foo = foo() { ... }; - case "AssignmentExpression": - return ( - parent.right !== node || - parent.left.type !== "MemberExpression" - ); - - // e.g. // class A { constructor() { ... } } // class A { foo() { ... } } // class A { get foo() { ... } } // class A { set foo() { ... } } // class A { static foo() { ... } } + case "Property": case "MethodDefinition": - return false; + return parent.value !== node; + + // e.g. + // obj.foo = function foo() { ... }; + // Foo = function() { ... }; + // [obj.foo = function foo() { ... }] = a; + // [Foo = function() { ... }] = a; + case "AssignmentExpression": + case "AssignmentPattern": + if (parent.right === node) { + if (parent.left.type === "MemberExpression") { + return false; + } + if (isAnonymous && + parent.left.type === "Identifier" && + startsWithUpperCase(parent.left.name) + ) { + return false; + } + } + return true; + + // e.g. + // var Foo = function() { ... }; + case "VariableDeclarator": + return !( + isAnonymous && + parent.init === node && + parent.id.type === "Identifier" && + startsWithUpperCase(parent.id.name) + ); // e.g. // var foo = function foo() { ... }.bind(obj); @@ -585,5 +611,74 @@ module.exports = { */ isFunction: function(node) { return Boolean(node && anyFunctionPattern.test(node.type)); + }, + + /** + * Gets the property name of a given node. + * The node can be a MemberExpression, a Property, or a MethodDefinition. + * + * If the name is dynamic, this returns `null`. + * + * For examples: + * + * a.b // => "b" + * a["b"] // => "b" + * a['b'] // => "b" + * a[`b`] // => "b" + * a[100] // => "100" + * a[b] // => null + * a["a" + "b"] // => null + * a[tag`b`] // => null + * a[`${b}`] // => null + * + * let a = {b: 1} // => "b" + * let a = {["b"]: 1} // => "b" + * let a = {['b']: 1} // => "b" + * let a = {[`b`]: 1} // => "b" + * let a = {[100]: 1} // => "100" + * let a = {[b]: 1} // => null + * let a = {["a" + "b"]: 1} // => null + * let a = {[tag`b`]: 1} // => null + * let a = {[`${b}`]: 1} // => null + * + * @param {ASTNode} node - The node to get. + * @returns {string|null} The property name if static. Otherwise, null. + */ + getStaticPropertyName(node) { + let prop; + + switch (node && node.type) { + case "Property": + case "MethodDefinition": + prop = node.key; + break; + + case "MemberExpression": + prop = node.property; + break; + + // 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; + + // no default + } + + return null; } }; diff --git a/tools/eslint/lib/cli-engine.js b/tools/eslint/lib/cli-engine.js index cf28aa1d59..110a844512 100644 --- a/tools/eslint/lib/cli-engine.js +++ b/tools/eslint/lib/cli-engine.js @@ -15,12 +15,8 @@ // Requirements //------------------------------------------------------------------------------ -let fs = require("fs"), +const fs = require("fs"), path = require("path"), - - lodash = require("lodash"), - debug = require("debug"), - rules = require("./rules"), eslint = require("./eslint"), defaultOptions = require("../conf/cli-options"), @@ -36,6 +32,7 @@ let fs = require("fs"), pkg = require("../package.json"); +const debug = require("debug")("eslint:cli-engine"); //------------------------------------------------------------------------------ // Typedefs @@ -84,8 +81,6 @@ let fs = require("fs"), // Helpers //------------------------------------------------------------------------------ -debug = debug("eslint:cli-engine"); - /** * It will calculate the error and warning count for collection of messages per file * @param {Object[]} messages - Collection of messages @@ -137,12 +132,11 @@ function calculateStatsPerRun(results) { * @private */ function multipassFix(text, config, options) { - + const MAX_PASSES = 10; let messages = [], fixedResult, fixed = false, - passNumber = 0, - MAX_PASSES = 10; + passNumber = 0; /** * This loop continues until one of the following is true: @@ -213,12 +207,9 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) { eslint.reset(); let filePath, - config, messages, - stats, fileExtension, processor, - loadedPlugins, fixedResult; if (filename) { @@ -228,15 +219,15 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) { filename = filename || "<text>"; debug("Linting " + filename); - config = configHelper.getConfig(filePath); + const config = configHelper.getConfig(filePath); if (config.plugins) { Plugins.loadAll(config.plugins); } - loadedPlugins = Plugins.getAll(); + const loadedPlugins = Plugins.getAll(); - for (let plugin in loadedPlugins) { + for (const plugin in loadedPlugins) { if (loadedPlugins[plugin].processors && Object.keys(loadedPlugins[plugin].processors).indexOf(fileExtension) >= 0) { processor = loadedPlugins[plugin].processors[fileExtension]; break; @@ -245,8 +236,8 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) { if (processor) { debug("Using processor"); - let parsedBlocks = processor.preprocess(text, filename); - let unprocessedMessages = []; + const parsedBlocks = processor.preprocess(text, filename); + const unprocessedMessages = []; parsedBlocks.forEach(function(block) { unprocessedMessages.push(eslint.verify(block, config, { @@ -275,9 +266,9 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) { } } - stats = calculateStatsPerFile(messages); + const stats = calculateStatsPerFile(messages); - let result = { + const result = { filePath: filename, messages: messages, errorCount: stats.errorCount, @@ -302,7 +293,7 @@ function processText(text, configHelper, filename, fix, allowInlineConfig) { */ function processFile(filename, configHelper, options) { - let text = fs.readFileSync(path.resolve(filename), "utf8"), + const text = fs.readFileSync(path.resolve(filename), "utf8"), result = processText(text, configHelper, filename, options.fix, options.allowInlineConfig); return result; @@ -318,9 +309,9 @@ function processFile(filename, configHelper, options) { */ function createIgnoreResult(filePath, baseDir) { let message; - let isHidden = /^\./.test(path.basename(filePath)); - let isInNodeModules = baseDir && /^node_modules/.test(path.relative(baseDir, filePath)); - let isInBowerComponents = baseDir && /^bower_components/.test(path.relative(baseDir, filePath)); + const isHidden = /^\./.test(path.basename(filePath)); + const isInNodeModules = baseDir && /^node_modules/.test(path.relative(baseDir, filePath)); + const isInBowerComponents = baseDir && /^bower_components/.test(path.relative(baseDir, filePath)); if (isHidden) { message = "File ignored by default. Use a negated ignore pattern (like \"--ignore-pattern \'!<relative/path/to/filename>\'\") to override."; @@ -377,8 +368,8 @@ function getCacheFile(cacheFile, cwd) { */ cacheFile = path.normalize(cacheFile); - let resolvedCacheFile = path.resolve(cwd, cacheFile); - let looksLikeADirectory = cacheFile[cacheFile.length - 1 ] === path.sep; + const resolvedCacheFile = path.resolve(cwd, cacheFile); + const looksLikeADirectory = cacheFile[cacheFile.length - 1 ] === path.sep; /** * return the name for the cache file in case the provided parameter is a directory @@ -442,7 +433,7 @@ function getCacheFile(cacheFile, cwd) { */ function CLIEngine(options) { - options = lodash.assign( + options = Object.assign( Object.create(null), defaultOptions, {cwd: process.cwd()}, @@ -455,7 +446,7 @@ function CLIEngine(options) { */ this.options = options; - let cacheFile = getCacheFile(this.options.cacheLocation || this.options.cacheFile, this.options.cwd); + const cacheFile = getCacheFile(this.options.cacheLocation || this.options.cacheFile, this.options.cwd); /** * Cache used to avoid operating on files that haven't changed since the @@ -467,7 +458,7 @@ function CLIEngine(options) { // load in additional rules if (this.options.rulePaths) { - let cwd = this.options.cwd; + const cwd = this.options.cwd; this.options.rulePaths.forEach(function(rulesdir) { debug("Loading rules from " + rulesdir); @@ -502,7 +493,7 @@ CLIEngine.getFormatter = function(format) { // if there's a slash, then it's a file if (format.indexOf("/") > -1) { - let cwd = this.options ? this.options.cwd : process.cwd(); + const cwd = this.options ? this.options.cwd : process.cwd(); formatterPath = path.resolve(cwd, format); } else { @@ -527,10 +518,10 @@ CLIEngine.getFormatter = function(format) { * @returns {LintResult[]} The filtered results. */ CLIEngine.getErrorResults = function(results) { - let filtered = []; + const filtered = []; results.forEach(function(result) { - let filteredMessages = result.messages.filter(isErrorMessage); + const filteredMessages = result.messages.filter(isErrorMessage); if (filteredMessages.length > 0) { filtered.push({ @@ -588,14 +579,11 @@ CLIEngine.prototype = { * @returns {Object} The results for all files that were linted. */ executeOnFiles: function(patterns) { - let results = [], + const results = [], options = this.options, fileCache = this._fileCache, - configHelper = new Config(options), - fileList, - stats, - startTime, - prevConfig; // the previous configuration used + configHelper = new Config(options); + let prevConfig; // the previous configuration used /** * Calculates the hash of the config file used to validate a given file @@ -603,7 +591,7 @@ CLIEngine.prototype = { * @returns {string} the hash of the config */ function hashOfConfigFor(filename) { - let config = configHelper.getConfig(filename); + const config = configHelper.getConfig(filename); if (!prevConfig) { prevConfig = {}; @@ -618,7 +606,7 @@ CLIEngine.prototype = { */ prevConfig.config = config; - let eslintVersion = pkg.version; + const eslintVersion = pkg.version; prevConfig.hash = hash(eslintVersion + "_" + stringify(config)); } @@ -650,11 +638,11 @@ CLIEngine.prototype = { * the file has changed */ descriptor = fileCache.getFileDescriptor(filename); - let meta = descriptor.meta || {}; + const meta = descriptor.meta || {}; hashOfConfig = hashOfConfigFor(filename); - let changed = descriptor.changed || meta.hashOfConfig !== hashOfConfig; + const changed = descriptor.changed || meta.hashOfConfig !== hashOfConfig; if (!changed) { debug("Skipping file since hasn't changed: " + filename); @@ -676,7 +664,7 @@ CLIEngine.prototype = { debug("Processing " + filename); - let res = processFile(filename, configHelper, options); + const res = processFile(filename, configHelper, options); if (options.cache) { @@ -706,17 +694,18 @@ CLIEngine.prototype = { results.push(res); } - startTime = Date.now(); + const startTime = Date.now(); patterns = this.resolveFileGlobPatterns(patterns); - fileList = globUtil.listFilesToProcess(patterns, options); + const fileList = globUtil.listFilesToProcess(patterns, options); + fileList.forEach(function(fileInfo) { executeOnFile(fileInfo.filename, fileInfo.ignored); }); - stats = calculateStatsPerRun(results); + const stats = calculateStatsPerRun(results); if (options.cache) { @@ -742,8 +731,7 @@ CLIEngine.prototype = { */ executeOnText: function(text, filename, warnIgnored) { - let results = [], - stats, + const results = [], options = this.options, configHelper = new Config(options), ignoredPaths = new IgnoredPaths(options); @@ -761,7 +749,7 @@ CLIEngine.prototype = { results.push(processText(text, configHelper, filename, options.fix, options.allowInlineConfig)); } - stats = calculateStatsPerRun(results); + const stats = calculateStatsPerRun(results); return { results: results, @@ -778,7 +766,7 @@ CLIEngine.prototype = { * @returns {Object} A configuration object for the file. */ getConfigForFile: function(filePath) { - let configHelper = new Config(this.options); + const configHelper = new Config(this.options); return configHelper.getConfig(filePath); }, @@ -789,10 +777,9 @@ CLIEngine.prototype = { * @returns {boolean} Whether or not the given path is ignored. */ isPathIgnored: function(filePath) { - let ignoredPaths; - let resolvedPath = path.resolve(this.options.cwd, filePath); + const resolvedPath = path.resolve(this.options.cwd, filePath); + const ignoredPaths = new IgnoredPaths(this.options); - ignoredPaths = new IgnoredPaths(this.options); return ignoredPaths.contains(resolvedPath); }, diff --git a/tools/eslint/lib/cli.js b/tools/eslint/lib/cli.js index b8bbda4cae..3a51d2acf3 100644 --- a/tools/eslint/lib/cli.js +++ b/tools/eslint/lib/cli.js @@ -15,22 +15,20 @@ // Requirements //------------------------------------------------------------------------------ -let fs = require("fs"), +const fs = require("fs"), path = require("path"), - - debug = require("debug"), - + shell = require("shelljs"), options = require("./options"), CLIEngine = require("./cli-engine"), mkdirp = require("mkdirp"), log = require("./logging"); +const debug = require("debug")("eslint:cli"); + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -debug = debug("eslint:cli"); - /** * Translates the CLI options into the options expected by the CLIEngine. * @param {Object} cliOptions The CLI options to translate. @@ -70,9 +68,7 @@ function translateOptions(cliOptions) { * @private */ function printResults(engine, results, format, outputFile) { - let formatter, - output, - filePath; + let formatter; try { formatter = engine.getFormatter(format); @@ -81,13 +77,13 @@ function printResults(engine, results, format, outputFile) { return false; } - output = formatter(results); + const output = formatter(results); if (output) { if (outputFile) { - filePath = path.resolve(process.cwd(), outputFile); + const filePath = path.resolve(process.cwd(), outputFile); - if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) { + if (shell.test("-d", filePath)) { log.error("Cannot write to output file path, it is a directory: %s", outputFile); return false; } @@ -116,7 +112,7 @@ function printResults(engine, results, format, outputFile) { * Encapsulates all CLI behavior for eslint. Makes it easier to test as well as * for other Node.js programs to effectively run the CLI. */ -let cli = { +const cli = { /** * Executes the CLI based on an array of arguments that is passed in. @@ -126,11 +122,7 @@ let cli = { */ execute: function(args, text) { - let currentOptions, - files, - report, - engine, - tooManyWarnings; + let currentOptions; try { currentOptions = options.parse(args); @@ -139,7 +131,7 @@ let cli = { return 1; } - files = currentOptions._; + const files = currentOptions._; if (currentOptions.version) { // version from package.json @@ -159,7 +151,8 @@ let cli = { return 1; } - engine = new CLIEngine(translateOptions(currentOptions)); + const engine = new CLIEngine(translateOptions(currentOptions)); + if (currentOptions.printConfig) { if (files.length !== 1) { log.error("The --print-config option requires a " + @@ -172,13 +165,14 @@ let cli = { return 1; } - let fileConfig = engine.getConfigForFile(files[0]); + const fileConfig = engine.getConfigForFile(files[0]); log.info(JSON.stringify(fileConfig, null, " ")); return 0; } - report = text ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files); + const report = text ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files); + if (currentOptions.fix) { debug("Fix mode enabled - applying fixes"); CLIEngine.outputFixes(report); @@ -190,7 +184,7 @@ let cli = { } if (printResults(engine, report.results, currentOptions.format, currentOptions.outputFile)) { - tooManyWarnings = currentOptions.maxWarnings >= 0 && report.warningCount > currentOptions.maxWarnings; + const tooManyWarnings = currentOptions.maxWarnings >= 0 && report.warningCount > currentOptions.maxWarnings; if (!report.errorCount && tooManyWarnings) { log.error("ESLint found too many warnings (maximum: %s).", currentOptions.maxWarnings); diff --git a/tools/eslint/lib/code-path-analysis/code-path-analyzer.js b/tools/eslint/lib/code-path-analysis/code-path-analyzer.js index 00db3064dc..2c596c47f0 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-analyzer.js +++ b/tools/eslint/lib/code-path-analysis/code-path-analyzer.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let assert = require("assert"), +const assert = require("assert"), CodePath = require("./code-path"), CodePathSegment = require("./code-path-segment"), IdGenerator = require("./id-generator"), @@ -38,7 +38,7 @@ function isCaseNode(node) { * @returns {boolean} `true` if the node is a test of a choice statement. */ function isForkingByTrueOrFalse(node) { - let parent = node.parent; + const parent = node.parent; switch (parent.type) { case "ConditionalExpression": @@ -83,7 +83,7 @@ function getBooleanValueIfSimpleConstant(node) { * @returns {boolean} `true` if the node is a reference. */ function isIdentifierReference(node) { - let parent = node.parent; + const parent = node.parent; switch (parent.type) { case "LabeledStatement": @@ -135,11 +135,11 @@ function isIdentifierReference(node) { * @returns {void} */ function forwardCurrentToHead(analyzer, node) { - let codePath = analyzer.codePath; - let state = CodePath.getState(codePath); - let currentSegments = state.currentSegments; - let headSegments = state.headSegments; - let end = Math.max(currentSegments.length, headSegments.length); + const codePath = analyzer.codePath; + const state = CodePath.getState(codePath); + const currentSegments = state.currentSegments; + const headSegments = state.headSegments; + const end = Math.max(currentSegments.length, headSegments.length); let i, currentSegment, headSegment; // Fires leaving events. @@ -191,11 +191,11 @@ function forwardCurrentToHead(analyzer, node) { * @returns {void} */ function leaveFromCurrentSegment(analyzer, node) { - let state = CodePath.getState(analyzer.codePath); - let currentSegments = state.currentSegments; + const state = CodePath.getState(analyzer.codePath); + const currentSegments = state.currentSegments; for (let i = 0; i < currentSegments.length; ++i) { - let currentSegment = currentSegments[i]; + const currentSegment = currentSegments[i]; debug.dump("onCodePathSegmentEnd " + currentSegment.id); if (currentSegment.reachable) { @@ -221,9 +221,9 @@ function leaveFromCurrentSegment(analyzer, node) { * @returns {void} */ function preprocess(analyzer, node) { - let codePath = analyzer.codePath; - let state = CodePath.getState(codePath); - let parent = node.parent; + const codePath = analyzer.codePath; + const state = CodePath.getState(codePath); + const parent = node.parent; switch (parent.type) { case "LogicalExpression": @@ -330,7 +330,7 @@ function preprocess(analyzer, node) { function processCodePathToEnter(analyzer, node) { let codePath = analyzer.codePath; let state = codePath && CodePath.getState(codePath); - let parent = node.parent; + const parent = node.parent; switch (node.type) { case "Program": @@ -419,8 +419,8 @@ function processCodePathToEnter(analyzer, node) { * @returns {void} */ function processCodePathToExit(analyzer, node) { - let codePath = analyzer.codePath; - let state = CodePath.getState(codePath); + const codePath = analyzer.codePath; + const state = CodePath.getState(codePath); let dontForward = false; switch (node.type) { diff --git a/tools/eslint/lib/code-path-analysis/code-path-segment.js b/tools/eslint/lib/code-path-analysis/code-path-segment.js index 544a9da278..53e39175a7 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-segment.js +++ b/tools/eslint/lib/code-path-analysis/code-path-segment.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let debug = require("./debug-helpers"); +const debug = require("./debug-helpers"); //------------------------------------------------------------------------------ // Helpers @@ -22,11 +22,11 @@ let debug = require("./debug-helpers"); * @returns {CodePathSegment[]} The replaced array. */ function flattenUnusedSegments(segments) { - let done = Object.create(null); - let retv = []; + const done = Object.create(null); + const retv = []; for (let i = 0; i < segments.length; ++i) { - let segment = segments[i]; + const segment = segments[i]; // Ignores duplicated. if (done[segment.id]) { @@ -36,7 +36,7 @@ function flattenUnusedSegments(segments) { // Use previous segments if unused. if (!segment.internal.used) { for (let j = 0; j < segment.allPrevSegments.length; ++j) { - let prevSegment = segment.allPrevSegments[j]; + const prevSegment = segment.allPrevSegments[j]; if (!done[prevSegment.id]) { done[prevSegment.id] = true; @@ -175,7 +175,7 @@ CodePathSegment.newNext = function(id, allPrevSegments) { * @returns {CodePathSegment} The created segment. */ CodePathSegment.newUnreachable = function(id, allPrevSegments) { - let segment = new CodePathSegment(id, flattenUnusedSegments(allPrevSegments), false); + const segment = new CodePathSegment(id, flattenUnusedSegments(allPrevSegments), false); // In `if (a) return a; foo();` case, the unreachable segment preceded by // the return statement is not used but must not be remove. @@ -215,7 +215,7 @@ CodePathSegment.markUsed = function(segment) { if (segment.reachable) { for (i = 0; i < segment.allPrevSegments.length; ++i) { - let prevSegment = segment.allPrevSegments[i]; + const prevSegment = segment.allPrevSegments[i]; prevSegment.allNextSegments.push(segment); prevSegment.nextSegments.push(segment); diff --git a/tools/eslint/lib/code-path-analysis/code-path-state.js b/tools/eslint/lib/code-path-analysis/code-path-state.js index 7c3d4a35e6..bfa93ac607 100644 --- a/tools/eslint/lib/code-path-analysis/code-path-state.js +++ b/tools/eslint/lib/code-path-analysis/code-path-state.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let CodePathSegment = require("./code-path-segment"), +const CodePathSegment = require("./code-path-segment"), ForkContext = require("./fork-context"); //------------------------------------------------------------------------------ @@ -31,7 +31,7 @@ let CodePathSegment = require("./code-path-segment"), */ function addToReturnedOrThrown(dest, others, all, segments) { for (let i = 0; i < segments.length; ++i) { - let segment = segments[i]; + const segment = segments[i]; dest.push(segment); if (others.indexOf(segment) === -1) { @@ -150,8 +150,8 @@ function remove(xs, x) { */ function removeConnection(prevSegments, nextSegments) { for (let i = 0; i < prevSegments.length; ++i) { - let prevSegment = prevSegments[i]; - let nextSegment = nextSegments[i]; + const prevSegment = prevSegments[i]; + const nextSegment = nextSegments[i]; remove(prevSegment.nextSegments, nextSegment); remove(prevSegment.allNextSegments, nextSegment); @@ -169,11 +169,11 @@ function removeConnection(prevSegments, nextSegments) { * @returns {void} */ function makeLooped(state, fromSegments, toSegments) { - let end = Math.min(fromSegments.length, toSegments.length); + const end = Math.min(fromSegments.length, toSegments.length); for (let i = 0; i < end; ++i) { - let fromSegment = fromSegments[i]; - let toSegment = toSegments[i]; + const fromSegment = fromSegments[i]; + const toSegment = toSegments[i]; if (toSegment.reachable) { fromSegment.nextSegments.push(toSegment); @@ -241,9 +241,9 @@ function CodePathState(idGenerator, onLooped) { this.initialSegment = this.forkContext.head[0]; // returnedSegments and thrownSegments push elements into finalSegments also. - let final = this.finalSegments = []; - let returned = this.returnedForkContext = []; - let thrown = this.thrownForkContext = []; + const final = this.finalSegments = []; + const returned = this.returnedForkContext = []; + const thrown = this.thrownForkContext = []; returned.add = addToReturnedOrThrown.bind(null, returned, thrown, final); thrown.add = addToReturnedOrThrown.bind(null, thrown, returned, final); @@ -266,7 +266,7 @@ CodePathState.prototype = { * @type {ForkContext} */ get parentForkContext() { - let current = this.forkContext; + const current = this.forkContext; return current && current.upper; }, @@ -292,7 +292,7 @@ CodePathState.prototype = { * @returns {ForkContext} The last context. */ popForkContext: function() { - let lastContext = this.forkContext; + const lastContext = this.forkContext; this.forkContext = lastContext.upper; this.forkContext.replaceHead(lastContext.makeNext(0, -1)); @@ -370,12 +370,12 @@ CodePathState.prototype = { * @returns {ChoiceContext} The popped context. */ popChoiceContext: function() { - let context = this.choiceContext; + const context = this.choiceContext; this.choiceContext = context.upper; - let forkContext = this.forkContext; - let headSegments = forkContext.head; + const forkContext = this.forkContext; + const headSegments = forkContext.head; switch (context.kind) { case "&&": @@ -396,7 +396,7 @@ CodePathState.prototype = { * test chunk. */ if (context.isForkingAsResult) { - let parentContext = this.choiceContext; + const parentContext = this.choiceContext; parentContext.trueForkContext.addAll(context.trueForkContext); parentContext.falseForkContext.addAll(context.falseForkContext); @@ -443,7 +443,7 @@ CodePathState.prototype = { } // Merges all paths. - let prevForkContext = context.trueForkContext; + const prevForkContext = context.trueForkContext; prevForkContext.addAll(context.falseForkContext); forkContext.replaceHead(prevForkContext.makeNext(0, -1)); @@ -458,8 +458,8 @@ CodePathState.prototype = { * @returns {void} */ makeLogicalRight: function() { - let context = this.choiceContext; - let forkContext = this.forkContext; + const context = this.choiceContext; + const forkContext = this.forkContext; if (context.processed) { @@ -467,7 +467,7 @@ CodePathState.prototype = { * This got segments already from the child choice context. * Creates the next path from own true/false fork context. */ - let prevForkContext = + const prevForkContext = context.kind === "&&" ? context.trueForkContext : /* kind === "||" */ context.falseForkContext; @@ -502,8 +502,8 @@ CodePathState.prototype = { * @returns {void} */ makeIfConsequent: function() { - let context = this.choiceContext; - let forkContext = this.forkContext; + const context = this.choiceContext; + const forkContext = this.forkContext; /* * If any result were not transferred from child contexts, @@ -529,8 +529,8 @@ CodePathState.prototype = { * @returns {void} */ makeIfAlternate: function() { - let context = this.choiceContext; - let forkContext = this.forkContext; + const context = this.choiceContext; + const forkContext = this.forkContext; /* * The head segments are the path of the `if` block. @@ -583,12 +583,12 @@ CodePathState.prototype = { * @returns {void} */ popSwitchContext: function() { - let context = this.switchContext; + const context = this.switchContext; this.switchContext = context.upper; - let forkContext = this.forkContext; - let brokenForkContext = this.popBreakContext().brokenForkContext; + const forkContext = this.forkContext; + const brokenForkContext = this.popBreakContext().brokenForkContext; if (context.countForks === 0) { @@ -605,10 +605,10 @@ CodePathState.prototype = { return; } - let lastSegments = forkContext.head; + const lastSegments = forkContext.head; this.forkBypassPath(); - let lastCaseSegments = forkContext.head; + const lastCaseSegments = forkContext.head; /* * `brokenForkContext` is used to make the next segment. @@ -659,7 +659,7 @@ CodePathState.prototype = { * @returns {void} */ makeSwitchCaseBody: function(isEmpty, isDefault) { - let context = this.switchContext; + const context = this.switchContext; if (!context.hasCase) { return; @@ -670,8 +670,8 @@ CodePathState.prototype = { * The parent fork context has two segments. * Those are from the current case and the body of the previous case. */ - let parentForkContext = this.forkContext; - let forkContext = this.pushForkContext(); + const parentForkContext = this.forkContext; + const forkContext = this.pushForkContext(); forkContext.add(parentForkContext.makeNext(0, -1)); @@ -731,7 +731,7 @@ CodePathState.prototype = { * @returns {void} */ popTryContext: function() { - let context = this.tryContext; + const context = this.tryContext; this.tryContext = context.upper; @@ -747,19 +747,19 @@ CodePathState.prototype = { * block. */ - let returned = context.returnedForkContext; - let thrown = context.thrownForkContext; + const returned = context.returnedForkContext; + const thrown = context.thrownForkContext; if (returned.empty && thrown.empty) { return; } // Separate head to normal paths and leaving paths. - let headSegments = this.forkContext.head; + const headSegments = this.forkContext.head; this.forkContext = this.forkContext.upper; - let normalSegments = headSegments.slice(0, headSegments.length / 2 | 0); - let leavingSegments = headSegments.slice(headSegments.length / 2 | 0); + const normalSegments = headSegments.slice(0, headSegments.length / 2 | 0); + const leavingSegments = headSegments.slice(headSegments.length / 2 | 0); // Forwards the leaving path to upper contexts. if (!returned.empty) { @@ -785,9 +785,9 @@ CodePathState.prototype = { * @returns {void} */ makeCatchBlock: function() { - let context = this.tryContext; - let forkContext = this.forkContext; - let thrown = context.thrownForkContext; + const context = this.tryContext; + const forkContext = this.forkContext; + const thrown = context.thrownForkContext; // Update state. context.position = "catch"; @@ -796,7 +796,7 @@ CodePathState.prototype = { // Merge thrown paths. thrown.add(forkContext.head); - let thrownSegments = thrown.makeNext(0, -1); + const thrownSegments = thrown.makeNext(0, -1); // Fork to a bypass and the merged thrown path. this.pushForkContext(); @@ -814,11 +814,11 @@ CodePathState.prototype = { * @returns {void} */ makeFinallyBlock: function() { - let context = this.tryContext; + const context = this.tryContext; let forkContext = this.forkContext; - let returned = context.returnedForkContext; - let thrown = context.thrownForkContext; - let headOfLeavingSegments = forkContext.head; + const returned = context.returnedForkContext; + const thrown = context.thrownForkContext; + const headOfLeavingSegments = forkContext.head; // Update state. if (context.position === "catch") { @@ -843,11 +843,11 @@ CodePathState.prototype = { * Create a parallel segment from merging returned and thrown. * This segment will leave at the end of this finally block. */ - let segments = forkContext.makeNext(-1, -1); + const segments = forkContext.makeNext(-1, -1); let j; for (let i = 0; i < forkContext.count; ++i) { - let prevSegsOfLeavingSegment = [headOfLeavingSegments[i]]; + const prevSegsOfLeavingSegment = [headOfLeavingSegments[i]]; for (j = 0; j < returned.segmentsList.length; ++j) { prevSegsOfLeavingSegment.push(returned.segmentsList[j][i]); @@ -872,13 +872,13 @@ CodePathState.prototype = { * @returns {void} */ makeFirstThrowablePathInTryBlock: function() { - let forkContext = this.forkContext; + const forkContext = this.forkContext; if (!forkContext.reachable) { return; } - let context = getThrowContext(this); + const context = getThrowContext(this); if (context === this || context.position !== "try" || @@ -905,8 +905,8 @@ CodePathState.prototype = { * @returns {void} */ pushLoopContext: function(type, label) { - let forkContext = this.forkContext; - let breakContext = this.pushBreakContext(true, label); + const forkContext = this.forkContext; + const breakContext = this.pushBreakContext(true, label); switch (type) { case "WhileStatement": @@ -977,12 +977,12 @@ CodePathState.prototype = { * @returns {void} */ popLoopContext: function() { - let context = this.loopContext; + const context = this.loopContext; this.loopContext = context.upper; - let forkContext = this.forkContext; - let brokenForkContext = this.popBreakContext().brokenForkContext; + const forkContext = this.forkContext; + const brokenForkContext = this.popBreakContext().brokenForkContext; let choiceContext; // Creates a looped path. @@ -1048,9 +1048,9 @@ CodePathState.prototype = { * @returns {void} */ makeWhileTest: function(test) { - let context = this.loopContext; - let forkContext = this.forkContext; - let testSegments = forkContext.makeNext(0, -1); + const context = this.loopContext; + const forkContext = this.forkContext; + const testSegments = forkContext.makeNext(0, -1); // Update state. context.test = test; @@ -1064,9 +1064,9 @@ CodePathState.prototype = { * @returns {void} */ makeWhileBody: function() { - let context = this.loopContext; - let choiceContext = this.choiceContext; - let forkContext = this.forkContext; + const context = this.loopContext; + const choiceContext = this.choiceContext; + const forkContext = this.forkContext; if (!choiceContext.processed) { choiceContext.trueForkContext.add(forkContext.head); @@ -1086,9 +1086,9 @@ CodePathState.prototype = { * @returns {void} */ makeDoWhileBody: function() { - let context = this.loopContext; - let forkContext = this.forkContext; - let bodySegments = forkContext.makeNext(-1, -1); + const context = this.loopContext; + const forkContext = this.forkContext; + const bodySegments = forkContext.makeNext(-1, -1); // Update state. context.entrySegments = bodySegments; @@ -1102,15 +1102,15 @@ CodePathState.prototype = { * @returns {void} */ makeDoWhileTest: function(test) { - let context = this.loopContext; - let forkContext = this.forkContext; + const context = this.loopContext; + const forkContext = this.forkContext; context.test = test; // Creates paths of `continue` statements. if (!context.continueForkContext.empty) { context.continueForkContext.add(forkContext.head); - let testSegments = context.continueForkContext.makeNext(0, -1); + const testSegments = context.continueForkContext.makeNext(0, -1); forkContext.replaceHead(testSegments); } @@ -1123,10 +1123,10 @@ CodePathState.prototype = { * @returns {void} */ makeForTest: function(test) { - let context = this.loopContext; - let forkContext = this.forkContext; - let endOfInitSegments = forkContext.head; - let testSegments = forkContext.makeNext(-1, -1); + const context = this.loopContext; + const forkContext = this.forkContext; + const endOfInitSegments = forkContext.head; + const testSegments = forkContext.makeNext(-1, -1); // Update state. context.test = test; @@ -1141,9 +1141,9 @@ CodePathState.prototype = { * @returns {void} */ makeForUpdate: function() { - let context = this.loopContext; - let choiceContext = this.choiceContext; - let forkContext = this.forkContext; + const context = this.loopContext; + const choiceContext = this.choiceContext; + const forkContext = this.forkContext; // Make the next paths of the test. if (context.testSegments) { @@ -1156,7 +1156,7 @@ CodePathState.prototype = { } // Update state. - let updateSegments = forkContext.makeDisconnected(-1, -1); + const updateSegments = forkContext.makeDisconnected(-1, -1); context.continueDestSegments = context.updateSegments = updateSegments; forkContext.replaceHead(updateSegments); @@ -1168,9 +1168,9 @@ CodePathState.prototype = { * @returns {void} */ makeForBody: function() { - let context = this.loopContext; - let choiceContext = this.choiceContext; - let forkContext = this.forkContext; + const context = this.loopContext; + const choiceContext = this.choiceContext; + const forkContext = this.forkContext; // Update state. if (context.updateSegments) { @@ -1200,7 +1200,7 @@ CodePathState.prototype = { * If there is not the `test` part, the `body` path comes from the * `init` part and the `update` part. */ - let prevForkContext = ForkContext.newEmpty(forkContext); + const prevForkContext = ForkContext.newEmpty(forkContext); prevForkContext.add(context.endOfInitSegments); if (context.endOfUpdateSegments) { @@ -1220,9 +1220,9 @@ CodePathState.prototype = { * @returns {void} */ makeForInOfLeft: function() { - let context = this.loopContext; - let forkContext = this.forkContext; - let leftSegments = forkContext.makeDisconnected(-1, -1); + const context = this.loopContext; + const forkContext = this.forkContext; + const leftSegments = forkContext.makeDisconnected(-1, -1); // Update state. context.prevSegments = forkContext.head; @@ -1237,12 +1237,12 @@ CodePathState.prototype = { * @returns {void} */ makeForInOfRight: function() { - let context = this.loopContext; - let forkContext = this.forkContext; - let temp = ForkContext.newEmpty(forkContext); + const context = this.loopContext; + const forkContext = this.forkContext; + const temp = ForkContext.newEmpty(forkContext); temp.add(context.prevSegments); - let rightSegments = temp.makeNext(-1, -1); + const rightSegments = temp.makeNext(-1, -1); // Update state. context.endOfLeftSegments = forkContext.head; @@ -1256,12 +1256,12 @@ CodePathState.prototype = { * @returns {void} */ makeForInOfBody: function() { - let context = this.loopContext; - let forkContext = this.forkContext; - let temp = ForkContext.newEmpty(forkContext); + const context = this.loopContext; + const forkContext = this.forkContext; + const temp = ForkContext.newEmpty(forkContext); temp.add(context.endOfLeftSegments); - let bodySegments = temp.makeNext(-1, -1); + const bodySegments = temp.makeNext(-1, -1); // Make a path: `right` -> `left`. makeLooped(this, forkContext.head, context.leftSegments); @@ -1299,14 +1299,14 @@ CodePathState.prototype = { * @returns {Object} The removed context. */ popBreakContext: function() { - let context = this.breakContext; - let forkContext = this.forkContext; + const context = this.breakContext; + const forkContext = this.forkContext; this.breakContext = context.upper; // Process this context here for other than switches and loops. if (!context.breakable) { - let brokenForkContext = context.brokenForkContext; + const brokenForkContext = context.brokenForkContext; if (!brokenForkContext.empty) { brokenForkContext.add(forkContext.head); @@ -1327,13 +1327,13 @@ CodePathState.prototype = { * @returns {void} */ makeBreak: function(label) { - let forkContext = this.forkContext; + const forkContext = this.forkContext; if (!forkContext.reachable) { return; } - let context = getBreakContext(this, label); + const context = getBreakContext(this, label); /* istanbul ignore else: foolproof (syntax error) */ if (context) { @@ -1353,13 +1353,13 @@ CodePathState.prototype = { * @returns {void} */ makeContinue: function(label) { - let forkContext = this.forkContext; + const forkContext = this.forkContext; if (!forkContext.reachable) { return; } - let context = getContinueContext(this, label); + const context = getContinueContext(this, label); /* istanbul ignore else: foolproof (syntax error) */ if (context) { @@ -1388,7 +1388,7 @@ CodePathState.prototype = { * @returns {void} */ makeReturn: function() { - let forkContext = this.forkContext; + const forkContext = this.forkContext; if (forkContext.reachable) { getReturnContext(this).returnedForkContext.add(forkContext.head); @@ -1405,7 +1405,7 @@ CodePathState.prototype = { * @returns {void} */ makeThrow: function() { - let forkContext = this.forkContext; + const forkContext = this.forkContext; if (forkContext.reachable) { getThrowContext(this).thrownForkContext.add(forkContext.head); @@ -1418,7 +1418,7 @@ CodePathState.prototype = { * @returns {void} */ makeFinal: function() { - let segments = this.currentSegments; + const segments = this.currentSegments; if (segments.length > 0 && segments[0].reachable) { this.returnedForkContext.add(segments); diff --git a/tools/eslint/lib/code-path-analysis/code-path.js b/tools/eslint/lib/code-path-analysis/code-path.js index 3fdc99afc3..cdafc89bbc 100644 --- a/tools/eslint/lib/code-path-analysis/code-path.js +++ b/tools/eslint/lib/code-path-analysis/code-path.js @@ -9,8 +9,8 @@ // Requirements //------------------------------------------------------------------------------ -let CodePathState = require("./code-path-state"); -let IdGenerator = require("./id-generator"); +const CodePathState = require("./code-path-state"); +const IdGenerator = require("./id-generator"); //------------------------------------------------------------------------------ // Public Interface @@ -130,18 +130,18 @@ CodePath.prototype = { } options = options || {}; - let startSegment = options.first || this.internal.initialSegment; - let lastSegment = options.last; + const startSegment = options.first || this.internal.initialSegment; + const lastSegment = options.last; let item = null; let index = 0; let end = 0; let segment = null; - let visited = Object.create(null); - let stack = [[startSegment, 0]]; + const visited = Object.create(null); + const stack = [[startSegment, 0]]; let skippedSegment = null; let broken = false; - let controller = { + const controller = { skip: function() { if (stack.length <= 1) { broken = true; diff --git a/tools/eslint/lib/code-path-analysis/debug-helpers.js b/tools/eslint/lib/code-path-analysis/debug-helpers.js index ea31a1a9d7..6c096867bf 100644 --- a/tools/eslint/lib/code-path-analysis/debug-helpers.js +++ b/tools/eslint/lib/code-path-analysis/debug-helpers.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let debug = require("debug")("eslint:code-path"); +const debug = require("debug")("eslint:code-path"); //------------------------------------------------------------------------------ // Helpers @@ -55,7 +55,7 @@ module.exports = { */ dumpState: !debug.enabled ? debug : /* istanbul ignore next */ function(node, state, leaving) { for (let i = 0; i < state.currentSegments.length; ++i) { - let segInternal = state.currentSegments[i].internal; + const segInternal = state.currentSegments[i].internal; if (leaving) { segInternal.exitNodes.push(node); @@ -93,11 +93,11 @@ module.exports = { text += "thrown[label=\"ā\",shape=circle,width=0.3,height=0.3,fixedsize];\n"; } - let traceMap = Object.create(null); - let arrows = this.makeDotArrows(codePath, traceMap); + const traceMap = Object.create(null); + const arrows = this.makeDotArrows(codePath, traceMap); - for (let id in traceMap) { // eslint-disable-line guard-for-in - let segment = traceMap[id]; + for (const id in traceMap) { // eslint-disable-line guard-for-in + const segment = traceMap[id]; text += id + "["; @@ -144,22 +144,22 @@ module.exports = { * @returns {string} A DOT code of the code path. */ makeDotArrows: function(codePath, traceMap) { - let stack = [[codePath.initialSegment, 0]]; - let done = traceMap || Object.create(null); + const stack = [[codePath.initialSegment, 0]]; + const done = traceMap || Object.create(null); let lastId = codePath.initialSegment.id; let text = "initial->" + codePath.initialSegment.id; while (stack.length > 0) { - let item = stack.pop(); - let segment = item[0]; - let index = item[1]; + const item = stack.pop(); + const segment = item[0]; + const index = item[1]; if (done[segment.id] && index === 0) { continue; } done[segment.id] = segment; - let nextSegment = segment.allNextSegments[index]; + const nextSegment = segment.allNextSegments[index]; if (!nextSegment) { continue; diff --git a/tools/eslint/lib/code-path-analysis/fork-context.js b/tools/eslint/lib/code-path-analysis/fork-context.js index 93e59e7a02..d728f11cbe 100644 --- a/tools/eslint/lib/code-path-analysis/fork-context.js +++ b/tools/eslint/lib/code-path-analysis/fork-context.js @@ -13,7 +13,7 @@ // Requirements //------------------------------------------------------------------------------ -let assert = require("assert"), +const assert = require("assert"), CodePathSegment = require("./code-path-segment"); //------------------------------------------------------------------------------ @@ -44,7 +44,7 @@ function isReachable(segment) { * @returns {CodePathSegment[]} New segments. */ function makeSegments(context, begin, end, create) { - let list = context.segmentsList; + const list = context.segmentsList; if (begin < 0) { begin = list.length + begin; @@ -53,10 +53,10 @@ function makeSegments(context, begin, end, create) { end = list.length + end; } - let segments = []; + const segments = []; for (let i = 0; i < context.count; ++i) { - let allPrevSegments = []; + const allPrevSegments = []; for (let j = begin; j <= end; ++j) { allPrevSegments.push(list[j][i]); @@ -80,7 +80,7 @@ function makeSegments(context, begin, end, create) { */ function mergeExtraSegments(context, segments) { while (segments.length > context.count) { - let merged = []; + const merged = []; for (let i = 0, length = segments.length / 2 | 0; i < length; ++i) { merged.push(CodePathSegment.newNext( @@ -120,7 +120,7 @@ ForkContext.prototype = { * @type {CodePathSegment[]} */ get head() { - let list = this.segmentsList; + const list = this.segmentsList; return list.length === 0 ? [] : list[list.length - 1]; }, @@ -138,7 +138,7 @@ ForkContext.prototype = { * @type {boolean} */ get reachable() { - let segments = this.head; + const segments = this.head; return segments.length > 0 && segments.some(isReachable); }, @@ -214,7 +214,7 @@ ForkContext.prototype = { addAll: function(context) { assert(context.count === this.count); - let source = context.segmentsList; + const source = context.segmentsList; for (let i = 0; i < source.length; ++i) { this.segmentsList.push(source[i]); @@ -238,7 +238,7 @@ ForkContext.prototype = { * @returns {ForkContext} New fork context. */ ForkContext.newRoot = function(idGenerator) { - let context = new ForkContext(idGenerator, null, 1); + const context = new ForkContext(idGenerator, null, 1); context.add([CodePathSegment.newRoot(idGenerator.next())]); diff --git a/tools/eslint/lib/config.js b/tools/eslint/lib/config.js index 8c8533a228..88c96ec3d4 100644 --- a/tools/eslint/lib/config.js +++ b/tools/eslint/lib/config.js @@ -9,28 +9,27 @@ // Requirements //------------------------------------------------------------------------------ -let path = require("path"), +const path = require("path"), ConfigOps = require("./config/config-ops"), ConfigFile = require("./config/config-file"), Plugins = require("./config/plugins"), FileFinder = require("./file-finder"), - debug = require("debug"), userHome = require("user-home"), isResolvable = require("is-resolvable"), pathIsInside = require("path-is-inside"); +const debug = require("debug")("eslint:config"); + //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -let PERSONAL_CONFIG_DIR = userHome || null; +const PERSONAL_CONFIG_DIR = userHome || null; //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -debug = debug("eslint:config"); - /** * Check if item is an javascript object * @param {*} item object to check for @@ -75,11 +74,10 @@ function loadConfig(configToLoad) { * @private */ function getPersonalConfig() { - let config, - filename; + let config; if (PERSONAL_CONFIG_DIR) { - filename = ConfigFile.getFilenameForDirectory(PERSONAL_CONFIG_DIR); + const filename = ConfigFile.getFilenameForDirectory(PERSONAL_CONFIG_DIR); if (filename) { debug("Using personal config"); @@ -106,20 +104,16 @@ function hasRules(options) { * @returns {Object} The local config object, or an empty object if there is no local config. */ function getLocalConfig(thisConfig, directory) { + const localConfigFiles = thisConfig.findLocalConfigFiles(directory), + numFiles = localConfigFiles.length, + projectConfigPath = ConfigFile.getFilenameForDirectory(thisConfig.options.cwd); let found, - i, - localConfig, - localConfigFile, config = {}, - localConfigFiles = thisConfig.findLocalConfigFiles(directory), - numFiles = localConfigFiles.length, - rootPath, - projectConfigPath = ConfigFile.getFilenameForDirectory(thisConfig.options.cwd), - personalConfig; + rootPath; - for (i = 0; i < numFiles; i++) { + for (let i = 0; i < numFiles; i++) { - localConfigFile = localConfigFiles[i]; + const localConfigFile = localConfigFiles[i]; // Don't consider the personal config file in the home directory, // except if the home directory is the same as the current working directory @@ -133,7 +127,7 @@ function getLocalConfig(thisConfig, directory) { } debug("Loading " + localConfigFile); - localConfig = loadConfig(localConfigFile); + const localConfig = loadConfig(localConfigFile); // Don't consider a local config file found if the config is null if (!localConfig) { @@ -158,14 +152,14 @@ function getLocalConfig(thisConfig, directory) { * - Otherwise, if no rules were manually passed in, throw and error. * - Note: This function is not called if useEslintrc is false. */ - personalConfig = getPersonalConfig(); + const personalConfig = getPersonalConfig(); if (personalConfig) { config = ConfigOps.merge(config, personalConfig); } else if (!hasRules(thisConfig.options) && !thisConfig.options.baseConfig) { // No config file, no manual configuration, and no rules, so error. - let noConfigError = new Error("No ESLint configuration found."); + const noConfigError = new Error("No ESLint configuration found."); noConfigError.messageTemplate = "no-config-found"; noConfigError.messageData = { @@ -191,8 +185,6 @@ function getLocalConfig(thisConfig, directory) { * @param {Object} options Options to be passed in */ function Config(options) { - let useConfig; - options = options || {}; this.ignore = options.ignore; @@ -217,14 +209,15 @@ function Config(options) { * If user declares "foo", convert to "foo:false". */ this.globals = (options.globals || []).reduce(function(globals, def) { - let parts = def.split(":"); + const parts = def.split(":"); globals[parts[0]] = (parts.length > 1 && parts[1] === "true"); return globals; }, {}); - useConfig = options.configFile; + const useConfig = options.configFile; + this.options = options; if (useConfig) { @@ -244,9 +237,9 @@ function Config(options) { * @returns {Object} config object */ Config.prototype.getConfig = function(filePath) { + const directory = filePath ? path.dirname(filePath) : this.options.cwd; let config, - userConfig, - directory = filePath ? path.dirname(filePath) : this.options.cwd; + userConfig; debug("Constructing config for " + (filePath ? filePath : "text")); diff --git a/tools/eslint/lib/config/autoconfig.js b/tools/eslint/lib/config/autoconfig.js index 2cd753e95d..d8f29d5a0d 100644 --- a/tools/eslint/lib/config/autoconfig.js +++ b/tools/eslint/lib/config/autoconfig.js @@ -9,26 +9,25 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), - debug = require("debug"), +const lodash = require("lodash"), eslint = require("../eslint"), configRule = require("./config-rule"), ConfigOps = require("./config-ops"), recConfig = require("../../conf/eslint.json"); +const debug = require("debug")("eslint:autoconfig"); + //------------------------------------------------------------------------------ // Data //------------------------------------------------------------------------------ -let MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only +const MAX_CONFIG_COMBINATIONS = 17, // 16 combinations + 1 for severity only RECOMMENDED_CONFIG_NAME = "eslint:recommended"; //------------------------------------------------------------------------------ // Private //------------------------------------------------------------------------------ -debug = debug("eslint:autoconfig"); - /** * Information about a rule configuration, in the context of a Registry. * @@ -89,7 +88,7 @@ Registry.prototype = { * @returns {void} */ populateFromCoreRules: function() { - let rulesConfig = configRule.createCoreRuleConfigs(); + const rulesConfig = configRule.createCoreRuleConfigs(); this.rules = makeRegistryItems(rulesConfig); }, @@ -109,8 +108,8 @@ Registry.prototype = { * @returns {Object[]} "rules" configurations to use for linting */ buildRuleSets: function() { - let idx = 0, - ruleIds = Object.keys(this.rules), + let idx = 0; + const ruleIds = Object.keys(this.rules), ruleSets = []; /** @@ -122,7 +121,7 @@ Registry.prototype = { * @param {string} rule The ruleId to add. * @returns {void} */ - let addRuleToRuleSet = function(rule) { + const addRuleToRuleSet = function(rule) { /* * This check ensures that there is a rule configuration and that @@ -130,7 +129,7 @@ Registry.prototype = { * If it has too many configs, we will only use the most basic of * the possible configurations. */ - let hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS); + const hasFewCombos = (this.rules[rule].length <= MAX_CONFIG_COMBINATIONS); if (this.rules[rule][idx] && (hasFewCombos || this.rules[rule][idx].specificity <= 2)) { @@ -170,12 +169,12 @@ Registry.prototype = { * @returns {void} */ stripFailingConfigs: function() { - let ruleIds = Object.keys(this.rules), + const ruleIds = Object.keys(this.rules), newRegistry = new Registry(); - newRegistry.rules = lodash.assign({}, this.rules); + newRegistry.rules = Object.assign({}, this.rules); ruleIds.forEach(function(ruleId) { - let errorFreeItems = newRegistry.rules[ruleId].filter(function(registryItem) { + const errorFreeItems = newRegistry.rules[ruleId].filter(function(registryItem) { return (registryItem.errorCount === 0); }); @@ -195,10 +194,10 @@ Registry.prototype = { * @returns {void} */ stripExtraConfigs: function() { - let ruleIds = Object.keys(this.rules), + const ruleIds = Object.keys(this.rules), newRegistry = new Registry(); - newRegistry.rules = lodash.assign({}, this.rules); + newRegistry.rules = Object.assign({}, this.rules); ruleIds.forEach(function(ruleId) { newRegistry.rules[ruleId] = newRegistry.rules[ruleId].filter(function(registryItem) { return (typeof registryItem.errorCount !== "undefined"); @@ -216,11 +215,11 @@ Registry.prototype = { * @returns {Registry} A registry of failing rules. */ getFailingRulesRegistry: function() { - let ruleIds = Object.keys(this.rules), + const ruleIds = Object.keys(this.rules), failingRegistry = new Registry(); ruleIds.forEach(function(ruleId) { - let failingConfigs = this.rules[ruleId].filter(function(registryItem) { + const failingConfigs = this.rules[ruleId].filter(function(registryItem) { return (registryItem.errorCount > 0); }); @@ -239,7 +238,7 @@ Registry.prototype = { * @returns {Object} An eslint config with rules section populated */ createConfig: function() { - let ruleIds = Object.keys(this.rules), + const ruleIds = Object.keys(this.rules), config = {rules: {}}; ruleIds.forEach(function(ruleId) { @@ -258,10 +257,10 @@ Registry.prototype = { * @returns {Registry} A registry of rules */ filterBySpecificity: function(specificity) { - let ruleIds = Object.keys(this.rules), + const ruleIds = Object.keys(this.rules), newRegistry = new Registry(); - newRegistry.rules = lodash.assign({}, this.rules); + newRegistry.rules = Object.assign({}, this.rules); ruleIds.forEach(function(ruleId) { newRegistry.rules[ruleId] = this.rules[ruleId].filter(function(registryItem) { return (registryItem.specificity === specificity); @@ -280,25 +279,20 @@ Registry.prototype = { * @returns {Registry} New registry with errorCount populated */ lintSourceCode: function(sourceCodes, config, cb) { - let totalFilesLinting, - lintConfig, - ruleSets, - ruleSetIdx, - filenames, + let ruleSetIdx, lintedRegistry; lintedRegistry = new Registry(); - lintedRegistry.rules = lodash.assign({}, this.rules); + lintedRegistry.rules = Object.assign({}, this.rules); - ruleSets = lintedRegistry.buildRuleSets(); + const ruleSets = lintedRegistry.buildRuleSets(); lintedRegistry = lintedRegistry.stripExtraConfigs(); debug("Linting with all possible rule combinations"); - filenames = Object.keys(sourceCodes); - - totalFilesLinting = filenames.length * ruleSets.length; + const filenames = Object.keys(sourceCodes); + const totalFilesLinting = filenames.length * ruleSets.length; filenames.forEach(function(filename) { debug("Linting file: " + filename); @@ -306,8 +300,8 @@ Registry.prototype = { ruleSetIdx = 0; ruleSets.forEach(function(ruleSet) { - lintConfig = lodash.assign({}, config, {rules: ruleSet}); - let lintResults = eslint.verify(sourceCodes[filename], lintConfig); + const lintConfig = Object.assign({}, config, {rules: ruleSet}); + const lintResults = eslint.verify(sourceCodes[filename], lintConfig); lintResults.forEach(function(result) { @@ -344,11 +338,11 @@ Registry.prototype = { * @returns {Object} config object using `"extends": "eslint:recommended"` */ function extendFromRecommended(config) { - let newConfig = lodash.assign({}, config); + const newConfig = Object.assign({}, config); ConfigOps.normalizeToStrings(newConfig); - let recRules = Object.keys(recConfig.rules).filter(function(ruleId) { + const recRules = Object.keys(recConfig.rules).filter(function(ruleId) { return ConfigOps.isErrorSeverity(recConfig.rules[ruleId]); }); diff --git a/tools/eslint/lib/config/config-file.js b/tools/eslint/lib/config/config-file.js index 9120c12f3c..ca46575120 100644 --- a/tools/eslint/lib/config/config-file.js +++ b/tools/eslint/lib/config/config-file.js @@ -11,9 +11,9 @@ // Requirements //------------------------------------------------------------------------------ -let debug = require("debug"), - fs = require("fs"), +const fs = require("fs"), path = require("path"), + shell = require("shelljs"), ConfigOps = require("./config-ops"), validator = require("./config-validator"), Plugins = require("./plugins"), @@ -26,6 +26,7 @@ let debug = require("debug"), defaultOptions = require("../../conf/eslint.json"), requireUncached = require("require-uncached"); +const debug = require("debug")("eslint:config-file"); //------------------------------------------------------------------------------ // Helpers @@ -48,7 +49,7 @@ function sortByKey(a, b) { // Private //------------------------------------------------------------------------------ -let CONFIG_FILES = [ +const CONFIG_FILES = [ ".eslintrc.js", ".eslintrc.yaml", ".eslintrc.yml", @@ -57,9 +58,7 @@ let CONFIG_FILES = [ "package.json" ]; -let resolver = new ModuleResolver(); - -debug = debug("eslint:config-file"); +const resolver = new ModuleResolver(); /** * Convenience wrapper for synchronously reading file contents. @@ -94,7 +93,7 @@ function loadYAMLConfigFile(filePath) { debug("Loading YAML config file: " + filePath); // lazy load YAML to improve performance when not used - let yaml = require("js-yaml"); + const yaml = require("js-yaml"); try { @@ -137,7 +136,7 @@ function loadLegacyConfigFile(filePath) { debug("Loading config file: " + filePath); // lazy load YAML to improve performance when not used - let yaml = require("js-yaml"); + const yaml = require("js-yaml"); try { return yaml.safeLoad(stripComments(readFile(filePath))) || /* istanbul ignore next */ {}; @@ -192,8 +191,8 @@ function loadPackageJSONConfigFile(filePath) { * @private */ function loadConfigFile(file) { - let config, - filePath = file.filePath; + const filePath = file.filePath; + let config; switch (path.extname(filePath)) { case ".js": @@ -236,7 +235,7 @@ function loadConfigFile(file) { function writeJSONConfigFile(config, filePath) { debug("Writing JSON config file: " + filePath); - let content = stringify(config, {cmp: sortByKey, space: 4}); + const content = stringify(config, {cmp: sortByKey, space: 4}); fs.writeFileSync(filePath, content, "utf8"); } @@ -252,9 +251,9 @@ function writeYAMLConfigFile(config, filePath) { debug("Writing YAML config file: " + filePath); // lazy load YAML to improve performance when not used - let yaml = require("js-yaml"); + const yaml = require("js-yaml"); - let content = yaml.safeDump(config, {sortKeys: true}); + const content = yaml.safeDump(config, {sortKeys: true}); fs.writeFileSync(filePath, content, "utf8"); } @@ -269,7 +268,7 @@ function writeYAMLConfigFile(config, filePath) { function writeJSConfigFile(config, filePath) { debug("Writing JS config file: " + filePath); - let content = "module.exports = " + stringify(config, {cmp: sortByKey, space: 4}) + ";"; + const content = "module.exports = " + stringify(config, {cmp: sortByKey, space: 4}) + ";"; fs.writeFileSync(filePath, content, "utf8"); } @@ -313,7 +312,7 @@ function write(config, filePath) { function getBaseDir(configFilePath) { // calculates the path of the project including ESLint as dependency - let projectPath = path.resolve(__dirname, "../../../"); + const projectPath = path.resolve(__dirname, "../../../"); if (configFilePath && pathIsInside(configFilePath, projectPath)) { @@ -336,7 +335,7 @@ function getBaseDir(configFilePath) { * @private */ function getLookupPath(configFilePath) { - let basedir = getBaseDir(configFilePath); + const basedir = getBaseDir(configFilePath); return path.join(basedir, "node_modules"); } @@ -431,7 +430,7 @@ function normalizePackageName(name, prefix) { * it's a scoped package * package name is "eslint-config", or just a username */ - let scopedPackageShortcutRegex = new RegExp("^(@[^\/]+)(?:\/(?:" + prefix + ")?)?$"), + const scopedPackageShortcutRegex = new RegExp("^(@[^\/]+)(?:\/(?:" + prefix + ")?)?$"), scopedPackageNameRegex = new RegExp("^" + prefix + "(-|$)"); if (scopedPackageShortcutRegex.test(name)) { @@ -466,8 +465,8 @@ function resolve(filePath, relativeTo) { let normalizedPackageName; if (filePath.indexOf("plugin:") === 0) { - let packagePath = filePath.substr(7, filePath.lastIndexOf("/") - 7); - let configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1); + const packagePath = filePath.substr(7, filePath.lastIndexOf("/") - 7); + const configName = filePath.substr(filePath.lastIndexOf("/") + 1, filePath.length - filePath.lastIndexOf("/") - 1); normalizedPackageName = normalizePackageName(packagePath, "eslint-plugin"); debug("Attempting to resolve " + normalizedPackageName); @@ -493,10 +492,10 @@ function resolve(filePath, relativeTo) { * @private */ function load(filePath, applyEnvironments, relativeTo) { - let resolvedPath = resolve(filePath, relativeTo), + const resolvedPath = resolve(filePath, relativeTo), dirname = path.dirname(resolvedPath.filePath), - lookupPath = getLookupPath(dirname), - config = loadConfigFile(resolvedPath); + lookupPath = getLookupPath(dirname); + let config = loadConfigFile(resolvedPath); if (config) { @@ -564,12 +563,10 @@ module.exports = { * or null if there is no configuration file in the directory. */ getFilenameForDirectory: function(directory) { - - let filename; - for (let i = 0, len = CONFIG_FILES.length; i < len; i++) { - filename = path.join(directory, CONFIG_FILES[i]); - if (fs.existsSync(filename)) { + const filename = path.join(directory, CONFIG_FILES[i]); + + if (shell.test("-f", filename)) { return filename; } } diff --git a/tools/eslint/lib/config/config-initializer.js b/tools/eslint/lib/config/config-initializer.js index ca52a06c65..36b641147e 100644 --- a/tools/eslint/lib/config/config-initializer.js +++ b/tools/eslint/lib/config/config-initializer.js @@ -9,9 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let util = require("util"), - debug = require("debug"), - lodash = require("lodash"), +const util = require("util"), inquirer = require("inquirer"), ProgressBar = require("progress"), autoconfig = require("./autoconfig.js"), @@ -22,7 +20,7 @@ let util = require("util"), recConfig = require("../../conf/eslint.json"), log = require("../logging"); -debug = debug("eslint:config-initializer"); +const debug = require("debug")("eslint:config-initializer"); //------------------------------------------------------------------------------ // Private @@ -60,9 +58,7 @@ function writeFile(config, format) { * @returns {void} */ function installModules(config) { - let modules = [], - installStatus, - modulesToInstall; + let modules = []; // Create a list of modules which should be installed based on config if (config.plugins) { @@ -82,11 +78,11 @@ function installModules(config) { // Add eslint to list in case user does not have it installed locally modules.unshift("eslint"); - installStatus = npmUtil.checkDevDeps(modules); + const installStatus = npmUtil.checkDevDeps(modules); // Install packages which aren't already installed - modulesToInstall = Object.keys(installStatus).filter(function(module) { - let notInstalled = installStatus[module] === false; + const modulesToInstall = Object.keys(installStatus).filter(function(module) { + const notInstalled = installStatus[module] === false; if (module === "eslint" && notInstalled) { log.info("Local ESLint installation not found."); @@ -113,31 +109,24 @@ function installModules(config) { * @returns {Object} config object with configured rules */ function configureRules(answers, config) { - let BAR_TOTAL = 20, - BAR_SOURCE_CODE_TOTAL = 4; - - let newConfig = lodash.assign({}, config), - bar, - patterns, - sourceCodes, - fileQty, - registry, - failingRegistry, - disabledConfigs = {}, - singleConfigs, - specTwoConfigs, - specThreeConfigs, - defaultConfigs; + const BAR_TOTAL = 20, + BAR_SOURCE_CODE_TOTAL = 4, + newConfig = Object.assign({}, config), + disabledConfigs = {}; + let sourceCodes, + registry; // Set up a progress bar, as this process can take a long time - bar = new ProgressBar("Determining Config: :percent [:bar] :elapseds elapsed, eta :etas ", { + const bar = new ProgressBar("Determining Config: :percent [:bar] :elapseds elapsed, eta :etas ", { width: 30, total: BAR_TOTAL }); + bar.tick(0); // Shows the progress bar // Get the SourceCode of all chosen files - patterns = answers.patterns.split(/[\s]+/); + const patterns = answers.patterns.split(/[\s]+/); + try { sourceCodes = getSourceCodeOfFiles(patterns, { baseConfig: newConfig, useEslintrc: false }, function(total) { bar.tick((BAR_SOURCE_CODE_TOTAL / total)); @@ -146,7 +135,8 @@ function configureRules(answers, config) { log.info("\n"); throw e; } - fileQty = Object.keys(sourceCodes).length; + const fileQty = Object.keys(sourceCodes).length; + if (fileQty === 0) { log.info("\n"); throw new Error("Automatic Configuration failed. No files were able to be parsed."); @@ -163,12 +153,12 @@ function configureRules(answers, config) { debug("\nRegistry: " + util.inspect(registry.rules, {depth: null})); // Create a list of recommended rules, because we don't want to disable them - let recRules = Object.keys(recConfig.rules).filter(function(ruleId) { + const recRules = Object.keys(recConfig.rules).filter(function(ruleId) { return ConfigOps.isErrorSeverity(recConfig.rules[ruleId]); }); // Find and disable rules which had no error-free configuration - failingRegistry = registry.getFailingRulesRegistry(); + const failingRegistry = registry.getFailingRulesRegistry(); Object.keys(failingRegistry.rules).forEach(function(ruleId) { @@ -181,33 +171,33 @@ function configureRules(answers, config) { // If there is only one config that results in no errors for a rule, we should use it. // createConfig will only add rules that have one configuration in the registry. - singleConfigs = registry.createConfig().rules; + const singleConfigs = registry.createConfig().rules; // The "sweet spot" for number of options in a config seems to be two (severity plus one option). // Very often, a third option (usually an object) is available to address // edge cases, exceptions, or unique situations. We will prefer to use a config with // specificity of two. - specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules; + const specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules; // Maybe a specific combination using all three options works - specThreeConfigs = registry.filterBySpecificity(3).createConfig().rules; + const specThreeConfigs = registry.filterBySpecificity(3).createConfig().rules; // If all else fails, try to use the default (severity only) - defaultConfigs = registry.filterBySpecificity(1).createConfig().rules; + const defaultConfigs = registry.filterBySpecificity(1).createConfig().rules; // Combine configs in reverse priority order (later take precedence) - newConfig.rules = lodash.assign({}, disabledConfigs, defaultConfigs, specThreeConfigs, specTwoConfigs, singleConfigs); + newConfig.rules = Object.assign({}, disabledConfigs, defaultConfigs, specThreeConfigs, specTwoConfigs, singleConfigs); // Make sure progress bar has finished (floating point rounding) bar.update(BAR_TOTAL); // Log out some stats to let the user know what happened - let finalRuleIds = Object.keys(newConfig.rules), - totalRules = finalRuleIds.length; - let enabledRules = finalRuleIds.filter(function(ruleId) { + const finalRuleIds = Object.keys(newConfig.rules); + const totalRules = finalRuleIds.length; + const enabledRules = finalRuleIds.filter(function(ruleId) { return (newConfig.rules[ruleId] !== 0); }).length; - let resultMessage = [ + const resultMessage = [ "\nEnabled " + enabledRules + " out of " + totalRules, "rules based on " + fileQty, "file" + ((fileQty === 1) ? "." : "s.") @@ -275,9 +265,9 @@ function processAnswers(answers) { * @returns {Object} config object */ function getConfigForStyleGuide(guide) { - let guides = { + const guides = { google: {extends: "google"}, - airbnb: {extends: "airbnb", plugins: ["react"]}, + airbnb: {extends: "airbnb", plugins: ["react", "jsx-a11y", "import"]}, standard: {extends: "standard", plugins: ["standard", "promise"]} }; @@ -419,7 +409,7 @@ function promptUser(callback) { // early exit if you are using automatic style generation if (earlyAnswers.source === "auto") { try { - let combinedAnswers = lodash.assign({}, earlyAnswers, secondAnswers); + const combinedAnswers = Object.assign({}, earlyAnswers, secondAnswers); config = processAnswers(combinedAnswers); installModules(config); @@ -469,7 +459,7 @@ function promptUser(callback) { } ], function(answers) { try { - let totalAnswers = lodash.assign({}, earlyAnswers, secondAnswers, answers); + const totalAnswers = Object.assign({}, earlyAnswers, secondAnswers, answers); config = processAnswers(totalAnswers); installModules(config); @@ -488,7 +478,7 @@ function promptUser(callback) { // Public Interface //------------------------------------------------------------------------------ -let init = { +const init = { getConfigForStyleGuide: getConfigForStyleGuide, processAnswers: processAnswers, initializeConfig: /* istanbul ignore next */ function(callback) { diff --git a/tools/eslint/lib/config/config-ops.js b/tools/eslint/lib/config/config-ops.js index 2e0c29a752..7a52f983f9 100644 --- a/tools/eslint/lib/config/config-ops.js +++ b/tools/eslint/lib/config/config-ops.js @@ -9,17 +9,15 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), - debug = require("debug"), - Environments = require("./environments"); +const Environments = require("./environments"); + +const debug = require("debug")("eslint:config-ops"); //------------------------------------------------------------------------------ // Private //------------------------------------------------------------------------------ -debug = debug("eslint:config-ops"); - -let RULE_SEVERITY_STRINGS = ["off", "warn", "error"], +const RULE_SEVERITY_STRINGS = ["off", "warn", "error"], RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce(function(map, value, index) { map[value] = index; return map; @@ -53,7 +51,7 @@ module.exports = { */ createEnvironmentConfig: function(env) { - let envConfig = this.createEmptyConfig(); + const envConfig = this.createEmptyConfig(); if (env) { @@ -62,16 +60,16 @@ module.exports = { Object.keys(env).filter(function(name) { return env[name]; }).forEach(function(name) { - let environment = Environments.get(name); + const environment = Environments.get(name); if (environment) { debug("Creating config for environment " + name); if (environment.globals) { - lodash.assign(envConfig.globals, environment.globals); + Object.assign(envConfig.globals, environment.globals); } if (environment.parserOptions) { - lodash.assign(envConfig.parserOptions, environment.parserOptions); + Object.assign(envConfig.parserOptions, environment.parserOptions); } } }); @@ -134,7 +132,7 @@ module.exports = { * (https://github.com/KyleAMathews/deepmerge) * and modified to meet our needs. */ - let array = Array.isArray(src) || Array.isArray(target); + const array = Array.isArray(src) || Array.isArray(target); let dst = array && [] || {}; combine = !!combine; @@ -202,7 +200,7 @@ module.exports = { if (config.rules) { Object.keys(config.rules).forEach(function(ruleId) { - let ruleConfig = config.rules[ruleId]; + const ruleConfig = config.rules[ruleId]; if (typeof ruleConfig === "string") { config.rules[ruleId] = RULE_SEVERITY[ruleConfig.toLowerCase()] || 0; @@ -224,7 +222,7 @@ module.exports = { if (config.rules) { Object.keys(config.rules).forEach(function(ruleId) { - let ruleConfig = config.rules[ruleId]; + const ruleConfig = config.rules[ruleId]; if (typeof ruleConfig === "number") { config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0]; diff --git a/tools/eslint/lib/config/config-rule.js b/tools/eslint/lib/config/config-rule.js index f4c2803ff7..ea8162d42d 100644 --- a/tools/eslint/lib/config/config-rule.js +++ b/tools/eslint/lib/config/config-rule.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let rules = require("../rules"), +const rules = require("../rules"), loadRules = require("../load-rules"); @@ -41,7 +41,7 @@ function explodeArray(xs) { * @returns {array} A mixture of the elements of the first and second arrays. */ function combineArrays(arr1, arr2) { - let res = []; + const res = []; if (arr1.length === 0) { return explodeArray(arr2); @@ -78,8 +78,8 @@ function combineArrays(arr1, arr2) { * @returns {Array[]} Array of arrays of objects grouped by property */ function groupByProperty(objects) { - let groupedObj = objects.reduce(function(accumulator, obj) { - let prop = Object.keys(obj)[0]; + const groupedObj = objects.reduce(function(accumulator, obj) { + const prop = Object.keys(obj)[0]; accumulator[prop] = accumulator[prop] ? accumulator[prop].concat(obj) : [obj]; return accumulator; @@ -144,7 +144,7 @@ function groupByProperty(objects) { * @returns {Object[]} Combined objects for each combination of input properties and values */ function combinePropertyObjects(objArr1, objArr2) { - let res = []; + const res = []; if (objArr1.length === 0) { return objArr2; @@ -154,9 +154,9 @@ function combinePropertyObjects(objArr1, objArr2) { } objArr1.forEach(function(obj1) { objArr2.forEach(function(obj2) { - let combinedObj = {}; - let obj1Props = Object.keys(obj1); - let obj2Props = Object.keys(obj2); + const combinedObj = {}; + const obj1Props = Object.keys(obj1); + const obj2Props = Object.keys(obj2); obj1Props.forEach(function(prop1) { combinedObj[prop1] = obj1[prop1]; @@ -229,13 +229,12 @@ RuleConfigSet.prototype = { * @returns {void} */ addObject: function(obj) { - let objectConfigSet = { + const objectConfigSet = { objectConfigs: [], add: function(property, values) { - let optionObj; - for (let idx = 0; idx < values.length; idx++) { - optionObj = {}; + const optionObj = {}; + optionObj[property] = values[idx]; this.objectConfigs.push(optionObj); } @@ -274,7 +273,7 @@ RuleConfigSet.prototype = { * @returns {array[]} Valid rule configurations */ function generateConfigsFromSchema(schema) { - let configSet = new RuleConfigSet(); + const configSet = new RuleConfigSet(); if (Array.isArray(schema)) { schema.forEach(function(opt) { @@ -301,11 +300,11 @@ function generateConfigsFromSchema(schema) { * @returns {rulesConfig} Hash of rule names and arrays of possible configurations */ function createCoreRuleConfigs() { - let ruleList = loadRules(); + const ruleList = loadRules(); return Object.keys(ruleList).reduce(function(accumulator, id) { - let rule = rules.get(id); - let schema = (typeof rule === "function") ? rule.schema : rule.meta.schema; + const rule = rules.get(id); + const schema = (typeof rule === "function") ? rule.schema : rule.meta.schema; accumulator[id] = generateConfigsFromSchema(schema); return accumulator; diff --git a/tools/eslint/lib/config/config-validator.js b/tools/eslint/lib/config/config-validator.js index 6695260a23..8bd1e28d82 100644 --- a/tools/eslint/lib/config/config-validator.js +++ b/tools/eslint/lib/config/config-validator.js @@ -9,12 +9,12 @@ // Requirements //------------------------------------------------------------------------------ -let rules = require("../rules"), +const rules = require("../rules"), Environments = require("./environments"), schemaValidator = require("is-my-json-valid"), util = require("util"); -let validators = { +const validators = { rules: Object.create(null) }; @@ -28,7 +28,7 @@ let validators = { * @returns {Object} JSON Schema for the rule's options. */ function getRuleOptionsSchema(id) { - let rule = rules.get(id), + const rule = rules.get(id), schema = rule && rule.schema || rule && rule.meta && rule.meta.schema; // Given a tuple of schemas, insert warning level at the beginning @@ -61,11 +61,10 @@ function getRuleOptionsSchema(id) { * @returns {void} */ function validateRuleOptions(id, options, source) { + const schema = getRuleOptionsSchema(id); let validateRule = validators.rules[id], - message, severity, localOptions, - schema = getRuleOptionsSchema(id), validSeverity = true; if (!validateRule && schema) { @@ -92,7 +91,7 @@ function validateRuleOptions(id, options, source) { } if ((validateRule && validateRule.errors) || !validSeverity) { - message = [ + const message = [ source, ":\n", "\tConfiguration for rule \"", id, "\" is invalid:\n" ]; @@ -137,7 +136,7 @@ function validateEnvironment(environment, source) { if (typeof environment === "object") { Object.keys(environment).forEach(function(env) { if (!Environments.get(env)) { - let message = [ + const message = [ source, ":\n", "\tEnvironment key \"", env, "\" is unknown\n" ]; diff --git a/tools/eslint/lib/config/environments.js b/tools/eslint/lib/config/environments.js index 9a5defbfc2..072d07b63c 100644 --- a/tools/eslint/lib/config/environments.js +++ b/tools/eslint/lib/config/environments.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let envs = require("../../conf/environments"); +const envs = require("../../conf/environments"); //------------------------------------------------------------------------------ // Private diff --git a/tools/eslint/lib/config/plugins.js b/tools/eslint/lib/config/plugins.js index 7065045c12..9b813f3c14 100644 --- a/tools/eslint/lib/config/plugins.js +++ b/tools/eslint/lib/config/plugins.js @@ -8,19 +8,18 @@ // Requirements //------------------------------------------------------------------------------ -let debug = require("debug"), - Environments = require("./environments"), +const Environments = require("./environments"), rules = require("../rules"); +const debug = require("debug")("eslint:plugins"); + //------------------------------------------------------------------------------ // Private //------------------------------------------------------------------------------ -debug = debug("eslint:plugins"); - let plugins = Object.create(null); -let PLUGIN_NAME_PREFIX = "eslint-plugin-", +const PLUGIN_NAME_PREFIX = "eslint-plugin-", NAMESPACE_REGEX = /^@.*\//i; /** @@ -67,7 +66,7 @@ module.exports = { * @returns {void} */ define: function(pluginName, plugin) { - let pluginNameWithoutNamespace = removeNamespace(pluginName), + const pluginNameWithoutNamespace = removeNamespace(pluginName), pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace); plugins[pluginNameWithoutPrefix] = plugin; @@ -104,10 +103,10 @@ module.exports = { * @throws {Error} If the plugin cannot be loaded. */ load: function(pluginName) { - let pluginNamespace = getNamespace(pluginName), + const pluginNamespace = getNamespace(pluginName), pluginNameWithoutNamespace = removeNamespace(pluginName), - pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace), - plugin = null; + pluginNameWithoutPrefix = removePrefix(pluginNameWithoutNamespace); + let plugin = null; if (!plugins[pluginNameWithoutPrefix]) { try { diff --git a/tools/eslint/lib/eslint.js b/tools/eslint/lib/eslint.js index 01b43eb4ee..87d02cc36e 100644..100755 --- a/tools/eslint/lib/eslint.js +++ b/tools/eslint/lib/eslint.js @@ -9,11 +9,10 @@ // Requirements //------------------------------------------------------------------------------ -let assert = require("assert"), +const assert = require("assert"), EventEmitter = require("events").EventEmitter, escope = require("escope"), levn = require("levn"), - lodash = require("lodash"), blankScriptAST = require("../conf/blank-script.json"), DEFAULT_PARSER = require("../conf/eslint.json").parser, replacements = require("../conf/replacements.json"), @@ -41,7 +40,7 @@ let assert = require("assert"), * @returns {Object} Result map object of names and boolean values */ function parseBooleanConfig(string, comment) { - let items = {}; + const items = {}; // Collapse whitespace around `:` and `,` to make parsing easier string = string.replace(/\s*([:,])\s*/g, "$1"); @@ -50,8 +49,8 @@ function parseBooleanConfig(string, comment) { if (!name) { return; } - let pos = name.indexOf(":"), - value; + const pos = name.indexOf(":"); + let value; if (pos !== -1) { value = name.substring(pos + 1, name.length); @@ -122,7 +121,7 @@ function parseJsonConfig(string, location, messages) { * @returns {Object} Result map of values and true values */ function parseListConfig(string) { - let items = {}; + const items = {}; // Collapse whitespace around , string = string.replace(/\s*,\s*/g, ","); @@ -147,27 +146,27 @@ function parseListConfig(string) { * @returns {void} */ function addDeclaredGlobals(program, globalScope, config) { - let declaredGlobals = {}, + const declaredGlobals = {}, exportedGlobals = {}, explicitGlobals = {}, builtin = Environments.get("builtin"); - lodash.assign(declaredGlobals, builtin); + Object.assign(declaredGlobals, builtin); Object.keys(config.env).forEach(function(name) { if (config.env[name]) { - let env = Environments.get(name), + const env = Environments.get(name), environmentGlobals = env && env.globals; if (environmentGlobals) { - lodash.assign(declaredGlobals, environmentGlobals); + Object.assign(declaredGlobals, environmentGlobals); } } }); - lodash.assign(exportedGlobals, config.exported); - lodash.assign(declaredGlobals, config.globals); - lodash.assign(explicitGlobals, config.astGlobals); + Object.assign(exportedGlobals, config.exported); + Object.assign(declaredGlobals, config.globals); + Object.assign(explicitGlobals, config.astGlobals); Object.keys(declaredGlobals).forEach(function(name) { let variable = globalScope.set.get(name); @@ -196,7 +195,7 @@ function addDeclaredGlobals(program, globalScope, config) { // mark all exported variables as such Object.keys(exportedGlobals).forEach(function(name) { - let variable = globalScope.set.get(name); + const variable = globalScope.set.get(name); if (variable) { variable.eslintUsed = true; @@ -209,8 +208,8 @@ function addDeclaredGlobals(program, globalScope, config) { * references and remove the ones that were added by configuration. */ globalScope.through = globalScope.through.filter(function(reference) { - let name = reference.identifier.name; - let variable = globalScope.set.get(name); + const name = reference.identifier.name; + const variable = globalScope.set.get(name); if (variable) { @@ -312,12 +311,12 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa rules: {}, env: {} }; - let commentRules = {}; + const commentRules = {}; ast.comments.forEach(function(comment) { let value = comment.value.trim(); - let match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value); + const match = /^(eslint(-\w+){0,3}|exported|globals?)(\s|$)/.exec(value); if (match) { value = value.substring(match.index + match[1].length); @@ -325,16 +324,16 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa if (comment.type === "Block") { switch (match[1]) { case "exported": - lodash.assign(commentConfig.exported, parseBooleanConfig(value, comment)); + Object.assign(commentConfig.exported, parseBooleanConfig(value, comment)); break; case "globals": case "global": - lodash.assign(commentConfig.astGlobals, parseBooleanConfig(value, comment)); + Object.assign(commentConfig.astGlobals, parseBooleanConfig(value, comment)); break; case "eslint-env": - lodash.assign(commentConfig.env, parseListConfig(value)); + Object.assign(commentConfig.env, parseListConfig(value)); break; case "eslint-disable": @@ -349,7 +348,7 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa const items = parseJsonConfig(value, comment.loc, messages); Object.keys(items).forEach(function(name) { - let ruleValue = items[name]; + const ruleValue = items[name]; validator.validateRuleOptions(name, ruleValue, filename + " line " + comment.loc.start.line); commentRules[name] = ruleValue; @@ -373,13 +372,13 @@ function modifyConfigsFromComments(filename, ast, config, reportingConfig, messa // apply environment configs Object.keys(commentConfig.env).forEach(function(name) { - let env = Environments.get(name); + const env = Environments.get(name); if (env) { commentConfig = ConfigOps.merge(commentConfig, env); } }); - lodash.assign(commentConfig.rules, commentRules); + Object.assign(commentConfig.rules, commentRules); return ConfigOps.merge(config, commentConfig); } @@ -395,7 +394,7 @@ function isDisabledByReportingConfig(reportingConfig, ruleId, location) { for (let i = 0, c = reportingConfig.length; i < c; i++) { - let ignore = reportingConfig[i]; + const ignore = reportingConfig[i]; if ((!ignore.rule || ignore.rule === ruleId) && (location.line > ignore.start.line || (location.line === ignore.start.line && location.column >= ignore.start.column)) && @@ -417,13 +416,12 @@ function prepareConfig(config) { config.globals = config.globals || config.global || {}; delete config.global; - let copiedRules = {}, - parserOptions = {}, - preparedConfig; + const copiedRules = {}; + let parserOptions = {}; if (typeof config.rules === "object") { Object.keys(config.rules).forEach(function(k) { - let rule = config.rules[k]; + const rule = config.rules[k]; if (rule === null) { throw new Error("Invalid config for rule '" + k + "'\."); @@ -439,7 +437,7 @@ function prepareConfig(config) { // merge in environment parserOptions if (typeof config.env === "object") { Object.keys(config.env).forEach(function(envName) { - let env = Environments.get(envName); + const env = Environments.get(envName); if (config.env[envName] && env && env.parserOptions) { parserOptions = ConfigOps.merge(parserOptions, env.parserOptions); @@ -447,7 +445,7 @@ function prepareConfig(config) { }); } - preparedConfig = { + const preparedConfig = { rules: copiedRules, parser: config.parser || DEFAULT_PARSER, globals: ConfigOps.merge({}, config.globals), @@ -507,7 +505,7 @@ function createStubRule(message) { */ function getRuleReplacementMessage(ruleId) { if (ruleId in replacements.rules) { - let newRules = replacements.rules[ruleId]; + const newRules = replacements.rules[ruleId]; return "Rule \'" + ruleId + "\' was removed and replaced by: " + newRules.join(", "); } @@ -515,7 +513,7 @@ function getRuleReplacementMessage(ruleId) { return null; } -let eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g; +const eslintEnvPattern = /\/\*\s*eslint-env\s(.+?)\*\//g; /** * Checks whether or not there is a comment which has "eslint-env *" in a given text. @@ -528,7 +526,7 @@ function findEslintEnv(text) { eslintEnvPattern.lastIndex = 0; while ((match = eslintEnvPattern.exec(text))) { - retv = lodash.assign(retv || {}, parseListConfig(match[1])); + retv = Object.assign(retv || {}, parseListConfig(match[1])); } return retv; @@ -563,8 +561,8 @@ function stripUnicodeBOM(text) { */ module.exports = (function() { - let api = Object.create(new EventEmitter()), - messages = [], + const api = Object.create(new EventEmitter()); + let messages = [], currentConfig = null, currentScopes = null, scopeMap = null, @@ -613,7 +611,7 @@ module.exports = (function() { // merge in any additional parser options if (config.parserOptions) { - parserOptions = lodash.assign({}, config.parserOptions, parserOptions); + parserOptions = Object.assign({}, config.parserOptions, parserOptions); } /* @@ -627,8 +625,8 @@ module.exports = (function() { } catch (ex) { // If the message includes a leading line number, strip it: - let message = ex.message.replace(/^line \d+:/i, "").trim(); - let source = (ex.lineNumber) ? SourceCode.splitLines(text)[ex.lineNumber - 1] : null; + const message = ex.message.replace(/^line \d+:/i, "").trim(); + const source = (ex.lineNumber) ? SourceCode.splitLines(text)[ex.lineNumber - 1] : null; messages.push({ ruleId: null, @@ -718,13 +716,10 @@ module.exports = (function() { * @returns {Object[]} The results as an array of messages or null if no messages. */ api.verify = function(textOrSourceCode, config, filenameOrOptions, saveState) { - + const text = (typeof textOrSourceCode === "string") ? textOrSourceCode : null; let ast, shebang, - ecmaFeatures, - ecmaVersion, - allowInlineConfig, - text = (typeof textOrSourceCode === "string") ? textOrSourceCode : null; + allowInlineConfig; // evaluate arguments if (typeof filenameOrOptions === "object") { @@ -740,14 +735,14 @@ module.exports = (function() { } // search and apply "eslint-env *". - let envInFile = findEslintEnv(text || textOrSourceCode.text); + const envInFile = findEslintEnv(text || textOrSourceCode.text); if (envInFile) { if (!config || !config.env) { - config = lodash.assign({}, config || {}, {env: envInFile}); + config = Object.assign({}, config || {}, {env: envInFile}); } else { - config = lodash.assign({}, config); - config.env = lodash.assign({}, config.env, envInFile); + config = Object.assign({}, config); + config.env = Object.assign({}, config.env, envInFile); } } @@ -795,15 +790,12 @@ module.exports = (function() { Object.keys(config.rules).filter(function(key) { return getRuleSeverity(config.rules[key]) > 0; }).forEach(function(key) { - let ruleCreator, - severity, - options, - rule; + let ruleCreator; ruleCreator = rules.get(key); if (!ruleCreator) { - let replacementMsg = getRuleReplacementMessage(key); + const replacementMsg = getRuleReplacementMessage(key); if (replacementMsg) { ruleCreator = createStubRule(replacementMsg); @@ -813,15 +805,15 @@ module.exports = (function() { rules.define(key, ruleCreator); } - severity = getRuleSeverity(config.rules[key]); - options = getRuleOptions(config.rules[key]); + const severity = getRuleSeverity(config.rules[key]); + const options = getRuleOptions(config.rules[key]); try { - let ruleContext = new RuleContext( + const ruleContext = new RuleContext( key, api, severity, options, config.settings, config.parserOptions, config.parser, ruleCreator.meta); - rule = ruleCreator.create ? ruleCreator.create(ruleContext) : + const rule = ruleCreator.create ? ruleCreator.create(ruleContext) : ruleCreator(ruleContext); // add all the node types as listeners @@ -841,8 +833,8 @@ module.exports = (function() { currentConfig = config; traverser = new Traverser(); - ecmaFeatures = currentConfig.parserOptions.ecmaFeatures || {}; - ecmaVersion = currentConfig.parserOptions.ecmaVersion || 5; + const ecmaFeatures = currentConfig.parserOptions.ecmaFeatures || {}; + const ecmaVersion = currentConfig.parserOptions.ecmaVersion || 5; // gather scope data that may be needed by the rules scopeManager = escope.analyze(ast, { @@ -863,7 +855,7 @@ module.exports = (function() { scopeMap = []; currentScopes.forEach(function(scope, index) { - let range = scope.block.range[0]; + const range = scope.block.range[0]; /* * Sometimes two scopes are returned for a given node. This is @@ -910,7 +902,7 @@ module.exports = (function() { // sort by line and column messages.sort(function(a, b) { - let lineDiff = a.line - b.line; + const lineDiff = a.line - b.line; if (lineDiff === 0) { return a.column - b.column; @@ -953,7 +945,7 @@ module.exports = (function() { } // Store end location. - let endLocation = location.end; + const endLocation = location.end; location = location.start || location; @@ -972,7 +964,7 @@ module.exports = (function() { }); } - let problem = { + const problem = { ruleId: ruleId, severity: severity, message: message, @@ -1011,7 +1003,7 @@ module.exports = (function() { }; // methods that exist on SourceCode object - let externalMethods = { + const externalMethods = { getSource: "getText", getSourceLines: "getLines", getAllComments: "getAllComments", @@ -1033,7 +1025,7 @@ module.exports = (function() { // copy over methods Object.keys(externalMethods).forEach(function(methodName) { - let exMethodName = externalMethods[methodName]; + const exMethodName = externalMethods[methodName]; // All functions expected to have less arguments than 5. api[methodName] = function(a, b, c, d, e) { @@ -1057,14 +1049,13 @@ module.exports = (function() { * @returns {Object} An object representing the current node's scope. */ api.getScope = function() { - let parents = traverser.parents(), - scope = currentScopes[0]; + const parents = traverser.parents(); // Don't do this for Program nodes - they have no parents if (parents.length) { // if current node introduces a scope, add it to the list - let current = traverser.current(); + const current = traverser.current(); if (currentConfig.parserOptions.ecmaVersion >= 6) { if (["BlockStatement", "SwitchStatement", "CatchClause", "FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(current.type) >= 0) { @@ -1080,7 +1071,8 @@ module.exports = (function() { for (let i = parents.length - 1; i >= 0; --i) { // Get the innermost scope - scope = scopeManager.acquire(parents[i], true); + const scope = scopeManager.acquire(parents[i], true); + if (scope) { if (scope.type === "function-expression-name") { return scope.childScopes[0]; @@ -1103,10 +1095,9 @@ module.exports = (function() { * false if not. */ api.markVariableAsUsed = function(name) { + const hasGlobalReturn = currentConfig.parserOptions.ecmaFeatures && currentConfig.parserOptions.ecmaFeatures.globalReturn, + specialScope = hasGlobalReturn || currentConfig.parserOptions.sourceType === "module"; let scope = this.getScope(), - hasGlobalReturn = currentConfig.parserOptions.ecmaFeatures && currentConfig.parserOptions.ecmaFeatures.globalReturn, - specialScope = hasGlobalReturn || currentConfig.parserOptions.sourceType === "module", - variables, i, len; @@ -1116,7 +1107,8 @@ module.exports = (function() { } do { - variables = scope.variables; + const variables = scope.variables; + for (i = 0, len = variables.length; i < len; i++) { if (variables[i].name === name) { variables[i].eslintUsed = true; @@ -1147,7 +1139,7 @@ module.exports = (function() { * @param {Function} ruleModule Function from context to object mapping AST node types to event handlers * @returns {void} */ - let defineRule = api.defineRule = function(ruleId, ruleModule) { + const defineRule = api.defineRule = function(ruleId, ruleModule) { rules.define(ruleId, ruleModule); }; diff --git a/tools/eslint/lib/file-finder.js b/tools/eslint/lib/file-finder.js index f003504c25..18f3b65133 100644 --- a/tools/eslint/lib/file-finder.js +++ b/tools/eslint/lib/file-finder.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let fs = require("fs"), +const fs = require("fs"), path = require("path"); //------------------------------------------------------------------------------ @@ -55,11 +55,11 @@ function FileFinder(files, cwd) { * @returns {Object} Hashmap of filenames */ function normalizeDirectoryEntries(entries, directory, supportedConfigs) { - let fileHash = {}; + const fileHash = {}; entries.forEach(function(entry) { if (supportedConfigs.indexOf(entry) >= 0) { - let resolvedEntry = path.resolve(directory, entry); + const resolvedEntry = path.resolve(directory, entry); if (fs.statSync(resolvedEntry).isFile()) { fileHash[entry] = resolvedEntry; @@ -79,14 +79,7 @@ function normalizeDirectoryEntries(entries, directory, supportedConfigs) { * @returns {string[]} The file paths found. */ FileFinder.prototype.findAllInDirectoryAndParents = function(directory) { - let cache = this.cache, - child, - dirs, - fileNames, - filePath, - i, - j, - searched; + const cache = this.cache; if (directory) { directory = path.resolve(this.cwd, directory); @@ -98,24 +91,24 @@ FileFinder.prototype.findAllInDirectoryAndParents = function(directory) { return cache[directory]; } - dirs = []; - searched = 0; - fileNames = this.fileNames; + const dirs = []; + const fileNames = this.fileNames; + let searched = 0; do { dirs[searched++] = directory; cache[directory] = []; - let filesMap = normalizeDirectoryEntries(getDirectoryEntries(directory), directory, fileNames); + const filesMap = normalizeDirectoryEntries(getDirectoryEntries(directory), directory, fileNames); if (Object.keys(filesMap).length) { for (let k = 0; k < fileNames.length; k++) { if (filesMap[fileNames[k]]) { - filePath = filesMap[fileNames[k]]; + const filePath = filesMap[fileNames[k]]; // Add the file path to the cache of each directory searched. - for (j = 0; j < searched; j++) { + for (let j = 0; j < searched; j++) { cache[dirs[j]].push(filePath); } @@ -123,7 +116,7 @@ FileFinder.prototype.findAllInDirectoryAndParents = function(directory) { } } } - child = directory; + const child = directory; // Assign parent directory to directory. directory = path.dirname(directory); @@ -134,7 +127,7 @@ FileFinder.prototype.findAllInDirectoryAndParents = function(directory) { } while (!cache.hasOwnProperty(directory)); // Add what has been cached previously to the cache of each directory searched. - for (i = 0; i < searched; i++) { + for (let i = 0; i < searched; i++) { dirs.push.apply(cache[dirs[i]], cache[directory]); } diff --git a/tools/eslint/lib/formatters/checkstyle.js b/tools/eslint/lib/formatters/checkstyle.js index 11ee60490a..1f4554c0fc 100644 --- a/tools/eslint/lib/formatters/checkstyle.js +++ b/tools/eslint/lib/formatters/checkstyle.js @@ -4,7 +4,7 @@ */ "use strict"; -let xmlEscape = require("../util/xml-escape"); +const xmlEscape = require("../util/xml-escape"); //------------------------------------------------------------------------------ // Helper Functions @@ -36,7 +36,7 @@ module.exports = function(results) { output += "<checkstyle version=\"4.3\">"; results.forEach(function(result) { - let messages = result.messages; + const messages = result.messages; output += "<file name=\"" + xmlEscape(result.filePath) + "\">"; diff --git a/tools/eslint/lib/formatters/compact.js b/tools/eslint/lib/formatters/compact.js index 72233f6f36..366ac8519a 100644 --- a/tools/eslint/lib/formatters/compact.js +++ b/tools/eslint/lib/formatters/compact.js @@ -34,7 +34,7 @@ module.exports = function(results) { results.forEach(function(result) { - let messages = result.messages; + const messages = result.messages; total += messages.length; diff --git a/tools/eslint/lib/formatters/html.js b/tools/eslint/lib/formatters/html.js index 87d2910b48..95437b95e2 100644 --- a/tools/eslint/lib/formatters/html.js +++ b/tools/eslint/lib/formatters/html.js @@ -4,17 +4,17 @@ */ "use strict"; -let lodash = require("lodash"); -let fs = require("fs"); -let path = require("path"); +const lodash = require("lodash"); +const fs = require("fs"); +const path = require("path"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let pageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-page.html"), "utf-8")); -let messageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-message.html"), "utf-8")); -let resultTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-result.html"), "utf-8")); +const pageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-page.html"), "utf-8")); +const messageTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-message.html"), "utf-8")); +const resultTemplate = lodash.template(fs.readFileSync(path.join(__dirname, "html-template-result.html"), "utf-8")); /** * Given a word and a count, append an s if count is not one. @@ -33,7 +33,7 @@ function pluralize(word, count) { * @returns {string} The formatted string, pluralized where necessary */ function renderSummary(totalErrors, totalWarnings) { - let totalProblems = totalErrors + totalWarnings; + const totalProblems = totalErrors + totalWarnings; let renderedText = totalProblems + " " + pluralize("problem", totalProblems); if (totalProblems !== 0) { @@ -71,11 +71,8 @@ function renderMessages(messages, parentIndex) { * @returns {string} HTML (table row) describing a message. */ return lodash.map(messages, function(message) { - let lineNumber, - columnNumber; - - lineNumber = message.line || 0; - columnNumber = message.column || 0; + const lineNumber = message.line || 0; + const columnNumber = message.column || 0; return messageTemplate({ parentIndex: parentIndex, diff --git a/tools/eslint/lib/formatters/jslint-xml.js b/tools/eslint/lib/formatters/jslint-xml.js index 11fe812d06..8ef2efcb7f 100644 --- a/tools/eslint/lib/formatters/jslint-xml.js +++ b/tools/eslint/lib/formatters/jslint-xml.js @@ -4,7 +4,7 @@ */ "use strict"; -let xmlEscape = require("../util/xml-escape"); +const xmlEscape = require("../util/xml-escape"); //------------------------------------------------------------------------------ // Public Interface @@ -18,7 +18,7 @@ module.exports = function(results) { output += "<jslint>"; results.forEach(function(result) { - let messages = result.messages; + const messages = result.messages; output += "<file name=\"" + result.filePath + "\">"; diff --git a/tools/eslint/lib/formatters/junit.js b/tools/eslint/lib/formatters/junit.js index 6b7bed30a1..7b2aa7a0ce 100644 --- a/tools/eslint/lib/formatters/junit.js +++ b/tools/eslint/lib/formatters/junit.js @@ -4,7 +4,7 @@ */ "use strict"; -let xmlEscape = require("../util/xml-escape"); +const xmlEscape = require("../util/xml-escape"); //------------------------------------------------------------------------------ // Helper Functions @@ -37,14 +37,14 @@ module.exports = function(results) { results.forEach(function(result) { - let messages = result.messages; + const messages = result.messages; if (messages.length) { output += "<testsuite package=\"org.eslint\" time=\"0\" tests=\"" + messages.length + "\" errors=\"" + messages.length + "\" name=\"" + result.filePath + "\">\n"; } messages.forEach(function(message) { - let type = message.fatal ? "error" : "failure"; + const type = message.fatal ? "error" : "failure"; output += "<testcase time=\"0\" name=\"org.eslint." + (message.ruleId || "unknown") + "\">"; output += "<" + type + " message=\"" + xmlEscape(message.message || "") + "\">"; diff --git a/tools/eslint/lib/formatters/stylish.js b/tools/eslint/lib/formatters/stylish.js index ebcea1ccdb..cb73777c2e 100644 --- a/tools/eslint/lib/formatters/stylish.js +++ b/tools/eslint/lib/formatters/stylish.js @@ -4,7 +4,7 @@ */ "use strict"; -let chalk = require("chalk"), +const chalk = require("chalk"), table = require("text-table"); //------------------------------------------------------------------------------ @@ -34,7 +34,7 @@ module.exports = function(results) { summaryColor = "yellow"; results.forEach(function(result) { - let messages = result.messages; + const messages = result.messages; if (messages.length === 0) { return; diff --git a/tools/eslint/lib/formatters/table.js b/tools/eslint/lib/formatters/table.js index d760c18ec5..7e793f80fb 100644 --- a/tools/eslint/lib/formatters/table.js +++ b/tools/eslint/lib/formatters/table.js @@ -8,13 +8,9 @@ // Requirements //------------------------------------------------------------------------------ -let chalk, - table, - pluralize; - -chalk = require("chalk"); -table = require("table").default; -pluralize = require("pluralize"); +const chalk = require("chalk"), + table = require("table").default, + pluralize = require("pluralize"); //------------------------------------------------------------------------------ // Helpers @@ -26,9 +22,7 @@ pluralize = require("pluralize"); * @returns {string} A text table. */ function drawTable(messages) { - let rows; - - rows = []; + const rows = []; if (messages.length === 0) { return ""; diff --git a/tools/eslint/lib/formatters/tap.js b/tools/eslint/lib/formatters/tap.js index c5c70171f1..df8668024f 100644 --- a/tools/eslint/lib/formatters/tap.js +++ b/tools/eslint/lib/formatters/tap.js @@ -4,7 +4,7 @@ */ "use strict"; -let yaml = require("js-yaml"); +const yaml = require("js-yaml"); //------------------------------------------------------------------------------ // Helper Functions @@ -29,7 +29,7 @@ function getMessageType(message) { * @returns {string} diagnostics string with YAML embedded - TAP version 13 compliant */ function outputDiagnostics(diagnostic) { - let prefix = " "; + const prefix = " "; let output = prefix + "---\n"; output += prefix + yaml.safeDump(diagnostic).split("\n").join("\n" + prefix); @@ -45,7 +45,7 @@ module.exports = function(results) { let output = "TAP version 13\n1.." + results.length + "\n"; results.forEach(function(result, id) { - let messages = result.messages; + const messages = result.messages; let testResult = "ok"; let diagnostics = {}; @@ -53,7 +53,7 @@ module.exports = function(results) { testResult = "not ok"; messages.forEach(function(message) { - let diagnostic = { + const diagnostic = { message: message.message, severity: getMessageType(message), data: { diff --git a/tools/eslint/lib/formatters/unix.js b/tools/eslint/lib/formatters/unix.js index ee4e14929b..f11f30a065 100644 --- a/tools/eslint/lib/formatters/unix.js +++ b/tools/eslint/lib/formatters/unix.js @@ -33,7 +33,7 @@ module.exports = function(results) { results.forEach(function(result) { - let messages = result.messages; + const messages = result.messages; total += messages.length; diff --git a/tools/eslint/lib/formatters/visualstudio.js b/tools/eslint/lib/formatters/visualstudio.js index 836577271e..e11474d5a4 100644 --- a/tools/eslint/lib/formatters/visualstudio.js +++ b/tools/eslint/lib/formatters/visualstudio.js @@ -35,7 +35,7 @@ module.exports = function(results) { results.forEach(function(result) { - let messages = result.messages; + const messages = result.messages; total += messages.length; diff --git a/tools/eslint/lib/ignored-paths.js b/tools/eslint/lib/ignored-paths.js index 729bddd20a..ab63fcee05 100644 --- a/tools/eslint/lib/ignored-paths.js +++ b/tools/eslint/lib/ignored-paths.js @@ -9,26 +9,25 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), - fs = require("fs"), +const fs = require("fs"), path = require("path"), - debug = require("debug"), ignore = require("ignore"), + shell = require("shelljs"), pathUtil = require("./util/path-util"); -debug = debug("eslint:ignored-paths"); +const debug = require("debug")("eslint:ignored-paths"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -let ESLINT_IGNORE_FILENAME = ".eslintignore"; -let DEFAULT_IGNORE_DIRS = [ +const ESLINT_IGNORE_FILENAME = ".eslintignore"; +const DEFAULT_IGNORE_DIRS = [ "node_modules/", "bower_components/" ]; -let DEFAULT_OPTIONS = { +const DEFAULT_OPTIONS = { dotfiles: false, cwd: process.cwd() }; @@ -47,9 +46,9 @@ let DEFAULT_OPTIONS = { function findIgnoreFile(cwd) { cwd = cwd || DEFAULT_OPTIONS.cwd; - let ignoreFilePath = path.resolve(cwd, ESLINT_IGNORE_FILENAME); + const ignoreFilePath = path.resolve(cwd, ESLINT_IGNORE_FILENAME); - return fs.existsSync(ignoreFilePath) ? ignoreFilePath : ""; + return shell.test("-f", ignoreFilePath) ? ignoreFilePath : ""; } /** @@ -59,7 +58,7 @@ function findIgnoreFile(cwd) { */ function mergeDefaultOptions(options) { options = (options || {}); - return lodash.assign({}, DEFAULT_OPTIONS, options); + return Object.assign({}, DEFAULT_OPTIONS, options); } //------------------------------------------------------------------------------ @@ -175,8 +174,8 @@ function IgnoredPaths(options) { IgnoredPaths.prototype.contains = function(filepath, category) { let result = false; - let absolutePath = path.resolve(this.options.cwd, filepath); - let relativePath = pathUtil.getRelativePath(absolutePath, this.options.cwd); + const absolutePath = path.resolve(this.options.cwd, filepath); + const relativePath = pathUtil.getRelativePath(absolutePath, this.options.cwd); if ((typeof category === "undefined") || (category === "default")) { result = result || (this.ig.default.filter([relativePath]).length === 0); @@ -201,7 +200,7 @@ IgnoredPaths.prototype.getIgnoredFoldersGlobPatterns = function() { /* eslint-disable no-underscore-dangle */ - let patterns = this.ig.custom._rules.filter(function(rule) { + const patterns = this.ig.custom._rules.filter(function(rule) { return rule.negative; }).map(function(rule) { return rule.origin; diff --git a/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js b/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js index 820218dc47..dea9b79e04 100644 --- a/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js +++ b/tools/eslint/lib/internal-rules/internal-no-invalid-meta.js @@ -17,7 +17,7 @@ * @returns {ASTNode} The Property node or null if not found. */ function getPropertyFromObject(property, node) { - let properties = node.properties; + const properties = node.properties; for (let i = 0; i < properties.length; i++) { if (properties[i].key.name === property) { @@ -55,7 +55,7 @@ function hasMetaDocs(metaPropertyNode) { * @returns {boolean} `true` if a `docs.description` property exists. */ function hasMetaDocsDescription(metaPropertyNode) { - let metaDocs = getPropertyFromObject("docs", metaPropertyNode.value); + const metaDocs = getPropertyFromObject("docs", metaPropertyNode.value); return metaDocs && getPropertyFromObject("description", metaDocs.value); } @@ -67,7 +67,7 @@ function hasMetaDocsDescription(metaPropertyNode) { * @returns {boolean} `true` if a `docs.category` property exists. */ function hasMetaDocsCategory(metaPropertyNode) { - let metaDocs = getPropertyFromObject("docs", metaPropertyNode.value); + const metaDocs = getPropertyFromObject("docs", metaPropertyNode.value); return metaDocs && getPropertyFromObject("category", metaDocs.value); } @@ -79,7 +79,7 @@ function hasMetaDocsCategory(metaPropertyNode) { * @returns {boolean} `true` if a `docs.recommended` property exists. */ function hasMetaDocsRecommended(metaPropertyNode) { - let metaDocs = getPropertyFromObject("docs", metaPropertyNode.value); + const metaDocs = getPropertyFromObject("docs", metaPropertyNode.value); return metaDocs && getPropertyFromObject("recommended", metaDocs.value); } @@ -113,7 +113,7 @@ function hasMetaFixable(metaPropertyNode) { * @returns {void} */ function checkMetaValidity(context, exportsNode, ruleIsFixable) { - let metaProperty = getMetaPropertyFromExportsNode(exportsNode); + const metaProperty = getMetaPropertyFromExportsNode(exportsNode); if (!metaProperty) { context.report(exportsNode, "Rule is missing a meta property."); @@ -151,6 +151,16 @@ function checkMetaValidity(context, exportsNode, ruleIsFixable) { } } +/** + * Whether this node is the correct format for a rule definition or not. + * + * @param {ASTNode} node node that the rule exports. + * @returns {boolean} `true` if the exported node is the correct format for a rule definition + */ +function isCorrectExportsFormat(node) { + return node.type === "ObjectExpression"; +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -167,7 +177,7 @@ module.exports = { }, create: function(context) { - let metaExportsValue; + let exportsNode; let ruleIsFixable = false; return { @@ -178,7 +188,7 @@ module.exports = { node.left.object.name === "module" && node.left.property.name === "exports") { - metaExportsValue = node.right; + exportsNode = node.right; } }, @@ -205,7 +215,12 @@ module.exports = { }, "Program:exit": function() { - checkMetaValidity(context, metaExportsValue, ruleIsFixable); + if (!isCorrectExportsFormat(exportsNode)) { + context.report(exportsNode, "Rule does not export an Object. Make sure the rule follows the new rule format."); + return; + } + + checkMetaValidity(context, exportsNode, ruleIsFixable); } }; } diff --git a/tools/eslint/lib/load-rules.js b/tools/eslint/lib/load-rules.js index ed7732db3f..c698faa5e1 100644 --- a/tools/eslint/lib/load-rules.js +++ b/tools/eslint/lib/load-rules.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let fs = require("fs"), +const fs = require("fs"), path = require("path"); //------------------------------------------------------------------------------ @@ -29,7 +29,7 @@ module.exports = function(rulesDir, cwd) { rulesDir = path.resolve(cwd, rulesDir); } - let rules = Object.create(null); + const rules = Object.create(null); fs.readdirSync(rulesDir).forEach(function(file) { if (path.extname(file) !== ".js") { diff --git a/tools/eslint/lib/options.js b/tools/eslint/lib/options.js index b1ab7eb967..bbb2456a98 100644 --- a/tools/eslint/lib/options.js +++ b/tools/eslint/lib/options.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let optionator = require("optionator"); +const optionator = require("optionator"); //------------------------------------------------------------------------------ // Initialization and Public Interface diff --git a/tools/eslint/lib/rule-context.js b/tools/eslint/lib/rule-context.js index e0428744b9..c400fc254f 100644 --- a/tools/eslint/lib/rule-context.js +++ b/tools/eslint/lib/rule-context.js @@ -8,13 +8,13 @@ // Requirements //------------------------------------------------------------------------------ -let RuleFixer = require("./util/rule-fixer"); +const RuleFixer = require("./util/rule-fixer"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -let PASSTHROUGHS = [ +const PASSTHROUGHS = [ "getAncestors", "getDeclaredVariables", "getFilename", @@ -111,12 +111,11 @@ RuleContext.prototype = { * @returns {void} */ report: function(nodeOrDescriptor, location, message, opts) { - let descriptor, - fix = null; // check to see if it's a new style call if (arguments.length === 1) { - descriptor = nodeOrDescriptor; + const descriptor = nodeOrDescriptor; + let fix = null; // if there's a fix specified, get it if (typeof descriptor.fix === "function") { diff --git a/tools/eslint/lib/rules.js b/tools/eslint/lib/rules.js index 3552d494a0..19ac9f469e 100644 --- a/tools/eslint/lib/rules.js +++ b/tools/eslint/lib/rules.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let loadRules = require("./load-rules"); +const loadRules = require("./load-rules"); //------------------------------------------------------------------------------ // Privates @@ -38,7 +38,7 @@ function define(ruleId, ruleModule) { * @returns {void} */ function load(rulesDir, cwd) { - let newRules = loadRules(rulesDir, cwd); + const newRules = loadRules(rulesDir, cwd); Object.keys(newRules).forEach(function(ruleId) { define(ruleId, newRules[ruleId]); @@ -53,7 +53,7 @@ function load(rulesDir, cwd) { */ function importPlugin(pluginRules, pluginName) { Object.keys(pluginRules).forEach(function(ruleId) { - let qualifiedRuleId = pluginName + "/" + ruleId, + const qualifiedRuleId = pluginName + "/" + ruleId, rule = pluginRules[ruleId]; define(qualifiedRuleId, rule); diff --git a/tools/eslint/lib/rules/accessor-pairs.js b/tools/eslint/lib/rules/accessor-pairs.js index b80b44dc9f..abd69668fc 100644 --- a/tools/eslint/lib/rules/accessor-pairs.js +++ b/tools/eslint/lib/rules/accessor-pairs.js @@ -28,7 +28,7 @@ function isIdentifier(node, name) { * @returns {boolean} `true` if the node is an argument of the specified method call. */ function isArgumentOfMethodCall(node, index, object, property) { - let parent = node.parent; + const parent = node.parent; return ( parent.type === "CallExpression" && @@ -91,9 +91,9 @@ module.exports = { }] }, create: function(context) { - let config = context.options[0] || {}; - let checkGetWithoutSet = config.getWithoutSet === true; - let checkSetWithoutGet = config.setWithoutGet !== false; + const config = context.options[0] || {}; + const checkGetWithoutSet = config.getWithoutSet === true; + const checkSetWithoutGet = config.setWithoutGet !== false; /** * Checks a object expression to see if it has setter and getter both present or none. @@ -104,10 +104,10 @@ module.exports = { function checkLonelySetGet(node) { let isSetPresent = false; let isGetPresent = false; - let isDescriptor = isPropertyDescriptor(node); + const isDescriptor = isPropertyDescriptor(node); for (let i = 0, end = node.properties.length; i < end; i++) { - let property = node.properties[i]; + const property = node.properties[i]; let propToCheck = ""; diff --git a/tools/eslint/lib/rules/array-bracket-spacing.js b/tools/eslint/lib/rules/array-bracket-spacing.js index 6e26e0cbd5..04376953f1 100644 --- a/tools/eslint/lib/rules/array-bracket-spacing.js +++ b/tools/eslint/lib/rules/array-bracket-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -40,7 +40,7 @@ module.exports = { ] }, create: function(context) { - let spaced = context.options[0] === "always", + const spaced = context.options[0] === "always", sourceCode = context.getSourceCode(); /** @@ -54,7 +54,7 @@ module.exports = { return context.options[1] ? context.options[1][option] === !spaced : false; } - let options = { + const options = { spaced: spaced, singleElementException: isOptionSet("singleValue"), objectsInArraysException: isOptionSet("objectsInArrays"), @@ -77,7 +77,7 @@ module.exports = { loc: token.loc.start, message: "There should be no space after '" + token.value + "'.", fix: function(fixer) { - let nextToken = sourceCode.getTokenAfter(token); + const nextToken = sourceCode.getTokenAfter(token); return fixer.removeRange([token.range[1], nextToken.range[0]]); } @@ -96,7 +96,7 @@ module.exports = { loc: token.loc.start, message: "There should be no space before '" + token.value + "'.", fix: function(fixer) { - let previousToken = sourceCode.getTokenBefore(token); + const previousToken = sourceCode.getTokenBefore(token); return fixer.removeRange([previousToken.range[1], token.range[0]]); } @@ -165,20 +165,20 @@ module.exports = { return; } - let first = sourceCode.getFirstToken(node), + const first = sourceCode.getFirstToken(node), second = sourceCode.getFirstToken(node, 1), penultimate = sourceCode.getLastToken(node, 1), last = sourceCode.getLastToken(node), firstElement = node.elements[0], lastElement = node.elements[node.elements.length - 1]; - let openingBracketMustBeSpaced = + const openingBracketMustBeSpaced = options.objectsInArraysException && isObjectType(firstElement) || options.arraysInArraysException && isArrayType(firstElement) || options.singleElementException && node.elements.length === 1 ? !options.spaced : options.spaced; - let closingBracketMustBeSpaced = + const closingBracketMustBeSpaced = options.objectsInArraysException && isObjectType(lastElement) || options.arraysInArraysException && isArrayType(lastElement) || options.singleElementException && node.elements.length === 1 diff --git a/tools/eslint/lib/rules/array-callback-return.js b/tools/eslint/lib/rules/array-callback-return.js index d72fd57b2e..4ea9529966 100644 --- a/tools/eslint/lib/rules/array-callback-return.js +++ b/tools/eslint/lib/rules/array-callback-return.js @@ -9,14 +9,14 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/; -let TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/; +const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/; +const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/; /** * Checks a given code path segment is reachable. @@ -46,38 +46,6 @@ function getLocation(node, sourceCode) { } /** - * Gets the name of a given node if the node is a Identifier node. - * - * @param {ASTNode} node - A node to get. - * @returns {string} The name of the node, or an empty string. - */ -function getIdentifierName(node) { - return node.type === "Identifier" ? node.name : ""; -} - -/** - * Gets the value of a given node if the node is a Literal node or a - * TemplateLiteral node. - * - * @param {ASTNode} node - A node to get. - * @returns {string} The value of the node, or an empty string. - */ -function getConstantStringValue(node) { - switch (node.type) { - case "Literal": - return String(node.value); - - case "TemplateLiteral": - return node.expressions.length === 0 - ? node.quasis[0].value.cooked - : ""; - - default: - return ""; - } -} - -/** * Checks a given node is a MemberExpression node which has the specified name's * property. * @@ -88,9 +56,7 @@ function getConstantStringValue(node) { function isTargetMethod(node) { return ( node.type === "MemberExpression" && - TARGET_METHODS.test( - (node.computed ? getConstantStringValue : getIdentifierName)(node.property) - ) + TARGET_METHODS.test(astUtils.getStaticPropertyName(node) || "") ); } @@ -104,7 +70,7 @@ function isTargetMethod(node) { */ function isCallbackOfArrayMethod(node) { while (node) { - let parent = node.parent; + const parent = node.parent; switch (parent.type) { diff --git a/tools/eslint/lib/rules/arrow-body-style.js b/tools/eslint/lib/rules/arrow-body-style.js index 16f082edae..521c101658 100644 --- a/tools/eslint/lib/rules/arrow-body-style.js +++ b/tools/eslint/lib/rules/arrow-body-style.js @@ -50,11 +50,11 @@ module.exports = { }, create: function(context) { - let options = context.options; - let always = options[0] === "always"; - let asNeeded = !options[0] || options[0] === "as-needed"; - let never = options[0] === "never"; - let requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral; + const options = context.options; + const always = options[0] === "always"; + const asNeeded = !options[0] || options[0] === "as-needed"; + const never = options[0] === "never"; + const requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral; /** * Determines whether a arrow function body needs braces @@ -62,7 +62,7 @@ module.exports = { * @returns {void} */ function validate(node) { - let arrowBody = node.body; + const arrowBody = node.body; if (arrowBody.type === "BlockStatement") { if (never) { @@ -72,7 +72,7 @@ module.exports = { message: "Unexpected block statement surrounding arrow body." }); } else { - let blockBody = arrowBody.body; + const blockBody = arrowBody.body; if (blockBody.length !== 1) { return; diff --git a/tools/eslint/lib/rules/arrow-parens.js b/tools/eslint/lib/rules/arrow-parens.js index fd70ee3465..60b683168e 100644 --- a/tools/eslint/lib/rules/arrow-parens.js +++ b/tools/eslint/lib/rules/arrow-parens.js @@ -21,16 +21,29 @@ module.exports = { schema: [ { enum: ["always", "as-needed"] + }, + { + type: "object", + properties: { + requireForBlockBody: { + type: "boolean" + } + }, + additionalProperties: false } ] }, create: function(context) { - let message = "Expected parentheses around arrow function argument."; - let asNeededMessage = "Unexpected parentheses around single function argument."; - let asNeeded = context.options[0] === "as-needed"; + const message = "Expected parentheses around arrow function argument."; + const asNeededMessage = "Unexpected parentheses around single function argument."; + const asNeeded = context.options[0] === "as-needed"; + const requireForBlockBodyMessage = "Unexpected parentheses around single function argument having a body with no curly braces"; + const requireForBlockBodyNoParensMessage = "Expected parentheses around arrow function argument having a body with curly braces."; + const requireForBlockBody = asNeeded && context.options[1] && context.options[1].requireForBlockBody === true; + + const sourceCode = context.getSourceCode(); - let sourceCode = context.getSourceCode(); /** * Determines whether a arrow function argument end with `)` @@ -38,17 +51,58 @@ module.exports = { * @returns {void} */ function parens(node) { - let token = sourceCode.getFirstToken(node); + const token = sourceCode.getFirstToken(node); + + // "as-needed", { "requireForBlockBody": true }: x => x + if ( + requireForBlockBody && + node.params.length === 1 && + node.params[0].type === "Identifier" && + node.body.type !== "BlockStatement" + ) { + if (token.type === "Punctuator" && token.value === "(") { + context.report({ + node: node, + message: requireForBlockBodyMessage, + fix: function(fixer) { + const paramToken = context.getTokenAfter(token); + const closingParenToken = context.getTokenAfter(paramToken); + + return fixer.replaceTextRange([ + token.range[0], + closingParenToken.range[1] + ], paramToken.value); + } + }); + } + return; + } + + if ( + requireForBlockBody && + node.body.type === "BlockStatement" + ) { + if (token.type !== "Punctuator" || token.value !== "(") { + context.report({ + node: node, + message: requireForBlockBodyNoParensMessage, + fix: function(fixer) { + return fixer.replaceText(token, "(" + token.value + ")"); + } + }); + } + return; + } - // as-needed: x => x + // "as-needed": x => x if (asNeeded && node.params.length === 1 && node.params[0].type === "Identifier") { if (token.type === "Punctuator" && token.value === "(") { context.report({ node: node, message: asNeededMessage, fix: function(fixer) { - let paramToken = context.getTokenAfter(token); - let closingParenToken = context.getTokenAfter(paramToken); + const paramToken = context.getTokenAfter(token); + const closingParenToken = context.getTokenAfter(paramToken); return fixer.replaceTextRange([ token.range[0], @@ -61,7 +115,7 @@ module.exports = { } if (token.type === "Identifier") { - let after = sourceCode.getTokenAfter(token); + const after = sourceCode.getTokenAfter(token); // (x) => x if (after.value !== ")") { diff --git a/tools/eslint/lib/rules/arrow-spacing.js b/tools/eslint/lib/rules/arrow-spacing.js index 354c860c7b..570dfe5d69 100644 --- a/tools/eslint/lib/rules/arrow-spacing.js +++ b/tools/eslint/lib/rules/arrow-spacing.js @@ -37,13 +37,13 @@ module.exports = { create: function(context) { // merge rules with default - let rule = { before: true, after: true }, + const rule = { before: true, after: true }, option = context.options[0] || {}; rule.before = option.before !== false; rule.after = option.after !== false; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Get tokens of arrow(`=>`) and before/after arrow. @@ -58,7 +58,7 @@ module.exports = { before = t; t = sourceCode.getTokenAfter(t); } - let after = sourceCode.getTokenAfter(t); + const after = sourceCode.getTokenAfter(t); return { before: before, arrow: t, after: after }; } @@ -69,8 +69,8 @@ module.exports = { * @returns {Object} count of space before/after arrow. */ function countSpaces(tokens) { - let before = tokens.arrow.range[0] - tokens.before.range[1]; - let after = tokens.after.range[0] - tokens.arrow.range[1]; + const before = tokens.arrow.range[0] - tokens.before.range[1]; + const after = tokens.after.range[0] - tokens.arrow.range[1]; return { before: before, after: after }; } @@ -83,8 +83,8 @@ module.exports = { * @returns {void} */ function spaces(node) { - let tokens = getTokens(node); - let countSpace = countSpaces(tokens); + const tokens = getTokens(node); + const countSpace = countSpaces(tokens); if (rule.before) { diff --git a/tools/eslint/lib/rules/block-scoped-var.js b/tools/eslint/lib/rules/block-scoped-var.js index f8198ea10a..c8b0d0c765 100644 --- a/tools/eslint/lib/rules/block-scoped-var.js +++ b/tools/eslint/lib/rules/block-scoped-var.js @@ -45,7 +45,7 @@ module.exports = { * @returns {void} */ function report(reference) { - let identifier = reference.identifier; + const identifier = reference.identifier; context.report( identifier, @@ -64,7 +64,7 @@ module.exports = { } // Defines a predicate to check whether or not a given reference is outside of valid scope. - let scopeRange = stack[stack.length - 1]; + const scopeRange = stack[stack.length - 1]; /** * Check if a reference is out of scope @@ -73,13 +73,13 @@ module.exports = { * @private */ function isOutsideOfScope(reference) { - let idRange = reference.identifier.range; + const idRange = reference.identifier.range; return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1]; } // Gets declared variables, and checks its references. - let variables = context.getDeclaredVariables(node); + const variables = context.getDeclaredVariables(node); for (let i = 0; i < variables.length; ++i) { diff --git a/tools/eslint/lib/rules/block-spacing.js b/tools/eslint/lib/rules/block-spacing.js index eb24cea319..f50e432179 100644 --- a/tools/eslint/lib/rules/block-spacing.js +++ b/tools/eslint/lib/rules/block-spacing.js @@ -5,7 +5,7 @@ "use strict"; -let util = require("../ast-utils"); +const util = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -27,7 +27,7 @@ module.exports = { }, create: function(context) { - let always = (context.options[0] !== "never"), + const always = (context.options[0] !== "never"), message = always ? "Requires a space" : "Unexpected space(s)", sourceCode = context.getSourceCode(); @@ -72,10 +72,10 @@ module.exports = { function checkSpacingInsideBraces(node) { // Gets braces and the first/last token of content. - let openBrace = getOpenBrace(node); - let closeBrace = sourceCode.getLastToken(node); - let firstToken = sourceCode.getTokenOrCommentAfter(openBrace); - let lastToken = sourceCode.getTokenOrCommentBefore(closeBrace); + const openBrace = getOpenBrace(node); + const closeBrace = sourceCode.getLastToken(node); + const firstToken = sourceCode.getTokenOrCommentAfter(openBrace); + const lastToken = sourceCode.getTokenOrCommentBefore(closeBrace); // Skip if the node is invalid or empty. if (openBrace.type !== "Punctuator" || diff --git a/tools/eslint/lib/rules/brace-style.js b/tools/eslint/lib/rules/brace-style.js index 325130a4a2..256f4c0349 100644 --- a/tools/eslint/lib/rules/brace-style.js +++ b/tools/eslint/lib/rules/brace-style.js @@ -34,11 +34,11 @@ module.exports = { }, create: function(context) { - let style = context.options[0] || "1tbs", + const style = context.options[0] || "1tbs", params = context.options[1] || {}, sourceCode = context.getSourceCode(); - let OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.", + const OPEN_MESSAGE = "Opening curly brace does not appear on the same line as controlling statement.", OPEN_MESSAGE_ALLMAN = "Opening curly brace appears on the same line as controlling statement.", BODY_MESSAGE = "Statement inside of curly braces should be on next line.", CLOSE_MESSAGE = "Closing curly brace does not appear on the same line as the subsequent block.", @@ -78,24 +78,20 @@ module.exports = { * @private */ function checkBlock() { - let blockProperties = arguments; + const blockProperties = arguments; return function(node) { Array.prototype.forEach.call(blockProperties, function(blockProp) { - let block = node[blockProp], - previousToken, - curlyToken, - curlyTokenEnd, - allOnSameLine; + const block = node[blockProp]; if (!isBlock(block)) { return; } - previousToken = sourceCode.getTokenBefore(block); - curlyToken = sourceCode.getFirstToken(block); - curlyTokenEnd = sourceCode.getLastToken(block); - allOnSameLine = previousToken.loc.start.line === curlyTokenEnd.loc.start.line; + const previousToken = sourceCode.getTokenBefore(block); + const curlyToken = sourceCode.getFirstToken(block); + const curlyTokenEnd = sourceCode.getLastToken(block); + const allOnSameLine = previousToken.loc.start.line === curlyTokenEnd.loc.start.line; if (allOnSameLine && params.allowSingleLine) { return; @@ -129,13 +125,11 @@ module.exports = { * @private */ function checkIfStatement(node) { - let tokens; - checkBlock("consequent", "alternate")(node); if (node.alternate) { - tokens = sourceCode.getTokensBefore(node.alternate, 2); + const tokens = sourceCode.getTokensBefore(node.alternate, 2); if (style === "1tbs") { if (tokens[0].loc.start.line !== tokens[1].loc.start.line && @@ -157,12 +151,11 @@ module.exports = { * @private */ function checkTryStatement(node) { - let tokens; - checkBlock("block", "finalizer")(node); if (isBlock(node.finalizer)) { - tokens = sourceCode.getTokensBefore(node.finalizer, 2); + const tokens = sourceCode.getTokensBefore(node.finalizer, 2); + if (style === "1tbs") { if (tokens[0].loc.start.line !== tokens[1].loc.start.line) { context.report(node.finalizer, CLOSE_MESSAGE); @@ -180,7 +173,7 @@ module.exports = { * @private */ function checkCatchClause(node) { - let previousToken = sourceCode.getTokenBefore(node), + const previousToken = sourceCode.getTokenBefore(node), firstToken = sourceCode.getFirstToken(node); checkBlock("body")(node); diff --git a/tools/eslint/lib/rules/callback-return.js b/tools/eslint/lib/rules/callback-return.js index 0b9d4a4894..699eaa7ea6 100644 --- a/tools/eslint/lib/rules/callback-return.js +++ b/tools/eslint/lib/rules/callback-return.js @@ -24,7 +24,7 @@ module.exports = { create: function(context) { - let callbacks = context.options[0] || ["callback", "cb", "next"], + const callbacks = context.options[0] || ["callback", "cb", "next"], sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- @@ -118,8 +118,7 @@ module.exports = { } // find the closest block, return or loop - let closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {}, - lastItem, parentType; + const closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {}; // if our parent is a return we know we're ok if (closestBlock.type === "ReturnStatement") { @@ -135,12 +134,12 @@ module.exports = { if (closestBlock.type === "BlockStatement") { // find the last item in the block - lastItem = closestBlock.body[closestBlock.body.length - 1]; + const lastItem = closestBlock.body[closestBlock.body.length - 1]; // if the callback is the last thing in a block that might be ok if (isCallbackExpression(node, lastItem)) { - parentType = closestBlock.parent.type; + const parentType = closestBlock.parent.type; // but only if the block is part of a function if (parentType === "FunctionExpression" || diff --git a/tools/eslint/lib/rules/camelcase.js b/tools/eslint/lib/rules/camelcase.js index b336e595dc..e3f8a10770 100644 --- a/tools/eslint/lib/rules/camelcase.js +++ b/tools/eslint/lib/rules/camelcase.js @@ -37,7 +37,7 @@ module.exports = { //-------------------------------------------------------------------------- // contains reported nodes to avoid reporting twice on destructuring with shorthand notation - let reported = []; + const reported = []; /** * Checks if a string contains an underscore and isn't all upper-case @@ -64,8 +64,8 @@ module.exports = { } } - let options = context.options[0] || {}, - properties = options.properties || ""; + const options = context.options[0] || {}; + let properties = options.properties || ""; if (properties !== "always" && properties !== "never") { properties = "always"; @@ -79,7 +79,7 @@ module.exports = { * Leading and trailing underscores are commonly used to flag * private/protected identifiers, strip them */ - let name = node.name.replace(/^_+|_+$/g, ""), + const name = node.name.replace(/^_+|_+$/g, ""), effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; // MemberExpressions get special rules @@ -122,6 +122,14 @@ module.exports = { report(node); } + // Check if it's an import specifier + } else if (["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"].indexOf(node.parent.type) >= 0) { + + // Report only if the local imported identifier is underscored + if (node.parent.local && node.parent.local.name === node.name && isUnderscored(name)) { + report(node); + } + // Report anything that is underscored that isn't a CallExpression } else if (isUnderscored(name) && effectiveParent.type !== "CallExpression") { report(node); diff --git a/tools/eslint/lib/rules/comma-dangle.js b/tools/eslint/lib/rules/comma-dangle.js index 69a72e8fca..719ae124c6 100644 --- a/tools/eslint/lib/rules/comma-dangle.js +++ b/tools/eslint/lib/rules/comma-dangle.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"); +const lodash = require("lodash"); /** * Checks whether or not a trailing comma is allowed in a given node. @@ -45,9 +45,9 @@ module.exports = { }, create: function(context) { - let mode = context.options[0]; - let UNEXPECTED_MESSAGE = "Unexpected trailing comma."; - let MISSING_MESSAGE = "Missing trailing comma."; + const mode = context.options[0]; + const UNEXPECTED_MESSAGE = "Unexpected trailing comma."; + const MISSING_MESSAGE = "Missing trailing comma."; /** * Checks whether or not a given node is multiline. @@ -58,14 +58,14 @@ module.exports = { * @returns {boolean} `true` if the node is multiline. */ function isMultiline(node) { - let lastItem = lodash.last(node.properties || node.elements || node.specifiers); + const lastItem = lodash.last(node.properties || node.elements || node.specifiers); if (!lastItem) { return false; } - let sourceCode = context.getSourceCode(), - penultimateToken = sourceCode.getLastToken(lastItem), + const sourceCode = context.getSourceCode(); + let penultimateToken = sourceCode.getLastToken(lastItem), lastToken = sourceCode.getTokenAfter(penultimateToken); // parentheses are a pain @@ -91,14 +91,14 @@ module.exports = { * @returns {void} */ function forbidTrailingComma(node) { - let lastItem = lodash.last(node.properties || node.elements || node.specifiers); + const lastItem = lodash.last(node.properties || node.elements || node.specifiers); if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { return; } - let sourceCode = context.getSourceCode(), - trailingToken; + const sourceCode = context.getSourceCode(); + let trailingToken; // last item can be surrounded by parentheses for object and array literals if (node.type === "ObjectExpression" || node.type === "ArrayExpression") { @@ -132,7 +132,7 @@ module.exports = { * @returns {void} */ function forceTrailingComma(node) { - let lastItem = lodash.last(node.properties || node.elements || node.specifiers); + const lastItem = lodash.last(node.properties || node.elements || node.specifiers); if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { return; @@ -142,8 +142,8 @@ module.exports = { return; } - let sourceCode = context.getSourceCode(), - penultimateToken = lastItem, + const sourceCode = context.getSourceCode(); + let penultimateToken = lastItem, trailingToken = sourceCode.getTokenAfter(lastItem); // Skip close parentheses. diff --git a/tools/eslint/lib/rules/comma-spacing.js b/tools/eslint/lib/rules/comma-spacing.js index ea516e0333..c8d01847df 100644 --- a/tools/eslint/lib/rules/comma-spacing.js +++ b/tools/eslint/lib/rules/comma-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -38,10 +38,10 @@ module.exports = { create: function(context) { - let sourceCode = context.getSourceCode(); - let tokensAndComments = sourceCode.tokensAndComments; + const sourceCode = context.getSourceCode(); + const tokensAndComments = sourceCode.tokensAndComments; - let options = { + const options = { before: context.options[0] ? !!context.options[0].before : false, after: context.options[0] ? !!context.options[0].after : true }; @@ -51,7 +51,7 @@ module.exports = { //-------------------------------------------------------------------------- // list of comma tokens to ignore for the check of leading whitespace - let commaTokensToIgnore = []; + const commaTokensToIgnore = []; /** * Determines if a given token is a comma operator. @@ -83,7 +83,7 @@ module.exports = { } } else { let start, end; - let newText = ""; + const newText = ""; if (dir === "before") { start = otherNode.range[1]; @@ -161,10 +161,6 @@ module.exports = { return { "Program:exit": function() { - - let previousToken, - nextToken; - tokensAndComments.forEach(function(token, i) { if (!isComma(token)) { @@ -175,8 +171,8 @@ module.exports = { return; } - previousToken = tokensAndComments[i - 1]; - nextToken = tokensAndComments[i + 1]; + const previousToken = tokensAndComments[i - 1]; + const nextToken = tokensAndComments[i + 1]; validateCommaItemSpacing({ comma: token, diff --git a/tools/eslint/lib/rules/comma-style.js b/tools/eslint/lib/rules/comma-style.js index 69b657f62d..9a7c4613d0 100644 --- a/tools/eslint/lib/rules/comma-style.js +++ b/tools/eslint/lib/rules/comma-style.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -39,9 +39,9 @@ module.exports = { }, create: function(context) { - let style = context.options[0] || "last", - exceptions = {}, + const style = context.options[0] || "last", sourceCode = context.getSourceCode(); + let exceptions = {}; if (context.options.length === 2 && context.options[1].hasOwnProperty("exceptions")) { exceptions = context.options[1].exceptions; @@ -108,17 +108,16 @@ module.exports = { * @returns {void} */ function validateComma(node, property) { - let items = node[property], - arrayLiteral = (node.type === "ArrayExpression"), - previousItemToken; + const items = node[property], + arrayLiteral = (node.type === "ArrayExpression"); if (items.length > 1 || arrayLiteral) { // seed as opening [ - previousItemToken = sourceCode.getFirstToken(node); + let previousItemToken = sourceCode.getFirstToken(node); items.forEach(function(item) { - let commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken, + const commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken, currentItemToken = item ? sourceCode.getFirstToken(item) : sourceCode.getTokenAfter(commaToken), reportItem = item || currentItemToken, tokenBeforeComma = sourceCode.getTokenBefore(commaToken); @@ -158,7 +157,7 @@ module.exports = { */ if (arrayLiteral) { - let lastToken = sourceCode.getLastToken(node), + const lastToken = sourceCode.getLastToken(node), nextToLastToken = sourceCode.getTokenBefore(lastToken); if (isComma(nextToLastToken)) { @@ -177,7 +176,7 @@ module.exports = { // Public //-------------------------------------------------------------------------- - let nodes = {}; + const nodes = {}; if (!exceptions.VariableDeclaration) { nodes.VariableDeclaration = function(node) { diff --git a/tools/eslint/lib/rules/complexity.js b/tools/eslint/lib/rules/complexity.js index 394df98c44..10f8655dcc 100644 --- a/tools/eslint/lib/rules/complexity.js +++ b/tools/eslint/lib/rules/complexity.js @@ -45,8 +45,8 @@ module.exports = { }, create: function(context) { - let option = context.options[0], - THRESHOLD = 20; + const option = context.options[0]; + let THRESHOLD = 20; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { THRESHOLD = option.maximum; @@ -63,7 +63,7 @@ module.exports = { //-------------------------------------------------------------------------- // Using a stack to store complexity (handling nested functions) - let fns = []; + const fns = []; /** * When parsing a new function, store it in our function stack @@ -81,8 +81,8 @@ module.exports = { * @private */ function endFunction(node) { - let complexity = fns.pop(), - name = "anonymous"; + const complexity = fns.pop(); + let name = "anonymous"; if (node.id) { name = node.id.name; diff --git a/tools/eslint/lib/rules/computed-property-spacing.js b/tools/eslint/lib/rules/computed-property-spacing.js index 1122c5c83c..d286155431 100644 --- a/tools/eslint/lib/rules/computed-property-spacing.js +++ b/tools/eslint/lib/rules/computed-property-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -28,8 +28,8 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); - let propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" + const sourceCode = context.getSourceCode(); + const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" //-------------------------------------------------------------------------- // Helpers @@ -117,9 +117,9 @@ module.exports = { return; } - let property = node[propertyName]; + const property = node[propertyName]; - let before = sourceCode.getTokenBefore(property), + const before = sourceCode.getTokenBefore(property), first = sourceCode.getFirstToken(property), last = sourceCode.getLastToken(property), after = sourceCode.getTokenAfter(property); diff --git a/tools/eslint/lib/rules/consistent-return.js b/tools/eslint/lib/rules/consistent-return.js index ffadd31bfd..42fd91e3fb 100644 --- a/tools/eslint/lib/rules/consistent-return.js +++ b/tools/eslint/lib/rules/consistent-return.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -57,8 +57,8 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let treatUndefinedAsUnspecified = options.treatUndefinedAsUnspecified === true; + const options = context.options[0] || {}; + const treatUndefinedAsUnspecified = options.treatUndefinedAsUnspecified === true; let funcInfo = null; /** @@ -135,7 +135,7 @@ module.exports = { // Reports a given return statement if it's inconsistent. ReturnStatement: function(node) { - let argument = node.argument; + const argument = node.argument; let hasReturnValue = Boolean(argument); if (treatUndefinedAsUnspecified && hasReturnValue) { diff --git a/tools/eslint/lib/rules/consistent-this.js b/tools/eslint/lib/rules/consistent-this.js index 339c43995e..c61f9da6cb 100644 --- a/tools/eslint/lib/rules/consistent-this.js +++ b/tools/eslint/lib/rules/consistent-this.js @@ -57,7 +57,7 @@ module.exports = { * @returns {void} */ function checkAssignment(node, name, value) { - let isThis = value.type === "ThisExpression"; + const isThis = value.type === "ThisExpression"; if (aliases.indexOf(name) !== -1) { if (!isThis || node.operator && node.operator !== "=") { @@ -78,7 +78,7 @@ module.exports = { * @returns {void} */ function checkWasAssigned(alias, scope) { - let variable = scope.set.get(alias); + const variable = scope.set.get(alias); if (!variable) { return; @@ -94,7 +94,7 @@ module.exports = { // The alias has been declared and not assigned: check it was // assigned later in the same scope. if (!variable.references.some(function(reference) { - let write = reference.writeExpr; + const write = reference.writeExpr; return ( reference.from === scope && @@ -115,7 +115,7 @@ module.exports = { * @returns {void} */ function ensureWasAssigned() { - let scope = context.getScope(); + const scope = context.getScope(); aliases.forEach(function(alias) { checkWasAssigned(alias, scope); @@ -128,8 +128,8 @@ module.exports = { "FunctionDeclaration:exit": ensureWasAssigned, VariableDeclarator: function(node) { - let id = node.id; - let isDestructuring = + const id = node.id; + const isDestructuring = id.type === "ArrayPattern" || id.type === "ObjectPattern"; if (node.init !== null && !isDestructuring) { diff --git a/tools/eslint/lib/rules/constructor-super.js b/tools/eslint/lib/rules/constructor-super.js index 7b7e8cfd3e..68bbc5ec18 100644 --- a/tools/eslint/lib/rules/constructor-super.js +++ b/tools/eslint/lib/rules/constructor-super.js @@ -164,8 +164,8 @@ module.exports = { if (isConstructorFunction(node)) { // Class > ClassBody > MethodDefinition > FunctionExpression - let classNode = node.parent.parent.parent; - let superClass = classNode.superClass; + const classNode = node.parent.parent.parent; + const superClass = classNode.superClass; funcInfo = { upper: funcInfo, @@ -193,7 +193,7 @@ module.exports = { * @returns {void} */ onCodePathEnd: function(codePath, node) { - let hasExtends = funcInfo.hasExtends; + const hasExtends = funcInfo.hasExtends; // Pop. funcInfo = funcInfo.upper; @@ -203,9 +203,9 @@ module.exports = { } // Reports if `super()` lacked. - let segments = codePath.returnedSegments; - let calledInEveryPaths = segments.every(isCalledInEveryPath); - let calledInSomePaths = segments.some(isCalledInSomePath); + const segments = codePath.returnedSegments; + const calledInEveryPaths = segments.every(isCalledInEveryPath); + const calledInSomePaths = segments.some(isCalledInSomePath); if (!calledInEveryPaths) { context.report({ @@ -228,14 +228,14 @@ module.exports = { } // Initialize info. - let info = segInfoMap[segment.id] = { + const info = segInfoMap[segment.id] = { calledInSomePaths: false, calledInEveryPaths: false, validNodes: [] }; // When there are previous segments, aggregates these. - let prevSegments = segment.prevSegments; + const prevSegments = segment.prevSegments; if (prevSegments.length > 0) { info.calledInSomePaths = prevSegments.some(isCalledInSomePath); @@ -258,13 +258,13 @@ module.exports = { } // Update information inside of the loop. - let isRealLoop = toSegment.prevSegments.length >= 2; + const isRealLoop = toSegment.prevSegments.length >= 2; funcInfo.codePath.traverseSegments( {first: toSegment, last: fromSegment}, function(segment) { - let info = segInfoMap[segment.id]; - let prevSegments = segment.prevSegments; + const info = segInfoMap[segment.id]; + const prevSegments = segment.prevSegments; // Updates flags. info.calledInSomePaths = prevSegments.some(isCalledInSomePath); @@ -272,12 +272,12 @@ module.exports = { // If flags become true anew, reports the valid nodes. if (info.calledInSomePaths || isRealLoop) { - let nodes = info.validNodes; + const nodes = info.validNodes; info.validNodes = []; for (let i = 0; i < nodes.length; ++i) { - let node = nodes[i]; + const node = nodes[i]; context.report({ message: "Unexpected duplicate 'super()'.", @@ -306,12 +306,12 @@ module.exports = { // Reports if needed. if (funcInfo.hasExtends) { - let segments = funcInfo.codePath.currentSegments; + const segments = funcInfo.codePath.currentSegments; let duplicate = false; let info = null; for (let i = 0; i < segments.length; ++i) { - let segment = segments[i]; + const segment = segments[i]; if (segment.reachable) { info = segInfoMap[segment.id]; @@ -360,13 +360,13 @@ module.exports = { } // Returning argument is a substitute of 'super()'. - let segments = funcInfo.codePath.currentSegments; + const segments = funcInfo.codePath.currentSegments; for (let i = 0; i < segments.length; ++i) { - let segment = segments[i]; + const segment = segments[i]; if (segment.reachable) { - let info = segInfoMap[segment.id]; + const info = segInfoMap[segment.id]; info.calledInSomePaths = info.calledInEveryPaths = true; } diff --git a/tools/eslint/lib/rules/curly.js b/tools/eslint/lib/rules/curly.js index 912f321565..5ca7713763 100644 --- a/tools/eslint/lib/rules/curly.js +++ b/tools/eslint/lib/rules/curly.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -53,12 +53,12 @@ module.exports = { create: function(context) { - let multiOnly = (context.options[0] === "multi"); - let multiLine = (context.options[0] === "multi-line"); - let multiOrNest = (context.options[0] === "multi-or-nest"); - let consistent = (context.options[1] === "consistent"); + const multiOnly = (context.options[0] === "multi"); + const multiLine = (context.options[0] === "multi-line"); + const multiOrNest = (context.options[0] === "multi-or-nest"); + const consistent = (context.options[1] === "consistent"); - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -71,7 +71,7 @@ module.exports = { * @private */ function isCollapsedOneLiner(node) { - let before = sourceCode.getTokenBefore(node), + const before = sourceCode.getTokenBefore(node), last = sourceCode.getLastToken(node); return before.loc.start.line === last.loc.end.line; @@ -84,7 +84,7 @@ module.exports = { * @private */ function isOneLiner(node) { - let first = sourceCode.getFirstToken(node), + const first = sourceCode.getFirstToken(node), last = sourceCode.getLastToken(node); return first.loc.start.line === last.loc.end.line; @@ -189,7 +189,7 @@ module.exports = { * properties. */ function prepareCheck(node, body, name, suffix) { - let hasBlock = (body.type === "BlockStatement"); + const hasBlock = (body.type === "BlockStatement"); let expected = null; if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) { @@ -234,7 +234,7 @@ module.exports = { * information. */ function prepareIfChecks(node) { - let preparedChecks = []; + const preparedChecks = []; do { preparedChecks.push(prepareCheck(node, node.consequent, "if", "condition")); @@ -252,7 +252,7 @@ module.exports = { * all have braces. * If all nodes shouldn't have braces, make sure they don't. */ - let expected = preparedChecks.some(function(preparedCheck) { + const expected = preparedChecks.some(function(preparedCheck) { if (preparedCheck.expected !== null) { return preparedCheck.expected; } diff --git a/tools/eslint/lib/rules/default-case.js b/tools/eslint/lib/rules/default-case.js index 9bcb1c065b..8a6135d24b 100644 --- a/tools/eslint/lib/rules/default-case.js +++ b/tools/eslint/lib/rules/default-case.js @@ -4,7 +4,7 @@ */ "use strict"; -let DEFAULT_COMMENT_PATTERN = /^no default$/; +const DEFAULT_COMMENT_PATTERN = /^no default$/; //------------------------------------------------------------------------------ // Rule Definition @@ -30,12 +30,12 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let commentPattern = options.commentPattern ? + const options = context.options[0] || {}; + const commentPattern = options.commentPattern ? new RegExp(options.commentPattern) : DEFAULT_COMMENT_PATTERN; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -67,18 +67,16 @@ module.exports = { return; } - let hasDefault = node.cases.some(function(v) { + const hasDefault = node.cases.some(function(v) { return v.test === null; }); if (!hasDefault) { let comment; - let comments; - let lastCase = last(node.cases); - - comments = sourceCode.getComments(lastCase).trailing; + const lastCase = last(node.cases); + const comments = sourceCode.getComments(lastCase).trailing; if (comments.length) { comment = last(comments); diff --git a/tools/eslint/lib/rules/dot-location.js b/tools/eslint/lib/rules/dot-location.js index 5a5ad353bf..f632ce5190 100644 --- a/tools/eslint/lib/rules/dot-location.js +++ b/tools/eslint/lib/rules/dot-location.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -28,12 +28,12 @@ module.exports = { create: function(context) { - let config = context.options[0]; + const config = context.options[0]; // default to onObject if no preference is passed - let onObject = config === "object" || !config; + const onObject = config === "object" || !config; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Reports if the dot between object and property is on the correct loccation. @@ -43,7 +43,7 @@ module.exports = { * @returns {void} */ function checkDotLocation(obj, prop, node) { - let dot = sourceCode.getTokenBefore(prop); + const dot = sourceCode.getTokenBefore(prop); if (dot.type === "Punctuator" && dot.value === ".") { if (onObject) { diff --git a/tools/eslint/lib/rules/dot-notation.js b/tools/eslint/lib/rules/dot-notation.js index e359b118cc..2cbbe07eb1 100644 --- a/tools/eslint/lib/rules/dot-notation.js +++ b/tools/eslint/lib/rules/dot-notation.js @@ -8,8 +8,8 @@ // Rule Definition //------------------------------------------------------------------------------ -let validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; -let keywords = require("../util/keywords"); +const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/; +const keywords = require("../util/keywords"); module.exports = { meta: { @@ -36,8 +36,8 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords; + const options = context.options[0] || {}; + const allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords; let allowPattern; diff --git a/tools/eslint/lib/rules/eol-last.js b/tools/eslint/lib/rules/eol-last.js index faa4521cf1..15021dd092 100644 --- a/tools/eslint/lib/rules/eol-last.js +++ b/tools/eslint/lib/rules/eol-last.js @@ -35,7 +35,7 @@ module.exports = { Program: function checkBadEOF(node) { - let sourceCode = context.getSourceCode(), + const sourceCode = context.getSourceCode(), src = sourceCode.getText(), location = {column: 1}, linebreakStyle = context.options[0] || "unix", diff --git a/tools/eslint/lib/rules/eqeqeq.js b/tools/eslint/lib/rules/eqeqeq.js index 124c9dd61a..7bec40ad38 100644 --- a/tools/eslint/lib/rules/eqeqeq.js +++ b/tools/eslint/lib/rules/eqeqeq.js @@ -17,15 +17,49 @@ module.exports = { recommended: false }, - schema: [ - { - enum: ["always", "smart", "allow-null"] - } - ] + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["always"] + }, + { + type: "object", + properties: { + null: { + enum: ["always", "never", "ignore"] + } + }, + additionalProperties: false + } + ], + additionalItems: false + }, + { + type: "array", + items: [ + { + enum: ["smart", "allow-null"] + } + ], + additionalItems: false + } + ] + } }, create: function(context) { - let sourceCode = context.getSourceCode(); + const config = context.options[0] || "always"; + const options = context.options[1] || {}; + const sourceCode = context.getSourceCode(); + + const nullOption = (config === "always") ? + options.null || "always" : + "ignore"; + const enforceRuleForNull = (nullOption === "always"); + const enforceInverseRuleForNull = (nullOption === "never"); /** * Checks if an expression is a typeof expression @@ -76,33 +110,48 @@ module.exports = { * @private */ function getOperatorLocation(node) { - let opToken = sourceCode.getTokenAfter(node.left); + const opToken = sourceCode.getTokenAfter(node.left); return {line: opToken.loc.start.line, column: opToken.loc.start.column}; } + /** + * Reports a message for this rule. + * @param {ASTNode} node The binary expression node that was checked + * @param {string} message The message to report + * @returns {void} + * @private + */ + function report(node, message) { + context.report({ + node: node, + loc: getOperatorLocation(node), + message: message, + data: { op: node.operator.charAt(0) } + }); + } + return { BinaryExpression: function(node) { + const isNull = isNullCheck(node); + if (node.operator !== "==" && node.operator !== "!=") { + if (enforceInverseRuleForNull && isNull) { + report(node, "Expected '{{op}}=' and instead saw '{{op}}=='."); + } return; } - if (context.options[0] === "smart" && (isTypeOfBinary(node) || - areLiteralsAndSameType(node) || isNullCheck(node))) { + if (config === "smart" && (isTypeOfBinary(node) || + areLiteralsAndSameType(node) || isNull)) { return; } - if (context.options[0] === "allow-null" && isNullCheck(node)) { + if (!enforceRuleForNull && isNull) { return; } - context.report({ - node: node, - loc: getOperatorLocation(node), - message: "Expected '{{op}}=' and instead saw '{{op}}'.", - data: { op: node.operator } - }); - + report(node, "Expected '{{op}}==' and instead saw '{{op}}='."); } }; diff --git a/tools/eslint/lib/rules/func-call-spacing.js b/tools/eslint/lib/rules/func-call-spacing.js new file mode 100644 index 0000000000..b0fc0f2ef3 --- /dev/null +++ b/tools/eslint/lib/rules/func-call-spacing.js @@ -0,0 +1,153 @@ +/** + * @fileoverview Rule to control spacing within function calls + * @author Matt DuVall <http://www.mattduvall.com> + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "require or disallow spacing between `function` identifiers and their invocations", + category: "Stylistic Issues", + recommended: false + }, + + fixable: "whitespace", + schema: { + anyOf: [ + { + type: "array", + items: [ + { + enum: ["never"] + } + ], + minItems: 0, + maxItems: 1 + }, + { + type: "array", + items: [ + { + enum: ["always"] + }, + { + type: "object", + properties: { + allowNewlines: { + type: "boolean" + } + }, + additionalProperties: false + } + ], + minItems: 0, + maxItems: 2 + } + ] + } + }, + + create: function(context) { + + const never = context.options[0] !== "always"; + const allowNewlines = !never && context.options[1] && context.options[1].allowNewlines; + const sourceCode = context.getSourceCode(); + const text = sourceCode.getText(); + + /** + * Check if open space is present in a function name + * @param {ASTNode} node node to evaluate + * @returns {void} + * @private + */ + function checkSpacing(node) { + const lastCalleeToken = sourceCode.getLastToken(node.callee); + let prevToken = lastCalleeToken; + let parenToken = sourceCode.getTokenAfter(lastCalleeToken); + + // advances to an open parenthesis. + while ( + parenToken && + parenToken.range[1] < node.range[1] && + parenToken.value !== "(" + ) { + prevToken = parenToken; + parenToken = sourceCode.getTokenAfter(parenToken); + } + + // Parens in NewExpression are optional + if (!(parenToken && parenToken.range[1] < node.range[1])) { + return; + } + + const hasWhitespace = sourceCode.isSpaceBetweenTokens(prevToken, parenToken); + const hasNewline = hasWhitespace && + /\n/.test(text.slice(prevToken.range[1], parenToken.range[0]).replace(/\/\*.*?\*\//g, "")); + + /* + * never allowNewlines hasWhitespace hasNewline message + * F F F F Missing space between function name and paren. + * F F F T (Invalid `!hasWhitespace && hasNewline`) + * F F T T Unexpected newline between function name and paren. + * F F T F (OK) + * F T T F (OK) + * F T T T (OK) + * F T F T (Invalid `!hasWhitespace && hasNewline`) + * F T F F Missing space between function name and paren. + * T T F F (Invalid `never && allowNewlines`) + * T T F T (Invalid `!hasWhitespace && hasNewline`) + * T T T T (Invalid `never && allowNewlines`) + * T T T F (Invalid `never && allowNewlines`) + * T F T F Unexpected space between function name and paren. + * T F T T Unexpected space between function name and paren. + * T F F T (Invalid `!hasWhitespace && hasNewline`) + * T F F F (OK) + * + * T T Unexpected space between function name and paren. + * F F Missing space between function name and paren. + * F F T Unexpected newline between function name and paren. + */ + + if (never && hasWhitespace) { + context.report({ + node: node, + loc: lastCalleeToken.loc.start, + message: "Unexpected space between function name and paren.", + fix: function(fixer) { + return fixer.removeRange([prevToken.range[1], parenToken.range[0]]); + } + }); + } else if (!never && !hasWhitespace) { + context.report({ + node: node, + loc: lastCalleeToken.loc.start, + message: "Missing space between function name and paren.", + fix: function(fixer) { + return fixer.insertTextBefore(parenToken, " "); + } + }); + } else if (!never && !allowNewlines && hasNewline) { + context.report({ + node: node, + loc: lastCalleeToken.loc.start, + message: "Unexpected newline between function name and paren.", + fix: function(fixer) { + return fixer.replaceTextRange([prevToken.range[1], parenToken.range[0]], " "); + } + }); + } + } + + return { + CallExpression: checkSpacing, + NewExpression: checkSpacing + }; + + } +}; diff --git a/tools/eslint/lib/rules/func-names.js b/tools/eslint/lib/rules/func-names.js index 12d8d34d5d..a2fe1e972d 100644 --- a/tools/eslint/lib/rules/func-names.js +++ b/tools/eslint/lib/rules/func-names.js @@ -34,7 +34,7 @@ module.exports = { }, create: function(context) { - let never = context.options[0] === "never"; + const never = context.options[0] === "never"; /** * Determines whether the current FunctionExpression node is a get, set, or @@ -42,7 +42,7 @@ module.exports = { * @returns {boolean} True if the node is a get, set, or shorthand method. */ function isObjectOrClassMethod() { - let parent = context.getAncestors().pop(); + const parent = context.getAncestors().pop(); return (parent.type === "MethodDefinition" || ( parent.type === "Property" && ( @@ -57,13 +57,13 @@ module.exports = { "FunctionExpression:exit": function(node) { // Skip recursive functions. - let nameVar = context.getDeclaredVariables(node)[0]; + const nameVar = context.getDeclaredVariables(node)[0]; if (isFunctionName(nameVar) && nameVar.references.length > 0) { return; } - let name = node.id && node.id.name; + const name = node.id && node.id.name; if (never) { if (name) { diff --git a/tools/eslint/lib/rules/func-style.js b/tools/eslint/lib/rules/func-style.js index e1cdc1d1bd..47cb76ee22 100644 --- a/tools/eslint/lib/rules/func-style.js +++ b/tools/eslint/lib/rules/func-style.js @@ -34,16 +34,12 @@ module.exports = { create: function(context) { - let style = context.options[0], + const style = context.options[0], allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions === true, enforceDeclarations = (style === "declaration"), stack = []; - let nodesToCheck = { - Program: function() { - stack = []; - }, - + const nodesToCheck = { FunctionDeclaration: function(node) { stack.push(false); @@ -79,7 +75,7 @@ module.exports = { }; nodesToCheck["ArrowFunctionExpression:exit"] = function(node) { - let hasThisExpr = stack.pop(); + const hasThisExpr = stack.pop(); if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { context.report(node.parent, "Expected a function declaration."); diff --git a/tools/eslint/lib/rules/generator-star-spacing.js b/tools/eslint/lib/rules/generator-star-spacing.js index e55fe9b512..1257617187 100644 --- a/tools/eslint/lib/rules/generator-star-spacing.js +++ b/tools/eslint/lib/rules/generator-star-spacing.js @@ -40,7 +40,7 @@ module.exports = { create: function(context) { - let mode = (function(option) { + const mode = (function(option) { if (!option || typeof option === "string") { return { before: { before: true, after: false }, @@ -52,7 +52,7 @@ module.exports = { return option; }(context.options[0])); - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Gets `*` token from a given node. @@ -83,11 +83,11 @@ module.exports = { */ function checkSpacing(side, leftToken, rightToken) { if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) { - let after = leftToken.value === "*"; - let spaceRequired = mode[side]; - let node = after ? leftToken : rightToken; - let type = spaceRequired ? "Missing" : "Unexpected"; - let message = type + " space " + side + " *."; + const after = leftToken.value === "*"; + const spaceRequired = mode[side]; + const node = after ? leftToken : rightToken; + const type = spaceRequired ? "Missing" : "Unexpected"; + const message = type + " space " + side + " *."; context.report({ node: node, @@ -111,7 +111,7 @@ module.exports = { * @returns {void} */ function checkFunction(node) { - let prevToken, starToken, nextToken; + let starToken; if (!node.generator) { return; @@ -124,12 +124,14 @@ module.exports = { } // Only check before when preceded by `function`|`static` keyword - prevToken = sourceCode.getTokenBefore(starToken); + const prevToken = sourceCode.getTokenBefore(starToken); + if (prevToken.value === "function" || prevToken.value === "static") { checkSpacing("before", prevToken, starToken); } - nextToken = sourceCode.getTokenAfter(starToken); + const nextToken = sourceCode.getTokenAfter(starToken); + checkSpacing("after", starToken, nextToken); } diff --git a/tools/eslint/lib/rules/global-require.js b/tools/eslint/lib/rules/global-require.js index 0a104bc349..6addefc8c8 100644 --- a/tools/eslint/lib/rules/global-require.js +++ b/tools/eslint/lib/rules/global-require.js @@ -5,7 +5,7 @@ "use strict"; -let ACCEPTABLE_PARENTS = [ +const ACCEPTABLE_PARENTS = [ "AssignmentExpression", "VariableDeclarator", "MemberExpression", @@ -23,7 +23,7 @@ let ACCEPTABLE_PARENTS = [ * @returns {Reference|null} Returns the found reference or null if none were found. */ function findReference(scope, node) { - let references = scope.references.filter(function(reference) { + const references = scope.references.filter(function(reference) { return reference.identifier.range[0] === node.range[0] && reference.identifier.range[1] === node.range[1]; }); @@ -43,7 +43,7 @@ function findReference(scope, node) { * @returns {boolean} Whether or not the name is shadowed. */ function isShadowed(scope, node) { - let reference = findReference(scope, node); + const reference = findReference(scope, node); return reference && reference.resolved && reference.resolved.defs.length > 0; } @@ -62,13 +62,13 @@ module.exports = { create: function(context) { return { CallExpression: function(node) { - let currentScope = context.getScope(), - isGoodRequire; + const currentScope = context.getScope(); if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) { - isGoodRequire = context.getAncestors().every(function(parent) { + const isGoodRequire = context.getAncestors().every(function(parent) { return ACCEPTABLE_PARENTS.indexOf(parent.type) > -1; }); + if (!isGoodRequire) { context.report(node, "Unexpected require()."); } diff --git a/tools/eslint/lib/rules/guard-for-in.js b/tools/eslint/lib/rules/guard-for-in.js index 7e4dfbc43e..bc25b2c9cb 100644 --- a/tools/eslint/lib/rules/guard-for-in.js +++ b/tools/eslint/lib/rules/guard-for-in.js @@ -30,7 +30,7 @@ module.exports = { * If the for-in statement has {}, then the real body is the body * of the BlockStatement. Otherwise, just use body as provided. */ - let body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body; + const body = node.body.type === "BlockStatement" ? node.body.body[0] : node.body; if (body && body.type !== "IfStatement") { context.report(node, "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype."); diff --git a/tools/eslint/lib/rules/handle-callback-err.js b/tools/eslint/lib/rules/handle-callback-err.js index 836d3a6de7..c6f464aa1b 100644 --- a/tools/eslint/lib/rules/handle-callback-err.js +++ b/tools/eslint/lib/rules/handle-callback-err.js @@ -26,7 +26,7 @@ module.exports = { create: function(context) { - let errorArgument = context.options[0] || "err"; + const errorArgument = context.options[0] || "err"; /** * Checks if the given argument should be interpreted as a regexp pattern. @@ -34,7 +34,7 @@ module.exports = { * @returns {boolean} Whether or not the string should be interpreted as a pattern. */ function isPattern(stringToCheck) { - let firstChar = stringToCheck[0]; + const firstChar = stringToCheck[0]; return firstChar === "^"; } @@ -46,7 +46,7 @@ module.exports = { */ function matchesConfiguredErrorName(name) { if (isPattern(errorArgument)) { - let regexp = new RegExp(errorArgument); + const regexp = new RegExp(errorArgument); return regexp.test(name); } @@ -70,7 +70,7 @@ module.exports = { * @returns {void} */ function checkForError(node) { - let scope = context.getScope(), + const scope = context.getScope(), parameters = getParameters(scope), firstParameter = parameters[0]; diff --git a/tools/eslint/lib/rules/id-blacklist.js b/tools/eslint/lib/rules/id-blacklist.js index d2be0d12c3..2d2b40100a 100644 --- a/tools/eslint/lib/rules/id-blacklist.js +++ b/tools/eslint/lib/rules/id-blacklist.js @@ -34,7 +34,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - let blacklist = context.options; + const blacklist = context.options; /** @@ -75,7 +75,7 @@ module.exports = { return { Identifier: function(node) { - let name = node.name, + const name = node.name, effectiveParent = (node.parent.type === "MemberExpression") ? node.parent.parent : node.parent; // MemberExpressions get special rules diff --git a/tools/eslint/lib/rules/id-length.js b/tools/eslint/lib/rules/id-length.js index d337cdacce..3f0d233529 100644 --- a/tools/eslint/lib/rules/id-length.js +++ b/tools/eslint/lib/rules/id-length.js @@ -45,18 +45,18 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let minLength = typeof options.min !== "undefined" ? options.min : 2; - let maxLength = typeof options.max !== "undefined" ? options.max : Infinity; - let properties = options.properties !== "never"; - let exceptions = (options.exceptions ? options.exceptions : []) + const options = context.options[0] || {}; + const minLength = typeof options.min !== "undefined" ? options.min : 2; + const maxLength = typeof options.max !== "undefined" ? options.max : Infinity; + const properties = options.properties !== "never"; + const exceptions = (options.exceptions ? options.exceptions : []) .reduce(function(obj, item) { obj[item] = true; return obj; }, {}); - let SUPPORTED_EXPRESSIONS = { + const SUPPORTED_EXPRESSIONS = { MemberExpression: properties && function(parent) { return !parent.computed && ( @@ -87,17 +87,17 @@ module.exports = { return { Identifier: function(node) { - let name = node.name; - let parent = node.parent; + const name = node.name; + const parent = node.parent; - let isShort = name.length < minLength; - let isLong = name.length > maxLength; + const isShort = name.length < minLength; + const isLong = name.length > maxLength; if (!(isShort || isLong) || exceptions[name]) { return; // Nothing to report } - let isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; + const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; if (isValidExpression && (isValidExpression === true || isValidExpression(parent, node))) { context.report( diff --git a/tools/eslint/lib/rules/id-match.js b/tools/eslint/lib/rules/id-match.js index 4128cbf3d1..777dacfbca 100644 --- a/tools/eslint/lib/rules/id-match.js +++ b/tools/eslint/lib/rules/id-match.js @@ -38,10 +38,10 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - let pattern = context.options[0] || "^.+$", + const pattern = context.options[0] || "^.+$", regexp = new RegExp(pattern); - let options = context.options[1] || {}, + const options = context.options[1] || {}, properties = !!options.properties, onlyDeclarations = !!options.onlyDeclarations; @@ -84,7 +84,7 @@ module.exports = { return { Identifier: function(node) { - let name = node.name, + const name = node.name, parent = node.parent, effectiveParent = (parent.type === "MemberExpression") ? parent.parent : parent; @@ -122,7 +122,7 @@ module.exports = { } } else { - let isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator"; + const isDeclaration = effectiveParent.type === "FunctionDeclaration" || effectiveParent.type === "VariableDeclarator"; if (onlyDeclarations && !isDeclaration) { return; diff --git a/tools/eslint/lib/rules/indent.js b/tools/eslint/lib/rules/indent.js index b24f942d1a..287e8dea37 100644 --- a/tools/eslint/lib/rules/indent.js +++ b/tools/eslint/lib/rules/indent.js @@ -11,8 +11,6 @@ //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ -let util = require("util"); -let lodash = require("lodash"); module.exports = { meta: { @@ -84,12 +82,12 @@ module.exports = { create: function(context) { - let MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}."; - let DEFAULT_VARIABLE_INDENT = 1; + const MESSAGE = "Expected indentation of {{needed}} {{type}} {{characters}} but found {{gotten}}."; + const DEFAULT_VARIABLE_INDENT = 1; let indentType = "space"; let indentSize = 4; - let options = { + const options = { SwitchCase: 0, VariableDeclarator: { var: DEFAULT_VARIABLE_INDENT, @@ -99,7 +97,7 @@ module.exports = { outerIIFEBody: null }; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); if (context.options.length) { if (context.options[0] === "tab") { @@ -111,10 +109,10 @@ module.exports = { } if (context.options[1]) { - let opts = context.options[1]; + const opts = context.options[1]; options.SwitchCase = opts.SwitchCase || 0; - let variableDeclaratorRules = opts.VariableDeclarator; + const variableDeclaratorRules = opts.VariableDeclarator; if (typeof variableDeclaratorRules === "number") { options.VariableDeclarator = { @@ -123,7 +121,7 @@ module.exports = { const: variableDeclaratorRules }; } else if (typeof variableDeclaratorRules === "object") { - lodash.assign(options.VariableDeclarator, variableDeclaratorRules); + Object.assign(options.VariableDeclarator, variableDeclaratorRules); } if (typeof opts.outerIIFEBody === "number") { @@ -136,12 +134,12 @@ module.exports = { } } - let indentPattern = { + const indentPattern = { normal: indentType === "space" ? /^ +/ : /^\t+/, excludeCommas: indentType === "space" ? /^[ ,]+/ : /^[\t,]+/ }; - let caseIndentStore = {}; + const caseIndentStore = {}; /** * Reports a given indent violation and properly pluralizes the message @@ -153,13 +151,13 @@ module.exports = { * @returns {void} */ function report(node, needed, gotten, loc, isLastNodeCheck) { - let msgContext = { + const msgContext = { needed: needed, type: indentType, characters: needed === 1 ? "character" : "characters", gotten: gotten }; - let indentChar = indentType === "space" ? " " : "\t"; + const indentChar = indentType === "space" ? " " : "\t"; /** * Responsible for fixing the indentation issue fix @@ -170,7 +168,7 @@ module.exports = { let rangeToFix = []; if (needed > gotten) { - let spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future + const spaces = "" + new Array(needed - gotten + 1).join(indentChar); // replace with repeat in future if (isLastNodeCheck === true) { rangeToFix = [ @@ -232,10 +230,10 @@ module.exports = { * @returns {int} Indent */ function getNodeIndent(node, byLastLine, excludeCommas) { - let token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node); - let src = sourceCode.getText(token, token.loc.start.column); - let regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal; - let indent = regExp.exec(src); + const token = byLastLine ? sourceCode.getLastToken(node) : sourceCode.getFirstToken(node); + const src = sourceCode.getText(token, token.loc.start.column); + const regExp = excludeCommas ? indentPattern.excludeCommas : indentPattern.normal; + const indent = regExp.exec(src); return indent ? indent[0].length : 0; } @@ -247,7 +245,7 @@ module.exports = { * @returns {boolean} true if its the first in the its start line */ function isNodeFirstInLine(node, byEndLocation) { - let firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node), + const firstToken = byEndLocation === true ? sourceCode.getLastToken(node, 1) : sourceCode.getTokenBefore(node), startLine = byEndLocation === true ? node.loc.end.line : node.loc.start.line, endLine = firstToken ? firstToken.loc.end.line : -1; @@ -262,7 +260,7 @@ module.exports = { * @returns {void} */ function checkNodeIndent(node, indent, excludeCommas) { - let nodeIndent = getNodeIndent(node, false, excludeCommas); + const nodeIndent = getNodeIndent(node, false, excludeCommas); if ( node.type !== "ArrayExpression" && node.type !== "ObjectExpression" && @@ -282,7 +280,7 @@ module.exports = { function checkNodesIndent(nodes, indent, excludeCommas) { nodes.forEach(function(node) { if (node.type === "IfStatement" && node.alternate) { - let elseToken = sourceCode.getTokenBefore(node.alternate); + const elseToken = sourceCode.getTokenBefore(node.alternate); checkNodeIndent(elseToken, indent, excludeCommas); } @@ -297,8 +295,8 @@ module.exports = { * @returns {void} */ function checkLastNodeLineIndent(node, lastLineIndent) { - let lastToken = sourceCode.getLastToken(node); - let endIndent = getNodeIndent(lastToken, true); + const lastToken = sourceCode.getLastToken(node); + const endIndent = getNodeIndent(lastToken, true); if (endIndent !== lastLineIndent && isNodeFirstInLine(node, true)) { report( @@ -318,7 +316,7 @@ module.exports = { * @returns {void} */ function checkFirstNodeLineIndent(node, firstLineIndent) { - let startIndent = getNodeIndent(node, false); + const startIndent = getNodeIndent(node, false); if (startIndent !== firstLineIndent && isNodeFirstInLine(node)) { report( @@ -387,7 +385,7 @@ module.exports = { * @returns {boolean} True if arguments are multi-line */ function isArgBeforeCalleeNodeMultiline(node) { - let parent = node.parent; + const parent = node.parent; if (parent.arguments.length >= 2 && parent.arguments[1] === node) { return parent.arguments[0].loc.end.line > parent.arguments[0].loc.start.line; @@ -402,7 +400,7 @@ module.exports = { * @returns {boolean} True if the node is the outer IIFE */ function isOuterIIFE(node) { - let parent = node.parent; + const parent = node.parent; let stmt = parent.parent; /* @@ -459,7 +457,7 @@ module.exports = { * * Looks for 'Models' */ - let calleeNode = node.parent; // FunctionExpression + const calleeNode = node.parent; // FunctionExpression let indent; if (calleeNode.parent && @@ -475,7 +473,7 @@ module.exports = { } if (calleeNode.parent.type === "CallExpression") { - let calleeParent = calleeNode.parent; + const calleeParent = calleeNode.parent; if (calleeNode.type !== "FunctionExpression" && calleeNode.type !== "ArrowFunctionExpression") { if (calleeParent && calleeParent.loc.start.line < node.loc.start.line) { @@ -500,7 +498,7 @@ module.exports = { indent += functionOffset; // check if the node is inside a variable - let parentVarNode = getVariableDeclaratorNode(node); + const parentVarNode = getVariableDeclaratorNode(node); if (parentVarNode && isNodeInVarOnTop(node, parentVarNode)) { indent += indentSize * options.VariableDeclarator[parentVarNode.parent.kind]; @@ -520,7 +518,7 @@ module.exports = { * @returns {boolean} Whether or not the block starts and ends on the same line. */ function isSingleLineNode(node) { - let lastToken = sourceCode.getLastToken(node), + const lastToken = sourceCode.getLastToken(node), startLine = node.loc.start.line, endLine = lastToken.loc.end.line; @@ -567,11 +565,11 @@ module.exports = { let nodeIndent; let elementsIndent; - let parentVarNode = getVariableDeclaratorNode(node); + const parentVarNode = getVariableDeclaratorNode(node); // TODO - come up with a better strategy in future if (isNodeFirstInLine(node)) { - let parent = node.parent; + const parent = node.parent; let effectiveParent = parent; if (parent.type === "MemberExpression") { @@ -668,7 +666,7 @@ module.exports = { * For this statements we should check indent from statement beginning, * not from the beginning of the block. */ - let statementsWithProperties = [ + const statementsWithProperties = [ "IfStatement", "WhileStatement", "ForStatement", "ForInStatement", "ForOfStatement", "DoWhileStatement", "ClassDeclaration" ]; @@ -680,7 +678,7 @@ module.exports = { if (node.type === "IfStatement" && node.consequent.type !== "BlockStatement") { nodesToCheck = [node.consequent]; - } else if (util.isArray(node.body)) { + } else if (Array.isArray(node.body)) { nodesToCheck = node.body; } else { nodesToCheck = [node.body]; @@ -703,7 +701,7 @@ module.exports = { */ function filterOutSameLineVars(node) { return node.declarations.reduce(function(finalCollection, elem) { - let lastElem = finalCollection[finalCollection.length - 1]; + const lastElem = finalCollection[finalCollection.length - 1]; if ((elem.loc.start.line !== node.loc.start.line && !lastElem) || (lastElem && lastElem.loc.start.line !== elem.loc.start.line)) { @@ -720,11 +718,11 @@ module.exports = { * @returns {void} */ function checkIndentInVariableDeclarations(node) { - let elements = filterOutSameLineVars(node); - let nodeIndent = getNodeIndent(node); - let lastElement = elements[elements.length - 1]; + const elements = filterOutSameLineVars(node); + const nodeIndent = getNodeIndent(node); + const lastElement = elements[elements.length - 1]; - let elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind]; + const elementsIndent = nodeIndent + indentSize * options.VariableDeclarator[node.kind]; // Comma can be placed before declaration checkNodesIndent(elements, elementsIndent, true); @@ -734,7 +732,7 @@ module.exports = { return; } - let tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement); + const tokenBeforeLastElement = sourceCode.getTokenBefore(lastElement); if (tokenBeforeLastElement.value === ",") { @@ -764,7 +762,7 @@ module.exports = { * @returns {int} indent size */ function expectedCaseIndent(node, switchIndent) { - let switchNode = (node.type === "SwitchStatement") ? node : node.parent; + const switchNode = (node.type === "SwitchStatement") ? node : node.parent; let caseIndent; if (caseIndentStore[switchNode.loc.start.line]) { @@ -849,11 +847,11 @@ module.exports = { return; } - let propertyIndent = getNodeIndent(node) + indentSize * options.MemberExpression; + const propertyIndent = getNodeIndent(node) + indentSize * options.MemberExpression; - let checkNodes = [node.property]; + const checkNodes = [node.property]; - let dot = context.getTokenBefore(node.property); + const dot = context.getTokenBefore(node.property); if (dot.type === "Punctuator" && dot.value === ".") { checkNodes.push(dot); @@ -865,8 +863,8 @@ module.exports = { SwitchStatement: function(node) { // Switch is not a 'BlockStatement' - let switchIndent = getNodeIndent(node); - let caseIndent = expectedCaseIndent(node, switchIndent); + const switchIndent = getNodeIndent(node); + const caseIndent = expectedCaseIndent(node, switchIndent); checkNodesIndent(node.cases, caseIndent); @@ -880,7 +878,7 @@ module.exports = { if (isSingleLineNode(node)) { return; } - let caseIndent = expectedCaseIndent(node); + const caseIndent = expectedCaseIndent(node); checkNodesIndent(node.consequent, caseIndent + indentSize); } diff --git a/tools/eslint/lib/rules/init-declarations.js b/tools/eslint/lib/rules/init-declarations.js index e51596f7af..bbcb3a92ff 100644 --- a/tools/eslint/lib/rules/init-declarations.js +++ b/tools/eslint/lib/rules/init-declarations.js @@ -26,8 +26,8 @@ function isForLoop(block) { * @returns {boolean} `true` when the node has its initializer. */ function isInitialized(node) { - let declaration = node.parent; - let block = declaration.parent; + const declaration = node.parent; + const block = declaration.parent; if (isForLoop(block)) { if (block.type === "ForStatement") { @@ -87,11 +87,11 @@ module.exports = { create: function(context) { - let MODE_ALWAYS = "always", + const MODE_ALWAYS = "always", MODE_NEVER = "never"; - let mode = context.options[0] || MODE_ALWAYS; - let params = context.options[1] || {}; + const mode = context.options[0] || MODE_ALWAYS; + const params = context.options[1] || {}; //-------------------------------------------------------------------------- // Public API @@ -100,11 +100,11 @@ module.exports = { return { "VariableDeclaration:exit": function(node) { - let kind = node.kind, + const kind = node.kind, declarations = node.declarations; for (let i = 0; i < declarations.length; ++i) { - let declaration = declarations[i], + const declaration = declarations[i], id = declaration.id, initialized = isInitialized(declaration), isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent); diff --git a/tools/eslint/lib/rules/jsx-quotes.js b/tools/eslint/lib/rules/jsx-quotes.js index c3d87623cd..99dfda76a2 100644 --- a/tools/eslint/lib/rules/jsx-quotes.js +++ b/tools/eslint/lib/rules/jsx-quotes.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -let QUOTE_SETTINGS = { +const QUOTE_SETTINGS = { "prefer-double": { quote: "\"", description: "singlequote", @@ -54,7 +54,7 @@ module.exports = { }, create: function(context) { - let quoteOption = context.options[0] || "prefer-double", + const quoteOption = context.options[0] || "prefer-double", setting = QUOTE_SETTINGS[quoteOption]; /** @@ -69,7 +69,7 @@ module.exports = { return { JSXAttribute: function(node) { - let attributeValue = node.value; + const attributeValue = node.value; if (attributeValue && astUtils.isStringLiteral(attributeValue) && !usesExpectedQuotes(attributeValue)) { context.report({ diff --git a/tools/eslint/lib/rules/key-spacing.js b/tools/eslint/lib/rules/key-spacing.js index 25aba47ba0..83741822f4 100644 --- a/tools/eslint/lib/rules/key-spacing.js +++ b/tools/eslint/lib/rules/key-spacing.js @@ -34,9 +34,8 @@ function last(arr) { * @returns {boolean} True if the candidate property is part of the group. */ function continuesPropertyGroup(lastMember, candidate) { - let groupEndLine = lastMember.loc.start.line, - candidateStartLine = candidate.loc.start.line, - comments, i; + const groupEndLine = lastMember.loc.start.line, + candidateStartLine = candidate.loc.start.line; if (candidateStartLine - groupEndLine <= 1) { return true; @@ -45,13 +44,14 @@ function continuesPropertyGroup(lastMember, candidate) { // Check that the first comment is adjacent to the end of the group, the // last comment is adjacent to the candidate property, and that successive // comments are adjacent to each other. - comments = candidate.leadingComments; + const comments = candidate.leadingComments; + if ( comments && comments[0].loc.start.line - groupEndLine <= 1 && candidateStartLine - last(comments).loc.end.line <= 1 ) { - for (i = 1; i < comments.length; i++) { + for (let i = 1; i < comments.length; i++) { if (comments[i].loc.start.line - comments[i - 1].loc.end.line > 1) { return false; } @@ -150,7 +150,7 @@ function initOptions(toOptions, fromOptions) { // Rule Definition //------------------------------------------------------------------------------ -let messages = { +const messages = { key: "{{error}} space after {{computed}}key '{{key}}'.", value: "{{error}} space before value for {{computed}}key '{{key}}'." }; @@ -333,13 +333,13 @@ module.exports = { * align: "colon" // Optional, or "value" * } */ - let options = context.options[0] || {}, + const options = context.options[0] || {}, ruleOptions = initOptions({}, options), multiLineOptions = ruleOptions.multiLine, singleLineOptions = ruleOptions.singleLine, alignmentOptions = ruleOptions.align || null; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Determines if the given property is key-value property. @@ -392,7 +392,7 @@ module.exports = { * @returns {string} The property's key. */ function getKey(property) { - let key = property.key; + const key = property.key; if (property.computed) { return sourceCode.getText().slice(key.range[0], key.range[1]); @@ -412,7 +412,7 @@ module.exports = { * @returns {void} */ function report(property, side, whitespace, expected, mode) { - let diff = whitespace.length - expected, + const diff = whitespace.length - expected, nextColon = getNextColon(property.key), tokenBeforeColon = sourceCode.getTokenBefore(nextColon), tokenAfterColon = sourceCode.getTokenAfter(nextColon), @@ -420,9 +420,8 @@ module.exports = { locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start, isExtra = diff > 0, diffAbs = Math.abs(diff), - spaces = Array(diffAbs + 1).join(" "), - fix, - range; + spaces = Array(diffAbs + 1).join(" "); + let fix; if (( diff && mode === "strict" || @@ -431,6 +430,7 @@ module.exports = { !(expected && containsLineTerminator(whitespace)) ) { if (isExtra) { + let range; // Remove whitespace if (isKeySide) { @@ -476,10 +476,8 @@ module.exports = { * @returns {int} Width of the key. */ function getKeyWidth(property) { - let startToken, endToken; - - startToken = sourceCode.getFirstToken(property); - endToken = getLastTokenBeforeColon(property.key); + const startToken = sourceCode.getFirstToken(property); + const endToken = getLastTokenBeforeColon(property.key); return endToken.range[1] - startToken.range[0]; } @@ -490,7 +488,7 @@ module.exports = { * @returns {Object} Whitespace before and after the property's colon. */ function getPropertyWhitespace(property) { - let whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice( + const whitespace = /(\s*):(\s*)/.exec(sourceCode.getText().slice( property.key.range[1], property.value.range[0] )); @@ -514,7 +512,7 @@ module.exports = { } return node.properties.reduce(function(groups, property) { - let currentGroup = last(groups), + const currentGroup = last(groups), prev = last(currentGroup); if (!prev || continuesPropertyGroup(prev, property)) { @@ -535,11 +533,10 @@ module.exports = { * @returns {void} */ function verifyGroupAlignment(properties) { - let length = properties.length, + const length = properties.length, widths = properties.map(getKeyWidth), // Width of keys, including quotes - targetWidth = Math.max.apply(null, widths), - align = alignmentOptions.on, // "value" or "colon" - i, property, whitespace, width, + align = alignmentOptions.on; // "value" or "colon" + let targetWidth = Math.max.apply(null, widths), beforeColon, afterColon, mode; if (alignmentOptions && length > 1) { // When aligning values within a group, use the alignment configuration. @@ -555,11 +552,12 @@ module.exports = { // Conditionally include one space before or after colon targetWidth += (align === "colon" ? beforeColon : afterColon); - for (i = 0; i < length; i++) { - property = properties[i]; - whitespace = getPropertyWhitespace(property); + for (let i = 0; i < length; i++) { + const property = properties[i]; + const whitespace = getPropertyWhitespace(property); + if (whitespace) { // Object literal getters/setters lack a colon - width = widths[i]; + const width = widths[i]; if (align === "value") { report(property, "key", whitespace.beforeColon, beforeColon, mode); @@ -590,7 +588,7 @@ module.exports = { * @returns {void} */ function verifySpacing(node, lineOptions) { - let actual = getPropertyWhitespace(node); + const actual = getPropertyWhitespace(node); if (actual) { // Object literal getters/setters lack colons report(node, "key", actual.beforeColon, lineOptions.beforeColon, lineOptions.mode); @@ -604,7 +602,7 @@ module.exports = { * @returns {void} */ function verifyListSpacing(properties) { - let length = properties.length; + const length = properties.length; for (let i = 0; i < length; i++) { verifySpacing(properties[i], singleLineOptions); diff --git a/tools/eslint/lib/rules/keyword-spacing.js b/tools/eslint/lib/rules/keyword-spacing.js index 3c8d171ce8..74bf4c5cb4 100644 --- a/tools/eslint/lib/rules/keyword-spacing.js +++ b/tools/eslint/lib/rules/keyword-spacing.js @@ -9,21 +9,21 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"), +const astUtils = require("../ast-utils"), keywords = require("../util/keywords"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -let PREV_TOKEN = /^[\)\]\}>]$/; -let NEXT_TOKEN = /^(?:[\(\[\{<~!]|\+\+?|--?)$/; -let PREV_TOKEN_M = /^[\)\]\}>*]$/; -let NEXT_TOKEN_M = /^[\{*]$/; -let TEMPLATE_OPEN_PAREN = /\$\{$/; -let TEMPLATE_CLOSE_PAREN = /^\}/; -let CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/; -let KEYS = keywords.concat(["as", "await", "from", "get", "let", "of", "set", "yield"]); +const PREV_TOKEN = /^[\)\]\}>]$/; +const NEXT_TOKEN = /^(?:[\(\[\{<~!]|\+\+?|--?)$/; +const PREV_TOKEN_M = /^[\)\]\}>*]$/; +const NEXT_TOKEN_M = /^[\{*]$/; +const TEMPLATE_OPEN_PAREN = /\$\{$/; +const TEMPLATE_CLOSE_PAREN = /^\}/; +const CHECK_TYPE = /^(?:JSXElement|RegularExpression|String|Template)$/; +const KEYS = keywords.concat(["as", "await", "from", "get", "let", "of", "set", "yield"]); // check duplications. (function() { @@ -101,7 +101,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Reports a given token if there are not space(s) before the token. @@ -114,7 +114,7 @@ module.exports = { function expectSpaceBefore(token, pattern) { pattern = pattern || PREV_TOKEN; - let prevToken = sourceCode.getTokenBefore(token); + const prevToken = sourceCode.getTokenBefore(token); if (prevToken && (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && @@ -144,7 +144,7 @@ module.exports = { function unexpectSpaceBefore(token, pattern) { pattern = pattern || PREV_TOKEN; - let prevToken = sourceCode.getTokenBefore(token); + const prevToken = sourceCode.getTokenBefore(token); if (prevToken && (CHECK_TYPE.test(prevToken.type) || pattern.test(prevToken.value)) && @@ -174,7 +174,7 @@ module.exports = { function expectSpaceAfter(token, pattern) { pattern = pattern || NEXT_TOKEN; - let nextToken = sourceCode.getTokenAfter(token); + const nextToken = sourceCode.getTokenAfter(token); if (nextToken && (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && @@ -204,7 +204,7 @@ module.exports = { function unexpectSpaceAfter(token, pattern) { pattern = pattern || NEXT_TOKEN; - let nextToken = sourceCode.getTokenAfter(token); + const nextToken = sourceCode.getTokenAfter(token); if (nextToken && (CHECK_TYPE.test(nextToken.type) || pattern.test(nextToken.value)) && @@ -232,22 +232,22 @@ module.exports = { * Values are instances of `{"before": function, "after": function}`. */ function parseOptions(options) { - let before = !options || options.before !== false; - let after = !options || options.after !== false; - let defaultValue = { + const before = !options || options.before !== false; + const after = !options || options.after !== false; + const defaultValue = { before: before ? expectSpaceBefore : unexpectSpaceBefore, after: after ? expectSpaceAfter : unexpectSpaceAfter }; - let overrides = (options && options.overrides) || {}; - let retv = Object.create(null); + const overrides = (options && options.overrides) || {}; + const retv = Object.create(null); for (let i = 0; i < KEYS.length; ++i) { - let key = KEYS[i]; - let override = overrides[key]; + const key = KEYS[i]; + const override = overrides[key]; if (override) { - let thisBefore = ("before" in override) ? override.before : before; - let thisAfter = ("after" in override) ? override.after : after; + const thisBefore = ("before" in override) ? override.before : before; + const thisAfter = ("after" in override) ? override.after : after; retv[key] = { before: thisBefore ? expectSpaceBefore : unexpectSpaceBefore, @@ -261,7 +261,7 @@ module.exports = { return retv; } - let checkMethodMap = parseOptions(context.options[0]); + const checkMethodMap = parseOptions(context.options[0]); /** * Reports a given token if usage of spacing followed by the token is @@ -308,7 +308,7 @@ module.exports = { * @returns {void} */ function checkSpacingAroundFirstToken(node) { - let firstToken = node && sourceCode.getFirstToken(node); + const firstToken = node && sourceCode.getFirstToken(node); if (firstToken && firstToken.type === "Keyword") { checkSpacingAround(firstToken); @@ -326,7 +326,7 @@ module.exports = { * @returns {void} */ function checkSpacingBeforeFirstToken(node) { - let firstToken = node && sourceCode.getFirstToken(node); + const firstToken = node && sourceCode.getFirstToken(node); if (firstToken && firstToken.type === "Keyword") { checkSpacingBefore(firstToken); @@ -445,13 +445,13 @@ module.exports = { * @returns {void} */ function checkSpacingForModuleDeclaration(node) { - let firstToken = sourceCode.getFirstToken(node); + const firstToken = sourceCode.getFirstToken(node); checkSpacingBefore(firstToken, PREV_TOKEN_M); checkSpacingAfter(firstToken, NEXT_TOKEN_M); if (node.source) { - let fromToken = sourceCode.getTokenBefore(node.source); + const fromToken = sourceCode.getTokenBefore(node.source); checkSpacingBefore(fromToken, PREV_TOKEN_M); checkSpacingAfter(fromToken, NEXT_TOKEN_M); @@ -466,7 +466,7 @@ module.exports = { * @returns {void} */ function checkSpacingForImportNamespaceSpecifier(node) { - let asToken = sourceCode.getFirstToken(node, 1); + const asToken = sourceCode.getFirstToken(node, 1); checkSpacingBefore(asToken, PREV_TOKEN_M); } @@ -483,7 +483,7 @@ module.exports = { checkSpacingAroundFirstToken(node); } if (node.kind === "get" || node.kind === "set") { - let token = sourceCode.getFirstToken( + const token = sourceCode.getFirstToken( node, node.static ? 1 : 0 ); diff --git a/tools/eslint/lib/rules/linebreak-style.js b/tools/eslint/lib/rules/linebreak-style.js index a8a5e4ed88..80b64e370a 100644 --- a/tools/eslint/lib/rules/linebreak-style.js +++ b/tools/eslint/lib/rules/linebreak-style.js @@ -28,10 +28,10 @@ module.exports = { create: function(context) { - let EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.", + const EXPECTED_LF_MSG = "Expected linebreaks to be 'LF' but found 'CRLF'.", EXPECTED_CRLF_MSG = "Expected linebreaks to be 'CRLF' but found 'LF'."; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -56,14 +56,12 @@ module.exports = { return { Program: function checkForlinebreakStyle(node) { - let linebreakStyle = context.options[0] || "unix", + const linebreakStyle = context.options[0] || "unix", expectedLF = linebreakStyle === "unix", expectedLFChars = expectedLF ? "\n" : "\r\n", source = sourceCode.getText(), - pattern = /\r\n|\r|\n|\u2028|\u2029/g, - match, - index, - range; + pattern = /\r\n|\r|\n|\u2028|\u2029/g; + let match; let i = 0; @@ -73,8 +71,9 @@ module.exports = { continue; } - index = match.index; - range = [index, index + match[0].length]; + const index = match.index; + const range = [index, index + match[0].length]; + context.report({ node: node, loc: { diff --git a/tools/eslint/lib/rules/lines-around-comment.js b/tools/eslint/lib/rules/lines-around-comment.js index 70775b4213..885d136b31 100644 --- a/tools/eslint/lib/rules/lines-around-comment.js +++ b/tools/eslint/lib/rules/lines-around-comment.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), +const lodash = require("lodash"), astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ @@ -21,7 +21,7 @@ let lodash = require("lodash"), * @returns {Array} An array of line numbers. */ function getEmptyLineNums(lines) { - let emptyLines = lines.map(function(line, i) { + const emptyLines = lines.map(function(line, i) { return { code: line.trim(), num: i + 1 @@ -41,11 +41,11 @@ function getEmptyLineNums(lines) { * @returns {Array} An array of line numbers. */ function getCommentLineNums(comments) { - let lines = []; + const lines = []; comments.forEach(function(token) { - let start = token.loc.start.line; - let end = token.loc.end.line; + const start = token.loc.start.line; + const end = token.loc.end.line; lines.push(start, end); }); @@ -108,7 +108,7 @@ module.exports = { create: function(context) { - let options = context.options[0] ? lodash.assign({}, context.options[0]) : {}; + const options = context.options[0] ? Object.assign({}, context.options[0]) : {}; options.beforeLineComment = options.beforeLineComment || false; options.afterLineComment = options.afterLineComment || false; @@ -117,9 +117,9 @@ module.exports = { options.allowBlockStart = options.allowBlockStart || false; options.allowBlockEnd = options.allowBlockEnd || false; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); - let lines = sourceCode.lines, + const lines = sourceCode.lines, numLines = lines.length + 1, comments = sourceCode.getAllComments(), commentLines = getCommentLineNums(comments), @@ -184,7 +184,7 @@ module.exports = { * @returns {boolean} True if the comment is at parent start. */ function isCommentAtParentStart(node, nodeType) { - let ancestors = context.getAncestors(); + const ancestors = context.getAncestors(); let parent; if (ancestors.length) { @@ -202,7 +202,7 @@ module.exports = { * @returns {boolean} True if the comment is at parent end. */ function isCommentAtParentEnd(node, nodeType) { - let ancestors = context.getAncestors(); + const ancestors = context.getAncestors(); let parent; if (ancestors.length) { @@ -279,19 +279,19 @@ module.exports = { let after = opts.after, before = opts.before; - let prevLineNum = node.loc.start.line - 1, + const prevLineNum = node.loc.start.line - 1, nextLineNum = node.loc.end.line + 1, commentIsNotAlone = codeAroundComment(node); - let blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node), + const blockStartAllowed = options.allowBlockStart && isCommentAtBlockStart(node), blockEndAllowed = options.allowBlockEnd && isCommentAtBlockEnd(node), objectStartAllowed = options.allowObjectStart && isCommentAtObjectStart(node), objectEndAllowed = options.allowObjectEnd && isCommentAtObjectEnd(node), arrayStartAllowed = options.allowArrayStart && isCommentAtArrayStart(node), arrayEndAllowed = options.allowArrayEnd && isCommentAtArrayEnd(node); - let exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed; - let exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed; + const exceptionStartAllowed = blockStartAllowed || objectStartAllowed || arrayStartAllowed; + const exceptionEndAllowed = blockEndAllowed || objectEndAllowed || arrayEndAllowed; // ignore top of the file and bottom of the file if (prevLineNum < 1) { @@ -306,14 +306,14 @@ module.exports = { return; } - let previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node); - let nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node); + const previousTokenOrComment = sourceCode.getTokenOrCommentBefore(node); + const nextTokenOrComment = sourceCode.getTokenOrCommentAfter(node); // check for newline before if (!exceptionStartAllowed && before && !lodash.includes(commentAndEmptyLines, prevLineNum) && !(isCommentNodeType(previousTokenOrComment) && astUtils.isTokenOnSameLine(previousTokenOrComment, node))) { - let lineStart = node.range[0] - node.loc.start.column; - let range = [lineStart, lineStart]; + const lineStart = node.range[0] - node.loc.start.column; + const range = [lineStart, lineStart]; context.report({ node: node, diff --git a/tools/eslint/lib/rules/max-depth.js b/tools/eslint/lib/rules/max-depth.js index dbc1f6d48c..383509f8cb 100644 --- a/tools/eslint/lib/rules/max-depth.js +++ b/tools/eslint/lib/rules/max-depth.js @@ -49,9 +49,9 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - let functionStack = [], - option = context.options[0], - maxDepth = 4; + const functionStack = [], + option = context.options[0]; + let maxDepth = 4; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { maxDepth = option.maximum; @@ -88,7 +88,7 @@ module.exports = { * @private */ function pushBlock(node) { - let len = ++functionStack[functionStack.length - 1]; + const len = ++functionStack[functionStack.length - 1]; if (len > maxDepth) { context.report(node, "Blocks are nested too deeply ({{depth}}).", diff --git a/tools/eslint/lib/rules/max-len.js b/tools/eslint/lib/rules/max-len.js index 1bb63990d8..2b19aedf0a 100644 --- a/tools/eslint/lib/rules/max-len.js +++ b/tools/eslint/lib/rules/max-len.js @@ -9,7 +9,7 @@ // Constants //------------------------------------------------------------------------------ -let OPTIONS_SCHEMA = { +const OPTIONS_SCHEMA = { type: "object", properties: { code: { @@ -40,7 +40,7 @@ let OPTIONS_SCHEMA = { additionalProperties: false }; -let OPTIONS_OR_INTEGER_SCHEMA = { +const OPTIONS_OR_INTEGER_SCHEMA = { anyOf: [ OPTIONS_SCHEMA, { @@ -79,9 +79,9 @@ module.exports = { * too many false positives * - We don't care about matching the entire URL, any small segment is fine */ - let URL_REGEXP = /[^:/?#]:\/\/[^?#]/; + const URL_REGEXP = /[^:/?#]:\/\/[^?#]/; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Computes the length of a line that may contain tabs. The width of each @@ -95,7 +95,7 @@ module.exports = { let extraCharacterCount = 0; line.replace(/\t/g, function(match, offset) { - let totalOffset = offset + extraCharacterCount, + const totalOffset = offset + extraCharacterCount, previousTabStopOffset = tabWidth ? totalOffset % tabWidth : 0, spaceCount = tabWidth - previousTabStopOffset; @@ -105,8 +105,8 @@ module.exports = { } // The options object must be the last option specifiedā¦ - let lastOption = context.options[context.options.length - 1]; - let options = typeof lastOption === "object" ? Object.create(lastOption) : {}; + const lastOption = context.options[context.options.length - 1]; + const options = typeof lastOption === "object" ? Object.create(lastOption) : {}; // ā¦but max code lengthā¦ if (typeof context.options[0] === "number") { @@ -118,13 +118,13 @@ module.exports = { options.tabWidth = context.options[1]; } - let maxLength = options.code || 80, + const maxLength = options.code || 80, tabWidth = options.tabWidth || 4, - ignorePattern = options.ignorePattern || null, ignoreComments = options.ignoreComments || false, ignoreTrailingComments = options.ignoreTrailingComments || options.ignoreComments || false, ignoreUrls = options.ignoreUrls || false, maxCommentLength = options.comments; + let ignorePattern = options.ignorePattern || null; if (ignorePattern) { ignorePattern = new RegExp(ignorePattern); @@ -156,7 +156,7 @@ module.exports = { * @returns {boolean} If the comment covers the entire line */ function isFullLineComment(line, lineNumber, comment) { - let start = comment.loc.start, + const start = comment.loc.start, end = comment.loc.end, isFirstTokenOnLine = !line.slice(0, comment.loc.start.column).trim(); @@ -188,18 +188,18 @@ module.exports = { function checkProgramForMaxLength(node) { // split (honors line-ending) - let lines = sourceCode.lines, + const lines = sourceCode.lines, // list of comments to ignore - comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? sourceCode.getAllComments() : [], + comments = ignoreComments || maxCommentLength || ignoreTrailingComments ? sourceCode.getAllComments() : []; // we iterate over comments in parallel with the lines - commentsIndex = 0; + let commentsIndex = 0; lines.forEach(function(line, i) { // i is zero-indexed, line numbers are one-indexed - let lineNumber = i + 1; + const lineNumber = i + 1; /* * if we're checking comment length; we need to know whether this @@ -235,7 +235,7 @@ module.exports = { return; } - let lineLength = computeLineLength(line, tabWidth); + const lineLength = computeLineLength(line, tabWidth); if (lineIsComment && ignoreComments) { return; diff --git a/tools/eslint/lib/rules/max-lines.js b/tools/eslint/lib/rules/max-lines.js index 1e311eaffb..333167de4b 100644 --- a/tools/eslint/lib/rules/max-lines.js +++ b/tools/eslint/lib/rules/max-lines.js @@ -8,8 +8,8 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"); -let astUtils = require("../ast-utils"); +const lodash = require("lodash"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -52,8 +52,8 @@ module.exports = { }, create: function(context) { - let option = context.options[0], - max = 300; + const option = context.options[0]; + let max = 300; if (typeof option === "object" && option.hasOwnProperty("max") && typeof option.max === "number") { max = option.max; @@ -63,10 +63,10 @@ module.exports = { max = option; } - let skipComments = option && option.skipComments; - let skipBlankLines = option && option.skipBlankLines; + const skipComments = option && option.skipComments; + const skipBlankLines = option && option.skipBlankLines; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Returns whether or not a token is a comment node type @@ -125,9 +125,9 @@ module.exports = { } if (skipComments) { - let comments = sourceCode.getAllComments(); + const comments = sourceCode.getAllComments(); - let commentLines = lodash.flatten(comments.map(function(comment) { + const commentLines = lodash.flatten(comments.map(function(comment) { return getLinesWithoutCode(comment); })); @@ -139,7 +139,11 @@ module.exports = { if (lines.length > max) { context.report({ loc: { line: 1, column: 0 }, - message: "File must be at most " + max + " lines long." + message: "File must be at most {{max}} lines long. It's {{actual}} lines long.", + data: { + max, + actual: lines.length, + } }); } } diff --git a/tools/eslint/lib/rules/max-nested-callbacks.js b/tools/eslint/lib/rules/max-nested-callbacks.js index a1145c1f1a..37953dc757 100644 --- a/tools/eslint/lib/rules/max-nested-callbacks.js +++ b/tools/eslint/lib/rules/max-nested-callbacks.js @@ -48,8 +48,8 @@ module.exports = { //-------------------------------------------------------------------------- // Constants //-------------------------------------------------------------------------- - let option = context.options[0], - THRESHOLD = 10; + const option = context.options[0]; + let THRESHOLD = 10; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { THRESHOLD = option.maximum; @@ -65,7 +65,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - let callbackStack = []; + const callbackStack = []; /** * Checks a given function node for too many callbacks. @@ -74,14 +74,14 @@ module.exports = { * @private */ function checkFunction(node) { - let parent = node.parent; + const parent = node.parent; if (parent.type === "CallExpression") { callbackStack.push(node); } if (callbackStack.length > THRESHOLD) { - let opts = {num: callbackStack.length, max: THRESHOLD}; + const opts = {num: callbackStack.length, max: THRESHOLD}; context.report(node, "Too many nested callbacks ({{num}}). Maximum allowed is {{max}}.", opts); } diff --git a/tools/eslint/lib/rules/max-params.js b/tools/eslint/lib/rules/max-params.js index 9fb922392b..f5a40d931c 100644 --- a/tools/eslint/lib/rules/max-params.js +++ b/tools/eslint/lib/rules/max-params.js @@ -45,8 +45,8 @@ module.exports = { create: function(context) { - let option = context.options[0], - numParams = 3; + const option = context.options[0]; + let numParams = 3; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { numParams = option.maximum; diff --git a/tools/eslint/lib/rules/max-statements-per-line.js b/tools/eslint/lib/rules/max-statements-per-line.js index 165c6dd137..a3482fea79 100644 --- a/tools/eslint/lib/rules/max-statements-per-line.js +++ b/tools/eslint/lib/rules/max-statements-per-line.js @@ -32,18 +32,18 @@ module.exports = { create: function(context) { - let sourceCode = context.getSourceCode(), + const sourceCode = context.getSourceCode(), options = context.options[0] || {}, - lastStatementLine = 0, - numberOfStatementsOnThisLine = 0, maxStatementsPerLine = typeof options.max !== "undefined" ? options.max : 1, message = "This line has too many statements. Maximum allowed is " + maxStatementsPerLine + "."; + let lastStatementLine = 0, + numberOfStatementsOnThisLine = 0; //-------------------------------------------------------------------------- // Helpers //-------------------------------------------------------------------------- - let SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/; + const SINGLE_CHILD_ALLOWED = /^(?:(?:DoWhile|For|ForIn|ForOf|If|Labeled|While)Statement|Export(?:Default|Named)Declaration)$/; /** * Gets the actual last token of a given node. @@ -68,7 +68,7 @@ module.exports = { * @returns {void} */ function enterStatement(node) { - let line = node.loc.start.line; + const line = node.loc.start.line; // Skip to allow non-block statements if this is direct child of control statements. // `if (a) foo();` is counted as 1. @@ -100,7 +100,7 @@ module.exports = { * @returns {void} */ function leaveStatement(node) { - let line = getActualLastToken(node).loc.end.line; + const line = getActualLastToken(node).loc.end.line; // Update state. if (line !== lastStatementLine) { diff --git a/tools/eslint/lib/rules/max-statements.js b/tools/eslint/lib/rules/max-statements.js index 6708be3a12..d56e755287 100644 --- a/tools/eslint/lib/rules/max-statements.js +++ b/tools/eslint/lib/rules/max-statements.js @@ -58,11 +58,11 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - let functionStack = [], + const functionStack = [], option = context.options[0], - maxStatements = 10, ignoreTopLevelFunctions = context.options[1] && context.options[1].ignoreTopLevelFunctions || false, topLevelFunctions = []; + let maxStatements = 10; if (typeof option === "object" && option.hasOwnProperty("maximum") && typeof option.maximum === "number") { maxStatements = option.maximum; @@ -107,7 +107,7 @@ module.exports = { * @private */ function endFunction(node) { - let count = functionStack.pop(); + const count = functionStack.pop(); if (ignoreTopLevelFunctions && functionStack.length === 0) { topLevelFunctions.push({ node: node, count: count}); @@ -147,8 +147,8 @@ module.exports = { } topLevelFunctions.forEach(function(element) { - let count = element.count; - let node = element.node; + const count = element.count; + const node = element.node; reportIfTooManyStatements(node, count, maxStatements); }); diff --git a/tools/eslint/lib/rules/multiline-ternary.js b/tools/eslint/lib/rules/multiline-ternary.js index 469eb134de..e6f680cf5c 100644 --- a/tools/eslint/lib/rules/multiline-ternary.js +++ b/tools/eslint/lib/rules/multiline-ternary.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -50,8 +50,8 @@ module.exports = { return { ConditionalExpression: function(node) { - let areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent); - let areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate); + const areTestAndConsequentOnSameLine = astUtils.isTokenOnSameLine(node.test, node.consequent); + const areConsequentAndAlternateOnSameLine = astUtils.isTokenOnSameLine(node.consequent, node.alternate); if (areTestAndConsequentOnSameLine) { reportError(node.test, node); diff --git a/tools/eslint/lib/rules/new-cap.js b/tools/eslint/lib/rules/new-cap.js index 5e1baa540c..ab158e9c8b 100644 --- a/tools/eslint/lib/rules/new-cap.js +++ b/tools/eslint/lib/rules/new-cap.js @@ -9,13 +9,11 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"); - //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let CAPS_ALLOWED = [ +const CAPS_ALLOWED = [ "Array", "Boolean", "Date", @@ -98,12 +96,18 @@ module.exports = { type: "string" } }, + newIsCapExceptionPattern: { + type: "string" + }, capIsNewExceptions: { type: "array", items: { type: "string" } }, + capIsNewExceptionPattern: { + type: "string" + }, properties: { type: "boolean" } @@ -115,19 +119,21 @@ module.exports = { create: function(context) { - let config = context.options[0] ? lodash.assign({}, context.options[0]) : {}; + const config = context.options[0] ? Object.assign({}, context.options[0]) : {}; config.newIsCap = config.newIsCap !== false; config.capIsNew = config.capIsNew !== false; - let skipProperties = config.properties === false; + const skipProperties = config.properties === false; - let newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {}); + const newIsCapExceptions = checkArray(config, "newIsCapExceptions", []).reduce(invert, {}); + const newIsCapExceptionPattern = config.newIsCapExceptionPattern ? new RegExp(config.newIsCapExceptionPattern) : null; - let capIsNewExceptions = calculateCapIsNewExceptions(config); + const capIsNewExceptions = calculateCapIsNewExceptions(config); + const capIsNewExceptionPattern = config.capIsNewExceptionPattern ? new RegExp(config.capIsNewExceptionPattern) : null; - let listeners = {}; + const listeners = {}; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -140,11 +146,10 @@ module.exports = { */ function extractNameFromExpression(node) { - let name = "", - property; + let name = ""; if (node.callee.type === "MemberExpression") { - property = node.callee.property; + const property = node.callee.property; if (property.type === "Literal" && (typeof property.value === "string")) { name = property.value; @@ -164,10 +169,10 @@ module.exports = { * @returns {string} capitalization state: "non-alpha", "lower", or "upper" */ function getCap(str) { - let firstChar = str.charAt(0); + const firstChar = str.charAt(0); - let firstCharLower = firstChar.toLowerCase(); - let firstCharUpper = firstChar.toUpperCase(); + const firstCharLower = firstChar.toLowerCase(); + const firstCharUpper = firstChar.toUpperCase(); if (firstCharLower === firstCharUpper) { @@ -185,10 +190,17 @@ module.exports = { * @param {Object} allowedMap Object mapping calleeName to a Boolean * @param {ASTNode} node CallExpression node * @param {string} calleeName Capitalized callee name from a CallExpression + * @param {Object} pattern RegExp object from options pattern * @returns {boolean} Returns true if the callee may be capitalized */ - function isCapAllowed(allowedMap, node, calleeName) { - if (allowedMap[calleeName] || allowedMap[sourceCode.getText(node.callee)]) { + function isCapAllowed(allowedMap, node, calleeName, pattern) { + const sourceText = sourceCode.getText(node.callee); + + if (allowedMap[calleeName] || allowedMap[sourceText]) { + return true; + } + + if (pattern && pattern.test(sourceText)) { return true; } @@ -225,11 +237,11 @@ module.exports = { if (config.newIsCap) { listeners.NewExpression = function(node) { - let constructorName = extractNameFromExpression(node); + const constructorName = extractNameFromExpression(node); if (constructorName) { - let capitalization = getCap(constructorName); - let isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName); + const capitalization = getCap(constructorName); + const isAllowed = capitalization !== "lower" || isCapAllowed(newIsCapExceptions, node, constructorName, newIsCapExceptionPattern); if (!isAllowed) { report(node, "A constructor name should not start with a lowercase letter."); @@ -241,11 +253,11 @@ module.exports = { if (config.capIsNew) { listeners.CallExpression = function(node) { - let calleeName = extractNameFromExpression(node); + const calleeName = extractNameFromExpression(node); if (calleeName) { - let capitalization = getCap(calleeName); - let isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName); + const capitalization = getCap(calleeName); + const isAllowed = capitalization !== "upper" || isCapAllowed(capIsNewExceptions, node, calleeName, capIsNewExceptionPattern); if (!isAllowed) { report(node, "A function with a name starting with an uppercase letter should only be used as a constructor."); diff --git a/tools/eslint/lib/rules/new-parens.js b/tools/eslint/lib/rules/new-parens.js index 7ebd144b7e..0509229bbb 100644 --- a/tools/eslint/lib/rules/new-parens.js +++ b/tools/eslint/lib/rules/new-parens.js @@ -21,13 +21,13 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { NewExpression: function(node) { - let tokens = sourceCode.getTokens(node); - let prenticesTokens = tokens.filter(function(token) { + const tokens = sourceCode.getTokens(node); + const prenticesTokens = tokens.filter(function(token) { return token.value === "(" || token.value === ")"; }); diff --git a/tools/eslint/lib/rules/newline-after-var.js b/tools/eslint/lib/rules/newline-after-var.js index cb06c6f261..433fa7ebf8 100644 --- a/tools/eslint/lib/rules/newline-after-var.js +++ b/tools/eslint/lib/rules/newline-after-var.js @@ -26,16 +26,16 @@ module.exports = { create: function(context) { - let ALWAYS_MESSAGE = "Expected blank line after variable declarations.", + const ALWAYS_MESSAGE = "Expected blank line after variable declarations.", NEVER_MESSAGE = "Unexpected blank line after variable declarations."; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); // Default `mode` to "always". - let mode = context.options[0] === "never" ? "never" : "always"; + const mode = context.options[0] === "never" ? "never" : "always"; // Cache starting and ending line numbers of comments for faster lookup - let commentEndLine = sourceCode.getAllComments().reduce(function(result, token) { + const commentEndLine = sourceCode.getAllComments().reduce(function(result, token) { result[token.loc.start.line] = token.loc.end.line; return result; }, {}); @@ -46,6 +46,37 @@ module.exports = { //-------------------------------------------------------------------------- /** + * Gets a token from the given node to compare line to the next statement. + * + * In general, the token is the last token of the node. However, the token is the second last token if the following conditions satisfy. + * + * - The last token is semicolon. + * - The semicolon is on a different line from the previous token of the semicolon. + * + * This behavior would address semicolon-less style code. e.g.: + * + * var foo = 1 + * + * ;(a || b).doSomething() + * + * @param {ASTNode} node - The node to get. + * @returns {Token} The token to compare line to the next statement. + */ + function getLastToken(node) { + const lastToken = sourceCode.getLastToken(node); + + if (lastToken.type === "Punctuator" && lastToken.value === ";") { + const prevToken = sourceCode.getTokenBefore(lastToken); + + if (prevToken.loc.end.line !== lastToken.loc.start.line) { + return prevToken; + } + } + + return lastToken; + } + + /** * Determine if provided keyword is a variable declaration * @private * @param {string} keyword - keyword to test @@ -83,7 +114,7 @@ module.exports = { * @returns {boolean} True if `node` is last of their parent block. */ function isLastNode(node) { - let token = sourceCode.getTokenAfter(node); + const token = sourceCode.getTokenAfter(node); return !token || (token.type === "Punctuator" && token.value === "}"); } @@ -95,7 +126,7 @@ module.exports = { * @returns {boolean} True if `token` does not start immediately after a comment */ function hasBlankLineAfterComment(token, commentStartLine) { - let commentEnd = commentEndLine[commentStartLine]; + const commentEnd = commentEndLine[commentStartLine]; // If there's another comment, repeat check for blank line if (commentEndLine[commentEnd + 1]) { @@ -114,11 +145,9 @@ module.exports = { * @returns {void} */ function checkForBlankLine(node) { - let lastToken = sourceCode.getLastToken(node), + const lastToken = getLastToken(node), nextToken = sourceCode.getTokenAfter(node), - nextLineNum = lastToken.loc.end.line + 1, - noNextLineToken, - hasNextLineComment; + nextLineNum = lastToken.loc.end.line + 1; // Ignore if there is no following statement if (!nextToken) { @@ -147,8 +176,8 @@ module.exports = { } // Next statement is not a `var`... - noNextLineToken = nextToken.loc.start.line > nextLineNum; - hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined"); + const noNextLineToken = nextToken.loc.start.line > nextLineNum; + const hasNextLineComment = (typeof commentEndLine[nextLineNum] !== "undefined"); if (mode === "never" && noNextLineToken && !hasNextLineComment) { context.report(node, NEVER_MESSAGE, { identifier: node.name }); diff --git a/tools/eslint/lib/rules/newline-before-return.js b/tools/eslint/lib/rules/newline-before-return.js index 966ddb9193..4a30a7d08a 100644 --- a/tools/eslint/lib/rules/newline-before-return.js +++ b/tools/eslint/lib/rules/newline-before-return.js @@ -20,7 +20,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -34,7 +34,7 @@ module.exports = { * @private */ function isPrecededByTokens(node, testTokens) { - let tokenBefore = sourceCode.getTokenBefore(node); + const tokenBefore = sourceCode.getTokenBefore(node); return testTokens.some(function(token) { return tokenBefore.value === token; @@ -48,7 +48,7 @@ module.exports = { * @private */ function isFirstNode(node) { - let parentType = node.parent.type; + const parentType = node.parent.type; if (node.parent.body) { return Array.isArray(node.parent.body) @@ -75,8 +75,8 @@ module.exports = { * @private */ function calcCommentLines(node, lineNumTokenBefore) { - let comments = sourceCode.getComments(node).leading, - numLinesComments = 0; + const comments = sourceCode.getComments(node).leading; + let numLinesComments = 0; if (!comments.length) { return numLinesComments; @@ -109,10 +109,9 @@ module.exports = { * @private */ function hasNewlineBefore(node) { - let tokenBefore = sourceCode.getTokenBefore(node), - lineNumNode = node.loc.start.line, - lineNumTokenBefore, - commentLines; + const tokenBefore = sourceCode.getTokenBefore(node), + lineNumNode = node.loc.start.line; + let lineNumTokenBefore; /** * Global return (at the beginning of a script) is a special case. @@ -128,7 +127,7 @@ module.exports = { lineNumTokenBefore = 0; // global return at beginning of script } - commentLines = calcCommentLines(node, lineNumTokenBefore); + const commentLines = calcCommentLines(node, lineNumTokenBefore); return (lineNumNode - lineNumTokenBefore - commentLines) > 1; } diff --git a/tools/eslint/lib/rules/newline-per-chained-call.js b/tools/eslint/lib/rules/newline-per-chained-call.js index 068e7b97ae..8959742d34 100644 --- a/tools/eslint/lib/rules/newline-per-chained-call.js +++ b/tools/eslint/lib/rules/newline-per-chained-call.js @@ -33,10 +33,10 @@ module.exports = { create: function(context) { - let options = context.options[0] || {}, + const options = context.options[0] || {}, ignoreChainWithDepth = options.ignoreChainWithDepth || 2; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Gets the property text of a given MemberExpression node. @@ -46,9 +46,9 @@ module.exports = { * @returns {string} The property text of the node. */ function getPropertyText(node) { - let prefix = node.computed ? "[" : "."; - let lines = sourceCode.getText(node.property).split(/\r\n|\r|\n/g); - let suffix = node.computed && lines.length === 1 ? "]" : ""; + const prefix = node.computed ? "[" : "."; + const lines = sourceCode.getText(node.property).split(/\r\n|\r|\n/g); + const suffix = node.computed && lines.length === 1 ? "]" : ""; return prefix + lines[0] + suffix; } @@ -59,7 +59,7 @@ module.exports = { return; } - let callee = node.callee; + const callee = node.callee; let parent = callee.object; let depth = 1; diff --git a/tools/eslint/lib/rules/no-alert.js b/tools/eslint/lib/rules/no-alert.js index 1ff04a3b68..6be98005a7 100644 --- a/tools/eslint/lib/rules/no-alert.js +++ b/tools/eslint/lib/rules/no-alert.js @@ -5,6 +5,12 @@ "use strict"; //------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const getPropertyName = require("../ast-utils").getStaticPropertyName; + +//------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ @@ -29,29 +35,13 @@ function report(context, node, identifierName) { } /** - * Returns the property name of a MemberExpression. - * @param {ASTNode} memberExpressionNode The MemberExpression node. - * @returns {string|null} Returns the property name if available, null else. - */ -function getPropertyName(memberExpressionNode) { - if (memberExpressionNode.computed) { - if (memberExpressionNode.property.type === "Literal") { - return memberExpressionNode.property.value; - } - } else { - return memberExpressionNode.property.name; - } - return null; -} - -/** * Finds the escope reference in the given scope. * @param {Object} scope The scope to search. * @param {ASTNode} node The identifier node. * @returns {Reference|null} Returns the found reference or null if none were found. */ function findReference(scope, node) { - let references = scope.references.filter(function(reference) { + const references = scope.references.filter(function(reference) { return reference.identifier.range[0] === node.range[0] && reference.identifier.range[1] === node.range[1]; }); @@ -70,7 +60,7 @@ function findReference(scope, node) { * @returns {boolean} Whether or not the name is shadowed. */ function isShadowed(scope, globalScope, node) { - let reference = findReference(scope, node); + const reference = findReference(scope, node); return reference && reference.resolved && reference.resolved.defs.length > 0; } @@ -117,20 +107,19 @@ module.exports = { }, CallExpression: function(node) { - let callee = node.callee, - identifierName, + const callee = node.callee, currentScope = context.getScope(); // without window. if (callee.type === "Identifier") { - identifierName = callee.name; + const identifierName = callee.name; if (!isShadowed(currentScope, globalScope, callee) && isProhibitedIdentifier(callee.name)) { report(context, node, identifierName); } } else if (callee.type === "MemberExpression" && isGlobalThisReferenceOrGlobalWindow(currentScope, globalScope, callee.object)) { - identifierName = getPropertyName(callee); + const identifierName = getPropertyName(callee); if (isProhibitedIdentifier(identifierName)) { report(context, node, identifierName); diff --git a/tools/eslint/lib/rules/no-bitwise.js b/tools/eslint/lib/rules/no-bitwise.js index bfb6c180da..a17a8a9b32 100644 --- a/tools/eslint/lib/rules/no-bitwise.js +++ b/tools/eslint/lib/rules/no-bitwise.js @@ -8,7 +8,7 @@ // // Set of bitwise operators. // -let BITWISE_OPERATORS = [ +const BITWISE_OPERATORS = [ "^", "|", "&", "<<", ">>", ">>>", "^=", "|=", "&=", "<<=", ">>=", ">>>=", "~" @@ -47,9 +47,9 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let allowed = options.allow || []; - let int32Hint = options.int32Hint === true; + const options = context.options[0] || {}; + const allowed = options.allow || []; + const int32Hint = options.int32Hint === true; /** * Reports an unexpected use of a bitwise operator. diff --git a/tools/eslint/lib/rules/no-caller.js b/tools/eslint/lib/rules/no-caller.js index 75cfb63f65..ff17262bce 100644 --- a/tools/eslint/lib/rules/no-caller.js +++ b/tools/eslint/lib/rules/no-caller.js @@ -25,7 +25,7 @@ module.exports = { return { MemberExpression: function(node) { - let objectName = node.object.name, + const objectName = node.object.name, propertyName = node.property.name; if (objectName === "arguments" && !node.computed && propertyName && propertyName.match(/^calle[er]$/)) { diff --git a/tools/eslint/lib/rules/no-case-declarations.js b/tools/eslint/lib/rules/no-case-declarations.js index 6538674d41..6a0db0e869 100644 --- a/tools/eslint/lib/rules/no-case-declarations.js +++ b/tools/eslint/lib/rules/no-case-declarations.js @@ -41,7 +41,7 @@ module.exports = { return { SwitchCase: function(node) { for (let i = 0; i < node.consequent.length; i++) { - let statement = node.consequent[i]; + const statement = node.consequent[i]; if (isLexicalDeclaration(statement)) { context.report({ diff --git a/tools/eslint/lib/rules/no-catch-shadow.js b/tools/eslint/lib/rules/no-catch-shadow.js index 919ad3bc37..7573e3d8a3 100644 --- a/tools/eslint/lib/rules/no-catch-shadow.js +++ b/tools/eslint/lib/rules/no-catch-shadow.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-class-assign.js b/tools/eslint/lib/rules/no-class-assign.js index e12d3a065a..059c36e56e 100644 --- a/tools/eslint/lib/rules/no-class-assign.js +++ b/tools/eslint/lib/rules/no-class-assign.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-cond-assign.js b/tools/eslint/lib/rules/no-cond-assign.js index 5cba25e8c7..908dc45770 100644 --- a/tools/eslint/lib/rules/no-cond-assign.js +++ b/tools/eslint/lib/rules/no-cond-assign.js @@ -4,7 +4,7 @@ */ "use strict"; -let NODE_DESCRIPTIONS = { +const NODE_DESCRIPTIONS = { DoWhileStatement: "a 'do...while' statement", ForStatement: "a 'for' statement", IfStatement: "an 'if' statement", @@ -32,9 +32,9 @@ module.exports = { create: function(context) { - let prohibitAssign = (context.options[0] || "except-parens"); + const prohibitAssign = (context.options[0] || "except-parens"); - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Check whether an AST node is the test expression for a conditional statement. @@ -70,7 +70,7 @@ module.exports = { * @returns {boolean} `true` if the code is enclosed in parentheses; otherwise, `false`. */ function isParenthesised(node) { - let previousToken = sourceCode.getTokenBefore(node), + const previousToken = sourceCode.getTokenBefore(node), nextToken = sourceCode.getTokenAfter(node); return previousToken.value === "(" && previousToken.range[1] <= node.range[0] && @@ -83,7 +83,7 @@ module.exports = { * @returns {boolean} `true` if the code is enclosed in two sets of parentheses; otherwise, `false`. */ function isParenthesisedTwice(node) { - let previousToken = sourceCode.getTokenBefore(node, 1), + const previousToken = sourceCode.getTokenBefore(node, 1), nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && @@ -120,7 +120,7 @@ module.exports = { * @returns {void} */ function testForConditionalAncestor(node) { - let ancestor = findConditionalAncestor(node); + const ancestor = findConditionalAncestor(node); if (ancestor) { context.report(ancestor, "Unexpected assignment within {{type}}.", { diff --git a/tools/eslint/lib/rules/no-confusing-arrow.js b/tools/eslint/lib/rules/no-confusing-arrow.js index 42d1f865e2..c4bd347046 100644 --- a/tools/eslint/lib/rules/no-confusing-arrow.js +++ b/tools/eslint/lib/rules/no-confusing-arrow.js @@ -6,7 +6,7 @@ "use strict"; -let astUtils = require("../ast-utils.js"); +const astUtils = require("../ast-utils.js"); //------------------------------------------------------------------------------ // Helpers @@ -43,8 +43,8 @@ module.exports = { }, create: function(context) { - let config = context.options[0] || {}; - let sourceCode = context.getSourceCode(); + const config = context.options[0] || {}; + const sourceCode = context.getSourceCode(); /** * Reports if an arrow function contains an ambiguous conditional. @@ -52,7 +52,7 @@ module.exports = { * @returns {void} */ function checkArrowFunc(node) { - let body = node.body; + const body = node.body; if (isConditional(body) && !(config.allowParens && astUtils.isParenthesised(sourceCode, body))) { context.report(node, "Arrow function used ambiguously with a conditional expression."); diff --git a/tools/eslint/lib/rules/no-console.js b/tools/eslint/lib/rules/no-console.js index 553fc72460..0daff2bb07 100644 --- a/tools/eslint/lib/rules/no-console.js +++ b/tools/eslint/lib/rules/no-console.js @@ -45,9 +45,9 @@ module.exports = { let blockConsole = true; if (context.options.length > 0) { - let allowedProperties = context.options[0].allow; - let passedProperty = node.property.name; - let propertyIsAllowed = (allowedProperties.indexOf(passedProperty) > -1); + const allowedProperties = context.options[0].allow; + const passedProperty = node.property.name; + const propertyIsAllowed = (allowedProperties.indexOf(passedProperty) > -1); if (propertyIsAllowed) { blockConsole = false; diff --git a/tools/eslint/lib/rules/no-const-assign.js b/tools/eslint/lib/rules/no-const-assign.js index 8015225dbd..a34d4c1f4b 100644 --- a/tools/eslint/lib/rules/no-const-assign.js +++ b/tools/eslint/lib/rules/no-const-assign.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-constant-condition.js b/tools/eslint/lib/rules/no-constant-condition.js index b2d3b64738..c4bd50785f 100644 --- a/tools/eslint/lib/rules/no-constant-condition.js +++ b/tools/eslint/lib/rules/no-constant-condition.js @@ -32,7 +32,7 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}, + const options = context.options[0] || {}, checkLoops = options.checkLoops !== false; //-------------------------------------------------------------------------- @@ -51,11 +51,15 @@ module.exports = { case "Literal": return (operator === "||" && node.value === true) || (operator === "&&" && node.value === false); + + case "UnaryExpression": + return (operator === "&&" && node.operator === "void"); + case "LogicalExpression": return isLogicalIdentity(node.left, node.operator) || isLogicalIdentity(node.right, node.operator); - // no default + // no default } return false; } @@ -78,6 +82,10 @@ module.exports = { return true; case "UnaryExpression": + if (node.operator === "void") { + return true; + } + return (node.operator === "typeof" && inBooleanPosition) || isConstant(node.argument, true); diff --git a/tools/eslint/lib/rules/no-control-regex.js b/tools/eslint/lib/rules/no-control-regex.js index 4032fb2af7..40fa013b4a 100644 --- a/tools/eslint/lib/rules/no-control-regex.js +++ b/tools/eslint/lib/rules/no-control-regex.js @@ -33,7 +33,7 @@ module.exports = { return node.value; } else if (typeof node.value === "string") { - let parent = context.getAncestors().pop(); + const parent = context.getAncestors().pop(); if ((parent.type === "NewExpression" || parent.type === "CallExpression") && parent.callee.type === "Identifier" && parent.callee.name === "RegExp" @@ -51,41 +51,70 @@ module.exports = { return null; } + + const controlChar = /[\x00-\x1f]/g; // eslint-disable-line no-control-regex + const consecutiveSlashes = /\\+/g; + const consecutiveSlashesAtEnd = /\\+$/g; + const stringControlChar = /\\x[01][0-9a-f]/ig; + const stringControlCharWithoutSlash = /x[01][0-9a-f]/ig; + /** - * Check if given regex string has control characters in it + * Return a list of the control characters in the given regex string * @param {string} regexStr regex as string to check - * @returns {boolean} returns true if finds control characters on given string + * @returns {array} returns a list of found control characters on given string * @private */ - function hasControlCharacters(regexStr) { + function getControlCharacters(regexStr) { // check control characters, if RegExp object used - let hasControlChars = /[\x00-\x1f]/.test(regexStr); // eslint-disable-line no-control-regex + const controlChars = regexStr.match(controlChar) || []; + + let stringControlChars = []; // check substr, if regex literal used - let subStrIndex = regexStr.search(/\\x[01][0-9a-f]/i); + const subStrIndex = regexStr.search(stringControlChar); - if (!hasControlChars && subStrIndex > -1) { + if (subStrIndex > -1) { // is it escaped, check backslash count - let possibleEscapeCharacters = regexStr.substr(0, subStrIndex).match(/\\+$/gi); + const possibleEscapeCharacters = regexStr.slice(0, subStrIndex).match(consecutiveSlashesAtEnd); + + const hasControlChars = possibleEscapeCharacters === null || !(possibleEscapeCharacters[0].length % 2); - hasControlChars = possibleEscapeCharacters === null || !(possibleEscapeCharacters[0].length % 2); + if (hasControlChars) { + stringControlChars = regexStr.slice(subStrIndex, -1) + .split(consecutiveSlashes) + .filter(Boolean) + .map(function(x) { + const match = x.match(stringControlCharWithoutSlash) || [x]; + + return "\\" + match[0]; + }); + } } - return hasControlChars; + return controlChars.map(function(x) { + return "\\x" + ("0" + x.charCodeAt(0).toString(16)).slice(-2); + }).concat(stringControlChars); } return { Literal: function(node) { - let computedValue, - regex = getRegExp(node); + const regex = getRegExp(node); if (regex) { - computedValue = regex.toString(); - - if (hasControlCharacters(computedValue)) { - context.report(node, "Unexpected control character in regular expression."); + const computedValue = regex.toString(); + + const controlCharacters = getControlCharacters(computedValue); + + if (controlCharacters.length > 0) { + context.report({ + node, + message: "Unexpected control character(s) in regular expression: {{controlChars}}.", + data: { + controlChars: controlCharacters.join(", ") + } + }); } } } diff --git a/tools/eslint/lib/rules/no-div-regex.js b/tools/eslint/lib/rules/no-div-regex.js index f54a534b22..908b200310 100644 --- a/tools/eslint/lib/rules/no-div-regex.js +++ b/tools/eslint/lib/rules/no-div-regex.js @@ -21,12 +21,12 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { Literal: function(node) { - let token = sourceCode.getFirstToken(node); + const token = sourceCode.getFirstToken(node); if (token.type === "RegularExpression" && token.value[1] === "=") { context.report(node, "A regular expression literal can be confused with '/='."); diff --git a/tools/eslint/lib/rules/no-dupe-args.js b/tools/eslint/lib/rules/no-dupe-args.js index f63fab5bb2..7e13f997a3 100644 --- a/tools/eslint/lib/rules/no-dupe-args.js +++ b/tools/eslint/lib/rules/no-dupe-args.js @@ -42,13 +42,13 @@ module.exports = { * @private */ function checkParams(node) { - let variables = context.getDeclaredVariables(node); + const variables = context.getDeclaredVariables(node); for (let i = 0; i < variables.length; ++i) { - let variable = variables[i]; + const variable = variables[i]; // Checks and reports duplications. - let defs = variable.defs.filter(isParameter); + const defs = variable.defs.filter(isParameter); if (defs.length >= 2) { context.report({ diff --git a/tools/eslint/lib/rules/no-dupe-class-members.js b/tools/eslint/lib/rules/no-dupe-class-members.js index 102072b8bb..f4385c56cb 100644 --- a/tools/eslint/lib/rules/no-dupe-class-members.js +++ b/tools/eslint/lib/rules/no-dupe-class-members.js @@ -33,8 +33,8 @@ module.exports = { * - retv.set {boolean} A flag which shows the name is declared as setter. */ function getState(name, isStatic) { - let stateMap = stack[stack.length - 1]; - let key = "$" + name; // to avoid "__proto__". + const stateMap = stack[stack.length - 1]; + const key = "$" + name; // to avoid "__proto__". if (!stateMap[key]) { stateMap[key] = { @@ -85,8 +85,8 @@ module.exports = { return; } - let name = getName(node.key); - let state = getState(name, node.static); + const name = getName(node.key); + const state = getState(name, node.static); let isDuplicate = false; if (node.kind === "get") { diff --git a/tools/eslint/lib/rules/no-dupe-keys.js b/tools/eslint/lib/rules/no-dupe-keys.js index d2a3fc6773..f34c323f1e 100644 --- a/tools/eslint/lib/rules/no-dupe-keys.js +++ b/tools/eslint/lib/rules/no-dupe-keys.js @@ -6,6 +6,79 @@ "use strict"; //------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const GET_KIND = /^(?:init|get)$/; +const SET_KIND = /^(?:init|set)$/; + +/** + * The class which stores properties' information of an object. + */ +class ObjectInfo { + + /** + * @param {ObjectInfo|null} upper - The information of the outer object. + * @param {ASTNode} node - The ObjectExpression node of this information. + */ + constructor(upper, node) { + this.upper = upper; + this.node = node; + this.properties = new Map(); + } + + /** + * Gets the information of the given Property node. + * @param {ASTNode} node - The Property node to get. + * @returns {{get: boolean, set: boolean}} The information of the property. + */ + getPropertyInfo(node) { + const name = astUtils.getStaticPropertyName(node); + + if (!this.properties.has(name)) { + this.properties.set(name, {get: false, set: false}); + } + return this.properties.get(name); + } + + /** + * Checks whether the given property has been defined already or not. + * @param {ASTNode} node - The Property node to check. + * @returns {boolean} `true` if the property has been defined. + */ + isPropertyDefined(node) { + const entry = this.getPropertyInfo(node); + + return ( + (GET_KIND.test(node.kind) && entry.get) || + (SET_KIND.test(node.kind) && entry.set) + ); + } + + /** + * Defines the given property. + * @param {ASTNode} node - The Property node to define. + * @returns {void} + */ + defineProperty(node) { + const entry = this.getPropertyInfo(node); + + if (GET_KIND.test(node.kind)) { + entry.get = true; + } + if (SET_KIND.test(node.kind)) { + entry.set = true; + } + } +} + +//------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -20,37 +93,43 @@ module.exports = { schema: [] }, - create: function(context) { + create(context) { + let info = null; return { + ObjectExpression(node) { + info = new ObjectInfo(info, node); + }, + "ObjectExpression:exit"() { + info = info.upper; + }, - ObjectExpression: function(node) { + Property(node) { + const name = astUtils.getStaticPropertyName(node); - // Object that will be a map of properties--safe because we will - // prefix all of the keys. - let nodeProps = Object.create(null); + // Skip destructuring. + if (node.parent.type !== "ObjectExpression") { + return; + } - node.properties.forEach(function(property) { + // Skip if the name is not static. + if (!name) { + return; + } - if (property.type !== "Property") { - return; - } - - let keyName = property.key.name || property.key.value, - key = property.kind + "-" + keyName, - checkProperty = (!property.computed || property.key.type === "Literal"); - - if (checkProperty) { - if (nodeProps[key]) { - context.report(node, property.loc.start, "Duplicate key '{{key}}'.", { key: keyName }); - } else { - nodeProps[key] = true; - } - } - }); + // Reports if the name is defined already. + if (info.isPropertyDefined(node)) { + context.report({ + node: info.node, + loc: node.key.loc, + message: "Duplicate key '{{name}}'.", + data: {name}, + }); + } + // Update info. + info.defineProperty(node); } }; - } }; diff --git a/tools/eslint/lib/rules/no-duplicate-case.js b/tools/eslint/lib/rules/no-duplicate-case.js index 9e9b8b5cd8..66afb731a5 100644 --- a/tools/eslint/lib/rules/no-duplicate-case.js +++ b/tools/eslint/lib/rules/no-duplicate-case.js @@ -22,14 +22,14 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { SwitchStatement: function(node) { - let mapping = {}; + const mapping = {}; node.cases.forEach(function(switchCase) { - let key = sourceCode.getText(switchCase.test); + const key = sourceCode.getText(switchCase.test); if (mapping[key]) { context.report(switchCase, "Duplicate case label."); diff --git a/tools/eslint/lib/rules/no-duplicate-imports.js b/tools/eslint/lib/rules/no-duplicate-imports.js index 8594541b14..204bfeedc0 100644 --- a/tools/eslint/lib/rules/no-duplicate-imports.js +++ b/tools/eslint/lib/rules/no-duplicate-imports.js @@ -60,7 +60,7 @@ function checkAndReport(context, node, value, array, message) { */ function handleImports(context, includeExports, importsInFile, exportsInFile) { return function(node) { - let value = getValue(node); + const value = getValue(node); if (value) { checkAndReport(context, node, value, importsInFile, "import is duplicated."); @@ -85,7 +85,7 @@ function handleImports(context, includeExports, importsInFile, exportsInFile) { */ function handleExports(context, importsInFile, exportsInFile) { return function(node) { - let value = getValue(node); + const value = getValue(node); if (value) { checkAndReport(context, node, value, exportsInFile, "export is duplicated."); @@ -116,11 +116,11 @@ module.exports = { }, create: function(context) { - let includeExports = (context.options[0] || {}).includeExports, + const includeExports = (context.options[0] || {}).includeExports, importsInFile = [], exportsInFile = []; - let handlers = { + const handlers = { ImportDeclaration: handleImports(context, includeExports, importsInFile, exportsInFile) }; diff --git a/tools/eslint/lib/rules/no-else-return.js b/tools/eslint/lib/rules/no-else-return.js index 05ead21586..6b8b096d02 100644 --- a/tools/eslint/lib/rules/no-else-return.js +++ b/tools/eslint/lib/rules/no-else-return.js @@ -56,7 +56,7 @@ module.exports = { */ function naiveHasReturn(node) { if (node.type === "BlockStatement") { - let body = node.body, + const body = node.body, lastChildNode = body[body.length - 1]; return lastChildNode && checkForReturn(lastChildNode); @@ -128,8 +128,8 @@ module.exports = { return { IfStatement: function(node) { - let parent = context.getAncestors().pop(), - consequents, + const parent = context.getAncestors().pop(); + let consequents, alternate; // Only "top-level" if statements are checked, meaning the first `if` diff --git a/tools/eslint/lib/rules/no-empty-character-class.js b/tools/eslint/lib/rules/no-empty-character-class.js index 4a1ae8f92f..47e48a420e 100644 --- a/tools/eslint/lib/rules/no-empty-character-class.js +++ b/tools/eslint/lib/rules/no-empty-character-class.js @@ -21,7 +21,7 @@ plain-English description of the following regexp: 4. `[gimuy]*`: optional regexp flags 5. `$`: fix the match at the end of the string */ -let regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimuy]*$/; +const regex = /^\/([^\\[]|\\.|\[([^\\\]]|\\.)+\])*\/[gimuy]*$/; //------------------------------------------------------------------------------ // Rule Definition @@ -39,12 +39,12 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { Literal: function(node) { - let token = sourceCode.getFirstToken(node); + const token = sourceCode.getFirstToken(node); if (token.type === "RegularExpression" && !regex.test(token.value)) { context.report(node, "Empty class."); diff --git a/tools/eslint/lib/rules/no-empty-function.js b/tools/eslint/lib/rules/no-empty-function.js index d7d8c2e886..1f02d230cf 100644 --- a/tools/eslint/lib/rules/no-empty-function.js +++ b/tools/eslint/lib/rules/no-empty-function.js @@ -9,7 +9,7 @@ // Helpers //------------------------------------------------------------------------------ -let ALLOW_OPTIONS = Object.freeze([ +const ALLOW_OPTIONS = Object.freeze([ "functions", "arrowFunctions", "generatorFunctions", @@ -19,7 +19,7 @@ let ALLOW_OPTIONS = Object.freeze([ "setters", "constructors" ]); -let SHOW_KIND = Object.freeze({ +const SHOW_KIND = Object.freeze({ functions: "function", arrowFunctions: "arrow function", generatorFunctions: "generator function", @@ -44,7 +44,7 @@ let SHOW_KIND = Object.freeze({ * "constructors". */ function getKind(node) { - let parent = node.parent; + const parent = node.parent; let kind = ""; if (node.type === "ArrowFunctionExpression") { @@ -118,10 +118,10 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let allowed = options.allow || []; + const options = context.options[0] || {}; + const allowed = options.allow || []; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Reports a given function node if the node matches the following patterns. @@ -136,7 +136,7 @@ module.exports = { * @returns {void} */ function reportIfEmpty(node) { - let kind = getKind(node); + const kind = getKind(node); if (allowed.indexOf(kind) === -1 && node.body.type === "BlockStatement" && diff --git a/tools/eslint/lib/rules/no-empty.js b/tools/eslint/lib/rules/no-empty.js index 8897cce02b..b3056033a3 100644 --- a/tools/eslint/lib/rules/no-empty.js +++ b/tools/eslint/lib/rules/no-empty.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -36,10 +36,10 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}, + const options = context.options[0] || {}, allowEmptyCatch = options.allowEmptyCatch || false; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { BlockStatement: function(node) { diff --git a/tools/eslint/lib/rules/no-eq-null.js b/tools/eslint/lib/rules/no-eq-null.js index 743f290803..57e4a3f4e4 100644 --- a/tools/eslint/lib/rules/no-eq-null.js +++ b/tools/eslint/lib/rules/no-eq-null.js @@ -26,7 +26,7 @@ module.exports = { return { BinaryExpression: function(node) { - let badOperator = node.operator === "==" || node.operator === "!="; + const badOperator = node.operator === "==" || node.operator === "!="; if (node.right.type === "Literal" && node.right.raw === "null" && badOperator || node.left.type === "Literal" && node.left.raw === "null" && badOperator) { diff --git a/tools/eslint/lib/rules/no-eval.js b/tools/eslint/lib/rules/no-eval.js index 67ac1017cf..b3ef724eed 100644 --- a/tools/eslint/lib/rules/no-eval.js +++ b/tools/eslint/lib/rules/no-eval.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let candidatesOfGlobalObject = Object.freeze([ +const candidatesOfGlobalObject = Object.freeze([ "global", "window" ]); @@ -94,11 +94,11 @@ module.exports = { }, create: function(context) { - let allowIndirect = Boolean( + const allowIndirect = Boolean( context.options[0] && context.options[0].allowIndirect ); - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); let funcInfo = null; /** @@ -112,7 +112,7 @@ module.exports = { * @returns {void} */ function enterVarScope(node) { - let strict = context.getScope().isStrict; + const strict = context.getScope().isStrict; funcInfo = { upper: funcInfo, @@ -147,7 +147,7 @@ module.exports = { */ function report(node) { let locationNode = node; - let parent = node.parent; + const parent = node.parent; if (node.type === "MemberExpression") { locationNode = node.property; @@ -171,17 +171,17 @@ module.exports = { */ function reportAccessingEvalViaGlobalObject(globalScope) { for (let i = 0; i < candidatesOfGlobalObject.length; ++i) { - let name = candidatesOfGlobalObject[i]; - let variable = astUtils.getVariableByName(globalScope, name); + const name = candidatesOfGlobalObject[i]; + const variable = astUtils.getVariableByName(globalScope, name); if (!variable) { continue; } - let references = variable.references; + const references = variable.references; for (let j = 0; j < references.length; ++j) { - let identifier = references[j].identifier; + const identifier = references[j].identifier; let node = identifier.parent; // To detect code like `window.window.eval`. @@ -204,17 +204,17 @@ module.exports = { * @returns {void} */ function reportAccessingEval(globalScope) { - let variable = astUtils.getVariableByName(globalScope, "eval"); + const variable = astUtils.getVariableByName(globalScope, "eval"); if (!variable) { return; } - let references = variable.references; + const references = variable.references; for (let i = 0; i < references.length; ++i) { - let reference = references[i]; - let id = reference.identifier; + const reference = references[i]; + const id = reference.identifier; if (id.name === "eval" && !astUtils.isCallee(id)) { @@ -229,7 +229,7 @@ module.exports = { // Checks only direct calls to eval. It's simple! return { "CallExpression:exit": function(node) { - let callee = node.callee; + const callee = node.callee; if (isIdentifier(callee, "eval")) { report(callee); @@ -240,7 +240,7 @@ module.exports = { return { "CallExpression:exit": function(node) { - let callee = node.callee; + const callee = node.callee; if (isIdentifier(callee, "eval")) { report(callee); @@ -248,7 +248,7 @@ module.exports = { }, Program: function(node) { - let scope = context.getScope(), + const scope = context.getScope(), features = context.parserOptions.ecmaFeatures || {}, strict = scope.isStrict || @@ -265,7 +265,7 @@ module.exports = { }, "Program:exit": function() { - let globalScope = context.getScope(); + const globalScope = context.getScope(); exitVarScope(); reportAccessingEval(globalScope); diff --git a/tools/eslint/lib/rules/no-ex-assign.js b/tools/eslint/lib/rules/no-ex-assign.js index 42aea52723..db1c61aa21 100644 --- a/tools/eslint/lib/rules/no-ex-assign.js +++ b/tools/eslint/lib/rules/no-ex-assign.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-extend-native.js b/tools/eslint/lib/rules/no-extend-native.js index c58e5c3554..daf4dd7a48 100644 --- a/tools/eslint/lib/rules/no-extend-native.js +++ b/tools/eslint/lib/rules/no-extend-native.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let globals = require("globals"); +const globals = require("globals"); //------------------------------------------------------------------------------ // Rule Definition @@ -42,8 +42,8 @@ module.exports = { create: function(context) { - let config = context.options[0] || {}; - let exceptions = config.exceptions || []; + const config = context.options[0] || {}; + const exceptions = config.exceptions || []; let modifiedBuiltins = Object.keys(globals.builtin).filter(function(builtin) { return builtin[0].toUpperCase() === builtin[0]; }); @@ -58,14 +58,13 @@ module.exports = { // handle the Array.prototype.extra style case AssignmentExpression: function(node) { - let lhs = node.left, - affectsProto; + const lhs = node.left; if (lhs.type !== "MemberExpression" || lhs.object.type !== "MemberExpression") { return; } - affectsProto = lhs.object.computed ? + const affectsProto = lhs.object.computed ? lhs.object.property.type === "Literal" && lhs.object.property.value === "prototype" : lhs.object.property.name === "prototype"; @@ -83,9 +82,7 @@ module.exports = { // handle the Object.definePropert[y|ies](Array.prototype) case CallExpression: function(node) { - let callee = node.callee, - subject, - object; + const callee = node.callee; // only worry about Object.definePropert[y|ies] if (callee.type === "MemberExpression" && @@ -93,8 +90,9 @@ module.exports = { (callee.property.name === "defineProperty" || callee.property.name === "defineProperties")) { // verify the object being added to is a native prototype - subject = node.arguments[0]; - object = subject && subject.object; + const subject = node.arguments[0]; + const object = subject && subject.object; + if (object && object.type === "Identifier" && (modifiedBuiltins.indexOf(object.name) > -1) && diff --git a/tools/eslint/lib/rules/no-extra-bind.js b/tools/eslint/lib/rules/no-extra-bind.js index bdafaf040f..8d433b0358 100644 --- a/tools/eslint/lib/rules/no-extra-bind.js +++ b/tools/eslint/lib/rules/no-extra-bind.js @@ -5,6 +5,12 @@ "use strict"; //------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const getPropertyName = require("../ast-utils").getStaticPropertyName; + +//------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -38,31 +44,6 @@ module.exports = { } /** - * Gets the property name of a given node. - * If the property name is dynamic, this returns an empty string. - * - * @param {ASTNode} node - A node to check. This is a MemberExpression. - * @returns {string} The property name of the node. - */ - function getPropertyName(node) { - if (node.computed) { - switch (node.property.type) { - case "Literal": - return String(node.property.value); - case "TemplateLiteral": - if (node.property.expressions.length === 0) { - return node.property.quasis[0].value.cooked; - } - - // fallthrough - default: - return false; - } - } - return node.property.name; - } - - /** * Checks whether or not a given function node is the callee of `.bind()` * method. * @@ -73,8 +54,8 @@ module.exports = { * @returns {boolean} `true` if the node is the callee of `.bind()` method. */ function isCalleeOfBindMethod(node) { - let parent = node.parent; - let grandparent = parent.parent; + const parent = node.parent; + const grandparent = parent.parent; return ( grandparent && diff --git a/tools/eslint/lib/rules/no-extra-boolean-cast.js b/tools/eslint/lib/rules/no-extra-boolean-cast.js index 890f7cb605..7f29493909 100644 --- a/tools/eslint/lib/rules/no-extra-boolean-cast.js +++ b/tools/eslint/lib/rules/no-extra-boolean-cast.js @@ -23,7 +23,7 @@ module.exports = { create: function(context) { // Node types which have a test which will coerce values to booleans. - let BOOLEAN_NODE_TYPES = [ + const BOOLEAN_NODE_TYPES = [ "IfStatement", "DoWhileStatement", "WhileStatement", @@ -52,7 +52,7 @@ module.exports = { return { UnaryExpression: function(node) { - let ancestors = context.getAncestors(), + const ancestors = context.getAncestors(), parent = ancestors.pop(), grandparent = ancestors.pop(); @@ -74,7 +74,7 @@ module.exports = { } }, CallExpression: function(node) { - let parent = node.parent; + const parent = node.parent; if (node.callee.type !== "Identifier" || node.callee.name !== "Boolean") { return; diff --git a/tools/eslint/lib/rules/no-extra-label.js b/tools/eslint/lib/rules/no-extra-label.js index 5b72209bf2..12be549403 100644 --- a/tools/eslint/lib/rules/no-extra-label.js +++ b/tools/eslint/lib/rules/no-extra-label.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -98,8 +98,8 @@ module.exports = { return; } - let labelNode = node.label; - let label = labelNode.name; + const labelNode = node.label; + const label = labelNode.name; let info = scopeInfo; while (info) { diff --git a/tools/eslint/lib/rules/no-extra-parens.js b/tools/eslint/lib/rules/no-extra-parens.js index 86ef6ddc0f..060f84ff79 100644 --- a/tools/eslint/lib/rules/no-extra-parens.js +++ b/tools/eslint/lib/rules/no-extra-parens.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils.js"); +const astUtils = require("../ast-utils.js"); module.exports = { meta: { @@ -54,14 +54,14 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); - let isParenthesised = astUtils.isParenthesised.bind(astUtils, sourceCode); - let precedence = astUtils.getPrecedence; - let ALL_NODES = context.options[0] !== "functions"; - let EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false; - let NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false; - let EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false; + const isParenthesised = astUtils.isParenthesised.bind(astUtils, sourceCode); + const precedence = astUtils.getPrecedence; + const ALL_NODES = context.options[0] !== "functions"; + const EXCEPT_COND_ASSIGN = ALL_NODES && context.options[1] && context.options[1].conditionalAssign === false; + const NESTED_BINARY = ALL_NODES && context.options[1] && context.options[1].nestedBinaryExpressions === false; + const EXCEPT_RETURN_ASSIGN = ALL_NODES && context.options[1] && context.options[1].returnAssign === false; /** * Determines if this rule should be enforced for a node given the current configuration. @@ -80,7 +80,7 @@ module.exports = { * @private */ function isParenthesisedTwice(node) { - let previousToken = sourceCode.getTokenBefore(node, 1), + const previousToken = sourceCode.getTokenBefore(node, 1), nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && previousToken && nextToken && @@ -263,7 +263,7 @@ module.exports = { * @private */ function report(node) { - let previousToken = sourceCode.getTokenBefore(node); + const previousToken = sourceCode.getTokenBefore(node); context.report(node, previousToken.loc.start, "Gratuitous parentheses around expression."); } @@ -317,7 +317,7 @@ module.exports = { */ function dryBinaryLogical(node) { if (!NESTED_BINARY) { - let prec = precedence(node); + const prec = precedence(node); if (hasExcessParens(node.left) && precedence(node.left) >= prec) { report(node.left); @@ -394,12 +394,10 @@ module.exports = { }, ExpressionStatement: function(node) { - let firstToken, secondToken, firstTokens; - if (hasExcessParens(node.expression)) { - firstTokens = sourceCode.getFirstTokens(node.expression, 2); - firstToken = firstTokens[0]; - secondToken = firstTokens[1]; + const firstTokens = sourceCode.getFirstTokens(node.expression, 2); + const firstToken = firstTokens[0]; + const secondToken = firstTokens[1]; if ( !firstToken || @@ -484,7 +482,7 @@ module.exports = { ObjectExpression: function(node) { [].forEach.call(node.properties, function(e) { - let v = e.value; + const v = e.value; if (v && hasExcessParens(v) && precedence(v) >= precedence({type: "AssignmentExpression"})) { report(v); @@ -493,7 +491,7 @@ module.exports = { }, ReturnStatement: function(node) { - let returnToken = sourceCode.getFirstToken(node); + const returnToken = sourceCode.getFirstToken(node); if (isReturnAssignException(node)) { return; @@ -529,7 +527,7 @@ module.exports = { }, ThrowStatement: function(node) { - let throwToken = sourceCode.getFirstToken(node); + const throwToken = sourceCode.getFirstToken(node); if (hasExcessParensNoLineTerminator(throwToken, node.argument)) { report(node.argument); @@ -562,10 +560,8 @@ module.exports = { }, YieldExpression: function(node) { - let yieldToken; - if (node.argument) { - yieldToken = sourceCode.getFirstToken(node); + const yieldToken = sourceCode.getFirstToken(node); if ((precedence(node.argument) >= precedence(node) && hasExcessParensNoLineTerminator(yieldToken, node.argument)) || diff --git a/tools/eslint/lib/rules/no-extra-semi.js b/tools/eslint/lib/rules/no-extra-semi.js index 37f2253c26..485c0d02f7 100644 --- a/tools/eslint/lib/rules/no-extra-semi.js +++ b/tools/eslint/lib/rules/no-extra-semi.js @@ -22,7 +22,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Reports an unnecessary semicolon error. @@ -65,7 +65,7 @@ module.exports = { * @returns {void} */ EmptyStatement: function(node) { - let parent = node.parent, + const parent = node.parent, allowedParentTypes = [ "ForStatement", "ForInStatement", diff --git a/tools/eslint/lib/rules/no-fallthrough.js b/tools/eslint/lib/rules/no-fallthrough.js index 24f3642fa1..a119438596 100644 --- a/tools/eslint/lib/rules/no-fallthrough.js +++ b/tools/eslint/lib/rules/no-fallthrough.js @@ -8,13 +8,13 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"); +const lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i; +const DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i; /** * Checks whether or not a given node has a fallthrough comment. @@ -24,8 +24,8 @@ let DEFAULT_FALLTHROUGH_COMMENT = /falls?\s?through/i; * @returns {boolean} `true` if the node has a valid fallthrough comment. */ function hasFallthroughComment(node, context, fallthroughCommentPattern) { - let sourceCode = context.getSourceCode(); - let comment = lodash.last(sourceCode.getComments(node).leading); + const sourceCode = context.getSourceCode(); + const comment = lodash.last(sourceCode.getComments(node).leading); return Boolean(comment && fallthroughCommentPattern.test(comment.value)); } @@ -75,9 +75,9 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; + const options = context.options[0] || {}; let currentCodePath = null; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /* * We need to use leading comments of the next SwitchCase node because @@ -117,7 +117,7 @@ module.exports = { }, "SwitchCase:exit": function(node) { - let nextToken = sourceCode.getTokenAfter(node); + const nextToken = sourceCode.getTokenAfter(node); /* * `reachable` meant fall through because statements preceded by diff --git a/tools/eslint/lib/rules/no-func-assign.js b/tools/eslint/lib/rules/no-func-assign.js index 2266a044fc..d57062dfc2 100644 --- a/tools/eslint/lib/rules/no-func-assign.js +++ b/tools/eslint/lib/rules/no-func-assign.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition diff --git a/tools/eslint/lib/rules/no-global-assign.js b/tools/eslint/lib/rules/no-global-assign.js new file mode 100644 index 0000000000..a5d389e7b0 --- /dev/null +++ b/tools/eslint/lib/rules/no-global-assign.js @@ -0,0 +1,83 @@ +/** + * @fileoverview Rule to disallow assignments to native objects or read-only global variables + * @author Ilya Volodin + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "disallow assignments to native objects or read-only global variables", + category: "Best Practices", + recommended: false + }, + + schema: [ + { + type: "object", + properties: { + exceptions: { + type: "array", + items: {type: "string"}, + uniqueItems: true + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + const config = context.options[0]; + const exceptions = (config && config.exceptions) || []; + + /** + * Reports write references. + * @param {Reference} reference - A reference to check. + * @param {int} index - The index of the reference in the references. + * @param {Reference[]} references - The array that the reference belongs to. + * @returns {void} + */ + function checkReference(reference, index, references) { + const identifier = reference.identifier; + + if (reference.init === false && + reference.isWrite() && + + // Destructuring assignments can have multiple default value, + // so possibly there are multiple writeable references for the same identifier. + (index === 0 || references[index - 1].identifier !== identifier) + ) { + context.report({ + node: identifier, + message: "Read-only global '{{name}}' should not be modified.", + data: identifier + }); + } + } + + /** + * Reports write references if a given variable is read-only builtin. + * @param {Variable} variable - A variable to check. + * @returns {void} + */ + function checkVariable(variable) { + if (variable.writeable === false && exceptions.indexOf(variable.name) === -1) { + variable.references.forEach(checkReference); + } + } + + return { + Program: function() { + const globalScope = context.getScope(); + + globalScope.variables.forEach(checkVariable); + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-implicit-coercion.js b/tools/eslint/lib/rules/no-implicit-coercion.js index ee11bd0087..a27af2b152 100644 --- a/tools/eslint/lib/rules/no-implicit-coercion.js +++ b/tools/eslint/lib/rules/no-implicit-coercion.js @@ -9,8 +9,8 @@ // Helpers //------------------------------------------------------------------------------ -let INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/; -let ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"]; +const INDEX_OF_PATTERN = /^(?:i|lastI)ndexOf$/; +const ALLOWABLE_OPERATORS = ["~", "!!", "+", "*"]; /** * Parses and normalizes an option object. @@ -91,7 +91,7 @@ function isNumeric(node) { * @returns {ASTNode|null} The first non-numeric item in the BinaryExpression tree or null */ function getNonNumericOperand(node) { - let left = node.left, + const left = node.left, right = node.right; if (right.type !== "BinaryExpression" && !isNumeric(right)) { @@ -176,13 +176,12 @@ module.exports = { }, create: function(context) { - let options = parseOptions(context.options[0]), - operatorAllowed = false; - - let sourceCode = context.getSourceCode(); + const options = parseOptions(context.options[0]); + const sourceCode = context.getSourceCode(); return { UnaryExpression: function(node) { + let operatorAllowed; // !!foo operatorAllowed = options.allow.indexOf("!!") >= 0; @@ -217,10 +216,11 @@ module.exports = { // Use `:exit` to prevent double reporting "BinaryExpression:exit": function(node) { + let operatorAllowed; // 1 * foo operatorAllowed = options.allow.indexOf("*") >= 0; - let nonNumericOperand = !operatorAllowed && options.number && isMultiplyByOne(node) && getNonNumericOperand(node); + const nonNumericOperand = !operatorAllowed && options.number && isMultiplyByOne(node) && getNonNumericOperand(node); if (nonNumericOperand) { context.report( @@ -244,8 +244,9 @@ module.exports = { AssignmentExpression: function(node) { // foo += "" - operatorAllowed = options.allow.indexOf("+") >= 0; - if (options.string && isAppendEmptyString(node)) { + const operatorAllowed = options.allow.indexOf("+") >= 0; + + if (!operatorAllowed && options.string && isAppendEmptyString(node)) { context.report( node, "use `{{code}} = String({{code}})` instead.", { diff --git a/tools/eslint/lib/rules/no-implicit-globals.js b/tools/eslint/lib/rules/no-implicit-globals.js index 9f8180394f..84968cb071 100644 --- a/tools/eslint/lib/rules/no-implicit-globals.js +++ b/tools/eslint/lib/rules/no-implicit-globals.js @@ -23,7 +23,7 @@ module.exports = { create: function(context) { return { Program: function() { - let scope = context.getScope(); + const scope = context.getScope(); scope.variables.forEach(function(variable) { if (variable.writeable) { @@ -38,7 +38,7 @@ module.exports = { }); scope.implicit.variables.forEach(function(variable) { - let scopeVariable = scope.set.get(variable.name); + const scopeVariable = scope.set.get(variable.name); if (scopeVariable && scopeVariable.writeable) { return; diff --git a/tools/eslint/lib/rules/no-implied-eval.js b/tools/eslint/lib/rules/no-implied-eval.js index ec660fa08f..c074098ba9 100644 --- a/tools/eslint/lib/rules/no-implied-eval.js +++ b/tools/eslint/lib/rules/no-implied-eval.js @@ -21,13 +21,13 @@ module.exports = { }, create: function(context) { - let CALLEE_RE = /set(?:Timeout|Interval)|execScript/; + const CALLEE_RE = /set(?:Timeout|Interval)|execScript/; /* * Figures out if we should inspect a given binary expression. Is a stack * of stacks, where the first element in each substack is a CallExpression. */ - let impliedEvalAncestorsStack = []; + const impliedEvalAncestorsStack = []; //-------------------------------------------------------------------------- // Helpers @@ -50,7 +50,7 @@ module.exports = { * @private */ function isImpliedEvalMemberExpression(node) { - let object = node.object, + const object = node.object, property = node.property, hasImpliedEvalName = CALLEE_RE.test(property.name) || CALLEE_RE.test(property.value); @@ -67,7 +67,7 @@ module.exports = { * @private */ function isImpliedEvalCallExpression(node) { - let isMemberExpression = (node.callee.type === "MemberExpression"), + const isMemberExpression = (node.callee.type === "MemberExpression"), isIdentifier = (node.callee.type === "Identifier"), isImpliedEvalCallee = (isIdentifier && CALLEE_RE.test(node.callee.name)) || @@ -103,7 +103,7 @@ module.exports = { if (hasImpliedEvalParent(node)) { // remove the entire substack, to avoid duplicate reports - let substack = impliedEvalAncestorsStack.pop(); + const substack = impliedEvalAncestorsStack.pop(); context.report(substack[0], "Implied eval. Consider passing a function instead of a string."); } diff --git a/tools/eslint/lib/rules/no-inline-comments.js b/tools/eslint/lib/rules/no-inline-comments.js index 87039d4697..8ca0c573c5 100644 --- a/tools/eslint/lib/rules/no-inline-comments.js +++ b/tools/eslint/lib/rules/no-inline-comments.js @@ -4,7 +4,7 @@ */ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -22,7 +22,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Will check that comments are not on lines starting with or ending with code @@ -33,16 +33,16 @@ module.exports = { function testCodeAroundComment(node) { // Get the whole line and cut it off at the start of the comment - let startLine = String(sourceCode.lines[node.loc.start.line - 1]); - let endLine = String(sourceCode.lines[node.loc.end.line - 1]); + const startLine = String(sourceCode.lines[node.loc.start.line - 1]); + const endLine = String(sourceCode.lines[node.loc.end.line - 1]); - let preamble = startLine.slice(0, node.loc.start.column).trim(); + const preamble = startLine.slice(0, node.loc.start.column).trim(); // Also check after the comment - let postamble = endLine.slice(node.loc.end.column).trim(); + const postamble = endLine.slice(node.loc.end.column).trim(); // Check that this comment isn't an ESLint directive - let isDirective = astUtils.isDirectiveComment(node); + const isDirective = astUtils.isDirectiveComment(node); // Should be empty if there was only whitespace around the comment if (!isDirective && (preamble || postamble)) { diff --git a/tools/eslint/lib/rules/no-inner-declarations.js b/tools/eslint/lib/rules/no-inner-declarations.js index 3e21385a59..22ef55b21e 100644 --- a/tools/eslint/lib/rules/no-inner-declarations.js +++ b/tools/eslint/lib/rules/no-inner-declarations.js @@ -31,8 +31,8 @@ module.exports = { * @returns {Object} Ancestor's type and distance from node. */ function nearestBody() { - let ancestors = context.getAncestors(), - ancestor = ancestors.pop(), + const ancestors = context.getAncestors(); + let ancestor = ancestors.pop(), generation = 1; while (ancestor && ["Program", "FunctionDeclaration", @@ -58,7 +58,7 @@ module.exports = { * @returns {void} */ function check(node) { - let body = nearestBody(node), + const body = nearestBody(node), valid = ((body.type === "Program" && body.distance === 1) || body.distance === 2); diff --git a/tools/eslint/lib/rules/no-invalid-regexp.js b/tools/eslint/lib/rules/no-invalid-regexp.js index eb693c55c6..123b80c39b 100644 --- a/tools/eslint/lib/rules/no-invalid-regexp.js +++ b/tools/eslint/lib/rules/no-invalid-regexp.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let espree = require("espree"); +const espree = require("espree"); //------------------------------------------------------------------------------ // Rule Definition @@ -38,8 +38,8 @@ module.exports = { create: function(context) { - let options = context.options[0], - allowedFlags = ""; + const options = context.options[0]; + let allowedFlags = ""; if (options && options.allowConstructorFlags) { allowedFlags = options.allowConstructorFlags.join(""); diff --git a/tools/eslint/lib/rules/no-invalid-this.js b/tools/eslint/lib/rules/no-invalid-this.js index e41c474699..9672c28467 100644 --- a/tools/eslint/lib/rules/no-invalid-this.js +++ b/tools/eslint/lib/rules/no-invalid-this.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -27,7 +27,7 @@ module.exports = { }, create: function(context) { - let stack = [], + const stack = [], sourceCode = context.getSourceCode(); /** @@ -40,7 +40,7 @@ module.exports = { * an object which has a flag that whether or not `this` keyword is valid. */ stack.getCurrent = function() { - let current = this[this.length - 1]; + const current = this[this.length - 1]; if (!current.init) { current.init = true; @@ -86,7 +86,7 @@ module.exports = { * Modules is always strict mode. */ Program: function(node) { - let scope = context.getScope(), + const scope = context.getScope(), features = context.parserOptions.ecmaFeatures || {}; stack.push({ @@ -111,7 +111,7 @@ module.exports = { // Reports if `this` of the current context is invalid. ThisExpression: function(node) { - let current = stack.getCurrent(); + const current = stack.getCurrent(); if (current && !current.valid) { context.report(node, "Unexpected 'this'."); diff --git a/tools/eslint/lib/rules/no-irregular-whitespace.js b/tools/eslint/lib/rules/no-irregular-whitespace.js index 0049de3dde..a34de284e0 100644 --- a/tools/eslint/lib/rules/no-irregular-whitespace.js +++ b/tools/eslint/lib/rules/no-irregular-whitespace.js @@ -10,10 +10,10 @@ // Constants //------------------------------------------------------------------------------ -let ALL_IRREGULARS = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/; -let IRREGULAR_WHITESPACE = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg; -let IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg; -let LINE_BREAK = /\r\n|\r|\n|\u2028|\u2029/g; +const ALL_IRREGULARS = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/; +const IRREGULAR_WHITESPACE = /[\f\v\u0085\u00A0\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/mg; +const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/mg; +const LINE_BREAK = /\r\n|\r|\n|\u2028|\u2029/g; //------------------------------------------------------------------------------ // Rule Definition @@ -55,16 +55,16 @@ module.exports = { let errors = []; // Comment nodes. We accumulate these as we go, so we can be sure to trigger them after the whole `Program` entity is parsed, even for top-of-file comments. - let commentNodes = []; + const commentNodes = []; // Lookup the `skipComments` option, which defaults to `false`. - let options = context.options[0] || {}; - let skipComments = !!options.skipComments; - let skipStrings = options.skipStrings !== false; - let skipRegExps = !!options.skipRegExps; - let skipTemplates = !!options.skipTemplates; + const options = context.options[0] || {}; + const skipComments = !!options.skipComments; + const skipStrings = options.skipStrings !== false; + const skipRegExps = !!options.skipRegExps; + const skipTemplates = !!options.skipTemplates; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Removes errors that occur inside a string node @@ -73,11 +73,11 @@ module.exports = { * @private */ function removeWhitespaceError(node) { - let locStart = node.loc.start; - let locEnd = node.loc.end; + const locStart = node.loc.start; + const locEnd = node.loc.end; errors = errors.filter(function(error) { - let errorLoc = error[1]; + const errorLoc = error[1]; if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) { if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) { @@ -95,8 +95,8 @@ module.exports = { * @private */ function removeInvalidNodeErrorsInIdentifierOrLiteral(node) { - let shouldCheckStrings = skipStrings && (typeof node.value === "string"); - let shouldCheckRegExps = skipRegExps && (node.value instanceof RegExp); + const shouldCheckStrings = skipStrings && (typeof node.value === "string"); + const shouldCheckRegExps = skipRegExps && (node.value instanceof RegExp); if (shouldCheckStrings || shouldCheckRegExps) { @@ -140,15 +140,14 @@ module.exports = { * @private */ function checkForIrregularWhitespace(node) { - let sourceLines = sourceCode.lines; + const sourceLines = sourceCode.lines; sourceLines.forEach(function(sourceLine, lineIndex) { - let lineNumber = lineIndex + 1, - location, - match; + const lineNumber = lineIndex + 1; + let match; while ((match = IRREGULAR_WHITESPACE.exec(sourceLine)) !== null) { - location = { + const location = { line: lineNumber, column: match.index }; @@ -165,18 +164,15 @@ module.exports = { * @private */ function checkForIrregularLineTerminators(node) { - let source = sourceCode.getText(), + const source = sourceCode.getText(), sourceLines = sourceCode.lines, - linebreaks = source.match(LINE_BREAK), - lastLineIndex = -1, - lineIndex, - location, + linebreaks = source.match(LINE_BREAK); + let lastLineIndex = -1, match; while ((match = IRREGULAR_LINE_TERMINATORS.exec(source)) !== null) { - lineIndex = linebreaks.indexOf(match[0], lastLineIndex + 1) || 0; - - location = { + const lineIndex = linebreaks.indexOf(match[0], lastLineIndex + 1) || 0; + const location = { line: lineIndex + 1, column: sourceLines[lineIndex].length }; @@ -203,7 +199,7 @@ module.exports = { */ function noop() {} - let nodes = {}; + const nodes = {}; if (ALL_IRREGULARS.test(sourceCode.getText())) { nodes.Program = function(node) { diff --git a/tools/eslint/lib/rules/no-label-var.js b/tools/eslint/lib/rules/no-label-var.js index a203324f14..e050f01139 100644 --- a/tools/eslint/lib/rules/no-label-var.js +++ b/tools/eslint/lib/rules/no-label-var.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -52,7 +52,7 @@ module.exports = { LabeledStatement: function(node) { // Fetch the innermost scope. - let scope = context.getScope(); + const scope = context.getScope(); // Recursively find the identifier walking up the scope, starting // with the innermost scope. diff --git a/tools/eslint/lib/rules/no-labels.js b/tools/eslint/lib/rules/no-labels.js index adc5bc0f81..90b696829b 100644 --- a/tools/eslint/lib/rules/no-labels.js +++ b/tools/eslint/lib/rules/no-labels.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -39,9 +39,9 @@ module.exports = { }, create: function(context) { - let options = context.options[0]; - let allowLoop = Boolean(options && options.allowLoop); - let allowSwitch = Boolean(options && options.allowSwitch); + const options = context.options[0]; + const allowLoop = Boolean(options && options.allowLoop); + const allowSwitch = Boolean(options && options.allowSwitch); let scopeInfo = null; /** diff --git a/tools/eslint/lib/rules/no-lone-blocks.js b/tools/eslint/lib/rules/no-lone-blocks.js index e93f1d0809..ae59e99fae 100644 --- a/tools/eslint/lib/rules/no-lone-blocks.js +++ b/tools/eslint/lib/rules/no-lone-blocks.js @@ -23,8 +23,8 @@ module.exports = { create: function(context) { // A stack of lone blocks to be checked for block-level bindings - let loneBlocks = [], - ruleDef; + const loneBlocks = []; + let ruleDef; /** * Reports a node as invalid. @@ -32,7 +32,7 @@ module.exports = { * @returns {void} */ function report(node) { - let parent = context.getAncestors().pop(); + const parent = context.getAncestors().pop(); context.report(node, parent.type === "Program" ? "Block is redundant." : @@ -45,7 +45,7 @@ module.exports = { * @returns {boolean} True if the current node is a lone block. */ function isLoneBlock() { - let parent = context.getAncestors().pop(); + const parent = context.getAncestors().pop(); return parent.type === "BlockStatement" || parent.type === "Program"; } @@ -60,7 +60,7 @@ module.exports = { return; } - let block = context.getAncestors().pop(); + const block = context.getAncestors().pop(); if (loneBlocks[loneBlocks.length - 1] === block) { loneBlocks.pop(); diff --git a/tools/eslint/lib/rules/no-lonely-if.js b/tools/eslint/lib/rules/no-lonely-if.js index 4c99bca838..4764908dfa 100644 --- a/tools/eslint/lib/rules/no-lonely-if.js +++ b/tools/eslint/lib/rules/no-lonely-if.js @@ -23,7 +23,7 @@ module.exports = { return { IfStatement: function(node) { - let ancestors = context.getAncestors(), + const ancestors = context.getAncestors(), parent = ancestors.pop(), grandparent = ancestors.pop(); diff --git a/tools/eslint/lib/rules/no-loop-func.js b/tools/eslint/lib/rules/no-loop-func.js index e940933896..f51a8327c2 100644 --- a/tools/eslint/lib/rules/no-loop-func.js +++ b/tools/eslint/lib/rules/no-loop-func.js @@ -74,7 +74,7 @@ function getContainingLoopNode(node) { */ function getTopLoopNode(node, excludedNode) { let retv = node; - let border = excludedNode ? excludedNode.range[1] : 0; + const border = excludedNode ? excludedNode.range[1] : 0; while (node && node.range[0] >= border) { retv = node; @@ -94,10 +94,10 @@ function getTopLoopNode(node, excludedNode) { * @returns {boolean} `true` if the reference is safe or not. */ function isSafe(funcNode, loopNode, reference) { - let variable = reference.resolved; - let definition = variable && variable.defs[0]; - let declaration = definition && definition.parent; - let kind = (declaration && declaration.type === "VariableDeclaration") + const variable = reference.resolved; + const definition = variable && variable.defs[0]; + const declaration = definition && definition.parent; + const kind = (declaration && declaration.type === "VariableDeclaration") ? declaration.kind : ""; @@ -117,7 +117,7 @@ function isSafe(funcNode, loopNode, reference) { // WriteReferences which exist after this border are unsafe because those // can modify the variable. - let border = getTopLoopNode( + const border = getTopLoopNode( loopNode, (kind === "let") ? declaration : null ).range[0]; @@ -135,7 +135,7 @@ function isSafe(funcNode, loopNode, reference) { * @returns {boolean} `true` if the reference is safe. */ function isSafeReference(upperRef) { - let id = upperRef.identifier; + const id = upperRef.identifier; return ( !upperRef.isWrite() || @@ -174,13 +174,13 @@ module.exports = { * @returns {boolean} Whether or not the node is within a loop. */ function checkForLoops(node) { - let loopNode = getContainingLoopNode(node); + const loopNode = getContainingLoopNode(node); if (!loopNode) { return; } - let references = context.getScope().through; + const references = context.getScope().through; if (references.length > 0 && !references.every(isSafe.bind(null, node, loopNode)) diff --git a/tools/eslint/lib/rules/no-magic-numbers.js b/tools/eslint/lib/rules/no-magic-numbers.js index 76d71c1e6c..92853c1c06 100644 --- a/tools/eslint/lib/rules/no-magic-numbers.js +++ b/tools/eslint/lib/rules/no-magic-numbers.js @@ -42,7 +42,7 @@ module.exports = { }, create: function(context) { - let config = context.options[0] || {}, + const config = context.options[0] || {}, detectObjects = !!config.detectObjects, enforceConst = !!config.enforceConst, ignore = config.ignore || [], @@ -102,8 +102,8 @@ module.exports = { Literal: function(node) { let parent = node.parent, value = node.value, - raw = node.raw, - okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"]; + raw = node.raw; + const okTypes = detectObjects ? [] : ["ObjectExpression", "Property", "AssignmentExpression"]; if (!isNumber(node)) { return; diff --git a/tools/eslint/lib/rules/no-mixed-operators.js b/tools/eslint/lib/rules/no-mixed-operators.js index f6e686521d..2ddf9a1867 100644 --- a/tools/eslint/lib/rules/no-mixed-operators.js +++ b/tools/eslint/lib/rules/no-mixed-operators.js @@ -9,32 +9,32 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils.js"); +const astUtils = require("../ast-utils.js"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let ARITHMETIC_OPERATORS = ["+", "-", "*", "/", "%", "**"]; -let BITWISE_OPERATORS = ["&", "|", "^", "~", "<<", ">>", ">>>"]; -let COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="]; -let LOGICAL_OPERATORS = ["&&", "||"]; -let RELATIONAL_OPERATORS = ["in", "instanceof"]; -let ALL_OPERATORS = [].concat( +const ARITHMETIC_OPERATORS = ["+", "-", "*", "/", "%", "**"]; +const BITWISE_OPERATORS = ["&", "|", "^", "~", "<<", ">>", ">>>"]; +const COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="]; +const LOGICAL_OPERATORS = ["&&", "||"]; +const RELATIONAL_OPERATORS = ["in", "instanceof"]; +const ALL_OPERATORS = [].concat( ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS ); -let DEFAULT_GROUPS = [ +const DEFAULT_GROUPS = [ ARITHMETIC_OPERATORS, BITWISE_OPERATORS, COMPARISON_OPERATORS, LOGICAL_OPERATORS, RELATIONAL_OPERATORS ]; -let TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/; +const TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/; /** * Normalizes options. @@ -43,9 +43,9 @@ let TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/; * @returns {Object} Normalized option object. */ function normalizeOptions(options) { - let hasGroups = (options && options.groups && options.groups.length > 0); - let groups = hasGroups ? options.groups : DEFAULT_GROUPS; - let allowSamePrecedence = (options && options.allowSamePrecedence) !== false; + const hasGroups = (options && options.groups && options.groups.length > 0); + const groups = hasGroups ? options.groups : DEFAULT_GROUPS; + const allowSamePrecedence = (options && options.allowSamePrecedence) !== false; return { groups: groups, @@ -102,8 +102,8 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); - let options = normalizeOptions(context.options[0]); + const sourceCode = context.getSourceCode(); + const options = normalizeOptions(context.options[0]); /** * Checks whether a given node should be ignored by options or not. @@ -114,8 +114,8 @@ module.exports = { * @returns {boolean} `true` if the node should be ignored. */ function shouldIgnore(node) { - let a = node; - let b = node.parent; + const a = node; + const b = node.parent; return ( !includesBothInAGroup(options.groups, a.operator, b.operator) || @@ -169,10 +169,10 @@ module.exports = { * @returns {void} */ function reportBothOperators(node) { - let parent = node.parent; - let left = (parent.left === node) ? node : parent; - let right = (parent.left !== node) ? node : parent; - let message = + const parent = node.parent; + const left = (parent.left === node) ? node : parent; + const right = (parent.left !== node) ? node : parent; + const message = "Unexpected mix of '" + left.operator + "' and '" + right.operator + "'."; diff --git a/tools/eslint/lib/rules/no-mixed-requires.js b/tools/eslint/lib/rules/no-mixed-requires.js index 68ce51f56f..9d25a1f090 100644 --- a/tools/eslint/lib/rules/no-mixed-requires.js +++ b/tools/eslint/lib/rules/no-mixed-requires.js @@ -42,9 +42,9 @@ module.exports = { create: function(context) { + const options = context.options[0]; let grouping = false, - allowCall = false, - options = context.options[0]; + allowCall = false; if (typeof options === "object") { grouping = options.grouping; @@ -74,13 +74,13 @@ module.exports = { ]; } - let BUILTIN_MODULES = getBuiltinModules(); + const BUILTIN_MODULES = getBuiltinModules(); - let DECL_REQUIRE = "require", + const DECL_REQUIRE = "require", DECL_UNINITIALIZED = "uninitialized", DECL_OTHER = "other"; - let REQ_CORE = "core", + const REQ_CORE = "core", REQ_FILE = "file", REQ_MODULE = "module", REQ_COMPUTED = "computed"; @@ -137,7 +137,7 @@ module.exports = { return REQ_COMPUTED; } - let arg = initExpression.arguments[0]; + const arg = initExpression.arguments[0]; if (arg.type !== "Literal" || typeof arg.value !== "string") { @@ -167,10 +167,10 @@ module.exports = { * @returns {boolean} True if the declarations are mixed, false if not. */ function isMixed(declarations) { - let contains = {}; + const contains = {}; declarations.forEach(function(declaration) { - let type = getDeclarationType(declaration.init); + const type = getDeclarationType(declaration.init); contains[type] = true; }); @@ -188,7 +188,7 @@ module.exports = { * @returns {boolean} True if the declarations are grouped, false if not. */ function isGrouped(declarations) { - let found = {}; + const found = {}; declarations.forEach(function(declaration) { if (getDeclarationType(declaration.init) === DECL_REQUIRE) { diff --git a/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js b/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js index 19734b1b5d..41e4714108 100644 --- a/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js +++ b/tools/eslint/lib/rules/no-mixed-spaces-and-tabs.js @@ -24,10 +24,10 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); - let smartTabs, - ignoredLocs = []; + let smartTabs; + const ignoredLocs = []; switch (context.options[0]) { case true: // Support old syntax, maybe add deprecation warning here @@ -85,9 +85,8 @@ module.exports = { * or the reverse before non-tab/-space * characters begin. */ - let regex = /^(?=[\t ]*(\t | \t))/, - match, - lines = sourceCode.lines, + let regex = /^(?=[\t ]*(\t | \t))/; + const lines = sourceCode.lines, comments = sourceCode.getAllComments(); comments.forEach(function(comment) { @@ -116,10 +115,10 @@ module.exports = { } lines.forEach(function(line, i) { - match = regex.exec(line); + const match = regex.exec(line); if (match) { - let lineNumber = i + 1, + const lineNumber = i + 1, column = match.index + 1; for (let j = 0; j < ignoredLocs.length; j++) { diff --git a/tools/eslint/lib/rules/no-multi-spaces.js b/tools/eslint/lib/rules/no-multi-spaces.js index 78d600c884..608843aff2 100644 --- a/tools/eslint/lib/rules/no-multi-spaces.js +++ b/tools/eslint/lib/rules/no-multi-spaces.js @@ -41,9 +41,9 @@ module.exports = { create: function(context) { // the index of the last comment that was checked - let exceptions = { Property: true }, - hasExceptions = true, - options = context.options[0], + const exceptions = { Property: true }, + options = context.options[0]; + let hasExceptions = true, lastCommentIndex = 0; if (options && options.exceptions) { @@ -68,12 +68,8 @@ module.exports = { * @private */ function isIndexInComment(index, comments) { - - let comment; - while (lastCommentIndex < comments.length) { - - comment = comments[lastCommentIndex]; + const comment = comments[lastCommentIndex]; if (comment.range[0] <= index && index < comment.range[1]) { return true; @@ -82,7 +78,6 @@ module.exports = { } else { break; } - } return false; @@ -95,13 +90,11 @@ module.exports = { return { Program: function() { - let sourceCode = context.getSourceCode(), + const sourceCode = context.getSourceCode(), source = sourceCode.getText(), allComments = sourceCode.getAllComments(), - pattern = /[^\n\r\u2028\u2029\t ].? {2,}/g, // note: repeating space - token, - previousToken, - parent; + pattern = /[^\n\r\u2028\u2029\t ].? {2,}/g; // note: repeating space + let parent; /** @@ -122,9 +115,10 @@ module.exports = { // do not flag anything inside of comments if (!isIndexInComment(pattern.lastIndex, allComments)) { - token = sourceCode.getTokenByRangeStart(pattern.lastIndex); + const token = sourceCode.getTokenByRangeStart(pattern.lastIndex); + if (token) { - previousToken = sourceCode.getTokenBefore(token); + const previousToken = sourceCode.getTokenBefore(token); if (hasExceptions) { parent = sourceCode.getNodeByRangeIndex(pattern.lastIndex - 1); diff --git a/tools/eslint/lib/rules/no-multi-str.js b/tools/eslint/lib/rules/no-multi-str.js index 1d88010459..78930ab0b7 100644 --- a/tools/eslint/lib/rules/no-multi-str.js +++ b/tools/eslint/lib/rules/no-multi-str.js @@ -39,7 +39,7 @@ module.exports = { return { Literal: function(node) { - let lineBreak = /\n/; + const lineBreak = /\n/; if (lineBreak.test(node.raw) && !isJSXElement(node.parent)) { context.report(node, "Multiline support is limited to browsers supporting ES5 only."); diff --git a/tools/eslint/lib/rules/no-multiple-empty-lines.js b/tools/eslint/lib/rules/no-multiple-empty-lines.js index cede2d5e78..7b8c73d0ac 100644 --- a/tools/eslint/lib/rules/no-multiple-empty-lines.js +++ b/tools/eslint/lib/rules/no-multiple-empty-lines.js @@ -50,7 +50,7 @@ module.exports = { maxBOF; // store lines that appear empty but really aren't - let notEmpty = []; + const notEmpty = []; if (context.options.length) { max = context.options[0].max; @@ -58,7 +58,7 @@ module.exports = { maxBOF = typeof context.options[0].maxBOF !== "undefined" ? context.options[0].maxBOF : max; } - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Public @@ -68,7 +68,7 @@ module.exports = { TemplateLiteral: function(node) { let start = node.loc.start.line; - let end = node.loc.end.line; + const end = node.loc.end.line; while (start <= end) { notEmpty.push(start); @@ -77,28 +77,31 @@ module.exports = { }, "Program:exit": function checkBlankLines(node) { - let lines = sourceCode.lines, + const lines = sourceCode.lines, fullLines = sourceCode.text.match(/.*(\r\n|\r|\n|\u2028|\u2029)/g) || [], - firstNonBlankLine = -1, + linesRangeStart = []; + let firstNonBlankLine = -1, trimmedLines = [], - linesRangeStart = [], blankCounter = 0, currentLocation, lastLocation, - location, firstOfEndingBlankLines, diff, - fix, rangeStart, rangeEnd; - fix = function(fixer) { + /** + * Fix code. + * @param {RuleFixer} fixer - The fixer of this context. + * @returns {Object} The fixing information. + */ + function fix(fixer) { return fixer.removeRange([rangeStart, rangeEnd]); - }; + } linesRangeStart.push(0); lines.forEach(function(str, i) { - let length = i < fullLines.length ? fullLines[i].length : 0, + const length = i < fullLines.length ? fullLines[i].length : 0, trimmed = str.trim(); if ((firstNonBlankLine === -1) && (trimmed !== "")) { @@ -157,7 +160,7 @@ module.exports = { if (lastLocation === currentLocation - 1) { blankCounter++; } else { - location = { + const location = { line: lastLocation + 1, column: 1 }; diff --git a/tools/eslint/lib/rules/no-native-reassign.js b/tools/eslint/lib/rules/no-native-reassign.js index aa8314dda6..46708e94b4 100644 --- a/tools/eslint/lib/rules/no-native-reassign.js +++ b/tools/eslint/lib/rules/no-native-reassign.js @@ -1,6 +1,7 @@ /** * @fileoverview Rule to disallow assignments to native objects or read-only global variables * @author Ilya Volodin + * @deprecated in ESLint v3.3.0 */ "use strict"; @@ -14,9 +15,12 @@ module.exports = { docs: { description: "disallow assignments to native objects or read-only global variables", category: "Best Practices", - recommended: true + recommended: true, + replacedBy: ["no-global-assign"] }, + deprecated: true, + schema: [ { type: "object", @@ -33,8 +37,8 @@ module.exports = { }, create: function(context) { - let config = context.options[0]; - let exceptions = (config && config.exceptions) || []; + const config = context.options[0]; + const exceptions = (config && config.exceptions) || []; /** * Reports write references. @@ -44,7 +48,7 @@ module.exports = { * @returns {void} */ function checkReference(reference, index, references) { - let identifier = reference.identifier; + const identifier = reference.identifier; if (reference.init === false && reference.isWrite() && @@ -74,7 +78,7 @@ module.exports = { return { Program: function() { - let globalScope = context.getScope(); + const globalScope = context.getScope(); globalScope.variables.forEach(checkVariable); } diff --git a/tools/eslint/lib/rules/no-negated-in-lhs.js b/tools/eslint/lib/rules/no-negated-in-lhs.js index 46f6c1cad4..d2c3994372 100644 --- a/tools/eslint/lib/rules/no-negated-in-lhs.js +++ b/tools/eslint/lib/rules/no-negated-in-lhs.js @@ -1,6 +1,7 @@ /** * @fileoverview A rule to disallow negated left operands of the `in` operator * @author Michael Ficarra + * @deprecated in ESLint v3.3.0 */ "use strict"; @@ -14,8 +15,10 @@ module.exports = { docs: { description: "disallow negating the left operand in `in` expressions", category: "Possible Errors", - recommended: true + recommended: true, + replacedBy: ["no-unsafe-negation"] }, + deprecated: true, schema: [] }, diff --git a/tools/eslint/lib/rules/no-new-symbol.js b/tools/eslint/lib/rules/no-new-symbol.js index d4c4e67b17..e8c87b1b63 100644 --- a/tools/eslint/lib/rules/no-new-symbol.js +++ b/tools/eslint/lib/rules/no-new-symbol.js @@ -24,12 +24,12 @@ module.exports = { return { "Program:exit": function() { - let globalScope = context.getScope(); - let variable = globalScope.set.get("Symbol"); + const globalScope = context.getScope(); + const variable = globalScope.set.get("Symbol"); if (variable && variable.defs.length === 0) { variable.references.forEach(function(ref) { - let node = ref.identifier; + const node = ref.identifier; if (node.parent && node.parent.type === "NewExpression") { context.report(node, "`Symbol` cannot be called as a constructor."); diff --git a/tools/eslint/lib/rules/no-new-wrappers.js b/tools/eslint/lib/rules/no-new-wrappers.js index 756ee80076..cfc80a7f9a 100644 --- a/tools/eslint/lib/rules/no-new-wrappers.js +++ b/tools/eslint/lib/rules/no-new-wrappers.js @@ -25,7 +25,7 @@ module.exports = { return { NewExpression: function(node) { - let wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"]; + const wrapperObjects = ["String", "Number", "Boolean", "Math", "JSON"]; if (wrapperObjects.indexOf(node.callee.name) > -1) { context.report(node, "Do not use {{fn}} as a constructor.", { fn: node.callee.name }); diff --git a/tools/eslint/lib/rules/no-obj-calls.js b/tools/eslint/lib/rules/no-obj-calls.js index ba1c45a31f..fafc31296f 100644 --- a/tools/eslint/lib/rules/no-obj-calls.js +++ b/tools/eslint/lib/rules/no-obj-calls.js @@ -26,7 +26,7 @@ module.exports = { CallExpression: function(node) { if (node.callee.type === "Identifier") { - let name = node.callee.name; + const name = node.callee.name; if (name === "Math" || name === "JSON") { context.report(node, "'{{name}}' is not a function.", { name: name }); diff --git a/tools/eslint/lib/rules/no-octal-escape.js b/tools/eslint/lib/rules/no-octal-escape.js index cf5953a986..e4af81db5e 100644 --- a/tools/eslint/lib/rules/no-octal-escape.js +++ b/tools/eslint/lib/rules/no-octal-escape.js @@ -29,11 +29,10 @@ module.exports = { return; } - let match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/), - octalDigit; + const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-3][0-7]{1,2}|[4-7][0-7]|[0-7])/); if (match) { - octalDigit = match[2]; + const octalDigit = match[2]; // \0 is actually not considered an octal if (match[2] !== "0" || typeof match[3] !== "undefined") { diff --git a/tools/eslint/lib/rules/no-param-reassign.js b/tools/eslint/lib/rules/no-param-reassign.js index 3a59106a2d..048e87bbc3 100644 --- a/tools/eslint/lib/rules/no-param-reassign.js +++ b/tools/eslint/lib/rules/no-param-reassign.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -let stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/; +const stopNodePattern = /(?:Statement|Declaration|Function(?:Expression)?|Program)$/; module.exports = { meta: { @@ -30,7 +30,7 @@ module.exports = { }, create: function(context) { - let props = context.options[0] && Boolean(context.options[0].props); + const props = context.options[0] && Boolean(context.options[0].props); /** * Checks whether or not the reference modifies properties of its variable. @@ -92,7 +92,7 @@ module.exports = { * @returns {void} */ function checkReference(reference, index, references) { - let identifier = reference.identifier; + const identifier = reference.identifier; if (identifier && !reference.init && diff --git a/tools/eslint/lib/rules/no-path-concat.js b/tools/eslint/lib/rules/no-path-concat.js index f13d942674..72fba0b9cd 100644 --- a/tools/eslint/lib/rules/no-path-concat.js +++ b/tools/eslint/lib/rules/no-path-concat.js @@ -21,7 +21,7 @@ module.exports = { create: function(context) { - let MATCHER = /^__(?:dir|file)name$/; + const MATCHER = /^__(?:dir|file)name$/; //-------------------------------------------------------------------------- // Public @@ -31,7 +31,7 @@ module.exports = { BinaryExpression: function(node) { - let left = node.left, + const left = node.left, right = node.right; if (node.operator === "+" && diff --git a/tools/eslint/lib/rules/no-plusplus.js b/tools/eslint/lib/rules/no-plusplus.js index 34e54001ae..7b4dd59569 100644 --- a/tools/eslint/lib/rules/no-plusplus.js +++ b/tools/eslint/lib/rules/no-plusplus.js @@ -33,8 +33,8 @@ module.exports = { create: function(context) { - let config = context.options[0], - allowInForAfterthought = false; + const config = context.options[0]; + let allowInForAfterthought = false; if (typeof config === "object") { allowInForAfterthought = config.allowForLoopAfterthoughts === true; diff --git a/tools/eslint/lib/rules/no-process-env.js b/tools/eslint/lib/rules/no-process-env.js index d1bf15a245..229b95f8d6 100644 --- a/tools/eslint/lib/rules/no-process-env.js +++ b/tools/eslint/lib/rules/no-process-env.js @@ -24,7 +24,7 @@ module.exports = { return { MemberExpression: function(node) { - let objectName = node.object.name, + const objectName = node.object.name, propertyName = node.property.name; if (objectName === "process" && !node.computed && propertyName && propertyName === "env") { diff --git a/tools/eslint/lib/rules/no-process-exit.js b/tools/eslint/lib/rules/no-process-exit.js index 045214e7e7..2ca84b9201 100644 --- a/tools/eslint/lib/rules/no-process-exit.js +++ b/tools/eslint/lib/rules/no-process-exit.js @@ -28,7 +28,7 @@ module.exports = { return { CallExpression: function(node) { - let callee = node.callee; + const callee = node.callee; if (callee.type === "MemberExpression" && callee.object.name === "process" && callee.property.name === "exit" diff --git a/tools/eslint/lib/rules/no-prototype-builtins.js b/tools/eslint/lib/rules/no-prototype-builtins.js index 08b0b6dcf9..a0ce73fc15 100644 --- a/tools/eslint/lib/rules/no-prototype-builtins.js +++ b/tools/eslint/lib/rules/no-prototype-builtins.js @@ -20,7 +20,7 @@ module.exports = { }, create: function(context) { - let DISALLOWED_PROPS = [ + const DISALLOWED_PROPS = [ "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable" @@ -35,7 +35,7 @@ module.exports = { if (node.callee.type !== "MemberExpression" || node.callee.computed) { return; } - let propName = node.callee.property.name; + const propName = node.callee.property.name; if (DISALLOWED_PROPS.indexOf(propName) > -1) { context.report({ diff --git a/tools/eslint/lib/rules/no-redeclare.js b/tools/eslint/lib/rules/no-redeclare.js index 8a1540ff79..8a26b34b42 100644 --- a/tools/eslint/lib/rules/no-redeclare.js +++ b/tools/eslint/lib/rules/no-redeclare.js @@ -29,7 +29,7 @@ module.exports = { }, create: function(context) { - let options = { + const options = { builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals) }; @@ -41,8 +41,8 @@ module.exports = { */ function findVariablesInScope(scope) { scope.variables.forEach(function(variable) { - let hasBuiltin = options.builtinGlobals && "writeable" in variable; - let count = (hasBuiltin ? 1 : 0) + variable.identifiers.length; + const hasBuiltin = options.builtinGlobals && "writeable" in variable; + const count = (hasBuiltin ? 1 : 0) + variable.identifiers.length; if (count >= 2) { variable.identifiers.sort(function(a, b) { @@ -67,7 +67,7 @@ module.exports = { * @private */ function checkForGlobal(node) { - let scope = context.getScope(), + const scope = context.getScope(), parserOptions = context.parserOptions, ecmaFeatures = parserOptions.ecmaFeatures || {}; diff --git a/tools/eslint/lib/rules/no-regex-spaces.js b/tools/eslint/lib/rules/no-regex-spaces.js index de179894b3..dc09e98e05 100644 --- a/tools/eslint/lib/rules/no-regex-spaces.js +++ b/tools/eslint/lib/rules/no-regex-spaces.js @@ -21,7 +21,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Validate regular expressions @@ -31,7 +31,7 @@ module.exports = { * @private */ function checkRegex(node, value) { - let multipleSpacesRegex = /( {2,})+?/, + const multipleSpacesRegex = /( {2,})+?/, regexResults = multipleSpacesRegex.exec(value); if (regexResults !== null) { @@ -46,7 +46,7 @@ module.exports = { * @private */ function checkLiteral(node) { - let token = sourceCode.getFirstToken(node), + const token = sourceCode.getFirstToken(node), nodeType = token.type, nodeValue = token.value; diff --git a/tools/eslint/lib/rules/no-restricted-globals.js b/tools/eslint/lib/rules/no-restricted-globals.js index 19bd6a94ae..3617f1a8d7 100644 --- a/tools/eslint/lib/rules/no-restricted-globals.js +++ b/tools/eslint/lib/rules/no-restricted-globals.js @@ -26,7 +26,7 @@ module.exports = { }, create: function(context) { - let restrictedGlobals = context.options; + const restrictedGlobals = context.options; // if no globals are restricted we don't need to check if (restrictedGlobals.length === 0) { @@ -57,7 +57,7 @@ module.exports = { return { Program: function() { - let scope = context.getScope(); + const scope = context.getScope(); // Report variables declared elsewhere (ex: variables defined as "global" by eslint) scope.variables.forEach(function(variable) { diff --git a/tools/eslint/lib/rules/no-restricted-imports.js b/tools/eslint/lib/rules/no-restricted-imports.js index da768c135c..3649f027ac 100644 --- a/tools/eslint/lib/rules/no-restricted-imports.js +++ b/tools/eslint/lib/rules/no-restricted-imports.js @@ -26,7 +26,7 @@ module.exports = { }, create: function(context) { - let restrictedImports = context.options; + const restrictedImports = context.options; // if no imports are restricted we don"t need to check if (restrictedImports.length === 0) { @@ -37,7 +37,7 @@ module.exports = { ImportDeclaration: function(node) { if (node && node.source && node.source.value) { - let value = node.source.value.trim(); + const value = node.source.value.trim(); if (restrictedImports.indexOf(value) !== -1) { context.report(node, "'{{importName}}' import is restricted from being used.", { diff --git a/tools/eslint/lib/rules/no-restricted-modules.js b/tools/eslint/lib/rules/no-restricted-modules.js index eeb6bf270d..982ad0110d 100644 --- a/tools/eslint/lib/rules/no-restricted-modules.js +++ b/tools/eslint/lib/rules/no-restricted-modules.js @@ -28,7 +28,7 @@ module.exports = { create: function(context) { // trim restricted module names - let restrictedModules = context.options; + const restrictedModules = context.options; // if no modules are restricted we don't need to check the CallExpressions if (restrictedModules.length === 0) { @@ -63,7 +63,7 @@ module.exports = { // node has arguments and first argument is string if (node.arguments.length && isString(node.arguments[0])) { - let argumentValue = node.arguments[0].value.trim(); + const argumentValue = node.arguments[0].value.trim(); // check if argument value is in restricted modules array if (restrictedModules.indexOf(argumentValue) !== -1) { @@ -77,7 +77,7 @@ module.exports = { return { CallExpression: function(node) { if (isRequireCall(node)) { - let restrictedModuleName = getRestrictedModuleName(node); + const restrictedModuleName = getRestrictedModuleName(node); if (restrictedModuleName) { context.report(node, "'{{moduleName}}' module is restricted from being used.", { diff --git a/tools/eslint/lib/rules/no-restricted-syntax.js b/tools/eslint/lib/rules/no-restricted-syntax.js index 84c62d63ac..7c4d234501 100644 --- a/tools/eslint/lib/rules/no-restricted-syntax.js +++ b/tools/eslint/lib/rules/no-restricted-syntax.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -let nodeTypes = require("espree").Syntax; +const nodeTypes = require("espree").Syntax; module.exports = { meta: { diff --git a/tools/eslint/lib/rules/no-return-assign.js b/tools/eslint/lib/rules/no-return-assign.js index 5493506071..d223fff7ad 100644 --- a/tools/eslint/lib/rules/no-return-assign.js +++ b/tools/eslint/lib/rules/no-return-assign.js @@ -8,7 +8,7 @@ // Helpers //------------------------------------------------------------------------------ -let SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/; +const SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExpression|ClassExpression)$/; /** * Checks whether or not a node is enclosed in parentheses. @@ -17,8 +17,8 @@ let SENTINEL_TYPE = /^(?:[a-zA-Z]+?Statement|ArrowFunctionExpression|FunctionExp * @returns {boolean} Whether or not the node is enclosed in parentheses. */ function isEnclosedInParens(node, sourceCode) { - let prevToken = sourceCode.getTokenBefore(node); - let nextToken = sourceCode.getTokenAfter(node); + const prevToken = sourceCode.getTokenBefore(node); + const nextToken = sourceCode.getTokenAfter(node); return prevToken && prevToken.value === "(" && nextToken && nextToken.value === ")"; } @@ -43,8 +43,8 @@ module.exports = { }, create: function(context) { - let always = (context.options[0] || "except-parens") !== "except-parens"; - let sourceCode = context.getSourceCode(); + const always = (context.options[0] || "except-parens") !== "except-parens"; + const sourceCode = context.getSourceCode(); return { AssignmentExpression: function(node) { diff --git a/tools/eslint/lib/rules/no-script-url.js b/tools/eslint/lib/rules/no-script-url.js index 1c12490b43..0d767bbd1e 100644 --- a/tools/eslint/lib/rules/no-script-url.js +++ b/tools/eslint/lib/rules/no-script-url.js @@ -27,11 +27,8 @@ module.exports = { return { Literal: function(node) { - - let value; - if (node.value && typeof node.value === "string") { - value = node.value.toLowerCase(); + const value = node.value.toLowerCase(); if (value.indexOf("javascript:") === 0) { context.report(node, "Script URL is a form of eval."); diff --git a/tools/eslint/lib/rules/no-self-assign.js b/tools/eslint/lib/rules/no-self-assign.js index e3dc35e81e..bfc0241664 100644 --- a/tools/eslint/lib/rules/no-self-assign.js +++ b/tools/eslint/lib/rules/no-self-assign.js @@ -6,9 +6,66 @@ "use strict"; //------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ +const SPACES = /\s+/g; + +/** + * Checks whether the property of 2 given member expression nodes are the same + * property or not. + * + * @param {ASTNode} left - A member expression node to check. + * @param {ASTNode} right - Another member expression node to check. + * @returns {boolean} `true` if the member expressions have the same property. + */ +function isSameProperty(left, right) { + if (left.property.type === "Identifier" && + left.property.type === right.property.type && + left.property.name === right.property.name && + left.computed === right.computed + ) { + return true; + } + + const lname = astUtils.getStaticPropertyName(left); + const rname = astUtils.getStaticPropertyName(right); + + return lname !== null && lname === rname; +} + +/** + * Checks whether 2 given member expression nodes are the reference to the same + * property or not. + * + * @param {ASTNode} left - A member expression node to check. + * @param {ASTNode} right - Another member expression node to check. + * @returns {boolean} `true` if the member expressions are the reference to the + * same property or not. + */ +function isSameMember(left, right) { + if (!isSameProperty(left, right)) { + return false; + } + + const lobj = left.object; + const robj = right.object; + + if (lobj.type !== robj.type) { + return false; + } + if (lobj.type === "MemberExpression") { + return isSameMember(lobj, robj); + } + return lobj.type === "Identifier" && lobj.name === robj.name; +} + /** * Traverses 2 Pattern nodes in parallel, then reports self-assignments. * @@ -16,12 +73,11 @@ * a Property. * @param {ASTNode|null} right - A right node to traverse. This is a Pattern or * a Property. + * @param {boolean} props - The flag to check member expressions as well. * @param {Function} report - A callback function to report. * @returns {void} */ -function eachSelfAssignment(left, right, report) { - let i, j; - +function eachSelfAssignment(left, right, props, report) { if (!left || !right) { // do nothing @@ -35,12 +91,12 @@ function eachSelfAssignment(left, right, report) { left.type === "ArrayPattern" && right.type === "ArrayExpression" ) { - let end = Math.min(left.elements.length, right.elements.length); + const end = Math.min(left.elements.length, right.elements.length); - for (i = 0; i < end; ++i) { - let rightElement = right.elements[i]; + for (let i = 0; i < end; ++i) { + const rightElement = right.elements[i]; - eachSelfAssignment(left.elements[i], rightElement, report); + eachSelfAssignment(left.elements[i], rightElement, props, report); // After a spread element, those indices are unknown. if (rightElement && rightElement.type === "SpreadElement") { @@ -51,7 +107,7 @@ function eachSelfAssignment(left, right, report) { left.type === "RestElement" && right.type === "SpreadElement" ) { - eachSelfAssignment(left.argument, right.argument, report); + eachSelfAssignment(left.argument, right.argument, props, report); } else if ( left.type === "ObjectPattern" && right.type === "ObjectExpression" && @@ -62,18 +118,19 @@ function eachSelfAssignment(left, right, report) { // It's possible to overwrite properties followed by it. let startJ = 0; - for (i = right.properties.length - 1; i >= 0; --i) { + for (let i = right.properties.length - 1; i >= 0; --i) { if (right.properties[i].type === "ExperimentalSpreadProperty") { startJ = i + 1; break; } } - for (i = 0; i < left.properties.length; ++i) { - for (j = startJ; j < right.properties.length; ++j) { + for (let i = 0; i < left.properties.length; ++i) { + for (let j = startJ; j < right.properties.length; ++j) { eachSelfAssignment( left.properties[i], right.properties[j], + props, report ); } @@ -87,7 +144,14 @@ function eachSelfAssignment(left, right, report) { !right.method && left.key.name === right.key.name ) { - eachSelfAssignment(left.value, right.value, report); + eachSelfAssignment(left.value, right.value, props, report); + } else if ( + props && + left.type === "MemberExpression" && + right.type === "MemberExpression" && + isSameMember(left, right) + ) { + report(right); } } @@ -103,10 +167,23 @@ module.exports = { recommended: true }, - schema: [] + schema: [ + { + type: "object", + properties: { + props: { + type: "boolean" + } + }, + additionalProperties: false + } + ] }, create: function(context) { + const sourceCode = context.getSourceCode(); + const options = context.options[0]; + const props = Boolean(options && options.props); /** * Reports a given node as self assignments. @@ -118,14 +195,16 @@ module.exports = { context.report({ node: node, message: "'{{name}}' is assigned to itself.", - data: node + data: { + name: sourceCode.getText(node).replace(SPACES, "") + } }); } return { AssignmentExpression: function(node) { if (node.operator === "=") { - eachSelfAssignment(node.left, node.right, report); + eachSelfAssignment(node.left, node.right, props, report); } } }; diff --git a/tools/eslint/lib/rules/no-self-compare.js b/tools/eslint/lib/rules/no-self-compare.js index c677e56ffd..db51796217 100644 --- a/tools/eslint/lib/rules/no-self-compare.js +++ b/tools/eslint/lib/rules/no-self-compare.js @@ -26,7 +26,7 @@ module.exports = { return { BinaryExpression: function(node) { - let operators = ["===", "==", "!==", "!=", ">", "<", ">=", "<="]; + const operators = ["===", "==", "!==", "!=", ">", "<", ">=", "<="]; if (operators.indexOf(node.operator) > -1 && (node.left.type === "Identifier" && node.right.type === "Identifier" && node.left.name === node.right.name || diff --git a/tools/eslint/lib/rules/no-sequences.js b/tools/eslint/lib/rules/no-sequences.js index 51c3b8e808..7971dac0dc 100644 --- a/tools/eslint/lib/rules/no-sequences.js +++ b/tools/eslint/lib/rules/no-sequences.js @@ -21,12 +21,12 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Parts of the grammar that are required to have parens. */ - let parenthesized = { + const parenthesized = { DoWhileStatement: "test", IfStatement: "test", SwitchStatement: "discriminant", @@ -57,7 +57,7 @@ module.exports = { * @returns {boolean} True if the node has a paren on each side. */ function isParenthesised(node) { - let previousToken = sourceCode.getTokenBefore(node), + const previousToken = sourceCode.getTokenBefore(node), nextToken = sourceCode.getTokenAfter(node); return previousToken && nextToken && @@ -71,7 +71,7 @@ module.exports = { * @returns {boolean} True if two parens surround the node on each side. */ function isParenthesisedTwice(node) { - let previousToken = sourceCode.getTokenBefore(node, 1), + const previousToken = sourceCode.getTokenBefore(node, 1), nextToken = sourceCode.getTokenAfter(node, 1); return isParenthesised(node) && previousToken && nextToken && @@ -99,7 +99,7 @@ module.exports = { } } - let child = sourceCode.getTokenAfter(node.expressions[0]); + const child = sourceCode.getTokenAfter(node.expressions[0]); context.report(node, child.loc.start, "Unexpected use of comma operator."); } diff --git a/tools/eslint/lib/rules/no-shadow-restricted-names.js b/tools/eslint/lib/rules/no-shadow-restricted-names.js index d932363d6f..54dc1e5873 100644 --- a/tools/eslint/lib/rules/no-shadow-restricted-names.js +++ b/tools/eslint/lib/rules/no-shadow-restricted-names.js @@ -21,7 +21,7 @@ module.exports = { create: function(context) { - let RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"]; + const RESTRICTED = ["undefined", "NaN", "Infinity", "arguments", "eval"]; /** * Check if the node name is present inside the restricted list diff --git a/tools/eslint/lib/rules/no-shadow.js b/tools/eslint/lib/rules/no-shadow.js index 62f7504780..6eca4a4176 100644 --- a/tools/eslint/lib/rules/no-shadow.js +++ b/tools/eslint/lib/rules/no-shadow.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -43,7 +43,7 @@ module.exports = { create: function(context) { - let options = { + const options = { builtinGlobals: Boolean(context.options[0] && context.options[0].builtinGlobals), hoist: (context.options[0] && context.options[0].hoist) || "functions", allow: (context.options[0] && context.options[0].allow) || [] @@ -69,7 +69,7 @@ module.exports = { * @returns {boolean} Whether or not the variable of the class name in the class scope of ClassDeclaration. */ function isDuplicatedClassNameVariable(variable) { - let block = variable.scope.block; + const block = variable.scope.block; return block.type === "ClassDeclaration" && block.id === variable.identifiers[0]; } @@ -85,12 +85,12 @@ module.exports = { * @returns {boolean} Whether or not the variable is inside initializer of scopeVar. */ function isOnInitializer(variable, scopeVar) { - let outerScope = scopeVar.scope; - let outerDef = scopeVar.defs[0]; - let outer = outerDef && outerDef.parent && outerDef.parent.range; - let innerScope = variable.scope; - let innerDef = variable.defs[0]; - let inner = innerDef && innerDef.name.range; + const outerScope = scopeVar.scope; + const outerDef = scopeVar.defs[0]; + const outer = outerDef && outerDef.parent && outerDef.parent.range; + const innerScope = variable.scope; + const innerDef = variable.defs[0]; + const inner = innerDef && innerDef.name.range; return ( outer && @@ -108,7 +108,7 @@ module.exports = { * @returns {Array|undefined} The range of the variable's identifier node. */ function getNameRange(variable) { - let def = variable.defs[0]; + const def = variable.defs[0]; return def && def.name.range; } @@ -120,9 +120,9 @@ module.exports = { * @returns {boolean} Whether or not the variable is in TDZ of scopeVar. */ function isInTdz(variable, scopeVar) { - let outerDef = scopeVar.defs[0]; - let inner = getNameRange(variable); - let outer = getNameRange(scopeVar); + const outerDef = scopeVar.defs[0]; + const inner = getNameRange(variable); + const outer = getNameRange(scopeVar); return ( inner && @@ -140,10 +140,10 @@ module.exports = { * @returns {void} */ function checkForShadows(scope) { - let variables = scope.variables; + const variables = scope.variables; for (let i = 0; i < variables.length; ++i) { - let variable = variables[i]; + const variable = variables[i]; // Skips "arguments" or variables of a class name in the class scope of ClassDeclaration. if (variable.identifiers.length === 0 || @@ -154,7 +154,7 @@ module.exports = { } // Gets shadowed variable. - let shadowed = astUtils.getVariableByName(scope.upper, variable.name); + const shadowed = astUtils.getVariableByName(scope.upper, variable.name); if (shadowed && (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) && @@ -172,12 +172,12 @@ module.exports = { return { "Program:exit": function() { - let globalScope = context.getScope(); - let stack = globalScope.childScopes.slice(); - let scope; + const globalScope = context.getScope(); + const stack = globalScope.childScopes.slice(); while (stack.length) { - scope = stack.pop(); + const scope = stack.pop(); + stack.push.apply(stack, scope.childScopes); checkForShadows(scope); } diff --git a/tools/eslint/lib/rules/no-spaced-func.js b/tools/eslint/lib/rules/no-spaced-func.js index 90765645e8..cf8266bca5 100644 --- a/tools/eslint/lib/rules/no-spaced-func.js +++ b/tools/eslint/lib/rules/no-spaced-func.js @@ -1,6 +1,7 @@ /** * @fileoverview Rule to check that spaced function application * @author Matt DuVall <http://www.mattduvall.com> + * @deprecated in ESLint v3.3.0 */ "use strict"; @@ -12,18 +13,21 @@ module.exports = { meta: { docs: { - description: "disallow spacing between `function` identifiers and their applications", + description: "disallow spacing between `function` identifiers and their applications (deprecated)", category: "Stylistic Issues", - recommended: false + recommended: false, + replacedBy: ["func-call-spacing"] }, + deprecated: true, + fixable: "whitespace", schema: [] }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Check if open space is present in a function name @@ -32,8 +36,8 @@ module.exports = { * @private */ function detectOpenSpaces(node) { - let lastCalleeToken = sourceCode.getLastToken(node.callee), - prevToken = lastCalleeToken, + const lastCalleeToken = sourceCode.getLastToken(node.callee); + let prevToken = lastCalleeToken, parenToken = sourceCode.getTokenAfter(lastCalleeToken); // advances to an open parenthesis. diff --git a/tools/eslint/lib/rules/no-sparse-arrays.js b/tools/eslint/lib/rules/no-sparse-arrays.js index 4d4bfd9944..1765c4c5fa 100644 --- a/tools/eslint/lib/rules/no-sparse-arrays.js +++ b/tools/eslint/lib/rules/no-sparse-arrays.js @@ -30,7 +30,7 @@ module.exports = { ArrayExpression: function(node) { - let emptySpot = node.elements.indexOf(null) > -1; + const emptySpot = node.elements.indexOf(null) > -1; if (emptySpot) { context.report(node, "Unexpected comma in middle of array."); diff --git a/tools/eslint/lib/rules/no-sync.js b/tools/eslint/lib/rules/no-sync.js index ddd1f9484b..449f27eba7 100644 --- a/tools/eslint/lib/rules/no-sync.js +++ b/tools/eslint/lib/rules/no-sync.js @@ -27,7 +27,7 @@ module.exports = { return { MemberExpression: function(node) { - let propertyName = node.property.name, + const propertyName = node.property.name, syncRegex = /.*Sync$/; if (syncRegex.exec(propertyName) !== null) { diff --git a/tools/eslint/lib/rules/no-template-curly-in-string.js b/tools/eslint/lib/rules/no-template-curly-in-string.js new file mode 100644 index 0000000000..c0227019dc --- /dev/null +++ b/tools/eslint/lib/rules/no-template-curly-in-string.js @@ -0,0 +1,37 @@ +/** + * @fileoverview Warn when using template string syntax in regular strings + * @author Jeroen Engels + */ +"use strict"; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "Disallow template literal placeholder syntax in regular strings", + category: "Possible Errors", + recommended: false + }, + + schema: [] + }, + + create: function(context) { + const regex = /\$\{[^}]+\}/; + + return { + Literal: function(node) { + if (typeof node.value === "string" && regex.test(node.value)) { + context.report({ + node: node, + message: "Unexpected template string expression." + }); + } + } + }; + + } +}; diff --git a/tools/eslint/lib/rules/no-this-before-super.js b/tools/eslint/lib/rules/no-this-before-super.js index 82eda02160..5f19b1819d 100644 --- a/tools/eslint/lib/rules/no-this-before-super.js +++ b/tools/eslint/lib/rules/no-this-before-super.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -101,10 +101,10 @@ module.exports = { * @returns {void} */ function setInvalid(node) { - let segments = funcInfo.codePath.currentSegments; + const segments = funcInfo.codePath.currentSegments; for (let i = 0; i < segments.length; ++i) { - let segment = segments[i]; + const segment = segments[i]; if (segment.reachable) { segInfoMap[segment.id].invalidNodes.push(node); @@ -117,10 +117,10 @@ module.exports = { * @returns {void} */ function setSuperCalled() { - let segments = funcInfo.codePath.currentSegments; + const segments = funcInfo.codePath.currentSegments; for (let i = 0; i < segments.length; ++i) { - let segment = segments[i]; + const segment = segments[i]; if (segment.reachable) { segInfoMap[segment.id].superCalled = true; @@ -140,7 +140,7 @@ module.exports = { if (isConstructorFunction(node)) { // Class > ClassBody > MethodDefinition > FunctionExpression - let classNode = node.parent.parent.parent; + const classNode = node.parent.parent.parent; funcInfo = { upper: funcInfo, @@ -172,7 +172,7 @@ module.exports = { * @returns {void} */ onCodePathEnd: function(codePath) { - let isDerivedClass = funcInfo.hasExtends; + const isDerivedClass = funcInfo.hasExtends; funcInfo = funcInfo.upper; if (!isDerivedClass) { @@ -180,10 +180,10 @@ module.exports = { } codePath.traverseSegments(function(segment, controller) { - let info = segInfoMap[segment.id]; + const info = segInfoMap[segment.id]; for (let i = 0; i < info.invalidNodes.length; ++i) { - let invalidNode = info.invalidNodes[i]; + const invalidNode = info.invalidNodes[i]; context.report({ message: "'{{kind}}' is not allowed before 'super()'.", @@ -238,7 +238,7 @@ module.exports = { funcInfo.codePath.traverseSegments( {first: toSegment, last: fromSegment}, function(segment, controller) { - let info = segInfoMap[segment.id]; + const info = segInfoMap[segment.id]; if (info.superCalled) { info.invalidNodes = []; diff --git a/tools/eslint/lib/rules/no-trailing-spaces.js b/tools/eslint/lib/rules/no-trailing-spaces.js index 6b82cfc38c..ed7356f193 100644 --- a/tools/eslint/lib/rules/no-trailing-spaces.js +++ b/tools/eslint/lib/rules/no-trailing-spaces.js @@ -32,13 +32,13 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); - let BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]", + const BLANK_CLASS = "[ \t\u00a0\u2000-\u200b\u2028\u2029\u3000]", SKIP_BLANK = "^" + BLANK_CLASS + "*$", NONBLANK = BLANK_CLASS + "+$"; - let options = context.options[0] || {}, + const options = context.options[0] || {}, skipBlankLines = options.skipBlankLines || false; /** @@ -78,36 +78,31 @@ module.exports = { // Let's hack. Since Espree does not return whitespace nodes, // fetch the source code and do matching via regexps. - let re = new RegExp(NONBLANK), + const re = new RegExp(NONBLANK), skipMatch = new RegExp(SKIP_BLANK), - matches, lines = sourceCode.lines, - linebreaks = sourceCode.getText().match(/\r\n|\r|\n|\u2028|\u2029/g), - location, - totalLength = 0, - rangeStart, - rangeEnd, - fixRange = [], - containingNode; + linebreaks = sourceCode.getText().match(/\r\n|\r|\n|\u2028|\u2029/g); + let totalLength = 0, + fixRange = []; for (let i = 0, ii = lines.length; i < ii; i++) { - matches = re.exec(lines[i]); + const matches = re.exec(lines[i]); // Always add linebreak length to line length to accommodate for line break (\n or \r\n) // Because during the fix time they also reserve one spot in the array. // Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF) - let linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1; - let lineLength = lines[i].length + linebreakLength; + const linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1; + const lineLength = lines[i].length + linebreakLength; if (matches) { - location = { + const location = { line: i + 1, column: matches.index }; - rangeStart = totalLength + location.column; - rangeEnd = totalLength + lineLength - linebreakLength; - containingNode = sourceCode.getNodeByRangeIndex(rangeStart); + const rangeStart = totalLength + location.column; + const rangeEnd = totalLength + lineLength - linebreakLength; + const containingNode = sourceCode.getNodeByRangeIndex(rangeStart); if (containingNode && containingNode.type === "TemplateElement" && rangeStart > containingNode.parent.range[0] && diff --git a/tools/eslint/lib/rules/no-undef-init.js b/tools/eslint/lib/rules/no-undef-init.js index 2683f61e8a..80a27f6b78 100644 --- a/tools/eslint/lib/rules/no-undef-init.js +++ b/tools/eslint/lib/rules/no-undef-init.js @@ -25,7 +25,7 @@ module.exports = { return { VariableDeclarator: function(node) { - let name = node.id.name, + const name = node.id.name, init = node.init && node.init.name; if (init === "undefined" && node.parent.kind !== "const") { diff --git a/tools/eslint/lib/rules/no-undef.js b/tools/eslint/lib/rules/no-undef.js index da9437157c..1206747086 100644 --- a/tools/eslint/lib/rules/no-undef.js +++ b/tools/eslint/lib/rules/no-undef.js @@ -14,7 +14,7 @@ * @returns {boolean} Whether or not the node is the argument of a typeof operator. */ function hasTypeOfOperator(node) { - let parent = node.parent; + const parent = node.parent; return parent.type === "UnaryExpression" && parent.operator === "typeof"; } @@ -45,15 +45,15 @@ module.exports = { }, create: function(context) { - let options = context.options[0]; - let considerTypeOf = options && options.typeof === true || false; + const options = context.options[0]; + const considerTypeOf = options && options.typeof === true || false; return { "Program:exit": function(/* node */) { - let globalScope = context.getScope(); + const globalScope = context.getScope(); globalScope.through.forEach(function(ref) { - let identifier = ref.identifier; + const identifier = ref.identifier; if (!considerTypeOf && hasTypeOfOperator(identifier)) { return; diff --git a/tools/eslint/lib/rules/no-undefined.js b/tools/eslint/lib/rules/no-undefined.js index a34d665203..7a785b80fb 100644 --- a/tools/eslint/lib/rules/no-undefined.js +++ b/tools/eslint/lib/rules/no-undefined.js @@ -25,7 +25,7 @@ module.exports = { Identifier: function(node) { if (node.name === "undefined") { - let parent = context.getAncestors().pop(); + const parent = context.getAncestors().pop(); if (!parent || parent.type !== "MemberExpression" || node !== parent.property || parent.computed) { context.report(node, "Unexpected use of undefined."); diff --git a/tools/eslint/lib/rules/no-underscore-dangle.js b/tools/eslint/lib/rules/no-underscore-dangle.js index a6a3b174fc..01f44309a9 100644 --- a/tools/eslint/lib/rules/no-underscore-dangle.js +++ b/tools/eslint/lib/rules/no-underscore-dangle.js @@ -41,10 +41,10 @@ module.exports = { create: function(context) { - let options = context.options[0] || {}; - let ALLOWED_VARIABLES = options.allow ? options.allow : []; - let allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false; - let allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false; + const options = context.options[0] || {}; + const ALLOWED_VARIABLES = options.allow ? options.allow : []; + const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false; + const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false; //------------------------------------------------------------------------- // Helpers @@ -69,7 +69,7 @@ module.exports = { * @private */ function hasTrailingUnderscore(identifier) { - let len = identifier.length; + const len = identifier.length; return identifier !== "_" && (identifier[0] === "_" || identifier[len - 1] === "_"); } @@ -104,7 +104,7 @@ module.exports = { */ function checkForTrailingUnderscoreInFunctionDeclaration(node) { if (node.id) { - let identifier = node.id.name; + const identifier = node.id.name; if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) { context.report(node, "Unexpected dangling '_' in '" + identifier + "'."); @@ -119,7 +119,7 @@ module.exports = { * @private */ function checkForTrailingUnderscoreInVariableExpression(node) { - let identifier = node.id.name; + const identifier = node.id.name; if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) && !isSpecialCaseIdentifierInVariableExpression(identifier) && !isAllowed(identifier)) { @@ -134,7 +134,7 @@ module.exports = { * @private */ function checkForTrailingUnderscoreInMemberExpression(node) { - let identifier = node.property.name, + const identifier = node.property.name, isMemberOfThis = node.object.type === "ThisExpression", isMemberOfSuper = node.object.type === "Super"; diff --git a/tools/eslint/lib/rules/no-unexpected-multiline.js b/tools/eslint/lib/rules/no-unexpected-multiline.js index 6fcb8c681a..832150e4e7 100644 --- a/tools/eslint/lib/rules/no-unexpected-multiline.js +++ b/tools/eslint/lib/rules/no-unexpected-multiline.js @@ -20,11 +20,11 @@ module.exports = { create: function(context) { - let FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call."; - let PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access."; - let TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal."; + const FUNCTION_MESSAGE = "Unexpected newline between function and ( of function call."; + const PROPERTY_MESSAGE = "Unexpected newline between object and [ of property access."; + const TAGGED_TEMPLATE_MESSAGE = "Unexpected newline between template tag and template literal."; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Check to see if there is a newline between the node and the following open bracket diff --git a/tools/eslint/lib/rules/no-unmodified-loop-condition.js b/tools/eslint/lib/rules/no-unmodified-loop-condition.js index 099dd5f955..3f3addf552 100644 --- a/tools/eslint/lib/rules/no-unmodified-loop-condition.js +++ b/tools/eslint/lib/rules/no-unmodified-loop-condition.js @@ -9,19 +9,19 @@ // Requirements //------------------------------------------------------------------------------ -let Traverser = require("../util/traverser"), +const Traverser = require("../util/traverser"), astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let pushAll = Function.apply.bind(Array.prototype.push); -let SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/; -let LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property. -let GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/; -let SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/; -let DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/; +const pushAll = Function.apply.bind(Array.prototype.push); +const SENTINEL_PATTERN = /(?:(?:Call|Class|Function|Member|New|Yield)Expression|Statement|Declaration)$/; +const LOOP_PATTERN = /^(?:DoWhile|For|While)Statement$/; // for-in/of statements don't have `test` property. +const GROUP_PATTERN = /^(?:BinaryExpression|ConditionalExpression)$/; +const SKIP_PATTERN = /^(?:ArrowFunction|Class|Function)Expression$/; +const DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/; /** * @typedef {Object} LoopConditionInfo @@ -42,7 +42,7 @@ let DYNAMIC_PATTERN = /^(?:Call|Member|New|TaggedTemplate|Yield)Expression$/; */ function isWriteReference(reference) { if (reference.init) { - let def = reference.resolved && reference.resolved.defs[0]; + const def = reference.resolved && reference.resolved.defs[0]; if (!def || def.type !== "Variable" || def.parent.kind !== "var") { return false; @@ -81,8 +81,8 @@ function isUnmodifiedAndNotBelongToGroup(condition) { * @returns {boolean} `true` if the reference is inside of the node. */ function isInRange(node, reference) { - let or = node.range; - let ir = reference.identifier.range; + const or = node.range; + const ir = reference.identifier.range; return or[0] <= ir[0] && ir[1] <= or[1]; } @@ -95,7 +95,7 @@ function isInRange(node, reference) { * @returns {boolean} `true` if the reference is inside of the loop node's * condition. */ -let isInLoop = { +const isInLoop = { WhileStatement: isInRange, DoWhileStatement: isInRange, ForStatement: function(node, reference) { @@ -114,8 +114,8 @@ let isInLoop = { * @returns {boolean} `true` if the node is dynamic. */ function hasDynamicExpressions(root) { - let retv = false, - traverser = new Traverser(); + let retv = false; + const traverser = new Traverser(); traverser.traverse(root, { enter: function(node) { @@ -216,11 +216,10 @@ function updateModifiedFlag(conditions, modifiers) { let funcNode, funcVar; for (let i = 0; i < conditions.length; ++i) { - let condition = conditions[i]; + const condition = conditions[i]; for (let j = 0; !condition.modified && j < modifiers.length; ++j) { - let modifier = modifiers[j], - inLoop; + const modifier = modifiers[j]; /* * Besides checking for the condition being in the loop, we want to @@ -228,11 +227,12 @@ function updateModifiedFlag(conditions, modifiers) { * in the loop. * FIXME: This should probably be extracted to a function. */ - inLoop = condition.isInLoop(modifier) || Boolean( + const inLoop = condition.isInLoop(modifier) || Boolean( (funcNode = getEncloseFunctionDeclaration(modifier)) && (funcVar = astUtils.getVariableByName(modifier.from.upper, funcNode.id.name)) && funcVar.references.some(condition.isInLoop) ); + condition.modified = inLoop; } } @@ -263,7 +263,7 @@ module.exports = { * @returns {void} */ function report(condition) { - let node = condition.reference.identifier; + const node = condition.reference.identifier; context.report({ node: node, @@ -281,7 +281,7 @@ module.exports = { */ function registerConditionsToGroup(conditions) { for (let i = 0; i < conditions.length; ++i) { - let condition = conditions[i]; + const condition = conditions[i]; if (condition.group) { let group = groupMap.get(condition.group); @@ -317,7 +317,7 @@ module.exports = { function checkReferences(variable) { // Gets references that exist in loop conditions. - let conditions = variable + const conditions = variable .references .map(toLoopCondition) .filter(Boolean); @@ -330,7 +330,7 @@ module.exports = { registerConditionsToGroup(conditions); // Check the conditions are modified. - let modifiers = variable.references.filter(isWriteReference); + const modifiers = variable.references.filter(isWriteReference); if (modifiers.length > 0) { updateModifiedFlag(conditions, modifiers); @@ -347,7 +347,7 @@ module.exports = { return { "Program:exit": function() { - let queue = [context.getScope()]; + const queue = [context.getScope()]; groupMap = new Map(); diff --git a/tools/eslint/lib/rules/no-unneeded-ternary.js b/tools/eslint/lib/rules/no-unneeded-ternary.js index 64c767ed0e..d22d703498 100644 --- a/tools/eslint/lib/rules/no-unneeded-ternary.js +++ b/tools/eslint/lib/rules/no-unneeded-ternary.js @@ -31,8 +31,8 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let defaultAssignment = options.defaultAssignment !== false; + const options = context.options[0] || {}; + const defaultAssignment = options.defaultAssignment !== false; /** * Test if the node is a boolean literal diff --git a/tools/eslint/lib/rules/no-unsafe-finally.js b/tools/eslint/lib/rules/no-unsafe-finally.js index 305cce28ad..05901abf04 100644 --- a/tools/eslint/lib/rules/no-unsafe-finally.js +++ b/tools/eslint/lib/rules/no-unsafe-finally.js @@ -9,9 +9,9 @@ // Helpers //------------------------------------------------------------------------------ -let SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/; -let SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/; -let SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/; +const SENTINEL_NODE_TYPE_RETURN_THROW = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression)$/; +const SENTINEL_NODE_TYPE_BREAK = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement|SwitchStatement)$/; +const SENTINEL_NODE_TYPE_CONTINUE = /^(?:Program|(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|DoWhileStatement|WhileStatement|ForOfStatement|ForInStatement|ForStatement)$/; //------------------------------------------------------------------------------ diff --git a/tools/eslint/lib/rules/no-unsafe-negation.js b/tools/eslint/lib/rules/no-unsafe-negation.js new file mode 100644 index 0000000000..c3852a24d7 --- /dev/null +++ b/tools/eslint/lib/rules/no-unsafe-negation.js @@ -0,0 +1,80 @@ +/** + * @fileoverview Rule to disallow negating the left operand of relational operators + * @author Toru Nagashima + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Checks whether the given operator is a relational operator or not. + * + * @param {string} op - The operator type to check. + * @returns {boolean} `true` if the operator is a relational operator. + */ +function isRelationalOperator(op) { + return op === "in" || op === "instanceof"; +} + +/** + * Checks whether the given node is a logical negation expression or not. + * + * @param {ASTNode} node - The node to check. + * @returns {boolean} `true` if the node is a logical negation expression. + */ +function isNegation(node) { + return node.type === "UnaryExpression" && node.operator === "!"; +} + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "disallow negating the left operand of relational operators", + category: "Possible Errors", + recommended: false + }, + schema: [], + fixable: "code" + }, + + create(context) { + const sourceCode = context.getSourceCode(); + + return { + BinaryExpression(node) { + if (isRelationalOperator(node.operator) && + isNegation(node.left) && + !astUtils.isParenthesised(sourceCode, node.left) + ) { + context.report({ + node: node, + loc: node.left.loc, + message: "Unexpected negating the left operand of '{{operator}}' operator.", + data: node, + + fix(fixer) { + const negationToken = sourceCode.getFirstToken(node.left); + const fixRange = [negationToken.range[1], node.range[1]]; + const text = sourceCode.text.slice(fixRange[0], fixRange[1]); + + return fixer.replaceTextRange(fixRange, `(${text})`); + } + }); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/no-unused-expressions.js b/tools/eslint/lib/rules/no-unused-expressions.js index d2bdda70f2..c5e062ad2a 100644 --- a/tools/eslint/lib/rules/no-unused-expressions.js +++ b/tools/eslint/lib/rules/no-unused-expressions.js @@ -33,7 +33,7 @@ module.exports = { }, create: function(context) { - let config = context.options[0] || {}, + const config = context.options[0] || {}, allowShortCircuit = config.allowShortCircuit || false, allowTernary = config.allowTernary || false; @@ -74,7 +74,7 @@ module.exports = { * @returns {boolean} whether the given node is considered a directive in its current position */ function isDirective(node, ancestors) { - let parent = ancestors[ancestors.length - 1], + const parent = ancestors[ancestors.length - 1], grandparent = ancestors[ancestors.length - 2]; return (parent.type === "Program" || parent.type === "BlockStatement" && diff --git a/tools/eslint/lib/rules/no-unused-labels.js b/tools/eslint/lib/rules/no-unused-labels.js index ec13c6168e..f7d9045b50 100644 --- a/tools/eslint/lib/rules/no-unused-labels.js +++ b/tools/eslint/lib/rules/no-unused-labels.js @@ -68,7 +68,7 @@ module.exports = { return; } - let label = node.label.name; + const label = node.label.name; let info = scopeInfo; while (info) { diff --git a/tools/eslint/lib/rules/no-unused-vars.js b/tools/eslint/lib/rules/no-unused-vars.js index 951330de9b..61052f6c1e 100644 --- a/tools/eslint/lib/rules/no-unused-vars.js +++ b/tools/eslint/lib/rules/no-unused-vars.js @@ -9,8 +9,8 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"); -let astUtils = require("../ast-utils"); +const lodash = require("lodash"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -60,15 +60,15 @@ module.exports = { create: function(context) { - let MESSAGE = "'{{name}}' is defined but never used."; + const MESSAGE = "'{{name}}' is defined but never used."; - let config = { + const config = { vars: "all", args: "after-used", caughtErrors: "none" }; - let firstOption = context.options[0]; + const firstOption = context.options[0]; if (firstOption) { if (typeof firstOption === "string") { @@ -96,7 +96,7 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - let STATEMENT_TYPE = /(?:Statement|Declaration)$/; + const STATEMENT_TYPE = /(?:Statement|Declaration)$/; /** * Determines if a given variable is being exported from a module. @@ -106,7 +106,7 @@ module.exports = { */ function isExported(variable) { - let definition = variable.defs[0]; + const definition = variable.defs[0]; if (definition) { @@ -209,12 +209,12 @@ module.exports = { * @private */ function getRhsNode(ref, prevRhsNode) { - let id = ref.identifier; - let parent = id.parent; - let granpa = parent.parent; - let refScope = ref.from.variableScope; - let varScope = ref.resolved.scope.variableScope; - let canBeUsedLater = refScope !== varScope || isInsideOfLoop(id); + const id = ref.identifier; + const parent = id.parent; + const granpa = parent.parent; + const refScope = ref.from.variableScope; + const varScope = ref.resolved.scope.variableScope; + const canBeUsedLater = refScope !== varScope || isInsideOfLoop(id); /* * Inherits the previous node if this reference is in the node. @@ -301,7 +301,7 @@ module.exports = { * @private */ function isInsideOfStorableFunction(id, rhsNode) { - let funcNode = astUtils.getUpperFunction(id); + const funcNode = astUtils.getUpperFunction(id); return ( funcNode && @@ -319,9 +319,9 @@ module.exports = { * @private */ function isReadForItself(ref, rhsNode) { - let id = ref.identifier; - let parent = id.parent; - let granpa = parent.parent; + const id = ref.identifier; + const parent = id.parent; + const granpa = parent.parent; return ref.isRead() && ( @@ -389,20 +389,20 @@ module.exports = { * @private */ function isUsedVariable(variable) { - let functionNodes = variable.defs.filter(function(def) { + const functionNodes = variable.defs.filter(function(def) { return def.type === "FunctionName"; }).map(function(def) { return def.node; }), - isFunctionDefinition = functionNodes.length > 0, - rhsNode = null; + isFunctionDefinition = functionNodes.length > 0; + let rhsNode = null; return variable.references.some(function(ref) { if (isForInRef(ref)) { return true; } - let forItself = isReadForItself(ref, rhsNode); + const forItself = isReadForItself(ref, rhsNode); rhsNode = getRhsNode(ref, rhsNode); @@ -422,13 +422,13 @@ module.exports = { * @private */ function collectUnusedVariables(scope, unusedVars) { - let variables = scope.variables; - let childScopes = scope.childScopes; + const variables = scope.variables; + const childScopes = scope.childScopes; let i, l; if (scope.type !== "TDZ" && (scope.type !== "global" || config.vars === "all")) { for (i = 0, l = variables.length; i < l; ++i) { - let variable = variables[i]; + const variable = variables[i]; // skip a variable of class itself name in the class scope if (scope.type === "class" && scope.block.id === variable.identifiers[0]) { @@ -446,10 +446,10 @@ module.exports = { } // explicit global variables don't have definitions. - let def = variable.defs[0]; + const def = variable.defs[0]; if (def) { - let type = def.type; + const type = def.type; // skip catch variables if (type === "CatchClause") { @@ -514,13 +514,13 @@ module.exports = { * @private */ function getColumnInComment(variable, comment) { - let namePattern = new RegExp("[\\s,]" + lodash.escapeRegExp(variable.name) + "(?:$|[\\s,:])", "g"); + const namePattern = new RegExp("[\\s,]" + lodash.escapeRegExp(variable.name) + "(?:$|[\\s,:])", "g"); // To ignore the first text "global". namePattern.lastIndex = comment.value.indexOf("global") + 6; // Search a given variable name. - let match = namePattern.exec(comment.value); + const match = namePattern.exec(comment.value); return match ? match.index + 1 : 0; } @@ -534,11 +534,11 @@ module.exports = { * @private */ function getLocation(variable) { - let comment = variable.eslintExplicitGlobalComment; - let baseLoc = comment.loc.start; + const comment = variable.eslintExplicitGlobalComment; + const baseLoc = comment.loc.start; let column = getColumnInComment(variable, comment); - let prefix = comment.value.slice(0, column); - let lineInComment = (prefix.match(/\n/g) || []).length; + const prefix = comment.value.slice(0, column); + const lineInComment = (prefix.match(/\n/g) || []).length; if (lineInComment > 0) { column -= 1 + prefix.lastIndexOf("\n"); @@ -560,10 +560,10 @@ module.exports = { return { "Program:exit": function(programNode) { - let unusedVars = collectUnusedVariables(context.getScope(), []); + const unusedVars = collectUnusedVariables(context.getScope(), []); for (let i = 0, l = unusedVars.length; i < l; ++i) { - let unusedVar = unusedVars[i]; + const unusedVar = unusedVars[i]; if (unusedVar.eslintExplicitGlobal) { context.report({ diff --git a/tools/eslint/lib/rules/no-use-before-define.js b/tools/eslint/lib/rules/no-use-before-define.js index 90dd05c8b1..edc7926fe9 100644 --- a/tools/eslint/lib/rules/no-use-before-define.js +++ b/tools/eslint/lib/rules/no-use-before-define.js @@ -9,8 +9,8 @@ // Helpers //------------------------------------------------------------------------------ -let SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; -let FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/; +const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; +const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/; /** * Parses a given value as options. @@ -106,7 +106,7 @@ function isInInitializer(variable, reference) { } let node = variable.identifiers[0].parent; - let location = reference.identifier.range[1]; + const location = reference.identifier.range[1]; while (node) { if (node.type === "VariableDeclarator") { @@ -165,7 +165,7 @@ module.exports = { }, create: function(context) { - let options = parseOptions(context.options[0]); + const options = parseOptions(context.options[0]); // Defines a function which checks whether or not a reference is allowed according to the option. let isAllowed; @@ -188,7 +188,7 @@ module.exports = { */ function findVariablesInScope(scope) { scope.references.forEach(function(reference) { - let variable = reference.resolved; + const variable = reference.resolved; // Skips when the reference is: // - initialization's. @@ -221,14 +221,14 @@ module.exports = { * @private */ function findVariables() { - let scope = context.getScope(); + const scope = context.getScope(); findVariablesInScope(scope); } - let ruleDefinition = { + const ruleDefinition = { "Program:exit": function(node) { - let scope = context.getScope(), + const scope = context.getScope(), ecmaFeatures = context.parserOptions.ecmaFeatures || {}; findVariablesInScope(scope); diff --git a/tools/eslint/lib/rules/no-useless-call.js b/tools/eslint/lib/rules/no-useless-call.js index b05292ff79..ace10f682a 100644 --- a/tools/eslint/lib/rules/no-useless-call.js +++ b/tools/eslint/lib/rules/no-useless-call.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -36,8 +36,8 @@ function isCallOrNonVariadicApply(node) { * @returns {boolean} the source code for the given node. */ function equalTokens(left, right, sourceCode) { - let tokensL = sourceCode.getTokens(left); - let tokensR = sourceCode.getTokens(right); + const tokensL = sourceCode.getTokens(left); + const tokensR = sourceCode.getTokens(right); if (tokensL.length !== tokensR.length) { return false; @@ -83,7 +83,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { CallExpression: function(node) { @@ -91,9 +91,9 @@ module.exports = { return; } - let applied = node.callee.object; - let expectedThis = (applied.type === "MemberExpression") ? applied.object : null; - let thisArg = node.arguments[0]; + const applied = node.callee.object; + const expectedThis = (applied.type === "MemberExpression") ? applied.object : null; + const thisArg = node.arguments[0]; if (isValidThisArg(expectedThis, thisArg, sourceCode)) { context.report( diff --git a/tools/eslint/lib/rules/no-useless-computed-key.js b/tools/eslint/lib/rules/no-useless-computed-key.js index f25b9e5474..e90f7aaca8 100644 --- a/tools/eslint/lib/rules/no-useless-computed-key.js +++ b/tools/eslint/lib/rules/no-useless-computed-key.js @@ -8,7 +8,7 @@ // Rule Definition //------------------------------------------------------------------------------ -let MESSAGE_UNNECESSARY_COMPUTED = "Unnecessarily computed property [{{property}}] found."; +const MESSAGE_UNNECESSARY_COMPUTED = "Unnecessarily computed property [{{property}}] found."; module.exports = { meta: { @@ -21,7 +21,7 @@ module.exports = { schema: [] }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { Property: function(node) { @@ -29,7 +29,7 @@ module.exports = { return; } - let key = node.key, + const key = node.key, nodeType = typeof key.value; if (key.type === "Literal" && (nodeType === "string" || nodeType === "number")) { diff --git a/tools/eslint/lib/rules/no-useless-concat.js b/tools/eslint/lib/rules/no-useless-concat.js index 6c4cecd7b6..20d2afeaca 100644 --- a/tools/eslint/lib/rules/no-useless-concat.js +++ b/tools/eslint/lib/rules/no-useless-concat.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -67,7 +67,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { BinaryExpression: function(node) { @@ -78,8 +78,8 @@ module.exports = { } // account for the `foo + "a" + "b"` case - let left = getLeft(node); - let right = getRight(node); + const left = getLeft(node); + const right = getRight(node); if (astUtils.isStringLiteral(left) && astUtils.isStringLiteral(right) && diff --git a/tools/eslint/lib/rules/no-useless-constructor.js b/tools/eslint/lib/rules/no-useless-constructor.js index f6be08f69d..323be4f1fa 100644 --- a/tools/eslint/lib/rules/no-useless-constructor.js +++ b/tools/eslint/lib/rules/no-useless-constructor.js @@ -163,9 +163,9 @@ module.exports = { return; } - let body = node.value.body.body; - let ctorParams = node.value.params; - let superClass = node.parent.parent.superClass; + const body = node.value.body.body; + const ctorParams = node.value.params; + const superClass = node.parent.parent.superClass; if (superClass ? isRedundantSuperCall(body, ctorParams) : (body.length === 0)) { context.report({ diff --git a/tools/eslint/lib/rules/no-useless-escape.js b/tools/eslint/lib/rules/no-useless-escape.js index 226a9da165..244249c389 100644 --- a/tools/eslint/lib/rules/no-useless-escape.js +++ b/tools/eslint/lib/rules/no-useless-escape.js @@ -9,7 +9,7 @@ // Rule Definition //------------------------------------------------------------------------------ -let VALID_STRING_ESCAPES = [ +const VALID_STRING_ESCAPES = [ "\\", "n", "r", @@ -23,7 +23,7 @@ let VALID_STRING_ESCAPES = [ "\r" ]; -let VALID_REGEX_ESCAPES = [ +const VALID_REGEX_ESCAPES = [ "\\", ".", "-", @@ -80,8 +80,8 @@ module.exports = { * @returns {void} */ function validate(escapes, node, elm) { - let escapeNotFound = escapes.indexOf(elm[0][1]) === -1; - let isQuoteEscape = elm[0][1] === node.raw[0]; + const escapeNotFound = escapes.indexOf(elm[0][1]) === -1; + const isQuoteEscape = elm[0][1] === node.raw[0]; if (escapeNotFound && !isQuoteEscape) { context.report({ @@ -103,7 +103,7 @@ module.exports = { */ function check(node) { let nodeEscapes, match; - let pattern = /\\[^\d]/g; + const pattern = /\\[^\d]/g; if (typeof node.value === "string") { diff --git a/tools/eslint/lib/rules/no-useless-rename.js b/tools/eslint/lib/rules/no-useless-rename.js index 80539e5772..91cdcc49ff 100644 --- a/tools/eslint/lib/rules/no-useless-rename.js +++ b/tools/eslint/lib/rules/no-useless-rename.js @@ -31,7 +31,7 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}, + const options = context.options[0] || {}, ignoreDestructuring = options.ignoreDestructuring === true, ignoreImport = options.ignoreImport === true, ignoreExport = options.ignoreExport === true; @@ -49,7 +49,7 @@ module.exports = { * @returns {void} */ function reportError(node, initial, result, type) { - let name = initial.type === "Identifier" ? initial.name : initial.value; + const name = initial.type === "Identifier" ? initial.name : initial.value; return context.report({ node: node, @@ -73,16 +73,13 @@ module.exports = { * @returns {void} */ function checkDestructured(node) { - let properties, - i; - if (ignoreDestructuring) { return; } - properties = node.properties; + const properties = node.properties; - for (i = 0; i < properties.length; i++) { + for (let i = 0; i < properties.length; i++) { if (properties[i].shorthand) { continue; } diff --git a/tools/eslint/lib/rules/no-var.js b/tools/eslint/lib/rules/no-var.js index fc7783d716..dfef7ceea6 100644 --- a/tools/eslint/lib/rules/no-var.js +++ b/tools/eslint/lib/rules/no-var.js @@ -9,7 +9,7 @@ // Helpers //------------------------------------------------------------------------------ -let SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement|ForInStatement|ForOfStatement)$/; +const SCOPE_NODE_TYPE = /^(?:Program|BlockStatement|SwitchStatement|ForStatement|ForInStatement|ForOfStatement)$/; /** * Gets the scope node which directly contains a given node. @@ -60,8 +60,8 @@ function isUsedFromOutsideOf(scopeNode) { * scope. */ function isOutsideOfScope(reference) { - let scope = scopeNode.range; - let id = reference.identifier.range; + const scope = scopeNode.range; + const id = reference.identifier.range; return id[0] < scope[0] || id[1] > scope[1]; } @@ -88,7 +88,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Checks whether it can fix a given variable declaration or not. @@ -119,8 +119,8 @@ module.exports = { * @returns {boolean} `true` if it can fix the node. */ function canFix(node) { - let variables = context.getDeclaredVariables(node); - let scopeNode = getScopeNode(node); + const variables = context.getDeclaredVariables(node); + const scopeNode = getScopeNode(node); return !( node.parent.type === "SwitchCase" || @@ -136,7 +136,7 @@ module.exports = { * @returns {void} */ function report(node) { - let varToken = sourceCode.getFirstToken(node); + const varToken = sourceCode.getFirstToken(node); context.report({ node: node, diff --git a/tools/eslint/lib/rules/no-warning-comments.js b/tools/eslint/lib/rules/no-warning-comments.js index 7db6ed1234..d0ae12da61 100644 --- a/tools/eslint/lib/rules/no-warning-comments.js +++ b/tools/eslint/lib/rules/no-warning-comments.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -40,11 +40,10 @@ module.exports = { create: function(context) { - let configuration = context.options[0] || {}, + const configuration = context.options[0] || {}, warningTerms = configuration.terms || ["todo", "fixme", "xxx"], location = configuration.location || "start", - selfConfigRegEx = /\bno-warning-comments\b/, - warningRegExps; + selfConfigRegEx = /\bno-warning-comments\b/; /** * Convert a warning term into a RegExp which will match a comment containing that whole word in the specified @@ -55,9 +54,8 @@ module.exports = { * @returns {RegExp} The term converted to a RegExp */ function convertToRegExp(term) { - let escaped = term.replace(/[-\/\\$\^*+?.()|\[\]{}]/g, "\\$&"), - suffix, - prefix; + const escaped = term.replace(/[-\/\\$\^*+?.()|\[\]{}]/g, "\\$&"); + let prefix; /* * If the term ends in a word character (a-z0-9_), ensure a word @@ -69,7 +67,7 @@ module.exports = { * In these cases, use no bounding match. Same applies for the * prefix, handled below. */ - suffix = /\w$/.test(term) ? "\\b" : ""; + const suffix = /\w$/.test(term) ? "\\b" : ""; if (location === "start") { @@ -87,13 +85,15 @@ module.exports = { return new RegExp(prefix + escaped + suffix, "i"); } + const warningRegExps = warningTerms.map(convertToRegExp); + /** * Checks the specified comment for matches of the configured warning terms and returns the matches. * @param {string} comment The comment which is checked. * @returns {Array} All matched warning terms for this comment. */ function commentContainsWarningTerm(comment) { - let matches = []; + const matches = []; warningRegExps.forEach(function(regex, index) { if (regex.test(comment)) { @@ -114,14 +114,13 @@ module.exports = { return; } - let matches = commentContainsWarningTerm(node.value); + const matches = commentContainsWarningTerm(node.value); matches.forEach(function(matchedTerm) { context.report(node, "Unexpected '" + matchedTerm + "' comment."); }); } - warningRegExps = warningTerms.map(convertToRegExp); return { BlockComment: checkComment, LineComment: checkComment diff --git a/tools/eslint/lib/rules/no-whitespace-before-property.js b/tools/eslint/lib/rules/no-whitespace-before-property.js index fd13ba9d5d..2c0ad7a750 100644 --- a/tools/eslint/lib/rules/no-whitespace-before-property.js +++ b/tools/eslint/lib/rules/no-whitespace-before-property.js @@ -4,7 +4,7 @@ */ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -23,7 +23,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -53,7 +53,7 @@ module.exports = { * @private */ function reportError(node, leftToken, rightToken) { - let replacementText = node.computed ? "" : "."; + const replacementText = node.computed ? "" : "."; context.report({ node: node, diff --git a/tools/eslint/lib/rules/object-curly-newline.js b/tools/eslint/lib/rules/object-curly-newline.js index b69bd19044..6b94ad3113 100644 --- a/tools/eslint/lib/rules/object-curly-newline.js +++ b/tools/eslint/lib/rules/object-curly-newline.js @@ -9,14 +9,14 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ // Schema objects. -let OPTION_VALUE = { +const OPTION_VALUE = { oneOf: [ { enum: ["always", "never"] @@ -78,7 +78,7 @@ function normalizeOptions(options) { }; } - let value = normalizeOptionValue(options); + const value = normalizeOptionValue(options); return {ObjectExpression: value, ObjectPattern: value}; } @@ -114,8 +114,8 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); - let normalizedOptions = normalizeOptions(context.options[0]); + const sourceCode = context.getSourceCode(); + const normalizedOptions = normalizeOptions(context.options[0]); /** * Reports a given node if it violated this rule. @@ -125,12 +125,12 @@ module.exports = { * @returns {void} */ function check(node) { - let options = normalizedOptions[node.type]; - let openBrace = sourceCode.getFirstToken(node); - let closeBrace = sourceCode.getLastToken(node); + const options = normalizedOptions[node.type]; + const openBrace = sourceCode.getFirstToken(node); + const closeBrace = sourceCode.getLastToken(node); let first = sourceCode.getTokenOrCommentAfter(openBrace); let last = sourceCode.getTokenOrCommentBefore(closeBrace); - let needsLinebreaks = ( + const needsLinebreaks = ( node.properties.length >= options.minProperties || ( options.multiline && diff --git a/tools/eslint/lib/rules/object-curly-spacing.js b/tools/eslint/lib/rules/object-curly-spacing.js index 4fe1f85758..46c678e6e8 100644 --- a/tools/eslint/lib/rules/object-curly-spacing.js +++ b/tools/eslint/lib/rules/object-curly-spacing.js @@ -4,7 +4,7 @@ */ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -40,7 +40,7 @@ module.exports = { }, create: function(context) { - let spaced = context.options[0] === "always", + const spaced = context.options[0] === "always", sourceCode = context.getSourceCode(); /** @@ -54,7 +54,7 @@ module.exports = { return context.options[1] ? context.options[1][option] === !spaced : false; } - let options = { + const options = { spaced: spaced, arraysInObjectsException: isOptionSet("arraysInObjects"), objectsInObjectsException: isOptionSet("objectsInObjects") @@ -76,7 +76,7 @@ module.exports = { loc: token.loc.start, message: "There should be no space after '" + token.value + "'.", fix: function(fixer) { - let nextToken = context.getSourceCode().getTokenAfter(token); + const nextToken = context.getSourceCode().getTokenAfter(token); return fixer.removeRange([token.range[1], nextToken.range[0]]); } @@ -95,7 +95,7 @@ module.exports = { loc: token.loc.start, message: "There should be no space before '" + token.value + "'.", fix: function(fixer) { - let previousToken = context.getSourceCode().getTokenBefore(token); + const previousToken = context.getSourceCode().getTokenBefore(token); return fixer.removeRange([previousToken.range[1], token.range[0]]); } @@ -146,14 +146,9 @@ module.exports = { * @returns {void} */ function validateBraceSpacing(node, first, second, penultimate, last) { - let shouldCheckPenultimate, - penultimateType, - closingCurlyBraceMustBeSpaced, - firstSpaced, - lastSpaced; - if (astUtils.isTokenOnSameLine(first, second)) { - firstSpaced = sourceCode.isSpaceBetweenTokens(first, second); + const firstSpaced = sourceCode.isSpaceBetweenTokens(first, second); + if (options.spaced && !firstSpaced) { reportRequiredBeginningSpace(node, first); } @@ -163,18 +158,18 @@ module.exports = { } if (astUtils.isTokenOnSameLine(penultimate, last)) { - shouldCheckPenultimate = ( + const shouldCheckPenultimate = ( options.arraysInObjectsException && penultimate.value === "]" || options.objectsInObjectsException && penultimate.value === "}" ); - penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.start).type; + const penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.start).type; - closingCurlyBraceMustBeSpaced = ( + const closingCurlyBraceMustBeSpaced = ( options.arraysInObjectsException && penultimateType === "ArrayExpression" || options.objectsInObjectsException && (penultimateType === "ObjectExpression" || penultimateType === "ObjectPattern") ) ? !options.spaced : options.spaced; - lastSpaced = sourceCode.isSpaceBetweenTokens(penultimate, last); + const lastSpaced = sourceCode.isSpaceBetweenTokens(penultimate, last); if (closingCurlyBraceMustBeSpaced && !lastSpaced) { reportRequiredEndingSpace(node, last); @@ -195,7 +190,7 @@ module.exports = { return; } - let first = sourceCode.getFirstToken(node), + const first = sourceCode.getFirstToken(node), last = sourceCode.getLastToken(node), second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); @@ -213,8 +208,8 @@ module.exports = { return; } - let firstSpecifier = node.specifiers[0], - lastSpecifier = node.specifiers[node.specifiers.length - 1]; + let firstSpecifier = node.specifiers[0]; + const lastSpecifier = node.specifiers[node.specifiers.length - 1]; if (lastSpecifier.type !== "ImportSpecifier") { return; @@ -223,15 +218,15 @@ module.exports = { firstSpecifier = node.specifiers[1]; } - let first = sourceCode.getTokenBefore(firstSpecifier), - last = sourceCode.getTokenAfter(lastSpecifier); + const first = sourceCode.getTokenBefore(firstSpecifier); + let last = sourceCode.getTokenAfter(lastSpecifier); // to support a trailing comma. if (last.value === ",") { last = sourceCode.getTokenAfter(last); } - let second = sourceCode.getTokenAfter(first), + const second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); validateBraceSpacing(node, first, second, penultimate, last); @@ -247,17 +242,17 @@ module.exports = { return; } - let firstSpecifier = node.specifiers[0], + const firstSpecifier = node.specifiers[0], lastSpecifier = node.specifiers[node.specifiers.length - 1], - first = sourceCode.getTokenBefore(firstSpecifier), - last = sourceCode.getTokenAfter(lastSpecifier); + first = sourceCode.getTokenBefore(firstSpecifier); + let last = sourceCode.getTokenAfter(lastSpecifier); // to support a trailing comma. if (last.value === ",") { last = sourceCode.getTokenAfter(last); } - let second = sourceCode.getTokenAfter(first), + const second = sourceCode.getTokenAfter(first), penultimate = sourceCode.getTokenBefore(last); validateBraceSpacing(node, first, second, penultimate, last); diff --git a/tools/eslint/lib/rules/object-property-newline.js b/tools/eslint/lib/rules/object-property-newline.js index fef7b871b4..d159f6f7db 100644 --- a/tools/eslint/lib/rules/object-property-newline.js +++ b/tools/eslint/lib/rules/object-property-newline.js @@ -31,21 +31,19 @@ module.exports = { }, create: function(context) { - let allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine); - let errorMessage = allowSameLine ? + const allowSameLine = context.options[0] && Boolean(context.options[0].allowMultiplePropertiesPerLine); + const errorMessage = allowSameLine ? "Object properties must go on a new line if they aren't all on the same line." : "Object properties must go on a new line."; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { ObjectExpression: function(node) { - let lastTokenOfPreviousProperty, firstTokenOfCurrentProperty; - if (allowSameLine) { if (node.properties.length > 1) { - let firstTokenOfFirstProperty = sourceCode.getFirstToken(node.properties[0]); - let lastTokenOfLastProperty = sourceCode.getLastToken(node.properties[node.properties.length - 1]); + const firstTokenOfFirstProperty = sourceCode.getFirstToken(node.properties[0]); + const lastTokenOfLastProperty = sourceCode.getLastToken(node.properties[node.properties.length - 1]); if (firstTokenOfFirstProperty.loc.end.line === lastTokenOfLastProperty.loc.start.line) { @@ -56,8 +54,8 @@ module.exports = { } for (let i = 1; i < node.properties.length; i++) { - lastTokenOfPreviousProperty = sourceCode.getLastToken(node.properties[i - 1]); - firstTokenOfCurrentProperty = sourceCode.getFirstToken(node.properties[i]); + const lastTokenOfPreviousProperty = sourceCode.getLastToken(node.properties[i - 1]); + const firstTokenOfCurrentProperty = sourceCode.getFirstToken(node.properties[i]); if (lastTokenOfPreviousProperty.loc.end.line === firstTokenOfCurrentProperty.loc.start.line) { context.report({ diff --git a/tools/eslint/lib/rules/object-shorthand.js b/tools/eslint/lib/rules/object-shorthand.js index 1d08178d57..0e5f6e3f10 100644 --- a/tools/eslint/lib/rules/object-shorthand.js +++ b/tools/eslint/lib/rules/object-shorthand.js @@ -5,11 +5,13 @@ "use strict"; -let OPTIONS = { +const OPTIONS = { always: "always", never: "never", methods: "methods", - properties: "properties" + properties: "properties", + consistent: "consistent", + consistentAsNeeded: "consistent-as-needed" }; //------------------------------------------------------------------------------ @@ -31,7 +33,7 @@ module.exports = { type: "array", items: [ { - enum: ["always", "methods", "properties", "never"] + enum: ["always", "methods", "properties", "never", "consistent", "consistent-as-needed"] } ], minItems: 0, @@ -83,14 +85,16 @@ module.exports = { }, create: function(context) { - let APPLY = context.options[0] || OPTIONS.always; - let APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always; - let APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always; - let APPLY_NEVER = APPLY === OPTIONS.never; + const APPLY = context.options[0] || OPTIONS.always; + const APPLY_TO_METHODS = APPLY === OPTIONS.methods || APPLY === OPTIONS.always; + const APPLY_TO_PROPS = APPLY === OPTIONS.properties || APPLY === OPTIONS.always; + const APPLY_NEVER = APPLY === OPTIONS.never; + const APPLY_CONSISTENT = APPLY === OPTIONS.consistent; + const APPLY_CONSISTENT_AS_NEEDED = APPLY === OPTIONS.consistentAsNeeded; - let PARAMS = context.options[1] || {}; - let IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors; - let AVOID_QUOTES = PARAMS.avoidQuotes; + const PARAMS = context.options[1] || {}; + const IGNORE_CONSTRUCTORS = PARAMS.ignoreConstructors; + const AVOID_QUOTES = PARAMS.avoidQuotes; //-------------------------------------------------------------------------- // Helpers @@ -103,12 +107,22 @@ module.exports = { * @private */ function isConstructor(name) { - let firstChar = name.charAt(0); + const firstChar = name.charAt(0); return firstChar === firstChar.toUpperCase(); } /** + * Determines if the property is not a getter and a setter. + * @param {ASTNode} property Property AST node + * @returns {boolean} True if the property is not a getter and a setter, false if it is. + * @private + **/ + function isNotGetterOrSetter(property) { + return (property.kind !== "set" && property.kind !== "get"); + } + + /** * Checks whether a node is a string literal. * @param {ASTNode} node - Any AST node. * @returns {boolean} `true` if it is a string literal. @@ -117,14 +131,86 @@ module.exports = { return node.type === "Literal" && typeof node.value === "string"; } + /** + * Determines if the property is a shorthand or not. + * @param {ASTNode} property Property AST node + * @returns {boolean} True if the property is considered shorthand, false if not. + * @private + **/ + function isShorthand(property) { + + // property.method is true when `{a(){}}`. + return (property.shorthand || property.method); + } + + /** + * Determines if the property's key and method or value are named equally. + * @param {ASTNode} property Property AST node + * @returns {boolean} True if the key and value are named equally, false if not. + * @private + **/ + function isRedudant(property) { + return (property.key && ( + + // A function expression + property.value && property.value.id && property.value.id.name === property.key.name || + + // A property + property.value && property.value.name === property.key.name + )); + } + + /** + * Ensures that an object's properties are consistently shorthand, or not shorthand at all. + * @param {ASTNode} node Property AST node + * @param {boolean} checkRedundancy Whether to check longform redundancy + * @returns {void} + **/ + function checkConsistency(node, checkRedundancy) { + + // We are excluding getters and setters as they are considered neither longform nor shorthand. + const properties = node.properties.filter(isNotGetterOrSetter); + + // Do we still have properties left after filtering the getters and setters? + if (properties.length > 0) { + const shorthandProperties = properties.filter(isShorthand); + + // If we do not have an equal number of longform properties as + // shorthand properties, we are using the annotations inconsistently + if (shorthandProperties.length !== properties.length) { + + // We have at least 1 shorthand property + if (shorthandProperties.length > 0) { + context.report(node, "Unexpected mix of shorthand and non-shorthand properties."); + } else if (checkRedundancy) { + + // If all properties of the object contain a method or value with a name matching it's key, + // all the keys are redudant. + const canAlwaysUseShorthand = properties.every(isRedudant); + + if (canAlwaysUseShorthand) { + context.report(node, "Expected shorthand for all properties."); + } + } + } + } + } + //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- return { + ObjectExpression: function(node) { + if (APPLY_CONSISTENT) { + checkConsistency(node, false); + } else if (APPLY_CONSISTENT_AS_NEEDED) { + checkConsistency(node, true); + } + }, + Property: function(node) { - let isConciseProperty = node.method || node.shorthand, - type; + const isConciseProperty = node.method || node.shorthand; // Ignore destructuring assignment if (node.parent.type === "ObjectPattern") { @@ -147,7 +233,8 @@ module.exports = { // if we're "never" and concise we should warn now if (APPLY_NEVER) { - type = node.method ? "method" : "property"; + const type = node.method ? "method" : "property"; + context.report({ node: node, message: "Expected longform " + type + " syntax.", diff --git a/tools/eslint/lib/rules/one-var-declaration-per-line.js b/tools/eslint/lib/rules/one-var-declaration-per-line.js index e7a29fb115..fe47b0333f 100644 --- a/tools/eslint/lib/rules/one-var-declaration-per-line.js +++ b/tools/eslint/lib/rules/one-var-declaration-per-line.js @@ -25,8 +25,8 @@ module.exports = { create: function(context) { - let ERROR_MESSAGE = "Expected variable declaration to be on a new line."; - let always = context.options[0] === "always"; + const ERROR_MESSAGE = "Expected variable declaration to be on a new line."; + const always = context.options[0] === "always"; //-------------------------------------------------------------------------- // Helpers @@ -54,7 +54,7 @@ module.exports = { return; } - let declarations = node.declarations; + const declarations = node.declarations; let prev; declarations.forEach(function(current) { diff --git a/tools/eslint/lib/rules/one-var.js b/tools/eslint/lib/rules/one-var.js index 10cdb626e5..0291c70973 100644 --- a/tools/eslint/lib/rules/one-var.js +++ b/tools/eslint/lib/rules/one-var.js @@ -57,12 +57,12 @@ module.exports = { create: function(context) { - let MODE_ALWAYS = "always", + const MODE_ALWAYS = "always", MODE_NEVER = "never"; - let mode = context.options[0] || MODE_ALWAYS; + const mode = context.options[0] || MODE_ALWAYS; - let options = { + const options = { }; if (typeof mode === "string") { // simple options configuration with just a string @@ -113,8 +113,8 @@ module.exports = { // Helpers //-------------------------------------------------------------------------- - let functionStack = []; - let blockStack = []; + const functionStack = []; + const blockStack = []; /** * Increments the blockStack counter. @@ -204,7 +204,7 @@ module.exports = { * @private */ function countDeclarations(declarations) { - let counts = { uninitialized: 0, initialized: 0 }; + const counts = { uninitialized: 0, initialized: 0 }; for (let i = 0; i < declarations.length; i++) { if (declarations[i].init === null) { @@ -225,9 +225,9 @@ module.exports = { */ function hasOnlyOneStatement(statementType, declarations) { - let declarationCounts = countDeclarations(declarations); - let currentOptions = options[statementType] || {}; - let currentScope = getCurrentScope(statementType); + const declarationCounts = countDeclarations(declarations); + const currentOptions = options[statementType] || {}; + const currentScope = getCurrentScope(statementType); if (currentOptions.uninitialized === MODE_ALWAYS && currentOptions.initialized === MODE_ALWAYS) { if (currentScope.uninitialized || currentScope.initialized) { @@ -266,16 +266,15 @@ module.exports = { SwitchStatement: startBlock, VariableDeclaration: function(node) { - let parent = node.parent, - type, declarations, declarationCounts; + const parent = node.parent; + const type = node.kind; - type = node.kind; if (!options[type]) { return; } - declarations = node.declarations; - declarationCounts = countDeclarations(declarations); + const declarations = node.declarations; + const declarationCounts = countDeclarations(declarations); // always if (!hasOnlyOneStatement(type, declarations)) { @@ -296,7 +295,7 @@ module.exports = { // never if (parent.type !== "ForStatement" || parent.init !== node) { - let totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; + const totalDeclarations = declarationCounts.uninitialized + declarationCounts.initialized; if (totalDeclarations > 1) { diff --git a/tools/eslint/lib/rules/operator-assignment.js b/tools/eslint/lib/rules/operator-assignment.js index 3088ff174f..6056b41d36 100644 --- a/tools/eslint/lib/rules/operator-assignment.js +++ b/tools/eslint/lib/rules/operator-assignment.js @@ -93,15 +93,13 @@ module.exports = { * @returns {void} */ function verify(node) { - let expr, left, operator; - if (node.operator !== "=" || node.right.type !== "BinaryExpression") { return; } - left = node.left; - expr = node.right; - operator = expr.operator; + const left = node.left; + const expr = node.right; + const operator = expr.operator; if (isCommutativeOperatorWithShorthand(operator)) { if (same(left, expr.left) || same(left, expr.right)) { diff --git a/tools/eslint/lib/rules/operator-linebreak.js b/tools/eslint/lib/rules/operator-linebreak.js index 2b2f1274aa..51c68be5ef 100644 --- a/tools/eslint/lib/rules/operator-linebreak.js +++ b/tools/eslint/lib/rules/operator-linebreak.js @@ -5,8 +5,7 @@ "use strict"; -let lodash = require("lodash"), - astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -44,10 +43,10 @@ module.exports = { create: function(context) { - let usedDefaultGlobal = !context.options[0]; - let globalStyle = context.options[0] || "after"; - let options = context.options[1] || {}; - let styleOverrides = options.overrides ? lodash.assign({}, options.overrides) : {}; + const usedDefaultGlobal = !context.options[0]; + const globalStyle = context.options[0] || "after"; + const options = context.options[1] || {}; + const styleOverrides = options.overrides ? Object.assign({}, options.overrides) : {}; if (usedDefaultGlobal && !styleOverrides["?"]) { styleOverrides["?"] = "before"; @@ -57,7 +56,7 @@ module.exports = { styleOverrides[":"] = "before"; } - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -84,10 +83,10 @@ module.exports = { operatorToken = sourceCode.getTokenAfter(operatorToken); } - let rightToken = sourceCode.getTokenAfter(operatorToken); - let operator = operatorToken.value; - let operatorStyleOverride = styleOverrides[operator]; - let style = operatorStyleOverride || globalStyle; + const rightToken = sourceCode.getTokenAfter(operatorToken); + const operator = operatorToken.value; + const operatorStyleOverride = styleOverrides[operator]; + const style = operatorStyleOverride || globalStyle; // if single line if (astUtils.isTokenOnSameLine(leftToken, operatorToken) && diff --git a/tools/eslint/lib/rules/padded-blocks.js b/tools/eslint/lib/rules/padded-blocks.js index 2754cda4de..b79a25c290 100644 --- a/tools/eslint/lib/rules/padded-blocks.js +++ b/tools/eslint/lib/rules/padded-blocks.js @@ -47,8 +47,8 @@ module.exports = { }, create: function(context) { - let options = {}; - let config = context.options[0] || "always"; + const options = {}; + const config = context.options[0] || "always"; if (typeof config === "string") { options.blocks = config === "always"; @@ -64,10 +64,10 @@ module.exports = { } } - let ALWAYS_MESSAGE = "Block must be padded by blank lines.", + const ALWAYS_MESSAGE = "Block must be padded by blank lines.", NEVER_MESSAGE = "Block must not be padded by blank lines."; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Gets the open brace token from a given node. @@ -96,17 +96,16 @@ module.exports = { * @returns {boolean} Whether or not the token is followed by a blank line. */ function isTokenTopPadded(token) { - let tokenStartLine = token.loc.start.line, - expectedFirstLine = tokenStartLine + 2, - first, - firstLine; + const tokenStartLine = token.loc.start.line, + expectedFirstLine = tokenStartLine + 2; + let first = token; - first = token; do { first = sourceCode.getTokenOrCommentAfter(first); } while (isComment(first) && first.loc.start.line === tokenStartLine); - firstLine = first.loc.start.line; + const firstLine = first.loc.start.line; + return expectedFirstLine <= firstLine; } @@ -116,17 +115,16 @@ module.exports = { * @returns {boolean} Whether or not the token is preceeded by a blank line */ function isTokenBottomPadded(token) { - let blockEnd = token.loc.end.line, - expectedLastLine = blockEnd - 2, - last, - lastLine; + const blockEnd = token.loc.end.line, + expectedLastLine = blockEnd - 2; + let last = token; - last = token; do { last = sourceCode.getTokenOrCommentBefore(last); } while (isComment(last) && last.loc.end.line === blockEnd); - lastLine = last.loc.end.line; + const lastLine = last.loc.end.line; + return lastLine <= expectedLastLine; } @@ -156,7 +154,7 @@ module.exports = { * @returns {void} undefined. */ function checkPadding(node) { - let openBrace = getOpenBrace(node), + const openBrace = getOpenBrace(node), closeBrace = sourceCode.getLastToken(node), blockHasTopPadding = isTokenTopPadded(openBrace), blockHasBottomPadding = isTokenBottomPadded(closeBrace); @@ -184,7 +182,7 @@ module.exports = { } } else { if (blockHasTopPadding) { - let nextToken = sourceCode.getTokenOrCommentAfter(openBrace); + const nextToken = sourceCode.getTokenOrCommentAfter(openBrace); context.report({ node: node, @@ -197,7 +195,7 @@ module.exports = { } if (blockHasBottomPadding) { - let previousToken = sourceCode.getTokenOrCommentBefore(closeBrace); + const previousToken = sourceCode.getTokenOrCommentBefore(closeBrace); context.report({ node: node, @@ -211,7 +209,7 @@ module.exports = { } } - let rule = {}; + const rule = {}; if (options.hasOwnProperty("switches")) { rule.SwitchStatement = function(node) { diff --git a/tools/eslint/lib/rules/prefer-arrow-callback.js b/tools/eslint/lib/rules/prefer-arrow-callback.js index 185bf16057..97aab40b2e 100644 --- a/tools/eslint/lib/rules/prefer-arrow-callback.js +++ b/tools/eslint/lib/rules/prefer-arrow-callback.js @@ -35,10 +35,10 @@ function checkMetaProperty(node, metaName, propertyName) { * @returns {escope.Variable} The found variable object. */ function getVariableOfArguments(scope) { - let variables = scope.variables; + const variables = scope.variables; for (let i = 0; i < variables.length; ++i) { - let variable = variables[i]; + const variable = variables[i]; if (variable.name === "arguments") { @@ -63,7 +63,7 @@ function getVariableOfArguments(scope) { * {boolean} retv.isLexicalThis - `true` if the node is with `.bind(this)`. */ function getCallbackInfo(node) { - let retv = {isCallback: false, isLexicalThis: false}; + const retv = {isCallback: false, isLexicalThis: false}; let parent = node.parent; while (node) { @@ -144,10 +144,10 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; + const options = context.options[0] || {}; - let allowUnboundThis = options.allowUnboundThis !== false; // default to true - let allowNamedFunctions = options.allowNamedFunctions; + const allowUnboundThis = options.allowUnboundThis !== false; // default to true + const allowNamedFunctions = options.allowNamedFunctions; /* * {Array<{this: boolean, super: boolean, meta: boolean}>} @@ -182,7 +182,7 @@ module.exports = { // If there are below, it cannot replace with arrow functions merely. ThisExpression: function() { - let info = stack[stack.length - 1]; + const info = stack[stack.length - 1]; if (info) { info.this = true; @@ -190,7 +190,7 @@ module.exports = { }, Super: function() { - let info = stack[stack.length - 1]; + const info = stack[stack.length - 1]; if (info) { info.super = true; @@ -198,7 +198,7 @@ module.exports = { }, MetaProperty: function(node) { - let info = stack[stack.length - 1]; + const info = stack[stack.length - 1]; if (info && checkMetaProperty(node, "new", "target")) { info.meta = true; @@ -212,7 +212,7 @@ module.exports = { // Main. FunctionExpression: enterScope, "FunctionExpression:exit": function(node) { - let scopeInfo = exitScope(); + const scopeInfo = exitScope(); // Skip named function expressions if (allowNamedFunctions && node.id && node.id.name) { @@ -225,21 +225,21 @@ module.exports = { } // Skip recursive functions. - let nameVar = context.getDeclaredVariables(node)[0]; + const nameVar = context.getDeclaredVariables(node)[0]; if (isFunctionName(nameVar) && nameVar.references.length > 0) { return; } // Skip if it's using arguments. - let variable = getVariableOfArguments(context.getScope()); + const variable = getVariableOfArguments(context.getScope()); if (variable && variable.references.length > 0) { return; } // Reports if it's a callback which can replace with arrows. - let callbackInfo = getCallbackInfo(node); + const callbackInfo = getCallbackInfo(node); if (callbackInfo.isCallback && (!allowUnboundThis || !scopeInfo.this || callbackInfo.isLexicalThis) && diff --git a/tools/eslint/lib/rules/prefer-const.js b/tools/eslint/lib/rules/prefer-const.js index 5935e02b2c..76931bfc1d 100644 --- a/tools/eslint/lib/rules/prefer-const.js +++ b/tools/eslint/lib/rules/prefer-const.js @@ -9,15 +9,15 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"); +const lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let PATTERN_TYPE = /^(?:.+?Pattern|RestElement|Property)$/; -let DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/; -let DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; +const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|Property)$/; +const DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/; +const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; /** * Adds multiple items to the tail of an array. @@ -26,7 +26,7 @@ let DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/; * @param {any[]} values - Items to be added. * @returns {void} */ -let pushAll = Function.apply.bind(Array.prototype.push); +const pushAll = Function.apply.bind(Array.prototype.push); /** * Checks whether a given node is located at `ForStatement.init` or not. @@ -89,13 +89,13 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) { // Finds the unique WriteReference. let writer = null; let isReadBeforeInit = false; - let references = variable.references; + const references = variable.references; for (let i = 0; i < references.length; ++i) { - let reference = references[i]; + const reference = references[i]; if (reference.isWrite()) { - let isReassigned = ( + const isReassigned = ( writer !== null && writer.identifier !== reference.identifier ); @@ -115,7 +115,7 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) { // If the assignment is from a different scope, ignore it. // If the assignment cannot change to a declaration, ignore it. - let shouldBeConst = ( + const shouldBeConst = ( writer !== null && writer.from === variable.scope && canBecomeVariableDeclaration(writer.identifier) @@ -168,17 +168,17 @@ function getDestructuringHost(reference) { * @returns {Map<ASTNode, ASTNode[]>} Grouped identifier nodes. */ function groupByDestructuring(variables, ignoreReadBeforeAssign) { - let identifierMap = new Map(); + const identifierMap = new Map(); for (let i = 0; i < variables.length; ++i) { - let variable = variables[i]; - let references = variable.references; - let identifier = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); + const variable = variables[i]; + const references = variable.references; + const identifier = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); let prevId = null; for (let j = 0; j < references.length; ++j) { - let reference = references[j]; - let id = reference.identifier; + const reference = references[j]; + const id = reference.identifier; // Avoid counting a reference twice or more for default values of // destructuring. @@ -188,7 +188,7 @@ function groupByDestructuring(variables, ignoreReadBeforeAssign) { prevId = id; // Add the identifier node into the destructuring group. - let group = getDestructuringHost(reference); + const group = getDestructuringHost(reference); if (group) { if (identifierMap.has(group)) { @@ -248,9 +248,9 @@ module.exports = { }, create: function(context) { - let options = context.options[0] || {}; - let checkingMixedDestructuring = options.destructuring !== "all"; - let ignoreReadBeforeAssign = options.ignoreReadBeforeAssign === true; + const options = context.options[0] || {}; + const checkingMixedDestructuring = options.destructuring !== "all"; + const ignoreReadBeforeAssign = options.ignoreReadBeforeAssign === true; let variables = null; /** @@ -260,7 +260,7 @@ module.exports = { * @returns {void} */ function report(node) { - let reportArgs = { + const reportArgs = { node: node, message: "'{{name}}' is never reassigned. Use 'const' instead.", data: node @@ -317,7 +317,7 @@ module.exports = { * @returns {void} */ function checkVariable(variable) { - let node = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); + const node = getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign); if (node) { report(node); diff --git a/tools/eslint/lib/rules/prefer-reflect.js b/tools/eslint/lib/rules/prefer-reflect.js index b2b0b9abda..103574428b 100644 --- a/tools/eslint/lib/rules/prefer-reflect.js +++ b/tools/eslint/lib/rules/prefer-reflect.js @@ -45,7 +45,7 @@ module.exports = { }, create: function(context) { - let existingNames = { + const existingNames = { apply: "Function.prototype.apply", call: "Function.prototype.call", defineProperty: "Object.defineProperty", @@ -57,7 +57,7 @@ module.exports = { preventExtensions: "Object.preventExtensions" }; - let reflectSubsitutes = { + const reflectSubsitutes = { apply: "Reflect.apply", call: "Reflect.apply", defineProperty: "Reflect.defineProperty", @@ -69,7 +69,7 @@ module.exports = { preventExtensions: "Reflect.preventExtensions" }; - let exceptions = (context.options[0] || {}).exceptions || []; + const exceptions = (context.options[0] || {}).exceptions || []; /** * Reports the Reflect violation based on the `existing` and `substitute` @@ -87,19 +87,19 @@ module.exports = { return { CallExpression: function(node) { - let methodName = (node.callee.property || {}).name; - let isReflectCall = (node.callee.object || {}).name === "Reflect"; - let hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName); - let userConfiguredException = exceptions.indexOf(methodName) !== -1; + const methodName = (node.callee.property || {}).name; + const isReflectCall = (node.callee.object || {}).name === "Reflect"; + const hasReflectSubsitute = reflectSubsitutes.hasOwnProperty(methodName); + const userConfiguredException = exceptions.indexOf(methodName) !== -1; if (hasReflectSubsitute && !isReflectCall && !userConfiguredException) { report(node, existingNames[methodName], reflectSubsitutes[methodName]); } }, UnaryExpression: function(node) { - let isDeleteOperator = node.operator === "delete"; - let targetsIdentifier = node.argument.type === "Identifier"; - let userConfiguredException = exceptions.indexOf("delete") !== -1; + const isDeleteOperator = node.operator === "delete"; + const targetsIdentifier = node.argument.type === "Identifier"; + const userConfiguredException = exceptions.indexOf("delete") !== -1; if (isDeleteOperator && !targetsIdentifier && !userConfiguredException) { report(node, "the delete keyword", "Reflect.deleteProperty"); diff --git a/tools/eslint/lib/rules/prefer-rest-params.js b/tools/eslint/lib/rules/prefer-rest-params.js index 5a9164ed7f..7d60b16f62 100644 --- a/tools/eslint/lib/rules/prefer-rest-params.js +++ b/tools/eslint/lib/rules/prefer-rest-params.js @@ -15,10 +15,10 @@ * @returns {escope.Variable} The found variable object. */ function getVariableOfArguments(scope) { - let variables = scope.variables; + const variables = scope.variables; for (let i = 0; i < variables.length; ++i) { - let variable = variables[i]; + const variable = variables[i]; if (variable.name === "arguments") { @@ -32,6 +32,28 @@ function getVariableOfArguments(scope) { return null; } +/** + * Checks if the given reference is not normal member access. + * + * - arguments .... true // not member access + * - arguments[i] .... true // computed member access + * - arguments[0] .... true // computed member access + * - arguments.length .... false // normal member access + * + * @param {escope.Reference} reference - The reference to check. + * @returns {boolean} `true` if the reference is not normal member access. + */ +function isNotNormalMemberAccess(reference) { + const id = reference.identifier; + const parent = id.parent; + + return !( + parent.type === "MemberExpression" && + parent.object === id && + !parent.computed + ); +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -58,6 +80,7 @@ module.exports = { function report(reference) { context.report({ node: reference.identifier, + loc: reference.identifier.loc, message: "Use the rest parameters instead of 'arguments'." }); } @@ -68,16 +91,19 @@ module.exports = { * @returns {void} */ function checkForArguments() { - let argumentsVar = getVariableOfArguments(context.getScope()); + const argumentsVar = getVariableOfArguments(context.getScope()); if (argumentsVar) { - argumentsVar.references.forEach(report); + argumentsVar + .references + .filter(isNotNormalMemberAccess) + .forEach(report); } } return { - FunctionDeclaration: checkForArguments, - FunctionExpression: checkForArguments + "FunctionDeclaration:exit": checkForArguments, + "FunctionExpression:exit": checkForArguments }; } }; diff --git a/tools/eslint/lib/rules/prefer-spread.js b/tools/eslint/lib/rules/prefer-spread.js index 58fc85ca90..2ad0dad4df 100644 --- a/tools/eslint/lib/rules/prefer-spread.js +++ b/tools/eslint/lib/rules/prefer-spread.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -35,8 +35,8 @@ function isVariadicApplyCalling(node) { * @returns {boolean} the source code for the given node. */ function equalTokens(left, right, sourceCode) { - let tokensL = sourceCode.getTokens(left); - let tokensR = sourceCode.getTokens(right); + const tokensL = sourceCode.getTokens(left); + const tokensR = sourceCode.getTokens(right); if (tokensL.length !== tokensR.length) { return false; @@ -82,7 +82,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { CallExpression: function(node) { @@ -90,9 +90,9 @@ module.exports = { return; } - let applied = node.callee.object; - let expectedThis = (applied.type === "MemberExpression") ? applied.object : null; - let thisArg = node.arguments[0]; + const applied = node.callee.object; + const expectedThis = (applied.type === "MemberExpression") ? applied.object : null; + const thisArg = node.arguments[0]; if (isValidThisArg(expectedThis, thisArg, sourceCode)) { context.report(node, "use the spread operator instead of the '.apply()'."); diff --git a/tools/eslint/lib/rules/prefer-template.js b/tools/eslint/lib/rules/prefer-template.js index 4a0da8e197..fa623b56ee 100644 --- a/tools/eslint/lib/rules/prefer-template.js +++ b/tools/eslint/lib/rules/prefer-template.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -79,7 +79,7 @@ module.exports = { return; } - let topBinaryExpr = getTopConcatBinaryExpression(node.parent); + const topBinaryExpr = getTopConcatBinaryExpression(node.parent); // Checks whether or not this node had been checked already. if (done[topBinaryExpr.range[0]]) { diff --git a/tools/eslint/lib/rules/quote-props.js b/tools/eslint/lib/rules/quote-props.js index ec65647450..26c527402d 100644 --- a/tools/eslint/lib/rules/quote-props.js +++ b/tools/eslint/lib/rules/quote-props.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let espree = require("espree"), +const espree = require("espree"), keywords = require("../util/keywords"); //------------------------------------------------------------------------------ @@ -66,7 +66,7 @@ module.exports = { create: function(context) { - let MODE = context.options[0], + const MODE = context.options[0], KEYWORDS = context.options[1] && context.options[1].keywords, CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false, NUMBERS = context.options[1] && context.options[1].numbers, @@ -106,9 +106,8 @@ module.exports = { * @returns {void} */ function checkUnnecessaryQuotes(node) { - let key = node.key, - isKeywordToken, - tokens; + const key = node.key; + let tokens; if (node.method || node.computed || node.shorthand) { return; @@ -125,7 +124,7 @@ module.exports = { return; } - isKeywordToken = isKeyword(tokens[0].value); + const isKeywordToken = isKeyword(tokens[0].value); if (isKeywordToken && KEYWORDS) { return; @@ -147,7 +146,7 @@ module.exports = { * @returns {void} */ function checkOmittedQuotes(node) { - let key = node.key; + const key = node.key; if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) { context.report(node, MESSAGE_UNQUOTED, { @@ -168,8 +167,8 @@ module.exports = { necessaryQuotes = false; node.properties.forEach(function(property) { - let key = property.key, - tokens; + const key = property.key; + let tokens; if (!key || property.method || property.computed || property.shorthand) { return; diff --git a/tools/eslint/lib/rules/quotes.js b/tools/eslint/lib/rules/quotes.js index 18635da537..a6fa7518ff 100644 --- a/tools/eslint/lib/rules/quotes.js +++ b/tools/eslint/lib/rules/quotes.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Constants //------------------------------------------------------------------------------ -let QUOTE_SETTINGS = { +const QUOTE_SETTINGS = { double: { quote: "\"", alternateQuote: "'", @@ -45,8 +45,8 @@ let QUOTE_SETTINGS = { QUOTE_SETTINGS.double.convert = QUOTE_SETTINGS.single.convert = QUOTE_SETTINGS.backtick.convert = function(str) { - let newQuote = this.quote; - let oldQuote = str[0]; + const newQuote = this.quote; + const oldQuote = str[0]; if (newQuote === oldQuote) { return str; @@ -65,7 +65,7 @@ QUOTE_SETTINGS.backtick.convert = function(str) { }) + newQuote; }; -let AVOID_ESCAPE = "avoid-escape"; +const AVOID_ESCAPE = "avoid-escape"; //------------------------------------------------------------------------------ // Rule Definition @@ -109,12 +109,12 @@ module.exports = { create: function(context) { - let quoteOption = context.options[0], + const quoteOption = context.options[0], settings = QUOTE_SETTINGS[quoteOption || "double"], options = context.options[1], - avoidEscape = options && options.avoidEscape === true, allowTemplateLiterals = options && options.allowTemplateLiterals === true, sourceCode = context.getSourceCode(); + let avoidEscape = options && options.avoidEscape === true; // deprecated if (options === AVOID_ESCAPE) { @@ -154,7 +154,7 @@ module.exports = { * @private */ function isPartOfDirectivePrologue(node) { - let block = node.parent.parent; + const block = node.parent.parent; if (block.type !== "Program" && (block.type !== "BlockStatement" || !astUtils.isFunction(block.parent))) { return false; @@ -162,7 +162,7 @@ module.exports = { // Check the node is at a prologue. for (let i = 0; i < block.body.length; ++i) { - let statement = block.body[i]; + const statement = block.body[i]; if (statement === node.parent) { return true; @@ -182,7 +182,7 @@ module.exports = { * @private */ function isAllowedAsNonBacktick(node) { - let parent = node.parent; + const parent = node.parent; switch (parent.type) { @@ -209,9 +209,9 @@ module.exports = { return { Literal: function(node) { - let val = node.value, - rawVal = node.raw, - isValid; + const val = node.value, + rawVal = node.raw; + let isValid; if (settings && typeof val === "string") { isValid = (quoteOption === "backtick" && isAllowedAsNonBacktick(node)) || @@ -241,7 +241,7 @@ module.exports = { return; } - let shouldWarn = node.quasis.length === 1 && (node.quasis[0].value.cooked.indexOf("\n") === -1); + const shouldWarn = node.quasis.length === 1 && (node.quasis[0].value.cooked.indexOf("\n") === -1); if (shouldWarn) { context.report({ diff --git a/tools/eslint/lib/rules/radix.js b/tools/eslint/lib/rules/radix.js index 4c9cb73beb..aab917ac21 100644 --- a/tools/eslint/lib/rules/radix.js +++ b/tools/eslint/lib/rules/radix.js @@ -9,13 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let MODE_ALWAYS = "always", +const MODE_ALWAYS = "always", MODE_AS_NEEDED = "as-needed"; /** @@ -92,7 +92,7 @@ module.exports = { }, create: function(context) { - let mode = context.options[0] || MODE_ALWAYS; + const mode = context.options[0] || MODE_ALWAYS; /** * Checks the arguments of a given CallExpression node and reports it if it @@ -102,7 +102,7 @@ module.exports = { * @returns {void} */ function checkArguments(node) { - let args = node.arguments; + const args = node.arguments; switch (args.length) { case 0: @@ -139,14 +139,14 @@ module.exports = { return { "Program:exit": function() { - let scope = context.getScope(); + const scope = context.getScope(); let variable; // Check `parseInt()` variable = astUtils.getVariableByName(scope, "parseInt"); if (!isShadowed(variable)) { variable.references.forEach(function(reference) { - let node = reference.identifier; + const node = reference.identifier; if (astUtils.isCallee(node)) { checkArguments(node.parent); @@ -158,7 +158,7 @@ module.exports = { variable = astUtils.getVariableByName(scope, "Number"); if (!isShadowed(variable)) { variable.references.forEach(function(reference) { - let node = reference.identifier.parent; + const node = reference.identifier.parent; if (isParseIntMethod(node) && astUtils.isCallee(node)) { checkArguments(node.parent); diff --git a/tools/eslint/lib/rules/require-jsdoc.js b/tools/eslint/lib/rules/require-jsdoc.js index 1503c0ff88..d271f839b3 100644 --- a/tools/eslint/lib/rules/require-jsdoc.js +++ b/tools/eslint/lib/rules/require-jsdoc.js @@ -4,8 +4,6 @@ */ "use strict"; -let lodash = require("lodash"); - module.exports = { meta: { docs: { @@ -40,13 +38,13 @@ module.exports = { }, create: function(context) { - let source = context.getSourceCode(); - let DEFAULT_OPTIONS = { + const source = context.getSourceCode(); + const DEFAULT_OPTIONS = { FunctionDeclaration: true, MethodDefinition: false, ClassDeclaration: false }; - let options = lodash.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {}); + const options = Object.assign(DEFAULT_OPTIONS, context.options[0] && context.options[0].require || {}); /** * Report the error message @@ -64,7 +62,7 @@ module.exports = { */ function checkClassMethodJsDoc(node) { if (node.parent.type === "MethodDefinition") { - let jsdocComment = source.getJSDocComment(node); + const jsdocComment = source.getJSDocComment(node); if (!jsdocComment) { report(node); @@ -78,7 +76,7 @@ module.exports = { * @returns {void} */ function checkJsDoc(node) { - let jsdocComment = source.getJSDocComment(node); + const jsdocComment = source.getJSDocComment(node); if (!jsdocComment) { report(node); diff --git a/tools/eslint/lib/rules/require-yield.js b/tools/eslint/lib/rules/require-yield.js index a4bb292b7a..e9d8281f69 100644 --- a/tools/eslint/lib/rules/require-yield.js +++ b/tools/eslint/lib/rules/require-yield.js @@ -21,7 +21,7 @@ module.exports = { }, create: function(context) { - let stack = []; + const stack = []; /** * If the node is a generator function, start counting `yield` keywords. @@ -45,7 +45,7 @@ module.exports = { return; } - let countYield = stack.pop(); + const countYield = stack.pop(); if (countYield === 0 && node.body.body.length > 0) { context.report( diff --git a/tools/eslint/lib/rules/rest-spread-spacing.js b/tools/eslint/lib/rules/rest-spread-spacing.js index 3be2a43421..c74c128409 100644 --- a/tools/eslint/lib/rules/rest-spread-spacing.js +++ b/tools/eslint/lib/rules/rest-spread-spacing.js @@ -25,7 +25,7 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(), + const sourceCode = context.getSourceCode(), alwaysSpace = context.options[0] === "always"; //-------------------------------------------------------------------------- @@ -38,10 +38,10 @@ module.exports = { * @returns {void} */ function checkWhiteSpace(node) { - let operator = sourceCode.getFirstToken(node), + const operator = sourceCode.getFirstToken(node), nextToken = sourceCode.getTokenAfter(operator), - hasWhitespace = sourceCode.isSpaceBetweenTokens(operator, nextToken), - type; + hasWhitespace = sourceCode.isSpaceBetweenTokens(operator, nextToken); + let type; switch (node.type) { case "SpreadElement": diff --git a/tools/eslint/lib/rules/semi-spacing.js b/tools/eslint/lib/rules/semi-spacing.js index 261905f96f..b7cffbf335 100644 --- a/tools/eslint/lib/rules/semi-spacing.js +++ b/tools/eslint/lib/rules/semi-spacing.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -39,10 +39,10 @@ module.exports = { create: function(context) { - let config = context.options[0], - requireSpaceBefore = false, - requireSpaceAfter = true, + const config = context.options[0], sourceCode = context.getSourceCode(); + let requireSpaceBefore = false, + requireSpaceAfter = true; if (typeof config === "object") { if (config.hasOwnProperty("before")) { @@ -59,7 +59,7 @@ module.exports = { * @returns {boolean} True if the given token has leading space, false if not. */ function hasLeadingSpace(token) { - let tokenBefore = sourceCode.getTokenBefore(token); + const tokenBefore = sourceCode.getTokenBefore(token); return tokenBefore && astUtils.isTokenOnSameLine(tokenBefore, token) && sourceCode.isSpaceBetweenTokens(tokenBefore, token); } @@ -70,7 +70,7 @@ module.exports = { * @returns {boolean} True if the given token has trailing space, false if not. */ function hasTrailingSpace(token) { - let tokenAfter = sourceCode.getTokenAfter(token); + const tokenAfter = sourceCode.getTokenAfter(token); return tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter) && sourceCode.isSpaceBetweenTokens(token, tokenAfter); } @@ -81,7 +81,7 @@ module.exports = { * @returns {boolean} Whether or not the token is the last in its line. */ function isLastTokenInCurrentLine(token) { - let tokenAfter = sourceCode.getTokenAfter(token); + const tokenAfter = sourceCode.getTokenAfter(token); return !(tokenAfter && astUtils.isTokenOnSameLine(token, tokenAfter)); } @@ -92,7 +92,7 @@ module.exports = { * @returns {boolean} Whether or not the token is the first in its line. */ function isFirstTokenInCurrentLine(token) { - let tokenBefore = sourceCode.getTokenBefore(token); + const tokenBefore = sourceCode.getTokenBefore(token); return !(tokenBefore && astUtils.isTokenOnSameLine(token, tokenBefore)); } @@ -103,7 +103,7 @@ module.exports = { * @returns {boolean} Whether or not the next token of a given token is a closing parenthesis. */ function isBeforeClosingParen(token) { - let nextToken = sourceCode.getTokenAfter(token); + const nextToken = sourceCode.getTokenAfter(token); return ( nextToken && @@ -128,10 +128,8 @@ module.exports = { * @returns {void} */ function checkSemicolonSpacing(token, node) { - let location; - if (isSemicolon(token)) { - location = token.loc.start; + const location = token.loc.start; if (hasLeadingSpace(token)) { if (!requireSpaceBefore) { @@ -140,7 +138,7 @@ module.exports = { loc: location, message: "Unexpected whitespace before semicolon.", fix: function(fixer) { - let tokenBefore = sourceCode.getTokenBefore(token); + const tokenBefore = sourceCode.getTokenBefore(token); return fixer.removeRange([tokenBefore.range[1], token.range[0]]); } @@ -167,7 +165,7 @@ module.exports = { loc: location, message: "Unexpected whitespace after semicolon.", fix: function(fixer) { - let tokenAfter = sourceCode.getTokenAfter(token); + const tokenAfter = sourceCode.getTokenAfter(token); return fixer.removeRange([token.range[1], tokenAfter.range[0]]); } @@ -195,7 +193,7 @@ module.exports = { * @returns {void} */ function checkNode(node) { - let token = sourceCode.getLastToken(node); + const token = sourceCode.getLastToken(node); checkSemicolonSpacing(token, node); } diff --git a/tools/eslint/lib/rules/semi.js b/tools/eslint/lib/rules/semi.js index 80b1e9d002..d495360a72 100644 --- a/tools/eslint/lib/rules/semi.js +++ b/tools/eslint/lib/rules/semi.js @@ -53,9 +53,9 @@ module.exports = { create: function(context) { - let OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+- - let options = context.options[1]; - let never = context.options[0] === "never", + const OPT_OUT_PATTERN = /[\[\(\/\+\-]/; // One of [(/+- + const options = context.options[1]; + const never = context.options[0] === "never", exceptOneLine = options && options.omitLastInOneLineBlock === true, sourceCode = context.getSourceCode(); @@ -70,9 +70,9 @@ module.exports = { * @returns {void} */ function report(node, missing) { + const lastToken = sourceCode.getLastToken(node); let message, fix, - lastToken = sourceCode.getLastToken(node), loc = lastToken.loc; if (!missing) { @@ -115,22 +115,20 @@ module.exports = { * @returns {boolean} whether the semicolon is unnecessary. */ function isUnnecessarySemicolon(lastToken) { - let isDivider, isOptOutToken, lastTokenLine, nextToken, nextTokenLine; - if (!isSemicolon(lastToken)) { return false; } - nextToken = sourceCode.getTokenAfter(lastToken); + const nextToken = sourceCode.getTokenAfter(lastToken); if (!nextToken) { return true; } - lastTokenLine = lastToken.loc.end.line; - nextTokenLine = nextToken.loc.start.line; - isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value); - isDivider = (nextToken.value === "}" || nextToken.value === ";"); + const lastTokenLine = lastToken.loc.end.line; + const nextTokenLine = nextToken.loc.start.line; + const isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value); + const isDivider = (nextToken.value === "}" || nextToken.value === ";"); return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider; } @@ -141,13 +139,13 @@ module.exports = { * @returns {boolean} whether the node is in a one-liner block statement. */ function isOneLinerBlock(node) { - let nextToken = sourceCode.getTokenAfter(node); + const nextToken = sourceCode.getTokenAfter(node); if (!nextToken || nextToken.value !== "}") { return false; } - let parent = node.parent; + const parent = node.parent; return parent && parent.type === "BlockStatement" && parent.loc.start.line === parent.loc.end.line; @@ -159,7 +157,7 @@ module.exports = { * @returns {void} */ function checkForSemicolon(node) { - let lastToken = sourceCode.getLastToken(node); + const lastToken = sourceCode.getLastToken(node); if (never) { if (isUnnecessarySemicolon(lastToken)) { @@ -184,7 +182,7 @@ module.exports = { * @returns {void} */ function checkForSemicolonForVariableDeclaration(node) { - let ancestors = context.getAncestors(), + const ancestors = context.getAncestors(), parentIndex = ancestors.length - 1, parent = ancestors[parentIndex]; diff --git a/tools/eslint/lib/rules/sort-imports.js b/tools/eslint/lib/rules/sort-imports.js index c8d3340b0c..9a546fbfe4 100644 --- a/tools/eslint/lib/rules/sort-imports.js +++ b/tools/eslint/lib/rules/sort-imports.js @@ -44,11 +44,11 @@ module.exports = { create: function(context) { - let configuration = context.options[0] || {}, + const configuration = context.options[0] || {}, ignoreCase = configuration.ignoreCase || false, ignoreMemberSort = configuration.ignoreMemberSort || false, - memberSyntaxSortOrder = configuration.memberSyntaxSortOrder || ["none", "all", "multiple", "single"], - previousDeclaration = null; + memberSyntaxSortOrder = configuration.memberSyntaxSortOrder || ["none", "all", "multiple", "single"]; + let previousDeclaration = null; /** * Gets the used member syntax style. @@ -98,10 +98,10 @@ module.exports = { return { ImportDeclaration: function(node) { if (previousDeclaration) { - let currentLocalMemberName = getFirstLocalMemberName(node), - currentMemberSyntaxGroupIndex = getMemberParameterGroupIndex(node), - previousLocalMemberName = getFirstLocalMemberName(previousDeclaration), + const currentMemberSyntaxGroupIndex = getMemberParameterGroupIndex(node), previousMemberSyntaxGroupIndex = getMemberParameterGroupIndex(previousDeclaration); + let currentLocalMemberName = getFirstLocalMemberName(node), + previousLocalMemberName = getFirstLocalMemberName(previousDeclaration); if (ignoreCase) { previousLocalMemberName = previousLocalMemberName && previousLocalMemberName.toLowerCase(); @@ -141,7 +141,7 @@ module.exports = { let previousSpecifierName = null; for (let i = 0; i < node.specifiers.length; ++i) { - let currentSpecifier = node.specifiers[i]; + const currentSpecifier = node.specifiers[i]; if (currentSpecifier.type !== "ImportSpecifier") { continue; diff --git a/tools/eslint/lib/rules/sort-keys.js b/tools/eslint/lib/rules/sort-keys.js new file mode 100644 index 0000000000..1c8a97b1d0 --- /dev/null +++ b/tools/eslint/lib/rules/sort-keys.js @@ -0,0 +1,153 @@ +/** + * @fileoverview Rule to requires object keys to be sorted + * @author Toru Nagashima + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"), + naturalCompare = require("natural-compare"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Gets the property name of the given `Property` node. + * + * - If the property's key is an `Identifier` node, this returns the key's name + * whether it's a computed property or not. + * - If the property has a static name, this returns the static name. + * - Otherwise, this returns null. + * + * @param {ASTNode} node - The `Property` node to get. + * @returns {string|null} The property name or null. + * @private + */ +function getPropertyName(node) { + return astUtils.getStaticPropertyName(node) || node.key.name || null; +} + +/** + * Functions which check that the given 2 names are in specific order. + * + * Postfix `I` is meant insensitive. + * Postfix `N` is meant natual. + * + * @private + */ +const isValidOrders = { + asc(a, b) { + return a <= b; + }, + ascI(a, b) { + return a.toLowerCase() <= b.toLowerCase(); + }, + ascN(a, b) { + return naturalCompare(a, b) <= 0; + }, + ascIN(a, b) { + return naturalCompare(a.toLowerCase(), b.toLowerCase()) <= 0; + }, + desc(a, b) { + return isValidOrders.asc(b, a); + }, + descI(a, b) { + return isValidOrders.ascI(b, a); + }, + descN(a, b) { + return isValidOrders.ascN(b, a); + }, + descIN(a, b) { + return isValidOrders.ascIN(b, a); + }, +}; + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "requires object keys to be sorted", + category: "Stylistic Issues", + recommended: false + }, + schema: [ + { + enum: ["asc", "desc"] + }, + { + type: "object", + properties: { + caseSensitive: { + type: "boolean" + }, + natural: { + type: "boolean" + } + }, + additionalProperties: false + } + ] + }, + + create: function(context) { + + // Parse options. + const order = context.options[0] || "asc"; + const options = context.options[1]; + const insensitive = (options && options.caseSensitive) === false; + const natual = Boolean(options && options.natural); + const isValidOrder = isValidOrders[ + order + (insensitive ? "I" : "") + (natual ? "N" : "") + ]; + + // The stack to save the previous property's name for each object literals. + let stack = null; + + return { + ObjectExpression() { + stack = { + upper: stack, + prevName: null + }; + }, + + "ObjectExpression:exit"() { + stack = stack.upper; + }, + + Property(node) { + const prevName = stack.prevName; + const thisName = getPropertyName(node); + + stack.prevName = thisName || prevName; + + if (!prevName || !thisName) { + return; + } + + if (!isValidOrder(prevName, thisName)) { + context.report({ + node: node, + loc: node.key.loc, + message: "Expected object keys to be in {{natual}}{{insensitive}}{{order}}ending order. '{{thisName}}' should be before '{{prevName}}'.", + data: { + thisName, + prevName, + order, + insensitive: insensitive ? "insensitive " : "", + natual: natual ? "natural " : "", + } + }); + } + } + }; + } +}; diff --git a/tools/eslint/lib/rules/sort-vars.js b/tools/eslint/lib/rules/sort-vars.js index 4b8187f36a..02711b53ed 100644 --- a/tools/eslint/lib/rules/sort-vars.js +++ b/tools/eslint/lib/rules/sort-vars.js @@ -32,7 +32,7 @@ module.exports = { create: function(context) { - let configuration = context.options[0] || {}, + const configuration = context.options[0] || {}, ignoreCase = configuration.ignoreCase || false; return { diff --git a/tools/eslint/lib/rules/space-before-blocks.js b/tools/eslint/lib/rules/space-before-blocks.js index b695e7ac12..b3dac2ff74 100644 --- a/tools/eslint/lib/rules/space-before-blocks.js +++ b/tools/eslint/lib/rules/space-before-blocks.js @@ -5,7 +5,7 @@ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -48,9 +48,9 @@ module.exports = { }, create: function(context) { - let config = context.options[0], - sourceCode = context.getSourceCode(), - checkFunctions = true, + const config = context.options[0], + sourceCode = context.getSourceCode(); + let checkFunctions = true, checkKeywords = true, checkClasses = true; @@ -81,14 +81,13 @@ module.exports = { * @returns {void} undefined. */ function checkPrecedingSpace(node) { - let precedingToken = sourceCode.getTokenBefore(node), - hasSpace, - parent, - requireSpace; + const precedingToken = sourceCode.getTokenBefore(node); + let requireSpace; if (precedingToken && !isConflicted(precedingToken) && astUtils.isTokenOnSameLine(precedingToken, node)) { - hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node); - parent = context.getAncestors().pop(); + const hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node); + const parent = context.getAncestors().pop(); + if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") { requireSpace = checkFunctions; } else if (node.type === "ClassBody") { @@ -127,13 +126,11 @@ module.exports = { * @returns {void} undefined. */ function checkSpaceBeforeCaseBlock(node) { - let cases = node.cases, - firstCase, - openingBrace; + const cases = node.cases; + let openingBrace; if (cases.length > 0) { - firstCase = cases[0]; - openingBrace = sourceCode.getTokenBefore(firstCase); + openingBrace = sourceCode.getTokenBefore(cases[0]); } else { openingBrace = sourceCode.getLastToken(node, 1); } diff --git a/tools/eslint/lib/rules/space-before-function-paren.js b/tools/eslint/lib/rules/space-before-function-paren.js index b43d11ed13..7d7183adb8 100644 --- a/tools/eslint/lib/rules/space-before-function-paren.js +++ b/tools/eslint/lib/rules/space-before-function-paren.js @@ -43,9 +43,9 @@ module.exports = { create: function(context) { - let configuration = context.options[0], - sourceCode = context.getSourceCode(), - requireAnonymousFunctionSpacing = true, + const configuration = context.options[0], + sourceCode = context.getSourceCode(); + let requireAnonymousFunctionSpacing = true, forbidAnonymousFunctionSpacing = false, requireNamedFunctionSpacing = true, forbidNamedFunctionSpacing = false; @@ -70,13 +70,12 @@ module.exports = { * @returns {boolean} Whether the function has a name. */ function isNamedFunction(node) { - let parent; - if (node.id) { return true; } - parent = node.parent; + const parent = node.parent; + return parent.type === "MethodDefinition" || (parent.type === "Property" && ( @@ -93,10 +92,8 @@ module.exports = { * @returns {void} */ function validateSpacingBeforeParentheses(node) { - let isNamed = isNamedFunction(node), - leftToken, - rightToken, - location; + const isNamed = isNamedFunction(node); + let rightToken; if (node.generator && !isNamed) { return; @@ -106,8 +103,8 @@ module.exports = { while (rightToken.value !== "(") { rightToken = sourceCode.getTokenAfter(rightToken); } - leftToken = sourceCode.getTokenBefore(rightToken); - location = leftToken.loc.end; + const leftToken = sourceCode.getTokenBefore(rightToken); + const location = leftToken.loc.end; if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken)) { if ((isNamed && forbidNamedFunctionSpacing) || (!isNamed && forbidAnonymousFunctionSpacing)) { diff --git a/tools/eslint/lib/rules/space-in-parens.js b/tools/eslint/lib/rules/space-in-parens.js index bd8c6eb3af..7c913d673d 100644 --- a/tools/eslint/lib/rules/space-in-parens.js +++ b/tools/eslint/lib/rules/space-in-parens.js @@ -4,7 +4,7 @@ */ "use strict"; -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Rule Definition @@ -42,13 +42,13 @@ module.exports = { create: function(context) { - let MISSING_SPACE_MESSAGE = "There must be a space inside this paren.", + const MISSING_SPACE_MESSAGE = "There must be a space inside this paren.", REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.", ALWAYS = context.options[0] === "always", exceptionsArrayOptions = (context.options.length === 2) ? context.options[1].exceptions : [], - options = {}, - exceptions; + options = {}; + let exceptions; if (exceptionsArrayOptions.length) { options.braceException = exceptionsArrayOptions.indexOf("{}") !== -1; @@ -64,7 +64,7 @@ module.exports = { * @private */ function getExceptions() { - let openers = [], + const openers = [], closers = []; if (options.braceException) { @@ -96,7 +96,7 @@ module.exports = { //-------------------------------------------------------------------------- // Helpers //-------------------------------------------------------------------------- - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Determines if a token is one of the exceptions for the opener paren @@ -217,14 +217,12 @@ module.exports = { return { Program: function checkParenSpaces(node) { - let tokens, prevToken, nextToken; - exceptions = getExceptions(); - tokens = sourceCode.tokensAndComments; + const tokens = sourceCode.tokensAndComments; tokens.forEach(function(token, i) { - prevToken = tokens[i - 1]; - nextToken = tokens[i + 1]; + const prevToken = tokens[i - 1]; + const nextToken = tokens[i + 1]; if (token.type !== "Punctuator") { return; diff --git a/tools/eslint/lib/rules/space-infix-ops.js b/tools/eslint/lib/rules/space-infix-ops.js index 9f5b08773a..88c12b439d 100644 --- a/tools/eslint/lib/rules/space-infix-ops.js +++ b/tools/eslint/lib/rules/space-infix-ops.js @@ -32,16 +32,16 @@ module.exports = { }, create: function(context) { - let int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; + const int32Hint = context.options[0] ? context.options[0].int32Hint === true : false; - let OPERATORS = [ + const OPERATORS = [ "*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in", "instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", "?", ":", ",", "**" ]; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Returns the first token which violates the rule @@ -51,11 +51,11 @@ module.exports = { * @private */ function getFirstNonSpacedToken(left, right) { - let op, - tokens = sourceCode.getTokensBetween(left, right, 1); + const tokens = sourceCode.getTokensBetween(left, right, 1); for (let i = 1, l = tokens.length - 1; i < l; ++i) { - op = tokens[i]; + const op = tokens[i]; + if ( op.type === "Punctuator" && OPERATORS.indexOf(op.value) >= 0 && @@ -80,8 +80,8 @@ module.exports = { loc: culpritToken.loc.start, message: "Infix operators must be spaced.", fix: function(fixer) { - let previousToken = sourceCode.getTokenBefore(culpritToken); - let afterToken = sourceCode.getTokenAfter(culpritToken); + const previousToken = sourceCode.getTokenBefore(culpritToken); + const afterToken = sourceCode.getTokenAfter(culpritToken); let fixString = ""; if (culpritToken.range[0] - previousToken.range[1] === 0) { @@ -110,7 +110,7 @@ module.exports = { return; } - let nonSpacedNode = getFirstNonSpacedToken(node.left, node.right); + const nonSpacedNode = getFirstNonSpacedToken(node.left, node.right); if (nonSpacedNode) { if (!(int32Hint && sourceCode.getText(node).substr(-2) === "|0")) { @@ -126,8 +126,8 @@ module.exports = { * @private */ function checkConditional(node) { - let nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent); - let nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate); + const nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent); + const nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate); if (nonSpacedConsequesntNode) { report(node, nonSpacedConsequesntNode); @@ -143,10 +143,9 @@ module.exports = { * @private */ function checkVar(node) { - let nonSpacedNode; - if (node.init) { - nonSpacedNode = getFirstNonSpacedToken(node.id, node.init); + const nonSpacedNode = getFirstNonSpacedToken(node.id, node.init); + if (nonSpacedNode) { report(node, nonSpacedNode); } diff --git a/tools/eslint/lib/rules/space-unary-ops.js b/tools/eslint/lib/rules/space-unary-ops.js index 77a98150b8..c5d66e65af 100644 --- a/tools/eslint/lib/rules/space-unary-ops.js +++ b/tools/eslint/lib/rules/space-unary-ops.js @@ -41,9 +41,9 @@ module.exports = { }, create: function(context) { - let options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false }; + const options = context.options && Array.isArray(context.options) && context.options[0] || { words: true, nonwords: false }; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); //-------------------------------------------------------------------------- // Helpers @@ -160,7 +160,7 @@ module.exports = { * @returns {void} */ function checkForSpacesAfterYield(node) { - let tokens = sourceCode.getFirstTokens(node, 3), + const tokens = sourceCode.getFirstTokens(node, 3), word = "yield"; if (!node.argument || node.delegate) { @@ -241,7 +241,7 @@ module.exports = { * @returns {void} */ function checkForSpaces(node) { - let tokens = sourceCode.getFirstTokens(node, 2), + const tokens = sourceCode.getFirstTokens(node, 2), firstToken = tokens[0], secondToken = tokens[1]; @@ -250,7 +250,7 @@ module.exports = { return; } - let operator = node.prefix ? tokens[0].value : tokens[1].value; + const operator = node.prefix ? tokens[0].value : tokens[1].value; if (overrideExistsForOperator(node, operator)) { if (overrideEnforcesSpaces(node, operator)) { diff --git a/tools/eslint/lib/rules/spaced-comment.js b/tools/eslint/lib/rules/spaced-comment.js index 7141ba1f42..666604df15 100644 --- a/tools/eslint/lib/rules/spaced-comment.js +++ b/tools/eslint/lib/rules/spaced-comment.js @@ -4,7 +4,7 @@ */ "use strict"; -let lodash = require("lodash"); +const lodash = require("lodash"); //------------------------------------------------------------------------------ // Helpers @@ -16,7 +16,7 @@ let lodash = require("lodash"); * @returns {string} An escaped string. */ function escape(s) { - let isOneChar = s.length === 1; + const isOneChar = s.length === 1; s = lodash.escapeRegExp(s); return isOneChar ? s : "(?:" + s + ")"; @@ -144,7 +144,7 @@ function createAlwaysStylePattern(markers, exceptions) { * @returns {RegExp} A RegExp object for `never` mode. */ function createNeverStylePattern(markers) { - let pattern = "^(" + markers.map(escape).join("|") + ")?[ \t]+"; + const pattern = "^(" + markers.map(escape).join("|") + ")?[ \t]+"; return new RegExp(pattern); } @@ -230,20 +230,20 @@ module.exports = { create: function(context) { // Unless the first option is never, require a space - let requireSpace = context.options[0] !== "never"; + const requireSpace = context.options[0] !== "never"; /* * Parse the second options. * If markers don't include `"*"`, it's added automatically for JSDoc * comments. */ - let config = context.options[1] || {}; - let balanced = config.block && config.block.balanced; + const config = context.options[1] || {}; + const balanced = config.block && config.block.balanced; - let styleRules = ["block", "line"].reduce(function(rule, type) { - let markers = parseMarkersOption(config[type] && config[type].markers || config.markers); - let exceptions = config[type] && config[type].exceptions || config.exceptions || []; - let endNeverPattern = "[ \t]+$"; + const styleRules = ["block", "line"].reduce(function(rule, type) { + const markers = parseMarkersOption(config[type] && config[type].markers || config.markers); + const exceptions = config[type] && config[type].exceptions || config.exceptions || []; + const endNeverPattern = "[ \t]+$"; // Create RegExp object for valid patterns. rule[type] = { @@ -264,14 +264,14 @@ module.exports = { * @returns {void} */ function reportBegin(node, message, match) { - let type = node.type.toLowerCase(), + const type = node.type.toLowerCase(), commentIdentifier = type === "block" ? "/*" : "//"; context.report({ node: node, fix: function(fixer) { - let start = node.range[0], - end = start + 2; + const start = node.range[0]; + let end = start + 2; if (requireSpace) { if (match) { @@ -301,7 +301,7 @@ module.exports = { if (requireSpace) { return fixer.insertTextAfterRange([node.start, node.end - 2], " "); } else { - let end = node.end - 2, + const end = node.end - 2, start = end - match[0].length; return fixer.replaceTextRange([start, end], ""); @@ -317,7 +317,7 @@ module.exports = { * @returns {void} */ function checkCommentForSpace(node) { - let type = node.type.toLowerCase(), + const type = node.type.toLowerCase(), rule = styleRules[type], commentIdentifier = type === "block" ? "/*" : "//"; @@ -326,14 +326,14 @@ module.exports = { return; } - let beginMatch = rule.beginRegex.exec(node.value); - let endMatch = rule.endRegex.exec(node.value); + const beginMatch = rule.beginRegex.exec(node.value); + const endMatch = rule.endRegex.exec(node.value); // Checks. if (requireSpace) { if (!beginMatch) { - let hasMarker = rule.markers.exec(node.value); - let marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier; + const hasMarker = rule.markers.exec(node.value); + const marker = hasMarker ? commentIdentifier + hasMarker[0] : commentIdentifier; if (rule.hasExceptions) { reportBegin(node, "Expected exception block, space or tab after '" + marker + "' in comment.", hasMarker); diff --git a/tools/eslint/lib/rules/strict.js b/tools/eslint/lib/rules/strict.js index 5f54b15e79..8c9ff05ce6 100644 --- a/tools/eslint/lib/rules/strict.js +++ b/tools/eslint/lib/rules/strict.js @@ -9,13 +9,11 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"); - //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let messages = { +const messages = { function: "Use the function form of 'use strict'.", global: "Use the global form of 'use strict'.", multiple: "Multiple 'use strict' directives.", @@ -35,11 +33,10 @@ let messages = { * @returns {ASTNode[]} All of the Use Strict Directives. */ function getUseStrictDirectives(statements) { - let directives = [], - i, statement; + const directives = []; - for (i = 0; i < statements.length; i++) { - statement = statements[i]; + for (let i = 0; i < statements.length; i++) { + const statement = statements[i]; if ( statement.type === "ExpressionStatement" && @@ -96,11 +93,10 @@ module.exports = { create: function(context) { - let mode = context.options[0] || "safe", - ecmaFeatures = context.parserOptions.ecmaFeatures || {}, + const ecmaFeatures = context.parserOptions.ecmaFeatures || {}, scopes = [], - classScopes = [], - rule; + classScopes = []; + let mode = context.options[0] || "safe"; if (ecmaFeatures.impliedStrict) { mode = "implied"; @@ -152,7 +148,7 @@ module.exports = { * @returns {void} */ function enterFunctionInFunctionMode(node, useStrictDirectives) { - let isInClass = classScopes.length > 0, + const isInClass = classScopes.length > 0, isParentGlobal = scopes.length === 0 && classScopes.length === 0, isParentStrict = scopes.length > 0 && scopes[scopes.length - 1], isStrict = useStrictDirectives.length > 0; @@ -194,7 +190,7 @@ module.exports = { * @returns {void} */ function enterFunction(node) { - let isBlock = node.body.type === "BlockStatement", + const isBlock = node.body.type === "BlockStatement", useStrictDirectives = isBlock ? getUseStrictDirectives(node.body.body) : []; @@ -210,9 +206,9 @@ module.exports = { } } - rule = { + const rule = { Program: function(node) { - let useStrictDirectives = getUseStrictDirectives(node.body); + const useStrictDirectives = getUseStrictDirectives(node.body); if (node.sourceType === "module") { mode = "module"; @@ -233,7 +229,7 @@ module.exports = { }; if (mode === "function") { - lodash.assign(rule, { + Object.assign(rule, { // Inside of class bodies are always strict mode. ClassBody: function() { diff --git a/tools/eslint/lib/rules/template-curly-spacing.js b/tools/eslint/lib/rules/template-curly-spacing.js index 36c33e5330..fb918ea4db 100644 --- a/tools/eslint/lib/rules/template-curly-spacing.js +++ b/tools/eslint/lib/rules/template-curly-spacing.js @@ -9,14 +9,14 @@ // Requirements //------------------------------------------------------------------------------ -let astUtils = require("../ast-utils"); +const astUtils = require("../ast-utils"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let OPEN_PAREN = /\$\{$/; -let CLOSE_PAREN = /^\}/; +const OPEN_PAREN = /\$\{$/; +const CLOSE_PAREN = /^\}/; //------------------------------------------------------------------------------ // Rule Definition @@ -38,9 +38,9 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); - let always = context.options[0] === "always"; - let prefix = always ? "Expected" : "Unexpected"; + const sourceCode = context.getSourceCode(); + const always = context.options[0] === "always"; + const prefix = always ? "Expected" : "Unexpected"; /** * Checks spacing before `}` of a given token. @@ -48,7 +48,7 @@ module.exports = { * @returns {void} */ function checkSpacingBefore(token) { - let prevToken = sourceCode.getTokenBefore(token); + const prevToken = sourceCode.getTokenBefore(token); if (prevToken && CLOSE_PAREN.test(token.value) && @@ -77,7 +77,7 @@ module.exports = { * @returns {void} */ function checkSpacingAfter(token) { - let nextToken = sourceCode.getTokenAfter(token); + const nextToken = sourceCode.getTokenAfter(token); if (nextToken && OPEN_PAREN.test(token.value) && @@ -105,7 +105,7 @@ module.exports = { return { TemplateElement: function(node) { - let token = sourceCode.getFirstToken(node); + const token = sourceCode.getFirstToken(node); checkSpacingBefore(token); checkSpacingAfter(token); diff --git a/tools/eslint/lib/rules/unicode-bom.js b/tools/eslint/lib/rules/unicode-bom.js index 931d840b55..d7f38a2dcb 100644 --- a/tools/eslint/lib/rules/unicode-bom.js +++ b/tools/eslint/lib/rules/unicode-bom.js @@ -35,7 +35,7 @@ module.exports = { Program: function checkUnicodeBOM(node) { - let sourceCode = context.getSourceCode(), + const sourceCode = context.getSourceCode(), location = {column: 0, line: 1}, requireBOM = context.options[0] || "never"; diff --git a/tools/eslint/lib/rules/valid-jsdoc.js b/tools/eslint/lib/rules/valid-jsdoc.js index 8af117e30e..d9575fa7ef 100644 --- a/tools/eslint/lib/rules/valid-jsdoc.js +++ b/tools/eslint/lib/rules/valid-jsdoc.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let doctrine = require("doctrine"); +const doctrine = require("doctrine"); //------------------------------------------------------------------------------ // Rule Definition @@ -61,7 +61,7 @@ module.exports = { create: function(context) { - let options = context.options[0] || {}, + const options = context.options[0] || {}, prefer = options.prefer || {}, sourceCode = context.getSourceCode(), @@ -78,7 +78,7 @@ module.exports = { //-------------------------------------------------------------------------- // Using a stack to store if a function returns or not (handling nested functions) - let fns = []; + const fns = []; /** * Check if node type is a Class @@ -110,7 +110,7 @@ module.exports = { * @private */ function addReturn(node) { - let functionState = fns[fns.length - 1]; + const functionState = fns[fns.length - 1]; if (functionState && node.argument !== null) { functionState.returnPresent = true; @@ -149,7 +149,6 @@ module.exports = { */ function getCurrentExpectedTypes(type) { let currentType; - let expectedType; if (type.name) { currentType = type.name; @@ -157,7 +156,7 @@ module.exports = { currentType = type.expression.name; } - expectedType = currentType && preferType[currentType]; + const expectedType = currentType && preferType[currentType]; return { currentType: currentType, @@ -177,7 +176,7 @@ module.exports = { return; } - let typesToCheck = []; + const typesToCheck = []; let elements = []; switch (type.type) { @@ -223,14 +222,14 @@ module.exports = { * @private */ function checkJSDoc(node) { - let jsdocNode = sourceCode.getJSDocComment(node), + const jsdocNode = sourceCode.getJSDocComment(node), functionData = fns.pop(), - hasReturns = false, + params = Object.create(null); + let hasReturns = false, hasConstructor = false, isInterface = false, isOverride = false, isAbstract = false, - params = Object.create(null), jsdoc; // make sure only to validate JSDoc comments @@ -336,7 +335,7 @@ module.exports = { } // check the parameters - let jsdocParams = Object.keys(params); + const jsdocParams = Object.keys(params); if (node.params) { node.params.forEach(function(param, i) { @@ -344,7 +343,7 @@ module.exports = { param = param.left; } - let name = param.name; + const name = param.name; // TODO(nzakas): Figure out logical things to do with destructured, default, rest params if (param.type === "Identifier") { @@ -363,7 +362,7 @@ module.exports = { } if (options.matchDescription) { - let regex = new RegExp(options.matchDescription); + const regex = new RegExp(options.matchDescription); if (!regex.test(jsdoc.description)) { context.report(jsdocNode, "JSDoc description does not satisfy the regex pattern."); diff --git a/tools/eslint/lib/rules/valid-typeof.js b/tools/eslint/lib/rules/valid-typeof.js index dc378d9401..532088b970 100644 --- a/tools/eslint/lib/rules/valid-typeof.js +++ b/tools/eslint/lib/rules/valid-typeof.js @@ -21,7 +21,7 @@ module.exports = { create: function(context) { - let VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"], + const VALID_TYPES = ["symbol", "undefined", "object", "boolean", "number", "string", "function"], OPERATORS = ["==", "===", "!=", "!=="]; //-------------------------------------------------------------------------- @@ -31,13 +31,11 @@ module.exports = { return { UnaryExpression: function(node) { - let parent, sibling; - if (node.operator === "typeof") { - parent = context.getAncestors().pop(); + const parent = context.getAncestors().pop(); if (parent.type === "BinaryExpression" && OPERATORS.indexOf(parent.operator) !== -1) { - sibling = parent.left === node ? parent.right : parent.left; + const sibling = parent.left === node ? parent.right : parent.left; if (sibling.type === "Literal" && VALID_TYPES.indexOf(sibling.value) === -1) { context.report(sibling, "Invalid typeof comparison value."); diff --git a/tools/eslint/lib/rules/vars-on-top.js b/tools/eslint/lib/rules/vars-on-top.js index e94e487559..43703f144f 100644 --- a/tools/eslint/lib/rules/vars-on-top.js +++ b/tools/eslint/lib/rules/vars-on-top.js @@ -21,7 +21,7 @@ module.exports = { }, create: function(context) { - let errorMessage = "All 'var' declarations must be at the top of the function scope."; + const errorMessage = "All 'var' declarations must be at the top of the function scope."; //-------------------------------------------------------------------------- // Helpers @@ -70,8 +70,8 @@ module.exports = { * @returns {boolean} True if var is on top otherwise false */ function isVarOnTop(node, statements) { - let i = 0, - l = statements.length; + const l = statements.length; + let i = 0; // skip over directives for (; i < l; ++i) { @@ -125,7 +125,7 @@ module.exports = { return { VariableDeclaration: function(node) { - let ancestors = context.getAncestors(); + const ancestors = context.getAncestors(); let parent = ancestors.pop(); let grandParent = ancestors.pop(); diff --git a/tools/eslint/lib/rules/wrap-iife.js b/tools/eslint/lib/rules/wrap-iife.js index 78554091c9..66275a2e71 100644 --- a/tools/eslint/lib/rules/wrap-iife.js +++ b/tools/eslint/lib/rules/wrap-iife.js @@ -26,9 +26,9 @@ module.exports = { create: function(context) { - let style = context.options[0] || "outside"; + const style = context.options[0] || "outside"; - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Check if the node is wrapped in () @@ -37,7 +37,7 @@ module.exports = { * @private */ function wrapped(node) { - let previousToken = sourceCode.getTokenBefore(node), + const previousToken = sourceCode.getTokenBefore(node), nextToken = sourceCode.getTokenAfter(node); return previousToken && previousToken.value === "(" && @@ -48,7 +48,7 @@ module.exports = { CallExpression: function(node) { if (node.callee.type === "FunctionExpression") { - let callExpressionWrapped = wrapped(node), + const callExpressionWrapped = wrapped(node), functionExpressionWrapped = wrapped(node.callee); if (!callExpressionWrapped && !functionExpressionWrapped) { diff --git a/tools/eslint/lib/rules/wrap-regex.js b/tools/eslint/lib/rules/wrap-regex.js index 44750a3fbd..a309d9ae1d 100644 --- a/tools/eslint/lib/rules/wrap-regex.js +++ b/tools/eslint/lib/rules/wrap-regex.js @@ -21,21 +21,18 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); return { Literal: function(node) { - let token = sourceCode.getFirstToken(node), - nodeType = token.type, - source, - grandparent, - ancestors; + const token = sourceCode.getFirstToken(node), + nodeType = token.type; if (nodeType === "RegularExpression") { - source = sourceCode.getTokenBefore(node); - ancestors = context.getAncestors(); - grandparent = ancestors[ancestors.length - 1]; + const source = sourceCode.getTokenBefore(node); + const ancestors = context.getAncestors(); + const grandparent = ancestors[ancestors.length - 1]; if (grandparent.type === "MemberExpression" && grandparent.object === node && (!source || source.value !== "(")) { diff --git a/tools/eslint/lib/rules/yield-star-spacing.js b/tools/eslint/lib/rules/yield-star-spacing.js index c9ca64e0c2..6566fc7d4d 100644 --- a/tools/eslint/lib/rules/yield-star-spacing.js +++ b/tools/eslint/lib/rules/yield-star-spacing.js @@ -39,9 +39,9 @@ module.exports = { }, create: function(context) { - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); - let mode = (function(option) { + const mode = (function(option) { if (!option || typeof option === "string") { return { before: { before: true, after: false }, @@ -64,11 +64,11 @@ module.exports = { */ function checkSpacing(side, leftToken, rightToken) { if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken) !== mode[side]) { - let after = leftToken.value === "*"; - let spaceRequired = mode[side]; - let node = after ? leftToken : rightToken; - let type = spaceRequired ? "Missing" : "Unexpected"; - let message = type + " space " + side + " *."; + const after = leftToken.value === "*"; + const spaceRequired = mode[side]; + const node = after ? leftToken : rightToken; + const type = spaceRequired ? "Missing" : "Unexpected"; + const message = type + " space " + side + " *."; context.report({ node: node, @@ -96,10 +96,10 @@ module.exports = { return; } - let tokens = sourceCode.getFirstTokens(node, 3); - let yieldToken = tokens[0]; - let starToken = tokens[1]; - let nextToken = tokens[2]; + const tokens = sourceCode.getFirstTokens(node, 3); + const yieldToken = tokens[0]; + const starToken = tokens[1]; + const nextToken = tokens[2]; checkSpacing("before", yieldToken, starToken); checkSpacing("after", starToken, nextToken); diff --git a/tools/eslint/lib/rules/yoda.js b/tools/eslint/lib/rules/yoda.js index 29f0602b98..cb8cee5e64 100644 --- a/tools/eslint/lib/rules/yoda.js +++ b/tools/eslint/lib/rules/yoda.js @@ -147,11 +147,11 @@ module.exports = { create: function(context) { // Default to "never" (!always) if no option - let always = (context.options[0] === "always"); - let exceptRange = (context.options[1] && context.options[1].exceptRange); - let onlyEquality = (context.options[1] && context.options[1].onlyEquality); + const always = (context.options[0] === "always"); + const exceptRange = (context.options[1] && context.options[1].exceptRange); + const onlyEquality = (context.options[1] && context.options[1].onlyEquality); - let sourceCode = context.getSourceCode(); + const sourceCode = context.getSourceCode(); /** * Determines whether node represents a range test. @@ -164,7 +164,7 @@ module.exports = { * @returns {boolean} Whether node is a range test. */ function isRangeTest(node) { - let left = node.left, + const left = node.left, right = node.right; /** diff --git a/tools/eslint/lib/testers/event-generator-tester.js b/tools/eslint/lib/testers/event-generator-tester.js index f77152c0bb..e4179bfb86 100644 --- a/tools/eslint/lib/testers/event-generator-tester.js +++ b/tools/eslint/lib/testers/event-generator-tester.js @@ -10,7 +10,7 @@ // Requirements //------------------------------------------------------------------------------ -let assert = require("assert"); +const assert = require("assert"); //------------------------------------------------------------------------------ // Public Interface diff --git a/tools/eslint/lib/testers/rule-tester.js b/tools/eslint/lib/testers/rule-tester.js index 703129ca05..ebf4beff79 100644 --- a/tools/eslint/lib/testers/rule-tester.js +++ b/tools/eslint/lib/testers/rule-tester.js @@ -40,7 +40,7 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), +const lodash = require("lodash"), assert = require("assert"), util = require("util"), validator = require("../config/config-validator"), @@ -58,14 +58,14 @@ let lodash = require("lodash"), * testerDefaultConfig must not be modified as it allows to reset the tester to * the initial default configuration */ -let testerDefaultConfig = { rules: {} }; +const testerDefaultConfig = { rules: {} }; let defaultConfig = { rules: {} }; /* * List every parameters possible on a test case that are not related to eslint * configuration */ -let RuleTesterParameters = [ +const RuleTesterParameters = [ "code", "filename", "options", @@ -73,9 +73,9 @@ let RuleTesterParameters = [ "errors" ]; -let validateSchema = validate(metaSchema, { verbose: true }); +const validateSchema = validate(metaSchema, { verbose: true }); -let hasOwnProperty = Function.call.bind(Object.hasOwnProperty); +const hasOwnProperty = Function.call.bind(Object.hasOwnProperty); /** * Clones a given value deeply. @@ -90,9 +90,9 @@ function cloneDeeplyExcludesParent(x) { return x.map(cloneDeeplyExcludesParent); } - let retv = {}; + const retv = {}; - for (let key in x) { + for (const key in x) { if (key !== "parent" && hasOwnProperty(x, key)) { retv[key] = cloneDeeplyExcludesParent(x[key]); } @@ -115,7 +115,7 @@ function freezeDeeply(x) { if (Array.isArray(x)) { x.forEach(freezeDeeply); } else { - for (let key in x) { + for (const key in x) { if (key !== "parent" && hasOwnProperty(x, key)) { freezeDeeply(x[key]); } @@ -211,7 +211,7 @@ RuleTester.prototype = { */ run: function(ruleName, rule, test) { - let testerConfig = this.testerConfig, + const testerConfig = this.testerConfig, result = {}; /* eslint-disable no-shadow */ @@ -225,7 +225,7 @@ RuleTester.prototype = { */ function runRuleForItem(ruleName, item) { let config = lodash.cloneDeep(testerConfig), - code, filename, schema, beforeAST, afterAST; + code, filename, beforeAST, afterAST; if (typeof item === "string") { code = item; @@ -234,7 +234,7 @@ RuleTester.prototype = { // Assumes everything on the item is a config except for the // parameters used by this tester - let itemConfig = lodash.omit(item, RuleTesterParameters); + const itemConfig = lodash.omit(item, RuleTesterParameters); // Create the config object from the tester config and this item // specific configurations. @@ -249,7 +249,7 @@ RuleTester.prototype = { } if (item.options) { - let options = item.options.concat(); + const options = item.options.concat(); options.unshift(1); config.rules[ruleName] = options; @@ -259,7 +259,7 @@ RuleTester.prototype = { eslint.defineRule(ruleName, rule); - schema = validator.getRuleOptionsSchema(ruleName); + const schema = validator.getRuleOptionsSchema(ruleName); if (schema) { validateSchema(schema); @@ -290,11 +290,11 @@ RuleTester.prototype = { }); // Freezes rule-context properties. - let originalGet = rules.get; + const originalGet = rules.get; try { rules.get = function(ruleId) { - let rule = originalGet(ruleId); + const rule = originalGet(ruleId); if (typeof rule === "function") { return function(context) { @@ -354,8 +354,8 @@ RuleTester.prototype = { * @private */ function testValidTemplate(ruleName, item) { - let result = runRuleForItem(ruleName, item); - let messages = result.messages; + const result = runRuleForItem(ruleName, item); + const messages = result.messages; assert.equal(messages.length, 0, util.format("Should have no errors but had %d: %s", messages.length, util.inspect(messages))); @@ -375,8 +375,8 @@ RuleTester.prototype = { assert.ok(item.errors || item.errors === 0, "Did not specify errors for an invalid test of " + ruleName); - let result = runRuleForItem(ruleName, item); - let messages = result.messages; + const result = runRuleForItem(ruleName, item); + const messages = result.messages; @@ -434,7 +434,7 @@ RuleTester.prototype = { } if (item.hasOwnProperty("output")) { - let fixResult = SourceCodeFixer.applyFixes(eslint.getSourceCode(), messages); + const fixResult = SourceCodeFixer.applyFixes(eslint.getSourceCode(), messages); assert.equal(fixResult.output, item.output, "Output is incorrect."); } diff --git a/tools/eslint/lib/timing.js b/tools/eslint/lib/timing.js index ff0dd7ffb2..19fbefb367 100644 --- a/tools/eslint/lib/timing.js +++ b/tools/eslint/lib/timing.js @@ -39,10 +39,10 @@ function alignRight(str, len, ch) { // Module definition //------------------------------------------------------------------------------ -let enabled = !!process.env.TIMING; +const enabled = !!process.env.TIMING; -let HEADERS = ["Rule", "Time (ms)", "Relative"]; -let ALIGN = [alignLeft, alignRight, alignRight]; +const HEADERS = ["Rule", "Time (ms)", "Relative"]; +const ALIGN = [alignLeft, alignRight, alignRight]; /* istanbul ignore next */ /** @@ -53,9 +53,9 @@ let ALIGN = [alignLeft, alignRight, alignRight]; */ function display(data) { let total = 0; - let rows = Object.keys(data) + const rows = Object.keys(data) .map(function(key) { - let time = data[key]; + const time = data[key]; total += time; return [key, time]; @@ -72,22 +72,21 @@ function display(data) { rows.unshift(HEADERS); - let widths = []; + const widths = []; rows.forEach(function(row) { - let len = row.length, - i, - n; + const len = row.length; + + for (let i = 0; i < len; i++) { + const n = row[i].length; - for (i = 0; i < len; i++) { - n = row[i].length; if (!widths[i] || n > widths[i]) { widths[i] = n; } } }); - let table = rows.map(function(row) { + const table = rows.map(function(row) { return row.map(function(cell, index) { return ALIGN[index](cell, widths[index]); }).join(" | "); @@ -107,7 +106,7 @@ function display(data) { /* istanbul ignore next */ module.exports = (function() { - let data = Object.create(null); + const data = Object.create(null); /** * Time the run diff --git a/tools/eslint/lib/token-store.js b/tools/eslint/lib/token-store.js index 183c7363ec..9cd37cd175 100644 --- a/tools/eslint/lib/token-store.js +++ b/tools/eslint/lib/token-store.js @@ -9,10 +9,10 @@ //------------------------------------------------------------------------------ module.exports = function(tokens) { - let api = {}, + const api = {}, starts = Object.create(null), ends = Object.create(null), - index, length, range; + length = tokens.length; /** * Gets tokens in a given interval. @@ -21,10 +21,9 @@ module.exports = function(tokens) { * @returns {Token[]} Tokens in the interval. */ function get(start, end) { - let result = [], - i; + const result = []; - for (i = Math.max(0, start); i < end && i < length; i++) { + for (let i = Math.max(0, start); i < end && i < length; i++) { result.push(tokens[i]); } @@ -39,8 +38,8 @@ module.exports = function(tokens) { * @returns {int} Index in the tokens array of the node's last token. */ function lastTokenIndex(node) { - let end = node.range[1], - cursor = ends[end]; + const end = node.range[1]; + let cursor = ends[end]; // If the node extends beyond its last token, get the token before the // next token @@ -58,10 +57,11 @@ module.exports = function(tokens) { } // Map tokens' start and end range to the index in the tokens array - for (index = 0, length = tokens.length; index < length; index++) { - range = tokens[index].range; - starts[range[0]] = index; - ends[range[1]] = index; + for (let i = 0; i < length; i++) { + const range = tokens[i].range; + + starts[range[0]] = i; + ends[range[1]] = i; } /** @@ -73,7 +73,7 @@ module.exports = function(tokens) { * @returns {Token[]} Array of objects representing tokens. */ api.getTokensBefore = function(node, beforeCount) { - let first = starts[node.range[0]]; + const first = starts[node.range[0]]; return get(first - (beforeCount || 0), first); }; @@ -98,7 +98,7 @@ module.exports = function(tokens) { * @returns {Token[]} Array of objects representing tokens. */ api.getTokensAfter = function(node, afterCount) { - let start = lastTokenIndex(node) + 1; + const start = lastTokenIndex(node) + 1; return get(start, start + (afterCount || 0)); }; @@ -135,7 +135,7 @@ module.exports = function(tokens) { * @returns {Token[]} Array of objects representing tokens. */ api.getFirstTokens = function(node, count) { - let first = starts[node.range[0]]; + const first = starts[node.range[0]]; return get( first, @@ -160,7 +160,7 @@ module.exports = function(tokens) { * @returns {Token[]} Array of objects representing tokens. */ api.getLastTokens = function(node, count) { - let last = lastTokenIndex(node) + 1; + const last = lastTokenIndex(node) + 1; return get(Math.max(starts[node.range[0]], last - (count || 0)), last); }; diff --git a/tools/eslint/lib/util/comment-event-generator.js b/tools/eslint/lib/util/comment-event-generator.js index 40771790b7..47cc68f296 100644 --- a/tools/eslint/lib/util/comment-event-generator.js +++ b/tools/eslint/lib/util/comment-event-generator.js @@ -21,7 +21,7 @@ function emitComments(comments, emitter, locs, eventName) { if (comments.length > 0) { comments.forEach(function(node) { - let index = locs.indexOf(node.loc); + const index = locs.indexOf(node.loc); if (index >= 0) { locs.splice(index, 1); @@ -91,7 +91,7 @@ CommentEventGenerator.prototype = { * @returns {void} */ enterNode: function enterNode(node) { - let comments = this.sourceCode.getComments(node); + const comments = this.sourceCode.getComments(node); emitCommentsEnter(this, comments.leading); this.original.enterNode(node); @@ -104,7 +104,7 @@ CommentEventGenerator.prototype = { * @returns {void} */ leaveNode: function leaveNode(node) { - let comments = this.sourceCode.getComments(node); + const comments = this.sourceCode.getComments(node); emitCommentsExit(this, comments.trailing); this.original.leaveNode(node); diff --git a/tools/eslint/lib/util/glob-util.js b/tools/eslint/lib/util/glob-util.js index 30784b2bfc..56b871a1bd 100644 --- a/tools/eslint/lib/util/glob-util.js +++ b/tools/eslint/lib/util/glob-util.js @@ -8,8 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let debug = require("debug"), - fs = require("fs"), +const fs = require("fs"), path = require("path"), glob = require("glob"), shell = require("shelljs"), @@ -17,7 +16,7 @@ let debug = require("debug"), pathUtil = require("./path-util"), IgnoredPaths = require("../ignored-paths"); -debug = debug("eslint:glob-util"); +const debug = require("debug")("eslint:glob-util"); //------------------------------------------------------------------------------ // Helpers @@ -41,7 +40,7 @@ debug = debug("eslint:glob-util"); * pathname is a directory. */ function processPath(options) { - let cwd = (options && options.cwd) || process.cwd(); + const cwd = (options && options.cwd) || process.cwd(); let extensions = (options && options.extensions) || [".js"]; extensions = extensions.map(function(ext) { @@ -65,7 +64,7 @@ function processPath(options) { */ return function(pathname) { let newPath = pathname; - let resolvedPath = path.resolve(cwd, pathname); + const resolvedPath = path.resolve(cwd, pathname); if (shell.test("-d", resolvedPath)) { newPath = pathname.replace(/[\/\\]$/, "") + suffix; @@ -87,7 +86,7 @@ function processPath(options) { */ function resolveFileGlobPatterns(patterns, options) { - let processPathExtensions = processPath(options); + const processPathExtensions = processPath(options); return patterns.map(processPathExtensions); } @@ -105,12 +104,18 @@ function resolveFileGlobPatterns(patterns, options) { * @returns {string[]} Resolved absolute filenames. */ function listFilesToProcess(globPatterns, options) { - let ignoredPaths, - files = [], - added = {}, - globOptions; + const files = [], + added = {}; - let cwd = (options && options.cwd) || process.cwd(); + const cwd = (options && options.cwd) || process.cwd(); + + options = options || { ignore: true, dotfiles: true }; + const ignoredPaths = new IgnoredPaths(options); + const globOptions = { + nodir: true, + cwd: cwd, + ignore: ignoredPaths.getIgnoredFoldersGlobPatterns() + }; /** * Executes the linter on a file defined by the `filename`. Skips @@ -150,17 +155,9 @@ function listFilesToProcess(globPatterns, options) { added[filename] = true; } - options = options || { ignore: true, dotfiles: true }; - ignoredPaths = new IgnoredPaths(options); - globOptions = { - nodir: true, - cwd: cwd, - ignore: ignoredPaths.getIgnoredFoldersGlobPatterns() - }; - debug("Creating list of files to process."); globPatterns.forEach(function(pattern) { - let file = path.resolve(cwd, pattern); + const file = path.resolve(cwd, pattern); if (shell.test("-f", file)) { addFile(fs.realpathSync(file), !shell.test("-d", file)); diff --git a/tools/eslint/lib/util/hash.js b/tools/eslint/lib/util/hash.js index 092c56e863..6d7ef8bf1b 100644 --- a/tools/eslint/lib/util/hash.js +++ b/tools/eslint/lib/util/hash.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let murmur = require("imurmurhash"); +const murmur = require("imurmurhash"); //------------------------------------------------------------------------------ // Helpers diff --git a/tools/eslint/lib/util/module-resolver.js b/tools/eslint/lib/util/module-resolver.js index 964988ec6e..3c2ba18879 100644 --- a/tools/eslint/lib/util/module-resolver.js +++ b/tools/eslint/lib/util/module-resolver.js @@ -9,14 +9,13 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), - Module = require("module"); +const Module = require("module"); //------------------------------------------------------------------------------ // Private //------------------------------------------------------------------------------ -let DEFAULT_OPTIONS = { +const DEFAULT_OPTIONS = { /* * module.paths is an array of paths to search for resolving things relative @@ -39,7 +38,7 @@ let DEFAULT_OPTIONS = { function ModuleResolver(options) { options = options || {}; - this.options = lodash.assign({}, DEFAULT_OPTIONS, options); + this.options = Object.assign({}, DEFAULT_OPTIONS, options); } ModuleResolver.prototype = { @@ -60,7 +59,7 @@ ModuleResolver.prototype = { * subsequent calls to this function. Then, move the extraLookupPath to the * top of the lookup paths list so it will be searched first. */ - let lookupPaths = this.options.lookupPaths.concat(); + const lookupPaths = this.options.lookupPaths.concat(); lookupPaths.unshift(extraLookupPath); @@ -69,7 +68,7 @@ ModuleResolver.prototype = { * lookup file paths when require() is called. So, we are hooking into the * exact same logic that Node.js uses. */ - let result = Module._findPath(name, lookupPaths); // eslint-disable-line no-underscore-dangle + const result = Module._findPath(name, lookupPaths); // eslint-disable-line no-underscore-dangle if (!result) { throw new Error("Cannot find module '" + name + "'"); diff --git a/tools/eslint/lib/util/npm-util.js b/tools/eslint/lib/util/npm-util.js index e888f8feb6..e772107e72 100644 --- a/tools/eslint/lib/util/npm-util.js +++ b/tools/eslint/lib/util/npm-util.js @@ -9,7 +9,7 @@ // Requirements //------------------------------------------------------------------------------ -let fs = require("fs"), +const fs = require("fs"), path = require("path"), shell = require("shelljs"), log = require("../logging"); @@ -29,9 +29,9 @@ function findPackageJson(startDir) { let dir = path.resolve(startDir || process.cwd()); do { - let pkgfile = path.join(dir, "package.json"); + const pkgfile = path.join(dir, "package.json"); - if (!fs.existsSync(pkgfile)) { + if (!shell.test("-f", pkgfile)) { dir = path.join(dir, ".."); continue; } @@ -69,7 +69,7 @@ function installSyncSaveDev(packages) { */ function check(packages, opt) { let deps = []; - let pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson(); + const pkgJson = (opt) ? findPackageJson(opt.startDir) : findPackageJson(); let fileJson; if (!pkgJson) { diff --git a/tools/eslint/lib/util/path-util.js b/tools/eslint/lib/util/path-util.js index 8add2064ad..5cec711a58 100644 --- a/tools/eslint/lib/util/path-util.js +++ b/tools/eslint/lib/util/path-util.js @@ -8,7 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let path = require("path"); +const path = require("path"); //------------------------------------------------------------------------------ // Private @@ -21,8 +21,8 @@ let path = require("path"); * @returns {string} Converted filepath */ function convertPathToPosix(filepath) { - let normalizedFilepath = path.normalize(filepath); - let posixFilepath = normalizedFilepath.replace(/\\/g, "/"); + const normalizedFilepath = path.normalize(filepath); + const posixFilepath = normalizedFilepath.replace(/\\/g, "/"); return posixFilepath; } diff --git a/tools/eslint/lib/util/source-code-fixer.js b/tools/eslint/lib/util/source-code-fixer.js index d855edb206..ebba46716d 100644 --- a/tools/eslint/lib/util/source-code-fixer.js +++ b/tools/eslint/lib/util/source-code-fixer.js @@ -8,13 +8,13 @@ // Requirements //------------------------------------------------------------------------------ -let debug = require("debug")("eslint:text-fixer"); +const debug = require("debug")("eslint:text-fixer"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let BOM = "\uFEFF"; +const BOM = "\uFEFF"; /** * Compares items in a messages array by line and column. @@ -24,7 +24,7 @@ let BOM = "\uFEFF"; * @private */ function compareMessagesByLocation(a, b) { - let lineDiff = a.line - b.line; + const lineDiff = a.line - b.line; if (lineDiff === 0) { return a.column - b.column; @@ -66,10 +66,10 @@ SourceCodeFixer.applyFixes = function(sourceCode, messages) { } // clone the array - let remainingMessages = [], + const remainingMessages = [], fixes = [], - text = sourceCode.text, - lastFixPos = text.length + 1, + text = sourceCode.text; + let lastFixPos = text.length + 1, prefix = (sourceCode.hasBOM ? BOM : ""); messages.forEach(function(problem) { @@ -89,12 +89,12 @@ SourceCodeFixer.applyFixes = function(sourceCode, messages) { }); // split into array of characters for easier manipulation - let chars = text.split(""); + const chars = text.split(""); fixes.forEach(function(problem) { - let fix = problem.fix; + const fix = problem.fix; let start = fix.range[0]; - let end = fix.range[1]; + const end = fix.range[1]; let insertionText = fix.text; if (end < lastFixPos) { diff --git a/tools/eslint/lib/util/source-code-util.js b/tools/eslint/lib/util/source-code-util.js index f07f61192b..6139e093bd 100644 --- a/tools/eslint/lib/util/source-code-util.js +++ b/tools/eslint/lib/util/source-code-util.js @@ -9,14 +9,12 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), - debug = require("debug"), - CLIEngine = require("../cli-engine"), +const CLIEngine = require("../cli-engine"), eslint = require("../eslint"), globUtil = require("./glob-util"), - defaultOptions = require("../../conf/cli-options"); + baseDefaultOptions = require("../../conf/cli-options"); -debug = debug("eslint:source-code-util"); +const debug = require("debug")("eslint:source-code-util"); //------------------------------------------------------------------------------ // Helpers @@ -31,16 +29,16 @@ debug = debug("eslint:source-code-util"); */ function getSourceCodeOfFile(filename, options) { debug("getting sourceCode of", filename); - let opts = lodash.assign({}, options, { rules: {}}); - let cli = new CLIEngine(opts); - let results = cli.executeOnFiles([filename]); + const opts = Object.assign({}, options, { rules: {}}); + const cli = new CLIEngine(opts); + const results = cli.executeOnFiles([filename]); if (results && results.results[0] && results.results[0].messages[0] && results.results[0].messages[0].fatal) { - let msg = results.results[0].messages[0]; + const msg = results.results[0].messages[0]; throw new Error("(" + filename + ":" + msg.line + ":" + msg.column + ") " + msg.message); } - let sourceCode = eslint.getSourceCode(); + const sourceCode = eslint.getSourceCode(); return sourceCode; } @@ -66,15 +64,14 @@ function getSourceCodeOfFile(filename, options) { * @returns {Object} The SourceCode of all processed files. */ function getSourceCodeOfFiles(patterns, options, cb) { - let sourceCodes = {}, - filenames, - opts; + const sourceCodes = {}; + let opts; if (typeof patterns === "string") { patterns = [patterns]; } - defaultOptions = lodash.assign({}, defaultOptions, {cwd: process.cwd()}); + const defaultOptions = Object.assign({}, baseDefaultOptions, {cwd: process.cwd()}); if (typeof options === "undefined") { opts = defaultOptions; @@ -82,19 +79,20 @@ function getSourceCodeOfFiles(patterns, options, cb) { cb = options; opts = defaultOptions; } else if (typeof options === "object") { - opts = lodash.assign({}, defaultOptions, options); + opts = Object.assign({}, defaultOptions, options); } debug("constructed options:", opts); patterns = globUtil.resolveFileGlobPatterns(patterns, opts); - filenames = globUtil.listFilesToProcess(patterns, opts).reduce(function(files, fileInfo) { + const filenames = globUtil.listFilesToProcess(patterns, opts).reduce(function(files, fileInfo) { return !fileInfo.ignored ? files.concat(fileInfo.filename) : files; }, []); + if (filenames.length === 0) { debug("Did not find any files matching pattern(s): " + patterns); } filenames.forEach(function(filename) { - let sourceCode = getSourceCodeOfFile(filename, opts); + const sourceCode = getSourceCodeOfFile(filename, opts); if (sourceCode) { debug("got sourceCode of", filename); diff --git a/tools/eslint/lib/util/source-code.js b/tools/eslint/lib/util/source-code.js index b8ed5841cd..557c450410 100644 --- a/tools/eslint/lib/util/source-code.js +++ b/tools/eslint/lib/util/source-code.js @@ -8,8 +8,7 @@ // Requirements //------------------------------------------------------------------------------ -let lodash = require("lodash"), - createTokenStore = require("../token-store.js"), +const createTokenStore = require("../token-store.js"), Traverser = require("./traverser"); //------------------------------------------------------------------------------ @@ -123,13 +122,13 @@ function SourceCode(text, ast) { }); // create token store methods - let tokenStore = createTokenStore(ast.tokens); + const tokenStore = createTokenStore(ast.tokens); Object.keys(tokenStore).forEach(function(methodName) { this[methodName] = tokenStore[methodName]; }, this); - let tokensAndCommentsStore = createTokenStore(this.tokensAndComments); + const tokensAndCommentsStore = createTokenStore(this.tokensAndComments); this.getTokenOrCommentBefore = tokensAndCommentsStore.getTokenBefore; this.getTokenOrCommentAfter = tokensAndCommentsStore.getTokenAfter; @@ -193,8 +192,8 @@ SourceCode.prototype = { */ getComments: function(node) { - let leadingComments = node.leadingComments || [], - trailingComments = node.trailingComments || []; + let leadingComments = node.leadingComments || []; + const trailingComments = node.trailingComments || []; /* * espree adds a "comments" array on Program nodes rather than @@ -262,8 +261,8 @@ SourceCode.prototype = { */ getNodeByRangeIndex: function(index) { let result = null, - resultParent = null, - traverser = new Traverser(); + resultParent = null; + const traverser = new Traverser(); traverser.traverse(this.ast, { enter: function(node, parent) { @@ -281,7 +280,7 @@ SourceCode.prototype = { } }); - return result ? lodash.assign({parent: resultParent}, result) : null; + return result ? Object.assign({parent: resultParent}, result) : null; }, /** @@ -294,7 +293,7 @@ SourceCode.prototype = { * if there is anything other than whitespace between tokens. */ isSpaceBetweenTokens: function(first, second) { - let text = this.text.slice(first.range[1], second.range[0]); + const text = this.text.slice(first.range[1], second.range[0]); return /\s/.test(text.replace(/\/\*.*?\*\//g, "")); } diff --git a/tools/eslint/lib/util/traverser.js b/tools/eslint/lib/util/traverser.js index b68d0993af..50d18b045e 100644 --- a/tools/eslint/lib/util/traverser.js +++ b/tools/eslint/lib/util/traverser.js @@ -8,13 +8,13 @@ // Requirements //------------------------------------------------------------------------------ -let estraverse = require("estraverse"); +const estraverse = require("estraverse"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -let KEY_BLACKLIST = [ +const KEY_BLACKLIST = [ "parent", "leadingComments", "trailingComments" @@ -27,7 +27,7 @@ let KEY_BLACKLIST = [ */ function Traverser() { - let controller = Object.create(new estraverse.Controller()), + const controller = Object.create(new estraverse.Controller()), originalTraverse = controller.traverse; // intercept call to traverse() and add the fallback key to the visitor diff --git a/tools/eslint/node_modules/del/package.json b/tools/eslint/node_modules/del/package.json index 74749f63ff..81e63a265b 100644 --- a/tools/eslint/node_modules/del/package.json +++ b/tools/eslint/node_modules/del/package.json @@ -14,20 +14,20 @@ ] ], "_from": "del@>=2.0.2 <3.0.0", - "_id": "del@2.2.1", + "_id": "del@2.2.2", "_inCache": true, "_installable": true, "_location": "/del", - "_nodeVersion": "4.4.2", + "_nodeVersion": "4.4.5", "_npmOperationalInternal": { - "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/del-2.2.1.tgz_1466503710609_0.6494583815801889" + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/del-2.2.2.tgz_1471046735537_0.4419694794341922" }, "_npmUser": { "name": "sindresorhus", "email": "sindresorhus@gmail.com" }, - "_npmVersion": "2.15.0", + "_npmVersion": "2.15.5", "_phantomChildren": {}, "_requested": { "raw": "del@^2.0.2", @@ -41,8 +41,8 @@ "_requiredBy": [ "/flat-cache" ], - "_resolved": "https://registry.npmjs.org/del/-/del-2.2.1.tgz", - "_shasum": "f6763026472209c4f0349111c5ac280868bec4fe", + "_resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "_shasum": "c12c981d067846c84bcaf862cff930d907ffd1a8", "_shrinkwrap": null, "_spec": "del@^2.0.2", "_where": "/Users/trott/io.js/tools/node_modules/flat-cache", @@ -67,14 +67,14 @@ "devDependencies": { "ava": "*", "fs-extra": "^0.30.0", - "path-exists": "^3.0.0", + "path-exists": "^2.0.0", "tempfile": "^1.1.1", "xo": "*" }, "directories": {}, "dist": { - "shasum": "f6763026472209c4f0349111c5ac280868bec4fe", - "tarball": "https://registry.npmjs.org/del/-/del-2.2.1.tgz" + "shasum": "c12c981d067846c84bcaf862cff930d907ffd1a8", + "tarball": "https://registry.npmjs.org/del/-/del-2.2.2.tgz" }, "engines": { "node": ">=0.10.0" @@ -82,7 +82,7 @@ "files": [ "index.js" ], - "gitHead": "d92f9d3b30aca21868239a60f639beb94dd00bf7", + "gitHead": "3a97a5ba131055fbf7eb39f5ed47db86a2fd4497", "homepage": "https://github.com/sindresorhus/del#readme", "keywords": [ "delete", @@ -125,5 +125,5 @@ "scripts": { "test": "xo && ava" }, - "version": "2.2.1" + "version": "2.2.2" } diff --git a/tools/eslint/node_modules/del/readme.md b/tools/eslint/node_modules/del/readme.md index 58d9264011..c0c1219235 100644 --- a/tools/eslint/node_modules/del/readme.md +++ b/tools/eslint/node_modules/del/readme.md @@ -4,6 +4,12 @@ Pretty much [rimraf](https://github.com/isaacs/rimraf) with a Promise API and support for multiple files and globbing. It also protects you against deleting the current working directory and above. +--- + +<p align="center"><b>š„ Want to strengthen your core JavaScript skills and master ES6?</b><br>I would personally recommend this awesome <a href="https://ES6.io/friend/AWESOME">ES6 course</a> by Wes Bos.</p> + +--- + ## Install diff --git a/tools/eslint/node_modules/lodash/README.md b/tools/eslint/node_modules/lodash/README.md index 2cf1492ccc..2052e053fc 100644 --- a/tools/eslint/node_modules/lodash/README.md +++ b/tools/eslint/node_modules/lodash/README.md @@ -1,4 +1,4 @@ -# lodash v4.14.1 +# lodash v4.15.0 The [Lodash](https://lodash.com/) library exported as [Node.js](https://nodejs.org/) modules. @@ -28,7 +28,7 @@ var chunk = require('lodash/chunk'); var extend = require('lodash/fp/extend'); ``` -See the [package source](https://github.com/lodash/lodash/tree/4.14.1-npm) for more details. +See the [package source](https://github.com/lodash/lodash/tree/4.15.0-npm) for more details. **Note:**<br> Donāt assign values to the [special variable](http://nodejs.org/api/repl.html#repl_repl_features) `_` in the Node.js < 6 REPL.<br> @@ -36,5 +36,5 @@ Install [n_](https://www.npmjs.com/package/n_) for a REPL that includes `lodash` ## Support -Tested in Chrome 50-51, Firefox 46-47, IE 9-11, Edge 13, Safari 8-9, Node.js 0.10-6, & PhantomJS 1.9.8.<br> +Tested in Chrome 51-52, Firefox 47-48, IE 9-11, Edge 14, Safari 8-9, Node.js 0.10-6, & PhantomJS 2.1.1.<br> Automated [browser](https://saucelabs.com/u/lodash) & [CI](https://travis-ci.org/lodash/lodash/) test runs are available. diff --git a/tools/eslint/node_modules/lodash/_Reflect.js b/tools/eslint/node_modules/lodash/_Reflect.js deleted file mode 100644 index 1de7475b8a..0000000000 --- a/tools/eslint/node_modules/lodash/_Reflect.js +++ /dev/null @@ -1,6 +0,0 @@ -var root = require('./_root'); - -/** Built-in value references. */ -var Reflect = root.Reflect; - -module.exports = Reflect; diff --git a/tools/eslint/node_modules/lodash/_arrayIncludes.js b/tools/eslint/node_modules/lodash/_arrayIncludes.js index cf9c1f0fc3..be53e60dc7 100644 --- a/tools/eslint/node_modules/lodash/_arrayIncludes.js +++ b/tools/eslint/node_modules/lodash/_arrayIncludes.js @@ -5,7 +5,7 @@ var baseIndexOf = require('./_baseIndexOf'); * specifying an index to search from. * * @private - * @param {Array} [array] The array to search. + * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ diff --git a/tools/eslint/node_modules/lodash/_arrayIncludesWith.js b/tools/eslint/node_modules/lodash/_arrayIncludesWith.js index d08356a86d..72ff0c8eda 100644 --- a/tools/eslint/node_modules/lodash/_arrayIncludesWith.js +++ b/tools/eslint/node_modules/lodash/_arrayIncludesWith.js @@ -2,7 +2,7 @@ * This function is like `arrayIncludes` except that it accepts a comparator. * * @private - * @param {Array} [array] The array to search. + * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @param {Function} comparator The comparator invoked per element. * @returns {boolean} Returns `true` if `target` is found, else `false`. diff --git a/tools/eslint/node_modules/lodash/_arrayLikeKeys.js b/tools/eslint/node_modules/lodash/_arrayLikeKeys.js new file mode 100644 index 0000000000..0cb3b18556 --- /dev/null +++ b/tools/eslint/node_modules/lodash/_arrayLikeKeys.js @@ -0,0 +1,39 @@ +var baseTimes = require('./_baseTimes'), + isArguments = require('./isArguments'), + isArray = require('./isArray'), + isIndex = require('./_isIndex'); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ +function arrayLikeKeys(value, inherited) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + // Safari 9 makes `arguments.length` enumerable in strict mode. + var result = (isArray(value) || isArguments(value)) + ? baseTimes(value.length, String) + : []; + + var length = result.length, + skipIndexes = !!length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && (key == 'length' || isIndex(key, length)))) { + result.push(key); + } + } + return result; +} + +module.exports = arrayLikeKeys; diff --git a/tools/eslint/node_modules/lodash/_asciiSize.js b/tools/eslint/node_modules/lodash/_asciiSize.js new file mode 100644 index 0000000000..11d29c33ad --- /dev/null +++ b/tools/eslint/node_modules/lodash/_asciiSize.js @@ -0,0 +1,12 @@ +var baseProperty = require('./_baseProperty'); + +/** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ +var asciiSize = baseProperty('length'); + +module.exports = asciiSize; diff --git a/tools/eslint/node_modules/lodash/_asciiToArray.js b/tools/eslint/node_modules/lodash/_asciiToArray.js new file mode 100644 index 0000000000..8e3dd5b47f --- /dev/null +++ b/tools/eslint/node_modules/lodash/_asciiToArray.js @@ -0,0 +1,12 @@ +/** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function asciiToArray(string) { + return string.split(''); +} + +module.exports = asciiToArray; diff --git a/tools/eslint/node_modules/lodash/_asciiWords.js b/tools/eslint/node_modules/lodash/_asciiWords.js new file mode 100644 index 0000000000..d765f0f763 --- /dev/null +++ b/tools/eslint/node_modules/lodash/_asciiWords.js @@ -0,0 +1,15 @@ +/** Used to match words composed of alphanumeric characters. */ +var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; + +/** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ +function asciiWords(string) { + return string.match(reAsciiWord) || []; +} + +module.exports = asciiWords; diff --git a/tools/eslint/node_modules/lodash/_assignValue.js b/tools/eslint/node_modules/lodash/_assignValue.js index 35d49f04e8..aa1dc78e1c 100644 --- a/tools/eslint/node_modules/lodash/_assignValue.js +++ b/tools/eslint/node_modules/lodash/_assignValue.js @@ -8,7 +8,7 @@ var hasOwnProperty = objectProto.hasOwnProperty; /** * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @private diff --git a/tools/eslint/node_modules/lodash/_assocIndexOf.js b/tools/eslint/node_modules/lodash/_assocIndexOf.js index 8f2c41fbcd..5b77a2bdd3 100644 --- a/tools/eslint/node_modules/lodash/_assocIndexOf.js +++ b/tools/eslint/node_modules/lodash/_assocIndexOf.js @@ -4,7 +4,7 @@ var eq = require('./eq'); * Gets the index at which the `key` is found in `array` of key-value pairs. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} key The key to search for. * @returns {number} Returns the index of the matched value, else `-1`. */ diff --git a/tools/eslint/node_modules/lodash/_baseConformsTo.js b/tools/eslint/node_modules/lodash/_baseConformsTo.js index a72deda2d5..e449cb84bd 100644 --- a/tools/eslint/node_modules/lodash/_baseConformsTo.js +++ b/tools/eslint/node_modules/lodash/_baseConformsTo.js @@ -11,14 +11,13 @@ function baseConformsTo(object, source, props) { if (object == null) { return !length; } - var index = length; - while (index--) { - var key = props[index], + object = Object(object); + while (length--) { + var key = props[length], predicate = source[key], value = object[key]; - if ((value === undefined && - !(key in Object(object))) || !predicate(value)) { + if ((value === undefined && !(key in object)) || !predicate(value)) { return false; } } diff --git a/tools/eslint/node_modules/lodash/_baseDelay.js b/tools/eslint/node_modules/lodash/_baseDelay.js index 1e4e69b68f..f21087747b 100644 --- a/tools/eslint/node_modules/lodash/_baseDelay.js +++ b/tools/eslint/node_modules/lodash/_baseDelay.js @@ -9,7 +9,7 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {Array} args The arguments to provide to `func`. - * @returns {number} Returns the timer id. + * @returns {number|Object} Returns the timer id or timeout object. */ function baseDelay(func, wait, args) { if (typeof func != 'function') { diff --git a/tools/eslint/node_modules/lodash/_baseFindIndex.js b/tools/eslint/node_modules/lodash/_baseFindIndex.js index bfd8259afd..e3f5d8aa2b 100644 --- a/tools/eslint/node_modules/lodash/_baseFindIndex.js +++ b/tools/eslint/node_modules/lodash/_baseFindIndex.js @@ -3,7 +3,7 @@ * support for iteratee shorthands. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} predicate The function invoked per iteration. * @param {number} fromIndex The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. diff --git a/tools/eslint/node_modules/lodash/_baseFindKey.js b/tools/eslint/node_modules/lodash/_baseFindKey.js index afbad85471..2e430f3a21 100644 --- a/tools/eslint/node_modules/lodash/_baseFindKey.js +++ b/tools/eslint/node_modules/lodash/_baseFindKey.js @@ -4,7 +4,7 @@ * using `eachFunc`. * * @private - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the found element or its key, else `undefined`. diff --git a/tools/eslint/node_modules/lodash/_baseGetTag.js b/tools/eslint/node_modules/lodash/_baseGetTag.js index ce773623cd..c8b9e394f3 100644 --- a/tools/eslint/node_modules/lodash/_baseGetTag.js +++ b/tools/eslint/node_modules/lodash/_baseGetTag.js @@ -3,7 +3,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/_baseHas.js b/tools/eslint/node_modules/lodash/_baseHas.js index 3d2e7bf74a..1b730321c2 100644 --- a/tools/eslint/node_modules/lodash/_baseHas.js +++ b/tools/eslint/node_modules/lodash/_baseHas.js @@ -1,5 +1,3 @@ -var getPrototype = require('./_getPrototype'); - /** Used for built-in method references. */ var objectProto = Object.prototype; @@ -15,12 +13,7 @@ var hasOwnProperty = objectProto.hasOwnProperty; * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHas(object, key) { - // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`, - // that are composed entirely of index properties, return `false` for - // `hasOwnProperty` checks of them. - return object != null && - (hasOwnProperty.call(object, key) || - (typeof object == 'object' && key in object && getPrototype(object) === null)); + return object != null && hasOwnProperty.call(object, key); } module.exports = baseHas; diff --git a/tools/eslint/node_modules/lodash/_baseIndexOf.js b/tools/eslint/node_modules/lodash/_baseIndexOf.js index 94d228996a..c232d43305 100644 --- a/tools/eslint/node_modules/lodash/_baseIndexOf.js +++ b/tools/eslint/node_modules/lodash/_baseIndexOf.js @@ -5,7 +5,7 @@ var baseFindIndex = require('./_baseFindIndex'), * The base implementation of `_.indexOf` without `fromIndex` bounds checks. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. diff --git a/tools/eslint/node_modules/lodash/_baseIndexOfWith.js b/tools/eslint/node_modules/lodash/_baseIndexOfWith.js index 8be568af26..f815fe0dda 100644 --- a/tools/eslint/node_modules/lodash/_baseIndexOfWith.js +++ b/tools/eslint/node_modules/lodash/_baseIndexOfWith.js @@ -2,7 +2,7 @@ * This function is like `baseIndexOf` except that it accepts a comparator. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @param {Function} comparator The comparator invoked per element. diff --git a/tools/eslint/node_modules/lodash/_baseIsArrayBuffer.js b/tools/eslint/node_modules/lodash/_baseIsArrayBuffer.js index a380bf7b2c..024ec8514c 100644 --- a/tools/eslint/node_modules/lodash/_baseIsArrayBuffer.js +++ b/tools/eslint/node_modules/lodash/_baseIsArrayBuffer.js @@ -7,7 +7,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/_baseIsDate.js b/tools/eslint/node_modules/lodash/_baseIsDate.js index 01b7c72d46..9dacf9b154 100644 --- a/tools/eslint/node_modules/lodash/_baseIsDate.js +++ b/tools/eslint/node_modules/lodash/_baseIsDate.js @@ -8,7 +8,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/_baseIsNative.js b/tools/eslint/node_modules/lodash/_baseIsNative.js index 4d7dd0773b..c79c77ccbb 100644 --- a/tools/eslint/node_modules/lodash/_baseIsNative.js +++ b/tools/eslint/node_modules/lodash/_baseIsNative.js @@ -6,7 +6,7 @@ var isFunction = require('./isFunction'), /** * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; @@ -14,10 +14,11 @@ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; var reIsHostCtor = /^\[object .+?Constructor\]$/; /** Used for built-in method references. */ -var objectProto = Object.prototype; +var funcProto = Function.prototype, + objectProto = Object.prototype; /** Used to resolve the decompiled source of functions. */ -var funcToString = Function.prototype.toString; +var funcToString = funcProto.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; diff --git a/tools/eslint/node_modules/lodash/_baseIsRegExp.js b/tools/eslint/node_modules/lodash/_baseIsRegExp.js index 6d10b42dee..926fbb3bd4 100644 --- a/tools/eslint/node_modules/lodash/_baseIsRegExp.js +++ b/tools/eslint/node_modules/lodash/_baseIsRegExp.js @@ -8,7 +8,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/_baseIsTypedArray.js b/tools/eslint/node_modules/lodash/_baseIsTypedArray.js index 5d1e43bdac..9e92756cbe 100644 --- a/tools/eslint/node_modules/lodash/_baseIsTypedArray.js +++ b/tools/eslint/node_modules/lodash/_baseIsTypedArray.js @@ -49,7 +49,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/_baseKeys.js b/tools/eslint/node_modules/lodash/_baseKeys.js index 2a27d55546..45e9e6f39f 100644 --- a/tools/eslint/node_modules/lodash/_baseKeys.js +++ b/tools/eslint/node_modules/lodash/_baseKeys.js @@ -1,16 +1,30 @@ -var overArg = require('./_overArg'); +var isPrototype = require('./_isPrototype'), + nativeKeys = require('./_nativeKeys'); -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeKeys = Object.keys; +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; /** - * The base implementation of `_.keys` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ -var baseKeys = overArg(nativeKeys, Object); +function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; +} module.exports = baseKeys; diff --git a/tools/eslint/node_modules/lodash/_baseKeysIn.js b/tools/eslint/node_modules/lodash/_baseKeysIn.js index 7455fd889e..ea8a0a1742 100644 --- a/tools/eslint/node_modules/lodash/_baseKeysIn.js +++ b/tools/eslint/node_modules/lodash/_baseKeysIn.js @@ -1,36 +1,33 @@ -var Reflect = require('./_Reflect'), - iteratorToArray = require('./_iteratorToArray'); +var isObject = require('./isObject'), + isPrototype = require('./_isPrototype'), + nativeKeysIn = require('./_nativeKeysIn'); /** Used for built-in method references. */ var objectProto = Object.prototype; -/** Built-in value references. */ -var enumerate = Reflect ? Reflect.enumerate : undefined, - propertyIsEnumerable = objectProto.propertyIsEnumerable; +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; /** - * The base implementation of `_.keysIn` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeysIn(object) { - object = object == null ? object : Object(object); + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; - var result = []; for (var key in object) { - result.push(key); + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } } return result; } -// Fallback for IE < 9 with es6-shim. -if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) { - baseKeysIn = function(object) { - return iteratorToArray(enumerate(object)); - }; -} - module.exports = baseKeysIn; diff --git a/tools/eslint/node_modules/lodash/_baseMerge.js b/tools/eslint/node_modules/lodash/_baseMerge.js index e18d3bf750..dfb4b15270 100644 --- a/tools/eslint/node_modules/lodash/_baseMerge.js +++ b/tools/eslint/node_modules/lodash/_baseMerge.js @@ -1,11 +1,11 @@ var Stack = require('./_Stack'), arrayEach = require('./_arrayEach'), assignMergeValue = require('./_assignMergeValue'), + baseKeysIn = require('./_baseKeysIn'), baseMergeDeep = require('./_baseMergeDeep'), isArray = require('./isArray'), isObject = require('./isObject'), - isTypedArray = require('./isTypedArray'), - keysIn = require('./keysIn'); + isTypedArray = require('./isTypedArray'); /** * The base implementation of `_.merge` without support for multiple sources. @@ -23,7 +23,7 @@ function baseMerge(object, source, srcIndex, customizer, stack) { return; } if (!(isArray(source) || isTypedArray(source))) { - var props = keysIn(source); + var props = baseKeysIn(source); } arrayEach(props || source, function(srcValue, key) { if (props) { diff --git a/tools/eslint/node_modules/lodash/_baseSet.js b/tools/eslint/node_modules/lodash/_baseSet.js index 34d63e5682..2be04d5f2a 100644 --- a/tools/eslint/node_modules/lodash/_baseSet.js +++ b/tools/eslint/node_modules/lodash/_baseSet.js @@ -9,13 +9,16 @@ var assignValue = require('./_assignValue'), * The base implementation of `_.set`. * * @private - * @param {Object} object The object to query. + * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @param {Function} [customizer] The function to customize path creation. * @returns {Object} Returns `object`. */ function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } path = isKey(path, object) ? [path] : castPath(path); var index = -1, @@ -24,20 +27,19 @@ function baseSet(object, path, value, customizer) { nested = object; while (nested != null && ++index < length) { - var key = toKey(path[index]); - if (isObject(nested)) { - var newValue = value; - if (index != lastIndex) { - var objValue = nested[key]; - newValue = customizer ? customizer(objValue, key, nested) : undefined; - if (newValue === undefined) { - newValue = objValue == null - ? (isIndex(path[index + 1]) ? [] : {}) - : objValue; - } + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); } - assignValue(nested, key, newValue); } + assignValue(nested, key, newValue); nested = nested[key]; } return object; diff --git a/tools/eslint/node_modules/lodash/_baseUnset.js b/tools/eslint/node_modules/lodash/_baseUnset.js index 754eb063cb..dda80fc196 100644 --- a/tools/eslint/node_modules/lodash/_baseUnset.js +++ b/tools/eslint/node_modules/lodash/_baseUnset.js @@ -1,10 +1,15 @@ -var baseHas = require('./_baseHas'), - castPath = require('./_castPath'), +var castPath = require('./_castPath'), isKey = require('./_isKey'), last = require('./last'), parent = require('./_parent'), toKey = require('./_toKey'); +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + /** * The base implementation of `_.unset`. * @@ -18,7 +23,7 @@ function baseUnset(object, path) { object = parent(object, path); var key = toKey(last(path)); - return !(object != null && baseHas(object, key)) || delete object[key]; + return !(object != null && hasOwnProperty.call(object, key)) || delete object[key]; } module.exports = baseUnset; diff --git a/tools/eslint/node_modules/lodash/_baseUpdate.js b/tools/eslint/node_modules/lodash/_baseUpdate.js index ec1b338366..92a623777c 100644 --- a/tools/eslint/node_modules/lodash/_baseUpdate.js +++ b/tools/eslint/node_modules/lodash/_baseUpdate.js @@ -5,7 +5,7 @@ var baseGet = require('./_baseGet'), * The base implementation of `_.update`. * * @private - * @param {Object} object The object to query. + * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to update. * @param {Function} updater The function to produce the updated value. * @param {Function} [customizer] The function to customize path creation. diff --git a/tools/eslint/node_modules/lodash/_createCaseFirst.js b/tools/eslint/node_modules/lodash/_createCaseFirst.js index 1a20532811..fe8ea48303 100644 --- a/tools/eslint/node_modules/lodash/_createCaseFirst.js +++ b/tools/eslint/node_modules/lodash/_createCaseFirst.js @@ -1,5 +1,5 @@ var castSlice = require('./_castSlice'), - reHasComplexSymbol = require('./_reHasComplexSymbol'), + hasUnicode = require('./_hasUnicode'), stringToArray = require('./_stringToArray'), toString = require('./toString'); @@ -14,7 +14,7 @@ function createCaseFirst(methodName) { return function(string) { string = toString(string); - var strSymbols = reHasComplexSymbol.test(string) + var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined; diff --git a/tools/eslint/node_modules/lodash/_createCtor.js b/tools/eslint/node_modules/lodash/_createCtor.js index ee904f4ff3..9047aa5fac 100644 --- a/tools/eslint/node_modules/lodash/_createCtor.js +++ b/tools/eslint/node_modules/lodash/_createCtor.js @@ -12,7 +12,7 @@ var baseCreate = require('./_baseCreate'), function createCtor(Ctor) { return function() { // Use a `switch` statement to work with class constructors. See - // http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { diff --git a/tools/eslint/node_modules/lodash/_createPadding.js b/tools/eslint/node_modules/lodash/_createPadding.js index cfc62256d2..2124612b81 100644 --- a/tools/eslint/node_modules/lodash/_createPadding.js +++ b/tools/eslint/node_modules/lodash/_createPadding.js @@ -1,7 +1,7 @@ var baseRepeat = require('./_baseRepeat'), baseToString = require('./_baseToString'), castSlice = require('./_castSlice'), - reHasComplexSymbol = require('./_reHasComplexSymbol'), + hasUnicode = require('./_hasUnicode'), stringSize = require('./_stringSize'), stringToArray = require('./_stringToArray'); @@ -25,7 +25,7 @@ function createPadding(length, chars) { return charsLength ? baseRepeat(chars, length) : chars; } var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); - return reHasComplexSymbol.test(chars) + return hasUnicode(chars) ? castSlice(stringToArray(result), 0, length).join('') : result.slice(0, length); } diff --git a/tools/eslint/node_modules/lodash/_deburrLetter.js b/tools/eslint/node_modules/lodash/_deburrLetter.js index f7be3d4f04..98283a467b 100644 --- a/tools/eslint/node_modules/lodash/_deburrLetter.js +++ b/tools/eslint/node_modules/lodash/_deburrLetter.js @@ -1,15 +1,16 @@ var basePropertyOf = require('./_basePropertyOf'); -/** Used to map latin-1 supplementary letters to basic latin letters. */ +/** Used to map Latin Unicode letters to basic Latin letters. */ var deburredLetters = { + // Latin-1 Supplement block. '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', '\xc7': 'C', '\xe7': 'c', '\xd0': 'D', '\xf0': 'd', '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', - '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', - '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', '\xd1': 'N', '\xf1': 'n', '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', @@ -18,11 +19,48 @@ var deburredLetters = { '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', '\xc6': 'Ae', '\xe6': 'ae', '\xde': 'Th', '\xfe': 'th', - '\xdf': 'ss' + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 'ss' }; /** - * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. * * @private * @param {string} letter The matched letter to deburr. diff --git a/tools/eslint/node_modules/lodash/_equalByTag.js b/tools/eslint/node_modules/lodash/_equalByTag.js index d6baa0a555..07d8c8c00f 100644 --- a/tools/eslint/node_modules/lodash/_equalByTag.js +++ b/tools/eslint/node_modules/lodash/_equalByTag.js @@ -75,7 +75,7 @@ function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) { case regexpTag: case stringTag: // Coerce regexes to strings and treat strings, primitives and objects, - // as equal. See http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.tostring + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring // for more details. return object == (other + ''); diff --git a/tools/eslint/node_modules/lodash/_equalObjects.js b/tools/eslint/node_modules/lodash/_equalObjects.js index 92646ed533..092cb3ff96 100644 --- a/tools/eslint/node_modules/lodash/_equalObjects.js +++ b/tools/eslint/node_modules/lodash/_equalObjects.js @@ -1,9 +1,14 @@ -var baseHas = require('./_baseHas'), - keys = require('./keys'); +var keys = require('./keys'); /** Used to compose bitmasks for comparison styles. */ var PARTIAL_COMPARE_FLAG = 2; +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + /** * A specialized version of `baseIsEqualDeep` for objects with support for * partial deep comparisons. @@ -31,7 +36,7 @@ function equalObjects(object, other, equalFunc, customizer, bitmask, stack) { var index = objLength; while (index--) { var key = objProps[index]; - if (!(isPartial ? key in other : baseHas(other, key))) { + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { return false; } } diff --git a/tools/eslint/node_modules/lodash/_getLength.js b/tools/eslint/node_modules/lodash/_getLength.js deleted file mode 100644 index 54071653aa..0000000000 --- a/tools/eslint/node_modules/lodash/_getLength.js +++ /dev/null @@ -1,16 +0,0 @@ -var baseProperty = require('./_baseProperty'); - -/** - * Gets the "length" property value of `object`. - * - * **Note:** This function is used to avoid a - * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects - * Safari on at least iOS 8.1-8.3 ARM64. - * - * @private - * @param {Object} object The object to query. - * @returns {*} Returns the "length" value. - */ -var getLength = baseProperty('length'); - -module.exports = getLength; diff --git a/tools/eslint/node_modules/lodash/_getPrototype.js b/tools/eslint/node_modules/lodash/_getPrototype.js index 5724793887..e808612129 100644 --- a/tools/eslint/node_modules/lodash/_getPrototype.js +++ b/tools/eslint/node_modules/lodash/_getPrototype.js @@ -1,15 +1,6 @@ var overArg = require('./_overArg'); -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeGetPrototype = Object.getPrototypeOf; - -/** - * Gets the `[[Prototype]]` of `value`. - * - * @private - * @param {*} value The value to query. - * @returns {null|Object} Returns the `[[Prototype]]`. - */ -var getPrototype = overArg(nativeGetPrototype, Object); +/** Built-in value references. */ +var getPrototype = overArg(Object.getPrototypeOf, Object); module.exports = getPrototype; diff --git a/tools/eslint/node_modules/lodash/_getTag.js b/tools/eslint/node_modules/lodash/_getTag.js index af186020ba..de560d676e 100644 --- a/tools/eslint/node_modules/lodash/_getTag.js +++ b/tools/eslint/node_modules/lodash/_getTag.js @@ -20,7 +20,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -42,7 +42,7 @@ var dataViewCtorString = toSource(DataView), var getTag = baseGetTag; // Fallback for data views, maps, sets, and weak maps in IE 11, -// for data views in Edge, and promises in Node.js. +// for data views in Edge < 14, and promises in Node.js. if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (Map && getTag(new Map) != mapTag) || (Promise && getTag(Promise.resolve()) != promiseTag) || diff --git a/tools/eslint/node_modules/lodash/_hasPath.js b/tools/eslint/node_modules/lodash/_hasPath.js index 4533c608db..1e2c3eac4f 100644 --- a/tools/eslint/node_modules/lodash/_hasPath.js +++ b/tools/eslint/node_modules/lodash/_hasPath.js @@ -4,7 +4,6 @@ var castPath = require('./_castPath'), isIndex = require('./_isIndex'), isKey = require('./_isKey'), isLength = require('./isLength'), - isString = require('./isString'), toKey = require('./_toKey'); /** @@ -35,7 +34,7 @@ function hasPath(object, path, hasFunc) { } var length = object ? object.length : 0; return !!length && isLength(length) && isIndex(key, length) && - (isArray(object) || isString(object) || isArguments(object)); + (isArray(object) || isArguments(object)); } module.exports = hasPath; diff --git a/tools/eslint/node_modules/lodash/_reHasComplexSymbol.js b/tools/eslint/node_modules/lodash/_hasUnicode.js index be78c4bf00..085161a3d2 100644 --- a/tools/eslint/node_modules/lodash/_reHasComplexSymbol.js +++ b/tools/eslint/node_modules/lodash/_hasUnicode.js @@ -8,6 +8,17 @@ var rsAstralRange = '\\ud800-\\udfff', var rsZWJ = '\\u200d'; /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ -var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); +var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); -module.exports = reHasComplexSymbol; +/** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ +function hasUnicode(string) { + return reHasUnicode.test(string); +} + +module.exports = hasUnicode; diff --git a/tools/eslint/node_modules/lodash/_hasUnicodeWord.js b/tools/eslint/node_modules/lodash/_hasUnicodeWord.js new file mode 100644 index 0000000000..a35d6e504d --- /dev/null +++ b/tools/eslint/node_modules/lodash/_hasUnicodeWord.js @@ -0,0 +1,15 @@ +/** Used to detect strings that need a more robust regexp to match words. */ +var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + +/** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ +function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); +} + +module.exports = hasUnicodeWord; diff --git a/tools/eslint/node_modules/lodash/_indexKeys.js b/tools/eslint/node_modules/lodash/_indexKeys.js deleted file mode 100644 index 0e2fc10481..0000000000 --- a/tools/eslint/node_modules/lodash/_indexKeys.js +++ /dev/null @@ -1,24 +0,0 @@ -var baseTimes = require('./_baseTimes'), - isArguments = require('./isArguments'), - isArray = require('./isArray'), - isLength = require('./isLength'), - isString = require('./isString'); - -/** - * Creates an array of index keys for `object` values of arrays, - * `arguments` objects, and strings, otherwise `null` is returned. - * - * @private - * @param {Object} object The object to query. - * @returns {Array|null} Returns index keys, else `null`. - */ -function indexKeys(object) { - var length = object ? object.length : undefined; - if (isLength(length) && - (isArray(object) || isString(object) || isArguments(object))) { - return baseTimes(length, String); - } - return null; -} - -module.exports = indexKeys; diff --git a/tools/eslint/node_modules/lodash/_nativeKeys.js b/tools/eslint/node_modules/lodash/_nativeKeys.js new file mode 100644 index 0000000000..479a104a1c --- /dev/null +++ b/tools/eslint/node_modules/lodash/_nativeKeys.js @@ -0,0 +1,6 @@ +var overArg = require('./_overArg'); + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeKeys = overArg(Object.keys, Object); + +module.exports = nativeKeys; diff --git a/tools/eslint/node_modules/lodash/_nativeKeysIn.js b/tools/eslint/node_modules/lodash/_nativeKeysIn.js new file mode 100644 index 0000000000..00ee505947 --- /dev/null +++ b/tools/eslint/node_modules/lodash/_nativeKeysIn.js @@ -0,0 +1,20 @@ +/** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ +function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; +} + +module.exports = nativeKeysIn; diff --git a/tools/eslint/node_modules/lodash/_overArg.js b/tools/eslint/node_modules/lodash/_overArg.js index f3c170a7af..651c5c55f2 100644 --- a/tools/eslint/node_modules/lodash/_overArg.js +++ b/tools/eslint/node_modules/lodash/_overArg.js @@ -1,5 +1,5 @@ /** - * Creates a function that invokes `func` with its first argument transformed. + * Creates a unary function that invokes `func` with its argument transformed. * * @private * @param {Function} func The function to wrap. diff --git a/tools/eslint/node_modules/lodash/_stringSize.js b/tools/eslint/node_modules/lodash/_stringSize.js index c64c7ff420..17ef462a68 100644 --- a/tools/eslint/node_modules/lodash/_stringSize.js +++ b/tools/eslint/node_modules/lodash/_stringSize.js @@ -1,30 +1,6 @@ -var reHasComplexSymbol = require('./_reHasComplexSymbol'); - -/** Used to compose unicode character classes. */ -var rsAstralRange = '\\ud800-\\udfff', - rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', - rsComboSymbolsRange = '\\u20d0-\\u20f0', - rsVarRange = '\\ufe0e\\ufe0f'; - -/** Used to compose unicode capture groups. */ -var rsAstral = '[' + rsAstralRange + ']', - rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', - rsFitz = '\\ud83c[\\udffb-\\udfff]', - rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', - rsNonAstral = '[^' + rsAstralRange + ']', - rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', - rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', - rsZWJ = '\\u200d'; - -/** Used to compose unicode regexes. */ -var reOptMod = rsModifier + '?', - rsOptVar = '[' + rsVarRange + ']?', - rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', - rsSeq = rsOptVar + reOptMod + rsOptJoin, - rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; - -/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ -var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); +var asciiSize = require('./_asciiSize'), + hasUnicode = require('./_hasUnicode'), + unicodeSize = require('./_unicodeSize'); /** * Gets the number of symbols in `string`. @@ -34,14 +10,9 @@ var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, * @returns {number} Returns the string size. */ function stringSize(string) { - if (!(string && reHasComplexSymbol.test(string))) { - return string.length; - } - var result = reComplexSymbol.lastIndex = 0; - while (reComplexSymbol.test(string)) { - result++; - } - return result; + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); } module.exports = stringSize; diff --git a/tools/eslint/node_modules/lodash/_stringToArray.js b/tools/eslint/node_modules/lodash/_stringToArray.js index 90986f09bb..d161158c6f 100644 --- a/tools/eslint/node_modules/lodash/_stringToArray.js +++ b/tools/eslint/node_modules/lodash/_stringToArray.js @@ -1,28 +1,6 @@ -/** Used to compose unicode character classes. */ -var rsAstralRange = '\\ud800-\\udfff', - rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', - rsComboSymbolsRange = '\\u20d0-\\u20f0', - rsVarRange = '\\ufe0e\\ufe0f'; - -/** Used to compose unicode capture groups. */ -var rsAstral = '[' + rsAstralRange + ']', - rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', - rsFitz = '\\ud83c[\\udffb-\\udfff]', - rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', - rsNonAstral = '[^' + rsAstralRange + ']', - rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', - rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', - rsZWJ = '\\u200d'; - -/** Used to compose unicode regexes. */ -var reOptMod = rsModifier + '?', - rsOptVar = '[' + rsVarRange + ']?', - rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', - rsSeq = rsOptVar + reOptMod + rsOptJoin, - rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; - -/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ -var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); +var asciiToArray = require('./_asciiToArray'), + hasUnicode = require('./_hasUnicode'), + unicodeToArray = require('./_unicodeToArray'); /** * Converts `string` to an array. @@ -32,7 +10,9 @@ var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, * @returns {Array} Returns the converted array. */ function stringToArray(string) { - return string.match(reComplexSymbol); + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); } module.exports = stringToArray; diff --git a/tools/eslint/node_modules/lodash/_toSource.js b/tools/eslint/node_modules/lodash/_toSource.js index 43f3ff8bf9..00ac454857 100644 --- a/tools/eslint/node_modules/lodash/_toSource.js +++ b/tools/eslint/node_modules/lodash/_toSource.js @@ -1,5 +1,8 @@ +/** Used for built-in method references. */ +var funcProto = Function.prototype; + /** Used to resolve the decompiled source of functions. */ -var funcToString = Function.prototype.toString; +var funcToString = funcProto.toString; /** * Converts `func` to its source code. diff --git a/tools/eslint/node_modules/lodash/_unicodeSize.js b/tools/eslint/node_modules/lodash/_unicodeSize.js new file mode 100644 index 0000000000..3f50ce86ae --- /dev/null +++ b/tools/eslint/node_modules/lodash/_unicodeSize.js @@ -0,0 +1,42 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange + ']', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + +/** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ +function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + result++; + } + return result; +} + +module.exports = unicodeSize; diff --git a/tools/eslint/node_modules/lodash/_unicodeToArray.js b/tools/eslint/node_modules/lodash/_unicodeToArray.js new file mode 100644 index 0000000000..11ac76311e --- /dev/null +++ b/tools/eslint/node_modules/lodash/_unicodeToArray.js @@ -0,0 +1,38 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', + rsVarRange = '\\ufe0e\\ufe0f'; + +/** Used to compose unicode capture groups. */ +var rsAstral = '[' + rsAstralRange + ']', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; + +/** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ +var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + +/** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ +function unicodeToArray(string) { + return string.match(reUnicode) || []; +} + +module.exports = unicodeToArray; diff --git a/tools/eslint/node_modules/lodash/_unicodeWords.js b/tools/eslint/node_modules/lodash/_unicodeWords.js new file mode 100644 index 0000000000..a02e93074a --- /dev/null +++ b/tools/eslint/node_modules/lodash/_unicodeWords.js @@ -0,0 +1,63 @@ +/** Used to compose unicode character classes. */ +var rsAstralRange = '\\ud800-\\udfff', + rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', + rsComboSymbolsRange = '\\u20d0-\\u20f0', + rsDingbatRange = '\\u2700-\\u27bf', + rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', + rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', + rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', + rsPunctuationRange = '\\u2000-\\u206f', + rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', + rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', + rsVarRange = '\\ufe0e\\ufe0f', + rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; + +/** Used to compose unicode capture groups. */ +var rsApos = "['\u2019]", + rsBreak = '[' + rsBreakRange + ']', + rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', + rsDigits = '\\d+', + rsDingbat = '[' + rsDingbatRange + ']', + rsLower = '[' + rsLowerRange + ']', + rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', + rsFitz = '\\ud83c[\\udffb-\\udfff]', + rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', + rsNonAstral = '[^' + rsAstralRange + ']', + rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', + rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', + rsUpper = '[' + rsUpperRange + ']', + rsZWJ = '\\u200d'; + +/** Used to compose unicode regexes. */ +var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', + rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', + rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', + rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', + reOptMod = rsModifier + '?', + rsOptVar = '[' + rsVarRange + ']?', + rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', + rsSeq = rsOptVar + reOptMod + rsOptJoin, + rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq; + +/** Used to match complex or compound words. */ +var reUnicodeWord = RegExp([ + rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', + rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', + rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, + rsUpper + '+' + rsOptUpperContr, + rsDigits, + rsEmoji +].join('|'), 'g'); + +/** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ +function unicodeWords(string) { + return string.match(reUnicodeWord) || []; +} + +module.exports = unicodeWords; diff --git a/tools/eslint/node_modules/lodash/assignIn.js b/tools/eslint/node_modules/lodash/assignIn.js index e77aebf189..e663473a0c 100644 --- a/tools/eslint/node_modules/lodash/assignIn.js +++ b/tools/eslint/node_modules/lodash/assignIn.js @@ -1,19 +1,7 @@ -var assignValue = require('./_assignValue'), - copyObject = require('./_copyObject'), +var copyObject = require('./_copyObject'), createAssigner = require('./_createAssigner'), - isArrayLike = require('./isArrayLike'), - isPrototype = require('./_isPrototype'), keysIn = require('./keysIn'); -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** Built-in value references. */ -var propertyIsEnumerable = objectProto.propertyIsEnumerable; - -/** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */ -var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); - /** * This method is like `_.assign` except that it iterates over own and * inherited source properties. @@ -46,13 +34,7 @@ var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } */ var assignIn = createAssigner(function(object, source) { - if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) { - copyObject(source, keysIn(source), object); - return; - } - for (var key in source) { - assignValue(object, key, source[key]); - } + copyObject(source, keysIn(source), object); }); module.exports = assignIn; diff --git a/tools/eslint/node_modules/lodash/core.js b/tools/eslint/node_modules/lodash/core.js index 99f6f66fc7..de27977d22 100644 --- a/tools/eslint/node_modules/lodash/core.js +++ b/tools/eslint/node_modules/lodash/core.js @@ -13,7 +13,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '4.14.1'; + var VERSION = '4.15.0'; /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; @@ -92,7 +92,7 @@ * support for iteratee shorthands. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} predicate The function invoked per iteration. * @param {number} fromIndex The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. @@ -195,7 +195,7 @@ } /** - * Creates a function that invokes `func` with its first argument transformed. + * Creates a unary function that invokes `func` with its argument transformed. * * @private * @param {Function} func The function to wrap. @@ -222,7 +222,7 @@ /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -236,7 +236,7 @@ /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeIsFinite = root.isFinite, - nativeKeys = Object.keys, + nativeKeys = overArg(Object.keys, Object), nativeMax = Math.max; /*------------------------------------------------------------------------*/ @@ -402,7 +402,7 @@ /** * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @private @@ -438,7 +438,7 @@ * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {Array} args The arguments to provide to `func`. - * @returns {number} Returns the timer id. + * @returns {number|Object} Returns the timer id or timeout object. */ function baseDelay(func, wait, args) { if (typeof func != 'function') { @@ -747,34 +747,6 @@ } /** - * The base implementation of `_.keys` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - var baseKeys = overArg(nativeKeys, Object); - - /** - * The base implementation of `_.keysIn` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - function baseKeysIn(object) { - object = object == null ? object : Object(object); - - var result = []; - for (var key in object) { - result.push(key); - } - return result; - } - - /** * The base implementation of `_.lt` which doesn't coerce arguments. * * @private @@ -813,7 +785,7 @@ * @returns {Function} Returns the new spec function. */ function baseMatches(source) { - var props = keys(source); + var props = nativeKeys(source); return function(object) { var length = props.length; if (object == null) { @@ -1116,7 +1088,7 @@ function createCtor(Ctor) { return function() { // Use a `switch` statement to work with class constructors. See - // http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; var thisBinding = baseCreate(Ctor.prototype), @@ -1281,7 +1253,7 @@ case regexpTag: case stringTag: // Coerce regexes to strings and treat strings, primitives and objects, - // as equal. See http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.tostring + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring // for more details. return object == (other + ''); @@ -1355,19 +1327,6 @@ } /** - * Gets the "length" property value of `object`. - * - * **Note:** This function is used to avoid a - * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects - * Safari on at least iOS 8.1-8.3 ARM64. - * - * @private - * @param {Object} object The object to query. - * @returns {*} Returns the "length" value. - */ - var getLength = baseProperty('length'); - - /** * Checks if `value` is a flattenable `arguments` object or array. * * @private @@ -1379,6 +1338,25 @@ } /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** * Converts `value` to a string key if it's not a string or symbol. * * @private @@ -1452,7 +1430,7 @@ * @memberOf _ * @since 1.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=0] The index to search from. @@ -1554,7 +1532,7 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it's used as the * offset from the end of `array`. * @@ -1562,7 +1540,7 @@ * @memberOf _ * @since 0.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. @@ -1784,6 +1762,11 @@ * Iteration is stopped once `predicate` returns falsey. The predicate is * invoked with three arguments: (value, index|key, collection). * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * * @static * @memberOf _ * @since 0.1.0 @@ -1872,7 +1855,7 @@ * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=0] The index to search from. @@ -2031,7 +2014,7 @@ * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to inspect. + * @param {Array|Object|string} collection The collection to inspect. * @returns {number} Returns the collection size. * @example * @@ -2048,7 +2031,7 @@ if (collection == null) { return 0; } - collection = isArrayLike(collection) ? collection : keys(collection); + collection = isArrayLike(collection) ? collection : nativeKeys(collection); return collection.length; } @@ -2342,12 +2325,12 @@ if (!isObject(value)) { return value; } - return isArray(value) ? copyArray(value) : copyObject(value, keys(value)); + return isArray(value) ? copyArray(value) : copyObject(value, nativeKeys(value)); } /** * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. * * @static @@ -2400,7 +2383,7 @@ * // => false */ function isArguments(value) { - // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); } @@ -2456,7 +2439,7 @@ * // => false */ function isArrayLike(value) { - return value != null && isLength(getLength(value)) && !isFunction(value); + return value != null && isLength(value.length) && !isFunction(value); } /** @@ -2568,7 +2551,7 @@ isFunction(value.splice) || isArguments(value))) { return !value.length; } - return !keys(value).length; + return !nativeKeys(value).length; } /** @@ -2587,8 +2570,7 @@ * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, - * else `false`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'a': 1 }; @@ -2615,8 +2597,7 @@ * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a finite number, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * * _.isFinite(3); @@ -2654,8 +2635,7 @@ */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array and weak map constructors, - // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. + // in Safari 8-9 which returns 'object' for typed array and other constructors. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } @@ -2663,16 +2643,15 @@ /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. * @example * * _.isLength(3); @@ -2694,7 +2673,7 @@ /** * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static @@ -2933,7 +2912,7 @@ * Converts `value` to an integer. * * **Note:** This method is loosely based on - * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). * * @static * @memberOf _ @@ -3045,7 +3024,7 @@ * // => { 'a': 1, 'c': 3 } */ var assign = createAssigner(function(object, source) { - copyObject(source, keys(source), object); + copyObject(source, nativeKeys(source), object); }); /** @@ -3080,7 +3059,7 @@ * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } */ var assignIn = createAssigner(function(object, source) { - copyObject(source, keysIn(source), object); + copyObject(source, nativeKeysIn(source), object); }); /** @@ -3216,7 +3195,7 @@ * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * for more details. * * @static @@ -3240,7 +3219,7 @@ * _.keys('hi'); * // => ['0', '1'] */ - var keys = baseKeys; + var keys = nativeKeys; /** * Creates an array of the own and inherited enumerable property names of `object`. @@ -3265,7 +3244,7 @@ * _.keysIn(new Foo); * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ - var keysIn = baseKeysIn; + var keysIn = nativeKeysIn; /** * Creates an object composed of the picked `object` properties. @@ -3469,8 +3448,12 @@ * object and `source`, returning `true` if the given object has equivalent * property values, else `false`. * - * **Note:** The created function supports comparing the same values as - * `_.isEqual` is equivalent to `_.isMatch` with `source` partially applied. + * **Note:** The created function is equivalent to `_.isMatch` with `source` + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. * * @static * @memberOf _ diff --git a/tools/eslint/node_modules/lodash/core.min.js b/tools/eslint/node_modules/lodash/core.min.js index 3336ee8d3b..f5c9efaeee 100644 --- a/tools/eslint/node_modules/lodash/core.min.js +++ b/tools/eslint/node_modules/lodash/core.min.js @@ -3,26 +3,26 @@ * lodash (Custom Build) /license | Underscore.js 1.8.3 underscorejs.org/LICENSE * Build: `lodash core -o ./dist/lodash.core.js` */ -;(function(){function n(n){n=null==n?n:Object(n);var t,r=[];for(t in n)r.push(t);return r}function t(n,t){return n.push.apply(n,t),n}function r(n){return function(t){return null==t?Z:t[n]}}function e(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function u(n,t){return m(t,function(t){return n[t]})}function o(n){return n instanceof i?n:new i(n)}function i(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function c(n,t,r,e){return n===Z||J(n,an[r])&&!ln.call(e,r)?t:n; -}function f(n){return V(n)?vn(n):{}}function a(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function");return setTimeout(function(){n.apply(Z,r)},t)}function l(n,t){var r=true;return jn(n,function(n,e,u){return r=!!t(n,e,u)}),r}function p(n,t,r){for(var e=-1,u=n.length;++e<u;){var o=n[e],i=t(o);if(null!=i&&(c===Z?i===i:r(i,c)))var c=i,f=o}return f}function s(n,t){var r=[];return jn(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function h(n,r,e,u,o){var i=-1,c=n.length;for(e||(e=I),o||(o=[]);++i<c;){ -var f=n[i];0<r&&e(f)?1<r?h(f,r-1,e,u,o):t(o,f):u||(o[o.length]=f)}return o}function v(n,t){return n&&dn(n,t,Dn)}function b(n,t){return s(t,function(t){return U(n[t])})}function y(n,t){return n>t}function g(n,t,r,e,u){return n===t||(null==n||null==t||!V(n)&&!H(t)?n!==n&&t!==t:_(n,t,g,r,e,u))}function _(n,t,r,e,u,o){var i=kn(n),c=kn(t),f="[object Array]",a="[object Array]";i||(f=sn.call(n),f="[object Arguments]"==f?"[object Object]":f),c||(a=sn.call(t),a="[object Arguments]"==a?"[object Object]":a); -var l="[object Object]"==f&&true,c="[object Object]"==a&&true,a=f==a;o||(o=[]);var p=An(o,function(t){return t[0]==n}),s=An(o,function(n){return n[0]==t});if(p&&s)return p[1]==t;if(o.push([n,t]),o.push([t,n]),a&&!l){if(i)r=R(n,t,r,e,u,o);else n:{switch(f){case"[object Boolean]":case"[object Date]":case"[object Number]":r=J(+n,+t);break n;case"[object Error]":r=n.name==t.name&&n.message==t.message;break n;case"[object RegExp]":case"[object String]":r=n==t+"";break n}r=false}return o.pop(),r}return 2&u||(i=l&&ln.call(n,"__wrapped__"), -f=c&&ln.call(t,"__wrapped__"),!i&&!f)?!!a&&(r=D(n,t,r,e,u,o),o.pop(),r):(i=i?n.value():n,f=f?t.value():t,r=r(i,f,e,u,o),o.pop(),r)}function j(n){return typeof n=="function"?n:null==n?X:(typeof n=="object"?O:r)(n)}function d(n,t){return n<t}function m(n,t){var r=-1,e=P(n)?Array(n.length):[];return jn(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function O(n){var t=Dn(n);return function(r){var e=t.length;if(null==r)return!e;for(r=Object(r);e--;){var u=t[e];if(!(u in r&&g(n[u],r[u],Z,3)))return false}return true}} -function x(n,t){return n=Object(n),C(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function A(n){var t;return t=_n(t===Z?n.length-1:t,0),function(){for(var r=arguments,e=-1,u=_n(r.length-t,0),o=Array(u);++e<u;)o[e]=r[t+e];for(e=-1,u=Array(t+1);++e<t;)u[e]=r[e];return u[t]=o,n.apply(this,u)}}function E(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e<u;)r[e]=n[e+t];return r}function w(n){return E(n,0,n.length)}function k(n,t){var r;return jn(n,function(n,e,u){ -return r=t(n,e,u),!r}),!!r}function N(n,r){return C(r,function(n,r){return r.func.apply(r.thisArg,t([n],r.args))},n)}function S(n,t,r,e){r||(r={});for(var u=-1,o=t.length;++u<o;){var i=t[u],c=e?e(r[i],n[i],i,r,n):Z,f=r,a=i,i=c===Z?n[i]:c,c=f[a];ln.call(f,a)&&J(c,i)&&(i!==Z||a in f)||(f[a]=i)}return r}function T(n){return A(function(t,r){var e=-1,u=r.length,o=1<u?r[u-1]:Z,o=3<n.length&&typeof o=="function"?(u--,o):Z;for(t=Object(t);++e<u;){var i=r[e];i&&n(t,i,e,o)}return t})}function F(n){return function(){ -var t=arguments,r=f(n.prototype),t=n.apply(r,t);return V(t)?t:r}}function B(n,t,r){function e(){for(var o=-1,i=arguments.length,c=-1,f=r.length,a=Array(f+i),l=this&&this!==un&&this instanceof e?u:n;++c<f;)a[c]=r[c];for(;i--;)a[c++]=arguments[++o];return l.apply(t,a)}if(typeof n!="function")throw new TypeError("Expected a function");var u=F(n);return e}function R(n,t,r,e,u,o){var i=n.length,c=t.length;if(i!=c&&!(2&u&&c>i))return false;for(var c=-1,f=true,a=1&u?[]:Z;++c<i;){var l=n[c],p=t[c];if(void 0!==Z){ -f=false;break}if(a){if(!k(t,function(n,t){if(!$(a,t)&&(l===n||r(l,n,e,u,o)))return a.push(t)})){f=false;break}}else if(l!==p&&!r(l,p,e,u,o)){f=false;break}}return f}function D(n,t,r,e,u,o){var i=2&u,c=Dn(n),f=c.length,a=Dn(t).length;if(f!=a&&!i)return false;for(var l=f;l--;){var p=c[l];if(!(i?p in t:ln.call(t,p)))return false}for(a=true;++l<f;){var p=c[l],s=n[p],h=t[p];if(void 0!==Z||s!==h&&!r(s,h,e,u,o)){a=false;break}i||(i="constructor"==p)}return a&&!i&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(a=false)), -a}function I(n){return kn(n)||M(n)}function q(n){return n&&n.length?n[0]:Z}function $(n,t,r){var e=n?n.length:0;r=typeof r=="number"?0>r?_n(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++r<e;){var o=n[r];if(u?o===t:o!==o)return r}return-1}function z(n,t){return jn(n,j(t))}function C(n,t,r){return e(n,j(t),r,3>arguments.length,jn)}function G(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function");return n=Nn(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=Z),r}}function J(n,t){ -return n===t||n!==n&&t!==t}function M(n){return H(n)&&P(n)&&ln.call(n,"callee")&&(!bn.call(n,"callee")||"[object Arguments]"==sn.call(n))}function P(n){var t;return(t=null!=n)&&(t=On(n),t=typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t),t&&!U(n)}function U(n){return n=V(n)?sn.call(n):"","[object Function]"==n||"[object GeneratorFunction]"==n}function V(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function H(n){return!!n&&typeof n=="object"}function K(n){return typeof n=="number"||H(n)&&"[object Number]"==sn.call(n); -}function L(n){return typeof n=="string"||!kn(n)&&H(n)&&"[object String]"==sn.call(n)}function Q(n){return typeof n=="string"?n:null==n?"":n+""}function W(n){return n?u(n,Dn(n)):[]}function X(n){return n}function Y(n,r,e){var u=Dn(r),o=b(r,u);null!=e||V(r)&&(o.length||!u.length)||(e=r,r=n,n=this,o=b(r,Dn(r)));var i=!(V(e)&&"chain"in e&&!e.chain),c=U(n);return jn(o,function(e){var u=r[e];n[e]=u,c&&(n.prototype[e]=function(){var r=this.__chain__;if(i||r){var e=n(this.__wrapped__);return(e.__actions__=w(this.__actions__)).push({ -func:u,args:arguments,thisArg:n}),e.__chain__=r,e}return u.apply(n,t([this.value()],arguments))})}),n}var Z,nn=1/0,tn=/[&<>"'`]/g,rn=RegExp(tn.source),en=typeof self=="object"&&self&&self.Object===Object&&self,un=typeof global=="object"&&global&&global.Object===Object&&global||en||Function("return this")(),on=(en=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,cn=function(n){return function(t){return null==n?Z:n[t]}}({"&":"&", -"<":"<",">":">",'"':""","'":"'","`":"`"}),fn=Array.prototype,an=Object.prototype,ln=an.hasOwnProperty,pn=0,sn=an.toString,hn=un._,vn=Object.create,bn=an.propertyIsEnumerable,yn=un.isFinite,gn=Object.keys,_n=Math.max;i.prototype=f(o.prototype),i.prototype.constructor=i;var jn=function(n,t){return function(r,e){if(null==r)return r;if(!P(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++o<u)&&false!==e(i[o],o,i););return r}}(v),dn=function(n){return function(t,r,e){var u=-1,o=Object(t); -e=e(t);for(var i=e.length;i--;){var c=e[n?i:++u];if(false===r(o[c],c,o))break}return t}}(),mn=function(n,t){return function(r){return n(t(r))}}(gn,Object),On=r("length"),xn=String,An=function(n){return function(t,r,e){var u=Object(t);if(!P(t)){var o=j(r);t=Dn(t),r=function(n){return o(u[n],n,u)}}return r=n(t,r,e),-1<r?u[o?t[r]:r]:Z}}(function(n,t,r){var e=n?n.length:0;if(!e)return-1;r=null==r?0:Nn(r),0>r&&(r=_n(e+r,0));n:{for(t=j(t),e=n.length,r+=-1;++r<e;)if(t(n[r],r,n)){n=r;break n}n=-1}return n}),gn=A(function(n,t,r){ -return B(n,t,r)}),En=A(function(n,t){return a(n,1,t)}),wn=A(function(n,t,r){return a(n,Sn(t)||0,r)}),kn=Array.isArray,Nn=Number,Sn=Number,Tn=T(function(n,t){S(t,Dn(t),n)}),Fn=T(function(t,r){S(r,n(r),t)}),Bn=T(function(t,r,e,u){S(r,n(r),t,u)}),Rn=A(function(n){return n.push(Z,c),Bn.apply(Z,n)}),Dn=mn,mn=A(function(n,t){return null==n?{}:x(n,m(h(t,1),xn))});o.assignIn=Fn,o.before=G,o.bind=gn,o.chain=function(n){return n=o(n),n.__chain__=true,n},o.compact=function(n){return s(n,Boolean)},o.concat=function(){ -for(var n=arguments.length,r=Array(n?n-1:0),e=arguments[0],u=n;u--;)r[u-1]=arguments[u];return n?t(kn(e)?w(e):[e],h(r,1)):[]},o.create=function(n,t){var r=f(n);return t?Tn(r,t):r},o.defaults=Rn,o.defer=En,o.delay=wn,o.filter=function(n,t){return s(n,j(t))},o.flatten=function(n){return n&&n.length?h(n,1):[]},o.flattenDeep=function(n){return n&&n.length?h(n,nn):[]},o.iteratee=j,o.keys=Dn,o.map=function(n,t){return m(n,j(t))},o.matches=function(n){return O(Tn({},n))},o.mixin=Y,o.negate=function(n){if(typeof n!="function")throw new TypeError("Expected a function"); -return function(){return!n.apply(this,arguments)}},o.once=function(n){return G(2,n)},o.pick=mn,o.slice=function(n,t,r){var e=n?n.length:0;return r=r===Z?e:+r,e?E(n,null==t?0:+t,r):[]},o.sortBy=function(n,t){var e=0;return t=j(t),m(m(n,function(n,r,u){return{value:n,index:e++,criteria:t(n,r,u)}}).sort(function(n,t){var r;n:{r=n.criteria;var e=t.criteria;if(r!==e){var u=r!==Z,o=null===r,i=r===r,c=e!==Z,f=null===e,a=e===e;if(!f&&r>e||o&&c&&a||!u&&a||!i){r=1;break n}if(!o&&r<e||f&&u&&i||!c&&i||!a){r=-1; -break n}}r=0}return r||n.index-t.index}),r("value"))},o.tap=function(n,t){return t(n),n},o.thru=function(n,t){return t(n)},o.toArray=function(n){return P(n)?n.length?w(n):[]:W(n)},o.values=W,o.extend=Fn,Y(o,o),o.clone=function(n){return V(n)?kn(n)?w(n):S(n,Dn(n)):n},o.escape=function(n){return(n=Q(n))&&rn.test(n)?n.replace(tn,cn):n},o.every=function(n,t,r){return t=r?Z:t,l(n,j(t))},o.find=An,o.forEach=z,o.has=function(n,t){return null!=n&&ln.call(n,t)},o.head=q,o.identity=X,o.indexOf=$,o.isArguments=M, -o.isArray=kn,o.isBoolean=function(n){return true===n||false===n||H(n)&&"[object Boolean]"==sn.call(n)},o.isDate=function(n){return H(n)&&"[object Date]"==sn.call(n)},o.isEmpty=function(n){return P(n)&&(kn(n)||L(n)||U(n.splice)||M(n))?!n.length:!Dn(n).length},o.isEqual=function(n,t){return g(n,t)},o.isFinite=function(n){return typeof n=="number"&&yn(n)},o.isFunction=U,o.isNaN=function(n){return K(n)&&n!=+n},o.isNull=function(n){return null===n},o.isNumber=K,o.isObject=V,o.isRegExp=function(n){return V(n)&&"[object RegExp]"==sn.call(n); -},o.isString=L,o.isUndefined=function(n){return n===Z},o.last=function(n){var t=n?n.length:0;return t?n[t-1]:Z},o.max=function(n){return n&&n.length?p(n,X,y):Z},o.min=function(n){return n&&n.length?p(n,X,d):Z},o.noConflict=function(){return un._===this&&(un._=hn),this},o.noop=function(){},o.reduce=C,o.result=function(n,t,r){return t=null==n?Z:n[t],t===Z&&(t=r),U(t)?t.call(n):t},o.size=function(n){return null==n?0:(n=P(n)?n:Dn(n),n.length)},o.some=function(n,t,r){return t=r?Z:t,k(n,j(t))},o.uniqueId=function(n){ -var t=++pn;return Q(n)+t},o.each=z,o.first=q,Y(o,function(){var n={};return v(o,function(t,r){ln.call(o.prototype,r)||(n[r]=t)}),n}(),{chain:false}),o.VERSION="4.14.1",jn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:fn)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);o.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(kn(u)?u:[],n); -}return this[r](function(r){return t.apply(kn(r)?r:[],n)})}}),o.prototype.toJSON=o.prototype.valueOf=o.prototype.value=function(){return N(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(un._=o, define(function(){return o})):on?((on.exports=o)._=o,en._=o):un._=o}).call(this);
\ No newline at end of file +;(function(){function n(n,t){return n.push.apply(n,t),n}function t(n){return function(t){return null==t?Z:t[n]}}function r(n,t,r,e,u){return u(n,function(n,u,o){r=e?(e=false,n):t(r,n,u,o)}),r}function e(n,t){return d(t,function(t){return n[t]})}function u(n){return n instanceof o?n:new o(n)}function o(n,t){this.__wrapped__=n,this.__actions__=[],this.__chain__=!!t}function i(n,t,r,e){return n===Z||J(n,an[r])&&!ln.call(e,r)?t:n}function c(n){return V(n)?vn(n):{}}function f(n,t,r){if(typeof n!="function")throw new TypeError("Expected a function"); +return setTimeout(function(){n.apply(Z,r)},t)}function a(n,t){var r=true;return jn(n,function(n,e,u){return r=!!t(n,e,u)}),r}function l(n,t,r){for(var e=-1,u=n.length;++e<u;){var o=n[e],i=t(o);if(null!=i&&(c===Z?i===i:r(i,c)))var c=i,f=o}return f}function p(n,t){var r=[];return jn(n,function(n,e,u){t(n,e,u)&&r.push(n)}),r}function s(t,r,e,u,o){var i=-1,c=t.length;for(e||(e=D),o||(o=[]);++i<c;){var f=t[i];0<r&&e(f)?1<r?s(f,r-1,e,u,o):n(o,f):u||(o[o.length]=f)}return o}function h(n,t){return n&&dn(n,t,Rn); +}function v(n,t){return p(t,function(t){return U(n[t])})}function b(n,t){return n>t}function y(n,t,r,e,u){return n===t||(null==n||null==t||!V(n)&&!H(t)?n!==n&&t!==t:g(n,t,y,r,e,u))}function g(n,t,r,e,u,o){var i=wn(n),c=wn(t),f="[object Array]",a="[object Array]";i||(f=sn.call(n),f="[object Arguments]"==f?"[object Object]":f),c||(a=sn.call(t),a="[object Arguments]"==a?"[object Object]":a);var l="[object Object]"==f&&true,c="[object Object]"==a&&true,a=f==a;o||(o=[]);var p=On(o,function(t){return t[0]==n; +}),s=On(o,function(n){return n[0]==t});if(p&&s)return p[1]==t;if(o.push([n,t]),o.push([t,n]),a&&!l){if(i)r=B(n,t,r,e,u,o);else n:{switch(f){case"[object Boolean]":case"[object Date]":case"[object Number]":r=J(+n,+t);break n;case"[object Error]":r=n.name==t.name&&n.message==t.message;break n;case"[object RegExp]":case"[object String]":r=n==t+"";break n}r=false}return o.pop(),r}return 2&u||(i=l&&ln.call(n,"__wrapped__"),f=c&&ln.call(t,"__wrapped__"),!i&&!f)?!!a&&(r=R(n,t,r,e,u,o),o.pop(),r):(i=i?n.value():n, +f=f?t.value():t,r=r(i,f,e,u,o),o.pop(),r)}function _(n){return typeof n=="function"?n:null==n?X:(typeof n=="object"?m:t)(n)}function j(n,t){return n<t}function d(n,t){var r=-1,e=P(n)?Array(n.length):[];return jn(n,function(n,u,o){e[++r]=t(n,u,o)}),e}function m(n){var t=gn(n);return function(r){var e=t.length;if(null==r)return!e;for(r=Object(r);e--;){var u=t[e];if(!(u in r&&y(n[u],r[u],Z,3)))return false}return true}}function O(n,t){return n=Object(n),C(t,function(t,r){return r in n&&(t[r]=n[r]),t},{})}function x(n){ +var t;return t=_n(t===Z?n.length-1:t,0),function(){for(var r=arguments,e=-1,u=_n(r.length-t,0),o=Array(u);++e<u;)o[e]=r[t+e];for(e=-1,u=Array(t+1);++e<t;)u[e]=r[e];return u[t]=o,n.apply(this,u)}}function A(n,t,r){var e=-1,u=n.length;for(0>t&&(t=-t>u?0:u+t),r=r>u?u:r,0>r&&(r+=u),u=t>r?0:r-t>>>0,t>>>=0,r=Array(u);++e<u;)r[e]=n[e+t];return r}function E(n){return A(n,0,n.length)}function w(n,t){var r;return jn(n,function(n,e,u){return r=t(n,e,u),!r}),!!r}function k(t,r){return C(r,function(t,r){return r.func.apply(r.thisArg,n([t],r.args)); +},t)}function N(n,t,r,e){r||(r={});for(var u=-1,o=t.length;++u<o;){var i=t[u],c=e?e(r[i],n[i],i,r,n):Z,f=r,a=i,i=c===Z?n[i]:c,c=f[a];ln.call(f,a)&&J(c,i)&&(i!==Z||a in f)||(f[a]=i)}return r}function S(n){return x(function(t,r){var e=-1,u=r.length,o=1<u?r[u-1]:Z,o=3<n.length&&typeof o=="function"?(u--,o):Z;for(t=Object(t);++e<u;){var i=r[e];i&&n(t,i,e,o)}return t})}function T(n){return function(){var t=arguments,r=c(n.prototype),t=n.apply(r,t);return V(t)?t:r}}function F(n,t,r){function e(){for(var o=-1,i=arguments.length,c=-1,f=r.length,a=Array(f+i),l=this&&this!==un&&this instanceof e?u:n;++c<f;)a[c]=r[c]; +for(;i--;)a[c++]=arguments[++o];return l.apply(t,a)}if(typeof n!="function")throw new TypeError("Expected a function");var u=T(n);return e}function B(n,t,r,e,u,o){var i=n.length,c=t.length;if(i!=c&&!(2&u&&c>i))return false;for(var c=-1,f=true,a=1&u?[]:Z;++c<i;){var l=n[c],p=t[c];if(void 0!==Z){f=false;break}if(a){if(!w(t,function(n,t){if(!$(a,t)&&(l===n||r(l,n,e,u,o)))return a.push(t)})){f=false;break}}else if(l!==p&&!r(l,p,e,u,o)){f=false;break}}return f}function R(n,t,r,e,u,o){var i=2&u,c=Rn(n),f=c.length,a=Rn(t).length; +if(f!=a&&!i)return false;for(var l=f;l--;){var p=c[l];if(!(i?p in t:ln.call(t,p)))return false}for(a=true;++l<f;){var p=c[l],s=n[p],h=t[p];if(void 0!==Z||s!==h&&!r(s,h,e,u,o)){a=false;break}i||(i="constructor"==p)}return a&&!i&&(r=n.constructor,e=t.constructor,r!=e&&"constructor"in n&&"constructor"in t&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(a=false)),a}function D(n){return wn(n)||M(n)}function I(n){var t=[];if(null!=n)for(var r in Object(n))t.push(r);return t}function q(n){ +return n&&n.length?n[0]:Z}function $(n,t,r){var e=n?n.length:0;r=typeof r=="number"?0>r?_n(e+r,0):r:0,r=(r||0)-1;for(var u=t===t;++r<e;){var o=n[r];if(u?o===t:o!==o)return r}return-1}function z(n,t){return jn(n,_(t))}function C(n,t,e){return r(n,_(t),e,3>arguments.length,jn)}function G(n,t){var r;if(typeof t!="function")throw new TypeError("Expected a function");return n=kn(n),function(){return 0<--n&&(r=t.apply(this,arguments)),1>=n&&(t=Z),r}}function J(n,t){return n===t||n!==n&&t!==t}function M(n){ +return H(n)&&P(n)&&ln.call(n,"callee")&&(!bn.call(n,"callee")||"[object Arguments]"==sn.call(n))}function P(n){var t;return(t=null!=n)&&(t=n.length,t=typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t),t&&!U(n)}function U(n){return n=V(n)?sn.call(n):"","[object Function]"==n||"[object GeneratorFunction]"==n}function V(n){var t=typeof n;return!!n&&("object"==t||"function"==t)}function H(n){return!!n&&typeof n=="object"}function K(n){return typeof n=="number"||H(n)&&"[object Number]"==sn.call(n)} +function L(n){return typeof n=="string"||!wn(n)&&H(n)&&"[object String]"==sn.call(n)}function Q(n){return typeof n=="string"?n:null==n?"":n+""}function W(n){return n?e(n,Rn(n)):[]}function X(n){return n}function Y(t,r,e){var u=Rn(r),o=v(r,u);null!=e||V(r)&&(o.length||!u.length)||(e=r,r=t,t=this,o=v(r,Rn(r)));var i=!(V(e)&&"chain"in e&&!e.chain),c=U(t);return jn(o,function(e){var u=r[e];t[e]=u,c&&(t.prototype[e]=function(){var r=this.__chain__;if(i||r){var e=t(this.__wrapped__);return(e.__actions__=E(this.__actions__)).push({ +func:u,args:arguments,thisArg:t}),e.__chain__=r,e}return u.apply(t,n([this.value()],arguments))})}),t}var Z,nn=1/0,tn=/[&<>"'`]/g,rn=RegExp(tn.source),en=typeof self=="object"&&self&&self.Object===Object&&self,un=typeof global=="object"&&global&&global.Object===Object&&global||en||Function("return this")(),on=(en=typeof exports=="object"&&exports&&!exports.nodeType&&exports)&&typeof module=="object"&&module&&!module.nodeType&&module,cn=function(n){return function(t){return null==n?Z:n[t]}}({"&":"&", +"<":"<",">":">",'"':""","'":"'","`":"`"}),fn=Array.prototype,an=Object.prototype,ln=an.hasOwnProperty,pn=0,sn=an.toString,hn=un._,vn=Object.create,bn=an.propertyIsEnumerable,yn=un.isFinite,gn=function(n,t){return function(r){return n(t(r))}}(Object.keys,Object),_n=Math.max;o.prototype=c(u.prototype),o.prototype.constructor=o;var jn=function(n,t){return function(r,e){if(null==r)return r;if(!P(r))return n(r,e);for(var u=r.length,o=t?u:-1,i=Object(r);(t?o--:++o<u)&&false!==e(i[o],o,i);); +return r}}(h),dn=function(n){return function(t,r,e){var u=-1,o=Object(t);e=e(t);for(var i=e.length;i--;){var c=e[n?i:++u];if(false===r(o[c],c,o))break}return t}}(),mn=String,On=function(n){return function(t,r,e){var u=Object(t);if(!P(t)){var o=_(r);t=Rn(t),r=function(n){return o(u[n],n,u)}}return r=n(t,r,e),-1<r?u[o?t[r]:r]:Z}}(function(n,t,r){var e=n?n.length:0;if(!e)return-1;r=null==r?0:kn(r),0>r&&(r=_n(e+r,0));n:{for(t=_(t),e=n.length,r+=-1;++r<e;)if(t(n[r],r,n)){n=r;break n}n=-1}return n}),xn=x(function(n,t,r){ +return F(n,t,r)}),An=x(function(n,t){return f(n,1,t)}),En=x(function(n,t,r){return f(n,Nn(t)||0,r)}),wn=Array.isArray,kn=Number,Nn=Number,Sn=S(function(n,t){N(t,gn(t),n)}),Tn=S(function(n,t){N(t,I(t),n)}),Fn=S(function(n,t,r,e){N(t,Dn(t),n,e)}),Bn=x(function(n){return n.push(Z,i),Fn.apply(Z,n)}),Rn=gn,Dn=I,In=x(function(n,t){return null==n?{}:O(n,d(s(t,1),mn))});u.assignIn=Tn,u.before=G,u.bind=xn,u.chain=function(n){return n=u(n),n.__chain__=true,n},u.compact=function(n){return p(n,Boolean)},u.concat=function(){ +for(var t=arguments.length,r=Array(t?t-1:0),e=arguments[0],u=t;u--;)r[u-1]=arguments[u];return t?n(wn(e)?E(e):[e],s(r,1)):[]},u.create=function(n,t){var r=c(n);return t?Sn(r,t):r},u.defaults=Bn,u.defer=An,u.delay=En,u.filter=function(n,t){return p(n,_(t))},u.flatten=function(n){return n&&n.length?s(n,1):[]},u.flattenDeep=function(n){return n&&n.length?s(n,nn):[]},u.iteratee=_,u.keys=Rn,u.map=function(n,t){return d(n,_(t))},u.matches=function(n){return m(Sn({},n))},u.mixin=Y,u.negate=function(n){if(typeof n!="function")throw new TypeError("Expected a function"); +return function(){return!n.apply(this,arguments)}},u.once=function(n){return G(2,n)},u.pick=In,u.slice=function(n,t,r){var e=n?n.length:0;return r=r===Z?e:+r,e?A(n,null==t?0:+t,r):[]},u.sortBy=function(n,r){var e=0;return r=_(r),d(d(n,function(n,t,u){return{value:n,index:e++,criteria:r(n,t,u)}}).sort(function(n,t){var r;n:{r=n.criteria;var e=t.criteria;if(r!==e){var u=r!==Z,o=null===r,i=r===r,c=e!==Z,f=null===e,a=e===e;if(!f&&r>e||o&&c&&a||!u&&a||!i){r=1;break n}if(!o&&r<e||f&&u&&i||!c&&i||!a){r=-1; +break n}}r=0}return r||n.index-t.index}),t("value"))},u.tap=function(n,t){return t(n),n},u.thru=function(n,t){return t(n)},u.toArray=function(n){return P(n)?n.length?E(n):[]:W(n)},u.values=W,u.extend=Tn,Y(u,u),u.clone=function(n){return V(n)?wn(n)?E(n):N(n,gn(n)):n},u.escape=function(n){return(n=Q(n))&&rn.test(n)?n.replace(tn,cn):n},u.every=function(n,t,r){return t=r?Z:t,a(n,_(t))},u.find=On,u.forEach=z,u.has=function(n,t){return null!=n&&ln.call(n,t)},u.head=q,u.identity=X,u.indexOf=$,u.isArguments=M, +u.isArray=wn,u.isBoolean=function(n){return true===n||false===n||H(n)&&"[object Boolean]"==sn.call(n)},u.isDate=function(n){return H(n)&&"[object Date]"==sn.call(n)},u.isEmpty=function(n){return P(n)&&(wn(n)||L(n)||U(n.splice)||M(n))?!n.length:!gn(n).length},u.isEqual=function(n,t){return y(n,t)},u.isFinite=function(n){return typeof n=="number"&&yn(n)},u.isFunction=U,u.isNaN=function(n){return K(n)&&n!=+n},u.isNull=function(n){return null===n},u.isNumber=K,u.isObject=V,u.isRegExp=function(n){return V(n)&&"[object RegExp]"==sn.call(n); +},u.isString=L,u.isUndefined=function(n){return n===Z},u.last=function(n){var t=n?n.length:0;return t?n[t-1]:Z},u.max=function(n){return n&&n.length?l(n,X,b):Z},u.min=function(n){return n&&n.length?l(n,X,j):Z},u.noConflict=function(){return un._===this&&(un._=hn),this},u.noop=function(){},u.reduce=C,u.result=function(n,t,r){return t=null==n?Z:n[t],t===Z&&(t=r),U(t)?t.call(n):t},u.size=function(n){return null==n?0:(n=P(n)?n:gn(n),n.length)},u.some=function(n,t,r){return t=r?Z:t,w(n,_(t))},u.uniqueId=function(n){ +var t=++pn;return Q(n)+t},u.each=z,u.first=q,Y(u,function(){var n={};return h(u,function(t,r){ln.call(u.prototype,r)||(n[r]=t)}),n}(),{chain:false}),u.VERSION="4.15.0",jn("pop join replace reverse split push shift sort splice unshift".split(" "),function(n){var t=(/^(?:replace|split)$/.test(n)?String.prototype:fn)[n],r=/^(?:push|sort|unshift)$/.test(n)?"tap":"thru",e=/^(?:pop|join|replace|shift)$/.test(n);u.prototype[n]=function(){var n=arguments;if(e&&!this.__chain__){var u=this.value();return t.apply(wn(u)?u:[],n); +}return this[r](function(r){return t.apply(wn(r)?r:[],n)})}}),u.prototype.toJSON=u.prototype.valueOf=u.prototype.value=function(){return k(this.__wrapped__,this.__actions__)},typeof define=="function"&&typeof define.amd=="object"&&define.amd?(un._=u, define(function(){return u})):on?((on.exports=u)._=u,en._=u):un._=u}).call(this);
\ No newline at end of file diff --git a/tools/eslint/node_modules/lodash/deburr.js b/tools/eslint/node_modules/lodash/deburr.js index 6862072121..bc08b05d5a 100644 --- a/tools/eslint/node_modules/lodash/deburr.js +++ b/tools/eslint/node_modules/lodash/deburr.js @@ -1,8 +1,8 @@ var deburrLetter = require('./_deburrLetter'), toString = require('./toString'); -/** Used to match latin-1 supplementary letters (excluding mathematical operators). */ -var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; +/** Used to match Latin Unicode letters (excluding mathematical operators). */ +var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; /** Used to compose unicode character classes. */ var rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', @@ -19,8 +19,9 @@ var reComboMark = RegExp(rsCombo, 'g'); /** * Deburrs `string` by converting - * [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) - * to basic latin letters and removing + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). * * @static @@ -36,7 +37,7 @@ var reComboMark = RegExp(rsCombo, 'g'); */ function deburr(string) { string = toString(string); - return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ''); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); } module.exports = deburr; diff --git a/tools/eslint/node_modules/lodash/difference.js b/tools/eslint/node_modules/lodash/difference.js index 8c4af3dcaa..c18e05785b 100644 --- a/tools/eslint/node_modules/lodash/difference.js +++ b/tools/eslint/node_modules/lodash/difference.js @@ -5,7 +5,7 @@ var baseDifference = require('./_baseDifference'), /** * Creates an array of `array` values not included in the other given arrays - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. The order of result values is determined by the * order they occur in the first array. * diff --git a/tools/eslint/node_modules/lodash/endsWith.js b/tools/eslint/node_modules/lodash/endsWith.js index dc43484f2f..76fc866e3e 100644 --- a/tools/eslint/node_modules/lodash/endsWith.js +++ b/tools/eslint/node_modules/lodash/endsWith.js @@ -10,7 +10,7 @@ var baseClamp = require('./_baseClamp'), * @memberOf _ * @since 3.0.0 * @category String - * @param {string} [string=''] The string to search. + * @param {string} [string=''] The string to inspect. * @param {string} [target] The string to search for. * @param {number} [position=string.length] The position to search up to. * @returns {boolean} Returns `true` if `string` ends with `target`, diff --git a/tools/eslint/node_modules/lodash/eq.js b/tools/eslint/node_modules/lodash/eq.js index b821483faa..a940688053 100644 --- a/tools/eslint/node_modules/lodash/eq.js +++ b/tools/eslint/node_modules/lodash/eq.js @@ -1,6 +1,6 @@ /** * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. * * @static diff --git a/tools/eslint/node_modules/lodash/escapeRegExp.js b/tools/eslint/node_modules/lodash/escapeRegExp.js index fe5196046b..0a58c69fc8 100644 --- a/tools/eslint/node_modules/lodash/escapeRegExp.js +++ b/tools/eslint/node_modules/lodash/escapeRegExp.js @@ -2,7 +2,7 @@ var toString = require('./toString'); /** * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); diff --git a/tools/eslint/node_modules/lodash/every.js b/tools/eslint/node_modules/lodash/every.js index 96495bdeb3..114f40f1ab 100644 --- a/tools/eslint/node_modules/lodash/every.js +++ b/tools/eslint/node_modules/lodash/every.js @@ -9,6 +9,11 @@ var arrayEvery = require('./_arrayEvery'), * Iteration is stopped once `predicate` returns falsey. The predicate is * invoked with three arguments: (value, index|key, collection). * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * * @static * @memberOf _ * @since 0.1.0 diff --git a/tools/eslint/node_modules/lodash/find.js b/tools/eslint/node_modules/lodash/find.js index 88fb9ab374..b6d0950d89 100644 --- a/tools/eslint/node_modules/lodash/find.js +++ b/tools/eslint/node_modules/lodash/find.js @@ -10,7 +10,7 @@ var createFind = require('./_createFind'), * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=0] The index to search from. diff --git a/tools/eslint/node_modules/lodash/findIndex.js b/tools/eslint/node_modules/lodash/findIndex.js index 224604a16b..0b11d9315c 100644 --- a/tools/eslint/node_modules/lodash/findIndex.js +++ b/tools/eslint/node_modules/lodash/findIndex.js @@ -13,7 +13,7 @@ var nativeMax = Math.max; * @memberOf _ * @since 1.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=0] The index to search from. diff --git a/tools/eslint/node_modules/lodash/findKey.js b/tools/eslint/node_modules/lodash/findKey.js index becfb5aa2f..cac0248a9d 100644 --- a/tools/eslint/node_modules/lodash/findKey.js +++ b/tools/eslint/node_modules/lodash/findKey.js @@ -10,7 +10,7 @@ var baseFindKey = require('./_baseFindKey'), * @memberOf _ * @since 1.1.0 * @category Object - * @param {Object} object The object to search. + * @param {Object} object The object to inspect. * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {string|undefined} Returns the key of the matched element, * else `undefined`. diff --git a/tools/eslint/node_modules/lodash/findLast.js b/tools/eslint/node_modules/lodash/findLast.js index a1dce40397..3ce09f47ec 100644 --- a/tools/eslint/node_modules/lodash/findLast.js +++ b/tools/eslint/node_modules/lodash/findLast.js @@ -9,7 +9,7 @@ var createFind = require('./_createFind'), * @memberOf _ * @since 2.0.0 * @category Collection - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=collection.length-1] The index to search from. diff --git a/tools/eslint/node_modules/lodash/findLastIndex.js b/tools/eslint/node_modules/lodash/findLastIndex.js index 684be484fa..63e8770442 100644 --- a/tools/eslint/node_modules/lodash/findLastIndex.js +++ b/tools/eslint/node_modules/lodash/findLastIndex.js @@ -14,7 +14,7 @@ var nativeMax = Math.max, * @memberOf _ * @since 2.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=array.length-1] The index to search from. diff --git a/tools/eslint/node_modules/lodash/findLastKey.js b/tools/eslint/node_modules/lodash/findLastKey.js index 9db2c5e732..66fb9fbcec 100644 --- a/tools/eslint/node_modules/lodash/findLastKey.js +++ b/tools/eslint/node_modules/lodash/findLastKey.js @@ -10,7 +10,7 @@ var baseFindKey = require('./_baseFindKey'), * @memberOf _ * @since 2.0.0 * @category Object - * @param {Object} object The object to search. + * @param {Object} object The object to inspect. * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {string|undefined} Returns the key of the matched element, * else `undefined`. diff --git a/tools/eslint/node_modules/lodash/fp/_baseConvert.js b/tools/eslint/node_modules/lodash/fp/_baseConvert.js index d294820d8c..0def5f67cb 100644 --- a/tools/eslint/node_modules/lodash/fp/_baseConvert.js +++ b/tools/eslint/node_modules/lodash/fp/_baseConvert.js @@ -143,6 +143,7 @@ function baseConvert(util, name, func, options) { 'keys': util.keys, 'rearg': util.rearg, 'spread': util.spread, + 'toInteger': util.toInteger, 'toPath': util.toPath }; @@ -156,6 +157,7 @@ function baseConvert(util, name, func, options) { keys = helpers.keys, rearg = helpers.rearg, spread = helpers.spread, + toInteger = helpers.toInteger, toPath = helpers.toPath; var aryMethodKeys = keys(mapping.aryMethod); @@ -209,10 +211,16 @@ function baseConvert(util, name, func, options) { return func; }; }, + 'nthArg': function(nthArg) { + return function(n) { + var arity = n < 0 ? 1 : (toInteger(n) + 1); + return curry(nthArg(n), arity); + }; + }, 'rearg': function(rearg) { return function(func, indexes) { - var n = indexes ? indexes.length : 0; - return curry(rearg(func, indexes), n); + var arity = indexes ? indexes.length : 0; + return curry(rearg(func, indexes), arity); }; }, 'runInContext': function(runInContext) { diff --git a/tools/eslint/node_modules/lodash/fp/_mapping.js b/tools/eslint/node_modules/lodash/fp/_mapping.js index cb36eedad1..dd4abcb551 100644 --- a/tools/eslint/node_modules/lodash/fp/_mapping.js +++ b/tools/eslint/node_modules/lodash/fp/_mapping.js @@ -73,10 +73,10 @@ exports.aryMethod = { '1': [ 'assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create', 'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow', - 'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', - 'mergeAll', 'methodOf', 'mixin', 'over', 'overEvery', 'overSome', 'rest', - 'reverse', 'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', - 'trimStart', 'uniqueId', 'words', 'zipAll' + 'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll', + 'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome','rest', 'reverse', + 'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart', + 'uniqueId', 'words', 'zipAll' ], '2': [ 'add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith', diff --git a/tools/eslint/node_modules/lodash/fp/_util.js b/tools/eslint/node_modules/lodash/fp/_util.js index d450396fc4..f8148129eb 100644 --- a/tools/eslint/node_modules/lodash/fp/_util.js +++ b/tools/eslint/node_modules/lodash/fp/_util.js @@ -10,5 +10,6 @@ module.exports = { 'keys': require('../_baseKeys'), 'rearg': require('../rearg'), 'spread': require('../spread'), + 'toInteger': require('../toInteger'), 'toPath': require('../toPath') }; diff --git a/tools/eslint/node_modules/lodash/fp/nthArg.js b/tools/eslint/node_modules/lodash/fp/nthArg.js index 8ccd8e60b1..fce3165942 100644 --- a/tools/eslint/node_modules/lodash/fp/nthArg.js +++ b/tools/eslint/node_modules/lodash/fp/nthArg.js @@ -1,5 +1,5 @@ var convert = require('./convert'), - func = convert('nthArg', require('../nthArg'), require('./_falseOptions')); + func = convert('nthArg', require('../nthArg')); func.placeholder = require('./placeholder'); module.exports = func; diff --git a/tools/eslint/node_modules/lodash/includes.js b/tools/eslint/node_modules/lodash/includes.js index 8c3c51376a..ae0deedc90 100644 --- a/tools/eslint/node_modules/lodash/includes.js +++ b/tools/eslint/node_modules/lodash/includes.js @@ -10,7 +10,7 @@ var nativeMax = Math.max; /** * Checks if `value` is in `collection`. If `collection` is a string, it's * checked for a substring of `value`, otherwise - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * is used for equality comparisons. If `fromIndex` is negative, it's used as * the offset from the end of `collection`. * @@ -18,7 +18,7 @@ var nativeMax = Math.max; * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object|string} collection The collection to search. + * @param {Array|Object|string} collection The collection to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. diff --git a/tools/eslint/node_modules/lodash/indexOf.js b/tools/eslint/node_modules/lodash/indexOf.js index 657e4b5eb6..8c9b86dc6a 100644 --- a/tools/eslint/node_modules/lodash/indexOf.js +++ b/tools/eslint/node_modules/lodash/indexOf.js @@ -6,7 +6,7 @@ var nativeMax = Math.max; /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it's used as the * offset from the end of `array`. * @@ -14,7 +14,7 @@ var nativeMax = Math.max; * @memberOf _ * @since 0.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. diff --git a/tools/eslint/node_modules/lodash/initial.js b/tools/eslint/node_modules/lodash/initial.js index f4441b547a..63e0c93ec9 100644 --- a/tools/eslint/node_modules/lodash/initial.js +++ b/tools/eslint/node_modules/lodash/initial.js @@ -1,4 +1,4 @@ -var dropRight = require('./dropRight'); +var baseSlice = require('./_baseSlice'); /** * Gets all but the last element of `array`. @@ -15,7 +15,8 @@ var dropRight = require('./dropRight'); * // => [1, 2] */ function initial(array) { - return dropRight(array, 1); + var length = array ? array.length : 0; + return length ? baseSlice(array, 0, -1) : []; } module.exports = initial; diff --git a/tools/eslint/node_modules/lodash/intersection.js b/tools/eslint/node_modules/lodash/intersection.js index 20c0a40840..b56d4dd325 100644 --- a/tools/eslint/node_modules/lodash/intersection.js +++ b/tools/eslint/node_modules/lodash/intersection.js @@ -5,7 +5,7 @@ var arrayMap = require('./_arrayMap'), /** * Creates an array of unique values that are included in all given arrays - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. The order of result values is determined by the * order they occur in the first array. * diff --git a/tools/eslint/node_modules/lodash/isArguments.js b/tools/eslint/node_modules/lodash/isArguments.js index a96e244baf..624a2f3caa 100644 --- a/tools/eslint/node_modules/lodash/isArguments.js +++ b/tools/eslint/node_modules/lodash/isArguments.js @@ -11,7 +11,7 @@ var hasOwnProperty = objectProto.hasOwnProperty; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -38,7 +38,7 @@ var propertyIsEnumerable = objectProto.propertyIsEnumerable; * // => false */ function isArguments(value) { - // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); } diff --git a/tools/eslint/node_modules/lodash/isArrayLike.js b/tools/eslint/node_modules/lodash/isArrayLike.js index 189a611f00..0f9668056e 100644 --- a/tools/eslint/node_modules/lodash/isArrayLike.js +++ b/tools/eslint/node_modules/lodash/isArrayLike.js @@ -1,5 +1,4 @@ -var getLength = require('./_getLength'), - isFunction = require('./isFunction'), +var isFunction = require('./isFunction'), isLength = require('./isLength'); /** @@ -28,7 +27,7 @@ var getLength = require('./_getLength'), * // => false */ function isArrayLike(value) { - return value != null && isLength(getLength(value)) && !isFunction(value); + return value != null && isLength(value.length) && !isFunction(value); } module.exports = isArrayLike; diff --git a/tools/eslint/node_modules/lodash/isBoolean.js b/tools/eslint/node_modules/lodash/isBoolean.js index b9083211c9..45cbdc1ce8 100644 --- a/tools/eslint/node_modules/lodash/isBoolean.js +++ b/tools/eslint/node_modules/lodash/isBoolean.js @@ -8,7 +8,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/isElement.js b/tools/eslint/node_modules/lodash/isElement.js index 67aca5dc7f..62cdb062ed 100644 --- a/tools/eslint/node_modules/lodash/isElement.js +++ b/tools/eslint/node_modules/lodash/isElement.js @@ -9,8 +9,7 @@ var isObjectLike = require('./isObjectLike'), * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a DOM element, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); diff --git a/tools/eslint/node_modules/lodash/isEmpty.js b/tools/eslint/node_modules/lodash/isEmpty.js index 9d4649690b..726ac9871f 100644 --- a/tools/eslint/node_modules/lodash/isEmpty.js +++ b/tools/eslint/node_modules/lodash/isEmpty.js @@ -3,10 +3,8 @@ var getTag = require('./_getTag'), isArray = require('./isArray'), isArrayLike = require('./isArrayLike'), isBuffer = require('./isBuffer'), - isFunction = require('./isFunction'), - isObjectLike = require('./isObjectLike'), - isString = require('./isString'), - keys = require('./keys'); + isPrototype = require('./_isPrototype'), + nativeKeys = require('./_nativeKeys'); /** `Object#toString` result references. */ var mapTag = '[object Map]', @@ -59,22 +57,23 @@ var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf'); */ function isEmpty(value) { if (isArrayLike(value) && - (isArray(value) || isString(value) || isFunction(value.splice) || - isArguments(value) || isBuffer(value))) { + (isArray(value) || typeof value == 'string' || + typeof value.splice == 'function' || isBuffer(value) || isArguments(value))) { return !value.length; } - if (isObjectLike(value)) { - var tag = getTag(value); - if (tag == mapTag || tag == setTag) { - return !value.size; - } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (nonEnumShadows || isPrototype(value)) { + return !nativeKeys(value).length; } for (var key in value) { if (hasOwnProperty.call(value, key)) { return false; } } - return !(nonEnumShadows && keys(value).length); + return true; } module.exports = isEmpty; diff --git a/tools/eslint/node_modules/lodash/isEqual.js b/tools/eslint/node_modules/lodash/isEqual.js index bd694dcf25..8a54126215 100644 --- a/tools/eslint/node_modules/lodash/isEqual.js +++ b/tools/eslint/node_modules/lodash/isEqual.js @@ -16,8 +16,7 @@ var baseIsEqual = require('./_baseIsEqual'); * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, - * else `false`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'a': 1 }; diff --git a/tools/eslint/node_modules/lodash/isEqualWith.js b/tools/eslint/node_modules/lodash/isEqualWith.js index a442b248f3..fb83d5010a 100644 --- a/tools/eslint/node_modules/lodash/isEqualWith.js +++ b/tools/eslint/node_modules/lodash/isEqualWith.js @@ -13,8 +13,7 @@ var baseIsEqual = require('./_baseIsEqual'); * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparisons. - * @returns {boolean} Returns `true` if the values are equivalent, - * else `false`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * function isGreeting(value) { diff --git a/tools/eslint/node_modules/lodash/isError.js b/tools/eslint/node_modules/lodash/isError.js index b4a93aebe2..85884b5202 100644 --- a/tools/eslint/node_modules/lodash/isError.js +++ b/tools/eslint/node_modules/lodash/isError.js @@ -8,7 +8,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -22,8 +22,7 @@ var objectToString = objectProto.toString; * @since 3.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an error object, - * else `false`. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. * @example * * _.isError(new Error); diff --git a/tools/eslint/node_modules/lodash/isFinite.js b/tools/eslint/node_modules/lodash/isFinite.js index 66af20699b..601842bc40 100644 --- a/tools/eslint/node_modules/lodash/isFinite.js +++ b/tools/eslint/node_modules/lodash/isFinite.js @@ -14,8 +14,7 @@ var nativeIsFinite = root.isFinite; * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a finite number, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * * _.isFinite(3); diff --git a/tools/eslint/node_modules/lodash/isFunction.js b/tools/eslint/node_modules/lodash/isFunction.js index 115f4667f5..f1d440b477 100644 --- a/tools/eslint/node_modules/lodash/isFunction.js +++ b/tools/eslint/node_modules/lodash/isFunction.js @@ -9,7 +9,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -33,8 +33,7 @@ var objectToString = objectProto.toString; */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array and weak map constructors, - // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. + // in Safari 8-9 which returns 'object' for typed array and other constructors. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } diff --git a/tools/eslint/node_modules/lodash/isLength.js b/tools/eslint/node_modules/lodash/isLength.js index cd9b257217..3a95caa962 100644 --- a/tools/eslint/node_modules/lodash/isLength.js +++ b/tools/eslint/node_modules/lodash/isLength.js @@ -4,16 +4,15 @@ var MAX_SAFE_INTEGER = 9007199254740991; /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. * @example * * _.isLength(3); diff --git a/tools/eslint/node_modules/lodash/isMatch.js b/tools/eslint/node_modules/lodash/isMatch.js index 32fc5fb501..9773a18cd7 100644 --- a/tools/eslint/node_modules/lodash/isMatch.js +++ b/tools/eslint/node_modules/lodash/isMatch.js @@ -5,8 +5,12 @@ var baseIsMatch = require('./_baseIsMatch'), * Performs a partial deep comparison between `object` and `source` to * determine if `object` contains equivalent property values. * - * **Note:** This method supports comparing the same values as `_.isEqual` - * and is equivalent to `_.matches` when `source` is partially applied. + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. * * @static * @memberOf _ diff --git a/tools/eslint/node_modules/lodash/isNumber.js b/tools/eslint/node_modules/lodash/isNumber.js index aa61488362..b8662920e7 100644 --- a/tools/eslint/node_modules/lodash/isNumber.js +++ b/tools/eslint/node_modules/lodash/isNumber.js @@ -8,7 +8,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/isObject.js b/tools/eslint/node_modules/lodash/isObject.js index d16542f8bf..4f96dd0a22 100644 --- a/tools/eslint/node_modules/lodash/isObject.js +++ b/tools/eslint/node_modules/lodash/isObject.js @@ -1,6 +1,6 @@ /** * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static diff --git a/tools/eslint/node_modules/lodash/isPlainObject.js b/tools/eslint/node_modules/lodash/isPlainObject.js index 13a90e7d03..3ac962c7f8 100644 --- a/tools/eslint/node_modules/lodash/isPlainObject.js +++ b/tools/eslint/node_modules/lodash/isPlainObject.js @@ -6,10 +6,11 @@ var getPrototype = require('./_getPrototype'), var objectTag = '[object Object]'; /** Used for built-in method references. */ -var objectProto = Object.prototype; +var funcProto = Function.prototype, + objectProto = Object.prototype; /** Used to resolve the decompiled source of functions. */ -var funcToString = Function.prototype.toString; +var funcToString = funcProto.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; @@ -19,7 +20,7 @@ var objectCtorString = funcToString.call(Object); /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -33,8 +34,7 @@ var objectToString = objectProto.toString; * @since 0.8.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * * function Foo() { diff --git a/tools/eslint/node_modules/lodash/isSafeInteger.js b/tools/eslint/node_modules/lodash/isSafeInteger.js index a780afb6b6..2a48526e10 100644 --- a/tools/eslint/node_modules/lodash/isSafeInteger.js +++ b/tools/eslint/node_modules/lodash/isSafeInteger.js @@ -15,8 +15,7 @@ var MAX_SAFE_INTEGER = 9007199254740991; * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a safe integer, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. * @example * * _.isSafeInteger(3); diff --git a/tools/eslint/node_modules/lodash/isString.js b/tools/eslint/node_modules/lodash/isString.js index b9d4f24feb..7b8be86ced 100644 --- a/tools/eslint/node_modules/lodash/isString.js +++ b/tools/eslint/node_modules/lodash/isString.js @@ -9,7 +9,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/isSymbol.js b/tools/eslint/node_modules/lodash/isSymbol.js index 060d97f17e..aef51150f5 100644 --- a/tools/eslint/node_modules/lodash/isSymbol.js +++ b/tools/eslint/node_modules/lodash/isSymbol.js @@ -8,7 +8,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/isWeakSet.js b/tools/eslint/node_modules/lodash/isWeakSet.js index a018f53c03..290164b4b5 100644 --- a/tools/eslint/node_modules/lodash/isWeakSet.js +++ b/tools/eslint/node_modules/lodash/isWeakSet.js @@ -8,7 +8,7 @@ var objectProto = Object.prototype; /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; diff --git a/tools/eslint/node_modules/lodash/keys.js b/tools/eslint/node_modules/lodash/keys.js index 186a4fedd0..d143c7186f 100644 --- a/tools/eslint/node_modules/lodash/keys.js +++ b/tools/eslint/node_modules/lodash/keys.js @@ -1,15 +1,12 @@ -var baseHas = require('./_baseHas'), +var arrayLikeKeys = require('./_arrayLikeKeys'), baseKeys = require('./_baseKeys'), - indexKeys = require('./_indexKeys'), - isArrayLike = require('./isArrayLike'), - isIndex = require('./_isIndex'), - isPrototype = require('./_isPrototype'); + isArrayLike = require('./isArrayLike'); /** * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * for more details. * * @static @@ -34,23 +31,7 @@ var baseHas = require('./_baseHas'), * // => ['0', '1'] */ function keys(object) { - var isProto = isPrototype(object); - if (!(isProto || isArrayLike(object))) { - return baseKeys(object); - } - var indexes = indexKeys(object), - skipIndexes = !!indexes, - result = indexes || [], - length = result.length; - - for (var key in object) { - if (baseHas(object, key) && - !(skipIndexes && (key == 'length' || isIndex(key, length))) && - !(isProto && key == 'constructor')) { - result.push(key); - } - } - return result; + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); } module.exports = keys; diff --git a/tools/eslint/node_modules/lodash/keysIn.js b/tools/eslint/node_modules/lodash/keysIn.js index d2fb91cb32..a62308f2c5 100644 --- a/tools/eslint/node_modules/lodash/keysIn.js +++ b/tools/eslint/node_modules/lodash/keysIn.js @@ -1,13 +1,6 @@ -var baseKeysIn = require('./_baseKeysIn'), - indexKeys = require('./_indexKeys'), - isIndex = require('./_isIndex'), - isPrototype = require('./_isPrototype'); - -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; +var arrayLikeKeys = require('./_arrayLikeKeys'), + baseKeysIn = require('./_baseKeysIn'), + isArrayLike = require('./isArrayLike'); /** * Creates an array of the own and inherited enumerable property names of `object`. @@ -33,23 +26,7 @@ var hasOwnProperty = objectProto.hasOwnProperty; * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { - var index = -1, - isProto = isPrototype(object), - props = baseKeysIn(object), - propsLength = props.length, - indexes = indexKeys(object), - skipIndexes = !!indexes, - result = indexes || [], - length = result.length; - - while (++index < propsLength) { - var key = props[index]; - if (!(skipIndexes && (key == 'length' || isIndex(key, length))) && - !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { - result.push(key); - } - } - return result; + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); } module.exports = keysIn; diff --git a/tools/eslint/node_modules/lodash/lastIndexOf.js b/tools/eslint/node_modules/lodash/lastIndexOf.js index f86516d517..c2e2c41124 100644 --- a/tools/eslint/node_modules/lodash/lastIndexOf.js +++ b/tools/eslint/node_modules/lodash/lastIndexOf.js @@ -14,7 +14,7 @@ var nativeMax = Math.max, * @memberOf _ * @since 0.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=array.length-1] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. diff --git a/tools/eslint/node_modules/lodash/lodash.js b/tools/eslint/node_modules/lodash/lodash.js index 22e73749bd..6b25256304 100644 --- a/tools/eslint/node_modules/lodash/lodash.js +++ b/tools/eslint/node_modules/lodash/lodash.js @@ -12,7 +12,7 @@ var undefined; /** Used as the semantic version number. */ - var VERSION = '4.14.1'; + var VERSION = '4.15.0'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; @@ -134,7 +134,7 @@ /** * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns). + * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). */ var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source); @@ -149,15 +149,15 @@ reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /; - /** Used to match non-compound words composed of alphanumeric characters. */ - var reBasicWord = /[a-zA-Z0-9]+/g; + /** Used to match words composed of alphanumeric characters. */ + var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; /** Used to match backslashes in property paths. */ var reEscapeChar = /\\(\\)?/g; /** * Used to match - * [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; @@ -182,8 +182,8 @@ /** Used to detect unsigned integer values. */ var reIsUint = /^(?:0|[1-9]\d*)$/; - /** Used to match latin-1 supplementary letters (excluding mathematical operators). */ - var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g; + /** Used to match Latin Unicode letters (excluding mathematical operators). */ + var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; /** Used to ensure capturing order of template delimiters. */ var reNoMatch = /($^)/; @@ -244,10 +244,10 @@ var reComboMark = RegExp(rsCombo, 'g'); /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ - var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); + var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); /** Used to match complex or compound words. */ - var reComplexWord = RegExp([ + var reUnicodeWord = RegExp([ rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, @@ -257,17 +257,17 @@ ].join('|'), 'g'); /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ - var reHasComplexSymbol = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); + var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboMarksRange + rsComboSymbolsRange + rsVarRange + ']'); /** Used to detect strings that need a more robust regexp to match words. */ - var reHasComplexWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; + var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; /** Used to assign default `context` object properties. */ var contextProps = [ 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', - 'Promise', 'Reflect', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', - 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', + 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', + 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' ]; @@ -306,16 +306,17 @@ cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false; - /** Used to map latin-1 supplementary letters to basic latin letters. */ + /** Used to map Latin Unicode letters to basic Latin letters. */ var deburredLetters = { + // Latin-1 Supplement block. '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', '\xc7': 'C', '\xe7': 'c', '\xd0': 'D', '\xf0': 'd', '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', - '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', - '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', + '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', + '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', '\xd1': 'N', '\xf1': 'n', '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', @@ -324,7 +325,43 @@ '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', '\xc6': 'Ae', '\xe6': 'ae', '\xde': 'Th', '\xfe': 'th', - '\xdf': 'ss' + '\xdf': 'ss', + // Latin Extended-A block. + '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', + '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', + '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', + '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', + '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', + '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', + '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', + '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', + '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', + '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', + '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', + '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', + '\u0134': 'J', '\u0135': 'j', + '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', + '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', + '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', + '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', + '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', + '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', + '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', + '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', + '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', + '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', + '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', + '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', + '\u0163': 't', '\u0165': 't', '\u0167': 't', + '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', + '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', + '\u0174': 'W', '\u0175': 'w', + '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', + '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', + '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', + '\u0132': 'IJ', '\u0133': 'ij', + '\u0152': 'Oe', '\u0153': 'oe', + '\u0149': "'n", '\u017f': 'ss' }; /** Used to map characters to HTML entities. */ @@ -560,7 +597,7 @@ * specifying an index to search from. * * @private - * @param {Array} [array] The array to search. + * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @returns {boolean} Returns `true` if `target` is found, else `false`. */ @@ -573,7 +610,7 @@ * This function is like `arrayIncludes` except that it accepts a comparator. * * @private - * @param {Array} [array] The array to search. + * @param {Array} [array] The array to inspect. * @param {*} target The value to search for. * @param {Function} comparator The comparator invoked per element. * @returns {boolean} Returns `true` if `target` is found, else `false`. @@ -700,12 +737,43 @@ } /** + * Gets the size of an ASCII `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + var asciiSize = baseProperty('length'); + + /** + * Converts an ASCII `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function asciiToArray(string) { + return string.split(''); + } + + /** + * Splits an ASCII `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function asciiWords(string) { + return string.match(reAsciiWord) || []; + } + + /** * The base implementation of methods like `_.findKey` and `_.findLastKey`, * without support for iteratee shorthands, which iterates over `collection` * using `eachFunc`. * * @private - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} predicate The function invoked per iteration. * @param {Function} eachFunc The function to iterate over `collection`. * @returns {*} Returns the found element or its key, else `undefined`. @@ -726,7 +794,7 @@ * support for iteratee shorthands. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} predicate The function invoked per iteration. * @param {number} fromIndex The index to search from. * @param {boolean} [fromRight] Specify iterating from right to left. @@ -748,7 +816,7 @@ * The base implementation of `_.indexOf` without `fromIndex` bounds checks. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. @@ -772,7 +840,7 @@ * This function is like `baseIndexOf` except that it accepts a comparator. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} fromIndex The index to search from. * @param {Function} comparator The comparator invoked per element. @@ -1035,7 +1103,8 @@ } /** - * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters. + * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A + * letters to basic Latin letters. * * @private * @param {string} letter The matched letter to deburr. @@ -1076,6 +1145,28 @@ } /** + * Checks if `string` contains Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a symbol is found, else `false`. + */ + function hasUnicode(string) { + return reHasUnicode.test(string); + } + + /** + * Checks if `string` contains a word composed of Unicode symbols. + * + * @private + * @param {string} string The string to inspect. + * @returns {boolean} Returns `true` if a word is found, else `false`. + */ + function hasUnicodeWord(string) { + return reHasUnicodeWord.test(string); + } + + /** * Checks if `value` is a host object in IE < 9. * * @private @@ -1129,7 +1220,7 @@ } /** - * Creates a function that invokes `func` with its first argument transformed. + * Creates a unary function that invokes `func` with its argument transformed. * * @private * @param {Function} func The function to wrap. @@ -1209,14 +1300,9 @@ * @returns {number} Returns the string size. */ function stringSize(string) { - if (!(string && reHasComplexSymbol.test(string))) { - return string.length; - } - var result = reComplexSymbol.lastIndex = 0; - while (reComplexSymbol.test(string)) { - result++; - } - return result; + return hasUnicode(string) + ? unicodeSize(string) + : asciiSize(string); } /** @@ -1227,7 +1313,9 @@ * @returns {Array} Returns the converted array. */ function stringToArray(string) { - return string.match(reComplexSymbol); + return hasUnicode(string) + ? unicodeToArray(string) + : asciiToArray(string); } /** @@ -1239,6 +1327,43 @@ */ var unescapeHtmlChar = basePropertyOf(htmlUnescapes); + /** + * Gets the size of a Unicode `string`. + * + * @private + * @param {string} string The string inspect. + * @returns {number} Returns the string size. + */ + function unicodeSize(string) { + var result = reUnicode.lastIndex = 0; + while (reUnicode.test(string)) { + result++; + } + return result; + } + + /** + * Converts a Unicode `string` to an array. + * + * @private + * @param {string} string The string to convert. + * @returns {Array} Returns the converted array. + */ + function unicodeToArray(string) { + return string.match(reUnicode) || []; + } + + /** + * Splits a Unicode `string` into an array of its words. + * + * @private + * @param {string} The string to inspect. + * @returns {Array} Returns the words of `string`. + */ + function unicodeWords(string) { + return string.match(reUnicodeWord) || []; + } + /*--------------------------------------------------------------------------*/ /** @@ -1278,20 +1403,23 @@ * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; */ function runInContext(context) { - context = context ? _.defaults({}, context, _.pick(root, contextProps)) : root; + context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root; /** Built-in constructor references. */ var Array = context.Array, Date = context.Date, Error = context.Error, + Function = context.Function, Math = context.Math, + Object = context.Object, RegExp = context.RegExp, + String = context.String, TypeError = context.TypeError; /** Used for built-in method references. */ - var arrayProto = context.Array.prototype, - objectProto = context.Object.prototype, - stringProto = context.String.prototype; + var arrayProto = Array.prototype, + funcProto = Function.prototype, + objectProto = Object.prototype; /** Used to detect overreaching core-js shims. */ var coreJsData = context['__core-js_shared__']; @@ -1303,7 +1431,7 @@ }()); /** Used to resolve the decompiled source of functions. */ - var funcToString = context.Function.prototype.toString; + var funcToString = funcProto.toString; /** Used to check objects for own properties. */ var hasOwnProperty = objectProto.hasOwnProperty; @@ -1316,7 +1444,7 @@ /** * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring) + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; @@ -1332,36 +1460,33 @@ /** Built-in value references. */ var Buffer = moduleExports ? context.Buffer : undefined, - Reflect = context.Reflect, Symbol = context.Symbol, Uint8Array = context.Uint8Array, - enumerate = Reflect ? Reflect.enumerate : undefined, + getPrototype = overArg(Object.getPrototypeOf, Object), iteratorSymbol = Symbol ? Symbol.iterator : undefined, - objectCreate = context.Object.create, + objectCreate = Object.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined; - /** Built-in method references that are mockable. */ - var clearTimeout = function(id) { return context.clearTimeout.call(root, id); }, - setTimeout = function(func, wait) { return context.setTimeout.call(root, func, wait); }; + /** Mocked built-ins. */ + var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, + ctxNow = Date && Date.now !== root.Date.now && Date.now, + ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeCeil = Math.ceil, nativeFloor = Math.floor, - nativeGetPrototype = Object.getPrototypeOf, nativeGetSymbols = Object.getOwnPropertySymbols, nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, - nativeKeys = Object.keys, + nativeKeys = overArg(Object.keys, Object), nativeMax = Math.max, nativeMin = Math.min, nativeParseInt = context.parseInt, nativeRandom = Math.random, - nativeReplace = stringProto.replace, - nativeReverse = arrayProto.reverse, - nativeSplit = stringProto.split; + nativeReverse = arrayProto.reverse; /* Built-in method references that are verified to be native. */ var DataView = getNative(context, 'DataView'), @@ -1369,11 +1494,11 @@ Promise = getNative(context, 'Promise'), Set = getNative(context, 'Set'), WeakMap = getNative(context, 'WeakMap'), - nativeCreate = getNative(context.Object, 'create'); + nativeCreate = getNative(Object, 'create'); /* Used to set `toString` methods. */ var defineProperty = (function() { - var func = getNative(context.Object, 'defineProperty'), + var func = getNative(Object, 'defineProperty'), name = getNative.name; return (name && name.length > 2) ? func : undefined; @@ -2202,6 +2327,33 @@ /*------------------------------------------------------------------------*/ /** + * Creates an array of the enumerable property names of the array-like `value`. + * + * @private + * @param {*} value The value to query. + * @param {boolean} inherited Specify returning inherited property names. + * @returns {Array} Returns the array of property names. + */ + function arrayLikeKeys(value, inherited) { + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. + // Safari 9 makes `arguments.length` enumerable in strict mode. + var result = (isArray(value) || isArguments(value)) + ? baseTimes(value.length, String) + : []; + + var length = result.length, + skipIndexes = !!length; + + for (var key in value) { + if ((inherited || hasOwnProperty.call(value, key)) && + !(skipIndexes && (key == 'length' || isIndex(key, length)))) { + result.push(key); + } + } + return result; + } + + /** * Used by `_.defaults` to customize its `_.assignIn` use. * * @private @@ -2237,7 +2389,7 @@ /** * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @private @@ -2257,7 +2409,7 @@ * Gets the index at which the `key` is found in `array` of key-value pairs. * * @private - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} key The key to search for. * @returns {number} Returns the index of the matched value, else `-1`. */ @@ -2445,14 +2597,13 @@ if (object == null) { return !length; } - var index = length; - while (index--) { - var key = props[index], + object = Object(object); + while (length--) { + var key = props[length], predicate = source[key], value = object[key]; - if ((value === undefined && - !(key in Object(object))) || !predicate(value)) { + if ((value === undefined && !(key in object)) || !predicate(value)) { return false; } } @@ -2479,7 +2630,7 @@ * @param {Function} func The function to delay. * @param {number} wait The number of milliseconds to delay invocation. * @param {Array} args The arguments to provide to `func`. - * @returns {number} Returns the timer id. + * @returns {number|Object} Returns the timer id or timeout object. */ function baseDelay(func, wait, args) { if (typeof func != 'function') { @@ -2824,12 +2975,7 @@ * @returns {boolean} Returns `true` if `key` exists, else `false`. */ function baseHas(object, key) { - // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`, - // that are composed entirely of index properties, return `false` for - // `hasOwnProperty` checks of them. - return object != null && - (hasOwnProperty.call(object, key) || - (typeof object == 'object' && key in object && getPrototype(object) === null)); + return object != null && hasOwnProperty.call(object, key); } /** @@ -3203,40 +3349,47 @@ } /** - * The base implementation of `_.keys` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. + * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ - var baseKeys = overArg(nativeKeys, Object); + function baseKeys(object) { + if (!isPrototype(object)) { + return nativeKeys(object); + } + var result = []; + for (var key in Object(object)) { + if (hasOwnProperty.call(object, key) && key != 'constructor') { + result.push(key); + } + } + return result; + } /** - * The base implementation of `_.keysIn` which doesn't skip the constructor - * property of prototypes or treat sparse arrays as dense. + * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. * * @private * @param {Object} object The object to query. * @returns {Array} Returns the array of property names. */ function baseKeysIn(object) { - object = object == null ? object : Object(object); + if (!isObject(object)) { + return nativeKeysIn(object); + } + var isProto = isPrototype(object), + result = []; - var result = []; for (var key in object) { - result.push(key); + if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { + result.push(key); + } } return result; } - // Fallback for IE < 9 with es6-shim. - if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) { - baseKeysIn = function(object) { - return iteratorToArray(enumerate(object)); - }; - } - /** * The base implementation of `_.lt` which doesn't coerce arguments. * @@ -3321,7 +3474,7 @@ return; } if (!(isArray(source) || isTypedArray(source))) { - var props = keysIn(source); + var props = baseKeysIn(source); } arrayEach(props || source, function(srcValue, key) { if (props) { @@ -3681,13 +3834,16 @@ * The base implementation of `_.set`. * * @private - * @param {Object} object The object to query. + * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to set. * @param {*} value The value to set. * @param {Function} [customizer] The function to customize path creation. * @returns {Object} Returns `object`. */ function baseSet(object, path, value, customizer) { + if (!isObject(object)) { + return object; + } path = isKey(path, object) ? [path] : castPath(path); var index = -1, @@ -3696,20 +3852,19 @@ nested = object; while (nested != null && ++index < length) { - var key = toKey(path[index]); - if (isObject(nested)) { - var newValue = value; - if (index != lastIndex) { - var objValue = nested[key]; - newValue = customizer ? customizer(objValue, key, nested) : undefined; - if (newValue === undefined) { - newValue = objValue == null - ? (isIndex(path[index + 1]) ? [] : {}) - : objValue; - } + var key = toKey(path[index]), + newValue = value; + + if (index != lastIndex) { + var objValue = nested[key]; + newValue = customizer ? customizer(objValue, key, nested) : undefined; + if (newValue === undefined) { + newValue = isObject(objValue) + ? objValue + : (isIndex(path[index + 1]) ? [] : {}); } - assignValue(nested, key, newValue); } + assignValue(nested, key, newValue); nested = nested[key]; } return object; @@ -4002,14 +4157,14 @@ object = parent(object, path); var key = toKey(last(path)); - return !(object != null && baseHas(object, key)) || delete object[key]; + return !(object != null && hasOwnProperty.call(object, key)) || delete object[key]; } /** * The base implementation of `_.update`. * * @private - * @param {Object} object The object to query. + * @param {Object} object The object to modify. * @param {Array|string} path The path of the property to update. * @param {Function} updater The function to produce the updated value. * @param {Function} [customizer] The function to customize path creation. @@ -4158,6 +4313,16 @@ } /** + * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). + * + * @private + * @param {number|Object} id The timer id or timeout object of the timer to clear. + */ + var clearTimeout = ctxClearTimeout || function(id) { + return root.clearTimeout(id); + }; + + /** * Creates a clone of `buffer`. * * @private @@ -4610,7 +4775,7 @@ return function(string) { string = toString(string); - var strSymbols = reHasComplexSymbol.test(string) + var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined; @@ -4650,7 +4815,7 @@ function createCtor(Ctor) { return function() { // Use a `switch` statement to work with class constructors. See - // http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist + // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist // for more details. var args = arguments; switch (args.length) { @@ -4953,7 +5118,7 @@ return charsLength ? baseRepeat(chars, length) : chars; } var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); - return reHasComplexSymbol.test(chars) + return hasUnicode(chars) ? castSlice(stringToArray(result), 0, length).join('') : result.slice(0, length); } @@ -5338,7 +5503,7 @@ case regexpTag: case stringTag: // Coerce regexes to strings and treat strings, primitives and objects, - // as equal. See http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.tostring + // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring // for more details. return object == (other + ''); @@ -5400,7 +5565,7 @@ var index = objLength; while (index--) { var key = objProps[index]; - if (!(isPartial ? key in other : baseHas(other, key))) { + if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { return false; } } @@ -5537,19 +5702,6 @@ } /** - * Gets the "length" property value of `object`. - * - * **Note:** This function is used to avoid a - * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects - * Safari on at least iOS 8.1-8.3 ARM64. - * - * @private - * @param {Object} object The object to query. - * @returns {*} Returns the "length" value. - */ - var getLength = baseProperty('length'); - - /** * Gets the data for `map`. * * @private @@ -5598,15 +5750,6 @@ } /** - * Gets the `[[Prototype]]` of `value`. - * - * @private - * @param {*} value The value to query. - * @returns {null|Object} Returns the `[[Prototype]]`. - */ - var getPrototype = overArg(nativeGetPrototype, Object); - - /** * Creates an array of the own enumerable symbol properties of `object`. * * @private @@ -5642,7 +5785,7 @@ var getTag = baseGetTag; // Fallback for data views, maps, sets, and weak maps in IE 11, - // for data views in Edge, and promises in Node.js. + // for data views in Edge < 14, and promises in Node.js. if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (Map && getTag(new Map) != mapTag) || (Promise && getTag(Promise.resolve()) != promiseTag) || @@ -5734,7 +5877,7 @@ } var length = object ? object.length : 0; return !!length && isLength(length) && isIndex(key, length) && - (isArray(object) || isString(object) || isArguments(object)); + (isArray(object) || isArguments(object)); } /** @@ -5819,23 +5962,6 @@ } /** - * Creates an array of index keys for `object` values of arrays, - * `arguments` objects, and strings, otherwise `null` is returned. - * - * @private - * @param {Object} object The object to query. - * @returns {Array|null} Returns index keys, else `null`. - */ - function indexKeys(object) { - var length = object ? object.length : undefined; - if (isLength(length) && - (isArray(object) || isString(object) || isArguments(object))) { - return baseTimes(length, String); - } - return null; - } - - /** * Inserts wrapper `details` in a comment at the top of the `source` body. * * @private @@ -6120,6 +6246,25 @@ } /** + * This function is like + * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) + * except that it includes inherited enumerable properties. + * + * @private + * @param {Object} object The object to query. + * @returns {Array} Returns the array of property names. + */ + function nativeKeysIn(object) { + var result = []; + if (object != null) { + for (var key in Object(object)) { + result.push(key); + } + } + return result; + } + + /** * Gets the parent value at `path` of `object`. * * @private @@ -6188,6 +6333,18 @@ }()); /** + * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). + * + * @private + * @param {Function} func The function to delay. + * @param {number} wait The number of milliseconds to delay invocation. + * @returns {number|Object} Returns the timer id or timeout object. + */ + var setTimeout = ctxSetTimeout || function(func, wait) { + return root.setTimeout(func, wait); + }; + + /** * Sets the `toString` method of `wrapper` to mimic the source of `reference` * with wrapper details in a comment at the top of the source body. * @@ -6407,7 +6564,7 @@ /** * Creates an array of `array` values not included in the other given arrays - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. The order of result values is determined by the * order they occur in the first array. * @@ -6701,7 +6858,7 @@ * @memberOf _ * @since 1.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=0] The index to search from. @@ -6749,7 +6906,7 @@ * @memberOf _ * @since 2.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=array.length-1] The index to search from. @@ -6910,7 +7067,7 @@ /** * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. If `fromIndex` is negative, it's used as the * offset from the end of `array`. * @@ -6918,7 +7075,7 @@ * @memberOf _ * @since 0.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. @@ -6958,12 +7115,13 @@ * // => [1, 2] */ function initial(array) { - return dropRight(array, 1); + var length = array ? array.length : 0; + return length ? baseSlice(array, 0, -1) : []; } /** * Creates an array of unique values that are included in all given arrays - * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. The order of result values is determined by the * order they occur in the first array. * @@ -7102,7 +7260,7 @@ * @memberOf _ * @since 0.1.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=array.length-1] The index to search from. * @returns {number} Returns the index of the matched value, else `-1`. @@ -7167,7 +7325,7 @@ /** * Removes all given values from `array` using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` @@ -7480,7 +7638,7 @@ * @memberOf _ * @since 4.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example @@ -7559,7 +7717,7 @@ * @memberOf _ * @since 4.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example @@ -7636,7 +7794,8 @@ * // => [2, 3] */ function tail(array) { - return drop(array, 1); + var length = array ? array.length : 0; + return length ? baseSlice(array, 1, length) : []; } /** @@ -7793,7 +7952,7 @@ /** * Creates an array of unique values, in order, from all given arrays using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @static @@ -7874,7 +8033,7 @@ /** * Creates a duplicate-free version of an array, using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurrence of each * element is kept. * @@ -8019,7 +8178,7 @@ /** * Creates an array excluding all given values using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.pull`, this method returns a new array. @@ -8590,6 +8749,11 @@ * Iteration is stopped once `predicate` returns falsey. The predicate is * invoked with three arguments: (value, index|key, collection). * + * **Note:** This method returns `true` for + * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because + * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of + * elements of empty collections. + * * @static * @memberOf _ * @since 0.1.0 @@ -8682,7 +8846,7 @@ * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=0] The index to search from. @@ -8720,7 +8884,7 @@ * @memberOf _ * @since 2.0.0 * @category Collection - * @param {Array|Object} collection The collection to search. + * @param {Array|Object} collection The collection to inspect. * @param {Function} [predicate=_.identity] * The function invoked per iteration. * @param {number} [fromIndex=collection.length-1] The index to search from. @@ -8907,7 +9071,7 @@ /** * Checks if `value` is in `collection`. If `collection` is a string, it's * checked for a substring of `value`, otherwise - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * is used for equality comparisons. If `fromIndex` is negative, it's used as * the offset from the end of `collection`. * @@ -8915,7 +9079,7 @@ * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object|string} collection The collection to search. + * @param {Array|Object|string} collection The collection to inspect. * @param {*} value The value to search for. * @param {number} [fromIndex=0] The index to search from. * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. @@ -9348,7 +9512,7 @@ * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to inspect. + * @param {Array|Object|string} collection The collection to inspect. * @returns {number} Returns the collection size. * @example * @@ -9366,16 +9530,13 @@ return 0; } if (isArrayLike(collection)) { - var result = collection.length; - return (result && isString(collection)) ? stringSize(collection) : result; + return isString(collection) ? stringSize(collection) : collection.length; } - if (isObjectLike(collection)) { - var tag = getTag(collection); - if (tag == mapTag || tag == setTag) { - return collection.size; - } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; } - return keys(collection).length; + return baseKeys(collection).length; } /** @@ -9487,9 +9648,9 @@ * }, _.now()); * // => Logs the number of milliseconds it took for the deferred invocation. */ - function now() { - return Date.now(); - } + var now = ctxNow || function() { + return root.Date.now(); + }; /*------------------------------------------------------------------------*/ @@ -10030,7 +10191,7 @@ * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` * constructor with one whose instances implement the - * [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) * method interface of `delete`, `get`, `has`, and `set`. * * @static @@ -10330,7 +10491,7 @@ /** * Creates a function that invokes `func` with the `this` binding of the * create function and an array of arguments much like - * [`Function#apply`](http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.apply). + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). * * **Note:** This method is based on the * [spread operator](https://mdn.io/spread_operator). @@ -10677,7 +10838,7 @@ /** * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * comparison between two values to determine if they are equivalent. * * @static @@ -10782,7 +10943,7 @@ * // => false */ function isArguments(value) { - // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode. + // Safari 8.1 makes `arguments.callee` enumerable in strict mode. return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') && (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag); } @@ -10857,7 +11018,7 @@ * // => false */ function isArrayLike(value) { - return value != null && isLength(getLength(value)) && !isFunction(value); + return value != null && isLength(value.length) && !isFunction(value); } /** @@ -10957,8 +11118,7 @@ * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a DOM element, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. * @example * * _.isElement(document.body); @@ -11006,22 +11166,23 @@ */ function isEmpty(value) { if (isArrayLike(value) && - (isArray(value) || isString(value) || isFunction(value.splice) || - isArguments(value) || isBuffer(value))) { + (isArray(value) || typeof value == 'string' || + typeof value.splice == 'function' || isBuffer(value) || isArguments(value))) { return !value.length; } - if (isObjectLike(value)) { - var tag = getTag(value); - if (tag == mapTag || tag == setTag) { - return !value.size; - } + var tag = getTag(value); + if (tag == mapTag || tag == setTag) { + return !value.size; + } + if (nonEnumShadows || isPrototype(value)) { + return !nativeKeys(value).length; } for (var key in value) { if (hasOwnProperty.call(value, key)) { return false; } } - return !(nonEnumShadows && keys(value).length); + return true; } /** @@ -11040,8 +11201,7 @@ * @category Lang * @param {*} value The value to compare. * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, - * else `false`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * var object = { 'a': 1 }; @@ -11070,8 +11230,7 @@ * @param {*} value The value to compare. * @param {*} other The other value to compare. * @param {Function} [customizer] The function to customize comparisons. - * @returns {boolean} Returns `true` if the values are equivalent, - * else `false`. + * @returns {boolean} Returns `true` if the values are equivalent, else `false`. * @example * * function isGreeting(value) { @@ -11105,8 +11264,7 @@ * @since 3.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an error object, - * else `false`. + * @returns {boolean} Returns `true` if `value` is an error object, else `false`. * @example * * _.isError(new Error); @@ -11134,8 +11292,7 @@ * @since 0.1.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a finite number, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. * @example * * _.isFinite(3); @@ -11173,8 +11330,7 @@ */ function isFunction(value) { // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 8 which returns 'object' for typed array and weak map constructors, - // and PhantomJS 1.9 which returns 'function' for `NodeList` instances. + // in Safari 8-9 which returns 'object' for typed array and other constructors. var tag = isObject(value) ? objectToString.call(value) : ''; return tag == funcTag || tag == genTag; } @@ -11212,16 +11368,15 @@ /** * Checks if `value` is a valid array-like length. * - * **Note:** This function is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * **Note:** This method is loosely based on + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. * @example * * _.isLength(3); @@ -11243,7 +11398,7 @@ /** * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static @@ -11322,8 +11477,12 @@ * Performs a partial deep comparison between `object` and `source` to * determine if `object` contains equivalent property values. * - * **Note:** This method supports comparing the same values as `_.isEqual` - * and is equivalent to `_.matches` when `source` is partially applied. + * **Note:** This method is equivalent to `_.matches` when `source` is + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. * * @static * @memberOf _ @@ -11536,8 +11695,7 @@ * @since 0.8.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. * @example * * function Foo() { @@ -11601,8 +11759,7 @@ * @since 4.0.0 * @category Lang * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a safe integer, - * else `false`. + * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. * @example * * _.isSafeInteger(3); @@ -11896,7 +12053,7 @@ * Converts `value` to an integer. * * **Note:** This method is loosely based on - * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). * * @static * @memberOf _ @@ -11930,7 +12087,7 @@ * array-like object. * * **Note:** This method is based on - * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ @@ -11987,7 +12144,7 @@ return NAN; } if (isObject(value)) { - var other = isFunction(value.valueOf) ? value.valueOf() : value; + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; } if (typeof value != 'string') { @@ -12159,13 +12316,7 @@ * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } */ var assignIn = createAssigner(function(object, source) { - if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) { - copyObject(source, keysIn(source), object); - return; - } - for (var key in source) { - assignValue(object, key, source[key]); - } + copyObject(source, keysIn(source), object); }); /** @@ -12351,7 +12502,7 @@ * @memberOf _ * @since 1.1.0 * @category Object - * @param {Object} object The object to search. + * @param {Object} object The object to inspect. * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {string|undefined} Returns the key of the matched element, * else `undefined`. @@ -12390,7 +12541,7 @@ * @memberOf _ * @since 2.0.0 * @category Object - * @param {Object} object The object to search. + * @param {Object} object The object to inspect. * @param {Function} [predicate=_.identity] The function invoked per iteration. * @returns {string|undefined} Returns the key of the matched element, * else `undefined`. @@ -12774,7 +12925,7 @@ * Creates an array of the own enumerable property names of `object`. * * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys) + * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) * for more details. * * @static @@ -12799,23 +12950,7 @@ * // => ['0', '1'] */ function keys(object) { - var isProto = isPrototype(object); - if (!(isProto || isArrayLike(object))) { - return baseKeys(object); - } - var indexes = indexKeys(object), - skipIndexes = !!indexes, - result = indexes || [], - length = result.length; - - for (var key in object) { - if (baseHas(object, key) && - !(skipIndexes && (key == 'length' || isIndex(key, length))) && - !(isProto && key == 'constructor')) { - result.push(key); - } - } - return result; + return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); } /** @@ -12842,23 +12977,7 @@ * // => ['a', 'b', 'c'] (iteration order is not guaranteed) */ function keysIn(object) { - var index = -1, - isProto = isPrototype(object), - props = baseKeysIn(object), - propsLength = props.length, - indexes = indexKeys(object), - skipIndexes = !!indexes, - result = indexes || [], - length = result.length; - - while (++index < propsLength) { - var key = props[index]; - if (!(skipIndexes && (key == 'length' || isIndex(key, length))) && - !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { - result.push(key); - } - } - return result; + return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); } /** @@ -13664,8 +13783,9 @@ /** * Deburrs `string` by converting - * [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) - * to basic latin letters and removing + * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) + * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) + * letters to basic Latin letters and removing * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). * * @static @@ -13681,7 +13801,7 @@ */ function deburr(string) { string = toString(string); - return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, ''); + return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); } /** @@ -13691,7 +13811,7 @@ * @memberOf _ * @since 3.0.0 * @category String - * @param {string} [string=''] The string to search. + * @param {string} [string=''] The string to inspect. * @param {string} [target] The string to search for. * @param {number} [position=string.length] The position to search up to. * @returns {boolean} Returns `true` if `string` ends with `target`, @@ -14047,7 +14167,7 @@ var args = arguments, string = toString(args[0]); - return args.length < 3 ? string : nativeReplace.call(string, args[1], args[2]); + return args.length < 3 ? string : string.replace(args[1], args[2]); } /** @@ -14108,11 +14228,11 @@ (separator != null && !isRegExp(separator)) )) { separator = baseToString(separator); - if (separator == '' && reHasComplexSymbol.test(string)) { + if (!separator && hasUnicode(string)) { return castSlice(stringToArray(string), 0, limit); } } - return nativeSplit.call(string, separator, limit); + return string.split(separator, limit); } /** @@ -14147,7 +14267,7 @@ * @memberOf _ * @since 3.0.0 * @category String - * @param {string} [string=''] The string to search. + * @param {string} [string=''] The string to inspect. * @param {string} [target] The string to search for. * @param {number} [position=0] The position to search from. * @returns {boolean} Returns `true` if `string` starts with `target`, @@ -14584,7 +14704,7 @@ string = toString(string); var strLength = string.length; - if (reHasComplexSymbol.test(string)) { + if (hasUnicode(string)) { var strSymbols = stringToArray(string); strLength = strSymbols.length; } @@ -14721,7 +14841,7 @@ pattern = guard ? undefined : pattern; if (pattern === undefined) { - pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord; + return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); } return string.match(pattern) || []; } @@ -15038,8 +15158,12 @@ * object and `source`, returning `true` if the given object has equivalent * property values, else `false`. * - * **Note:** The created function supports comparing the same values as - * `_.isEqual` is equivalent to `_.isMatch` with `source` partially applied. + * **Note:** The created function is equivalent to `_.isMatch` with `source` + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. * * @static * @memberOf _ @@ -15066,7 +15190,9 @@ * value at `path` of a given object to `srcValue`, returning `true` if the * object value is equivalent, else `false`. * - * **Note:** This method supports comparing the same values as `_.isEqual`. + * **Note:** Partial comparisons will match empty array and empty object + * `srcValue` values against any array or object value, respectively. See + * `_.isEqual` for a list of supported value comparisons. * * @static * @memberOf _ diff --git a/tools/eslint/node_modules/lodash/lodash.min.js b/tools/eslint/node_modules/lodash/lodash.min.js index 5c282e70a2..867ecf2a32 100644 --- a/tools/eslint/node_modules/lodash/lodash.min.js +++ b/tools/eslint/node_modules/lodash/lodash.min.js @@ -5,126 +5,128 @@ ;(function(){function t(t,n){return t.set(n[0],n[1]),t}function n(t,n){return t.add(n),t}function r(t,n,r){switch(r.length){case 0:return t.call(n);case 1:return t.call(n,r[0]);case 2:return t.call(n,r[0],r[1]);case 3:return t.call(n,r[0],r[1],r[2])}return t.apply(n,r)}function e(t,n,r,e){for(var u=-1,o=t?t.length:0;++u<o;){var i=t[u];n(e,i,r(i),t)}return e}function u(t,n){for(var r=-1,e=t?t.length:0;++r<e&&false!==n(t[r],r,t););return t}function o(t,n){for(var r=t?t.length:0;r--&&false!==n(t[r],r,t);); return t}function i(t,n){for(var r=-1,e=t?t.length:0;++r<e;)if(!n(t[r],r,t))return false;return true}function f(t,n){for(var r=-1,e=t?t.length:0,u=0,o=[];++r<e;){var i=t[r];n(i,r,t)&&(o[u++]=i)}return o}function c(t,n){return!(!t||!t.length)&&-1<d(t,n,0)}function a(t,n,r){for(var e=-1,u=t?t.length:0;++e<u;)if(r(n,t[e]))return true;return false}function l(t,n){for(var r=-1,e=t?t.length:0,u=Array(e);++r<e;)u[r]=n(t[r],r,t);return u}function s(t,n){for(var r=-1,e=n.length,u=t.length;++r<e;)t[u+r]=n[r];return t}function h(t,n,r,e){ var u=-1,o=t?t.length:0;for(e&&o&&(r=t[++u]);++u<o;)r=n(r,t[u],u,t);return r}function p(t,n,r,e){var u=t?t.length:0;for(e&&u&&(r=t[--u]);u--;)r=n(r,t[u],u,t);return r}function _(t,n){for(var r=-1,e=t?t.length:0;++r<e;)if(n(t[r],r,t))return true;return false}function v(t,n,r){var e;return r(t,function(t,r,u){if(n(t,r,u))return e=r,false}),e}function g(t,n,r,e){var u=t.length;for(r+=e?1:-1;e?r--:++r<u;)if(n(t[r],r,t))return r;return-1}function d(t,n,r){if(n!==n)return g(t,b,r);--r;for(var e=t.length;++r<e;)if(t[r]===n)return r; -return-1}function y(t,n,r,e){--r;for(var u=t.length;++r<u;)if(e(t[r],n))return r;return-1}function b(t){return t!==t}function x(t,n){var r=t?t.length:0;return r?O(t,n)/r:q}function j(t){return function(n){return null==n?P:n[t]}}function w(t){return function(n){return null==t?P:t[n]}}function m(t,n,r,e,u){return u(t,function(t,u,o){r=e?(e=false,t):n(r,t,u,o)}),r}function A(t,n){var r=t.length;for(t.sort(n);r--;)t[r]=t[r].c;return t}function O(t,n){for(var r,e=-1,u=t.length;++e<u;){var o=n(t[e]);o!==P&&(r=r===P?o:r+o); -}return r}function k(t,n){for(var r=-1,e=Array(t);++r<t;)e[r]=n(r);return e}function E(t,n){return l(n,function(n){return[n,t[n]]})}function S(t){return function(n){return t(n)}}function R(t,n){return l(n,function(n){return t[n]})}function I(t,n){return t.has(n)}function W(t,n){for(var r=-1,e=t.length;++r<e&&-1<d(n,t[r],0););return r}function B(t,n){for(var r=t.length;r--&&-1<d(n,t[r],0););return r}function M(t){return"\\"+Tt[t]}function C(t){var n=false;if(null!=t&&typeof t.toString!="function")try{ -n=!!(t+"")}catch(t){}return n}function L(t){for(var n,r=[];!(n=t.next()).done;)r.push(n.value);return r}function z(t){var n=-1,r=Array(t.size);return t.forEach(function(t,e){r[++n]=[e,t]}),r}function U(t){var n=Object;return function(r){return t(n(r))}}function D(t,n){for(var r=-1,e=t.length,u=0,o=[];++r<e;){var i=t[r];i!==n&&"__lodash_placeholder__"!==i||(t[r]="__lodash_placeholder__",o[u++]=r)}return o}function $(t){var n=-1,r=Array(t.size);return t.forEach(function(t){r[++n]=t}),r}function F(t){ -var n=-1,r=Array(t.size);return t.forEach(function(t){r[++n]=[t,t]}),r}function T(t){if(!t||!Lt.test(t))return t.length;for(var n=Mt.lastIndex=0;Mt.test(t);)n++;return n}function N(w){function St(t){return Xu.call(t)}function Rt(t,n){return w.setTimeout.call(Vt,t,n)}function It(t){if(au(t)&&!Zi(t)&&!(t instanceof Zt)){if(t instanceof Tt)return t;if(Yu.call(t,"__wrapped__"))return Se(t)}return new Tt(t)}function Ft(){}function Tt(t,n){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!n,this.__index__=0, -this.__values__=P}function Zt(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function qt(t){var n=-1,r=t?t.length:0;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Kt(t){var n=-1,r=t?t.length:0;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Gt(t){var n=-1,r=t?t.length:0;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Yt(t){var n=-1,r=t?t.length:0; -for(this.__data__=new Gt;++n<r;)this.add(t[n])}function cn(t){this.__data__=new Kt(t)}function an(t,n,r,e){return t===P||tu(t,qu[r])&&!Yu.call(e,r)?n:t}function ln(t,n,r){(r===P||tu(t[n],r))&&(typeof n!="number"||r!==P||n in t)||(t[n]=r)}function sn(t,n,r){var e=t[n];Yu.call(t,n)&&tu(e,r)&&(r!==P||n in t)||(t[n]=r)}function hn(t,n){for(var r=t.length;r--;)if(tu(t[r][0],n))return r;return-1}function pn(t,n,r,e){return Vo(t,function(t,u,o){n(e,t,r(t),o)}),e}function _n(t,n){return t&&Br(n,mu(n),t)} -function vn(t,n){for(var r=-1,e=null==t,u=n.length,o=Du(u);++r<u;)o[r]=e?P:ju(t,n[r]);return o}function gn(t,n,r){return t===t&&(r!==P&&(t=t<=r?t:r),n!==P&&(t=t>=n?t:n)),t}function dn(t,n,r,e,o,i,f){var c;if(e&&(c=i?e(t,o,i,f):e(t)),c!==P)return c;if(!cu(t))return t;if(o=Zi(t)){if(c=he(t),!n)return Wr(t,c)}else{var a=St(t),l="[object Function]"==a||"[object GeneratorFunction]"==a;if(Vi(t))return kr(t,n);if("[object Object]"==a||"[object Arguments]"==a||l&&!i){if(C(t))return i?t:{};if(c=pe(l?{}:t), -!n)return Mr(t,_n(c,t))}else{if(!$t[a])return i?t:{};c=_e(t,a,dn,n)}}if(f||(f=new cn),i=f.get(t))return i;if(f.set(t,c),!o)var s=r?Wn(t,mu,ri):mu(t);return u(s||t,function(u,o){s&&(o=u,u=t[o]),sn(c,o,dn(u,n,r,e,o,t,f))}),c}function yn(t){var n=mu(t);return function(r){return bn(r,t,n)}}function bn(t,n,r){var e=r.length;if(null==t)return!e;for(;e--;){var u=r[e],o=n[u],i=t[u];if(i===P&&!(u in Object(t))||!o(i))return false}return true}function xn(t){return cu(t)?co(t):{}}function jn(t,n,r){if(typeof t!="function")throw new Pu("Expected a function"); -return Rt(function(){t.apply(P,r)},n)}function wn(t,n,r,e){var u=-1,o=c,i=true,f=t.length,s=[],h=n.length;if(!f)return s;r&&(n=l(n,S(r))),e?(o=a,i=false):200<=n.length&&(o=I,i=false,n=new Yt(n));t:for(;++u<f;){var p=t[u],_=r?r(p):p,p=e||0!==p?p:0;if(i&&_===_){for(var v=h;v--;)if(n[v]===_)continue t;s.push(p)}else o(n,_,e)||s.push(p)}return s}function mn(t,n){var r=true;return Vo(t,function(t,e,u){return r=!!n(t,e,u)}),r}function An(t,n,r){for(var e=-1,u=t.length;++e<u;){var o=t[e],i=n(o);if(null!=i&&(f===P?i===i&&!pu(i):r(i,f)))var f=i,c=o; -}return c}function On(t,n){var r=[];return Vo(t,function(t,e,u){n(t,e,u)&&r.push(t)}),r}function kn(t,n,r,e,u){var o=-1,i=t.length;for(r||(r=ge),u||(u=[]);++o<i;){var f=t[o];0<n&&r(f)?1<n?kn(f,n-1,r,e,u):s(u,f):e||(u[u.length]=f)}return u}function En(t,n){return t&&Go(t,n,mu)}function Sn(t,n){return t&&Jo(t,n,mu)}function Rn(t,n){return f(n,function(n){return ou(t[n])})}function In(t,n){n=be(n,t)?[n]:Ar(n);for(var r=0,e=n.length;null!=t&&r<e;)t=t[Oe(n[r++])];return r&&r==e?t:P}function Wn(t,n,r){ -return n=n(t),Zi(t)?n:s(n,r(t))}function Bn(t,n){return t>n}function Mn(t,n){return null!=t&&(Yu.call(t,n)||typeof t=="object"&&n in t&&null===ni(t))}function Cn(t,n){return null!=t&&n in Object(t)}function Ln(t,n,r){for(var e=r?a:c,u=t[0].length,o=t.length,i=o,f=Du(o),s=1/0,h=[];i--;){var p=t[i];i&&n&&(p=l(p,S(n))),s=wo(p.length,s),f[i]=!r&&(n||120<=u&&120<=p.length)?new Yt(i&&p):P}var p=t[0],_=-1,v=f[0];t:for(;++_<u&&h.length<s;){var g=p[_],d=n?n(g):g,g=r||0!==g?g:0;if(v?!I(v,d):!e(h,d,r)){for(i=o;--i;){ -var y=f[i];if(y?!I(y,d):!e(t[i],d,r))continue t}v&&v.push(d),h.push(g)}}return h}function zn(t,n,r){var e={};return En(t,function(t,u,o){n(e,r(t),u,o)}),e}function Un(t,n,e){return be(n,t)||(n=Ar(n),t=Ae(t,n),n=Ce(n)),n=null==t?t:t[Oe(n)],null==n?P:r(n,t,e)}function Dn(t){return au(t)&&"[object ArrayBuffer]"==Xu.call(t)}function $n(t){return au(t)&&"[object Date]"==Xu.call(t)}function Fn(t,n,r,e,u){if(t===n)n=true;else if(null==t||null==n||!cu(t)&&!au(n))n=t!==t&&n!==n;else t:{var o=Zi(t),i=Zi(n),f="[object Array]",c="[object Array]"; -o||(f=St(t),f="[object Arguments]"==f?"[object Object]":f),i||(c=St(n),c="[object Arguments]"==c?"[object Object]":c);var a="[object Object]"==f&&!C(t),i="[object Object]"==c&&!C(n);if((c=f==c)&&!a)u||(u=new cn),n=o||Hi(t)?ee(t,n,Fn,r,e,u):ue(t,n,f,Fn,r,e,u);else{if(!(2&e)&&(o=a&&Yu.call(t,"__wrapped__"),f=i&&Yu.call(n,"__wrapped__"),o||f)){t=o?t.value():t,n=f?n.value():n,u||(u=new cn),n=Fn(t,n,r,e,u);break t}if(c)n:if(u||(u=new cn),o=2&e,f=mu(t),i=f.length,c=mu(n).length,i==c||o){for(a=i;a--;){var l=f[a]; -if(!(o?l in n:Mn(n,l))){n=false;break n}}if((c=u.get(t))&&u.get(n))n=c==n;else{c=true,u.set(t,n),u.set(n,t);for(var s=o;++a<i;){var l=f[a],h=t[l],p=n[l];if(r)var _=o?r(p,h,l,n,t,u):r(h,p,l,t,n,u);if(_===P?h!==p&&!Fn(h,p,r,e,u):!_){c=false;break}s||(s="constructor"==l)}c&&!s&&(r=t.constructor,e=n.constructor,r!=e&&"constructor"in t&&"constructor"in n&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)),u.delete(t),u.delete(n),n=c}}else n=false;else n=false}}return n}function Tn(t){ -return au(t)&&"[object Map]"==St(t)}function Nn(t,n,r,e){var u=r.length,o=u,i=!e;if(null==t)return!o;for(t=Object(t);u--;){var f=r[u];if(i&&f[2]?f[1]!==t[f[0]]:!(f[0]in t))return false}for(;++u<o;){var f=r[u],c=f[0],a=t[c],l=f[1];if(i&&f[2]){if(a===P&&!(c in t))return false}else{if(f=new cn,e)var s=e(a,l,c,t,n,f);if(s===P?!Fn(l,a,e,3,f):!s)return false}}return true}function Pn(t){return!(!cu(t)||Gu&&Gu in t)&&(ou(t)||C(t)?no:wt).test(ke(t))}function Zn(t){return cu(t)&&"[object RegExp]"==Xu.call(t)}function qn(t){ -return au(t)&&"[object Set]"==St(t)}function Vn(t){return au(t)&&fu(t.length)&&!!Dt[Xu.call(t)]}function Kn(t){return typeof t=="function"?t:null==t?Wu:typeof t=="object"?Zi(t)?Qn(t[0],t[1]):Hn(t):Lu(t)}function Gn(t){t=null==t?t:Object(t);var n,r=[];for(n in t)r.push(n);return r}function Jn(t,n){return t<n}function Yn(t,n){var r=-1,e=ru(t)?Du(t.length):[];return Vo(t,function(t,u,o){e[++r]=n(t,u,o)}),e}function Hn(t){var n=ae(t);return 1==n.length&&n[0][2]?we(n[0][0],n[0][1]):function(r){return r===t||Nn(r,t,n); -}}function Qn(t,n){return be(t)&&n===n&&!cu(n)?we(Oe(t),n):function(r){var e=ju(r,t);return e===P&&e===n?wu(r,t):Fn(n,e,P,3)}}function Xn(t,n,r,e,o){if(t!==n){if(!Zi(n)&&!Hi(n))var i=Au(n);u(i||n,function(u,f){if(i&&(f=u,u=n[f]),cu(u)){o||(o=new cn);var c=f,a=o,l=t[c],s=n[c],h=a.get(s);if(h)ln(t,c,h);else{var h=e?e(l,s,c+"",t,n,a):P,p=h===P;p&&(h=s,Zi(s)||Hi(s)?Zi(l)?h=l:eu(l)?h=Wr(l):(p=false,h=dn(s,true)):su(s)||nu(s)?nu(l)?h=bu(l):!cu(l)||r&&ou(l)?(p=false,h=dn(s,true)):h=l:p=false),p&&(a.set(s,h),Xn(h,s,r,e,a), -a.delete(s)),ln(t,c,h)}}else c=e?e(t[f],u,f+"",t,n,o):P,c===P&&(c=u),ln(t,f,c)})}}function tr(t,n){var r=t.length;if(r)return n+=0>n?r:0,de(n,r)?t[n]:P}function nr(t,n,r){var e=-1;return n=l(n.length?n:[Wu],S(fe())),t=Yn(t,function(t){return{a:l(n,function(n){return n(t)}),b:++e,c:t}}),A(t,function(t,n){var e;t:{e=-1;for(var u=t.a,o=n.a,i=u.length,f=r.length;++e<i;){var c=Sr(u[e],o[e]);if(c){e=e>=f?c:c*("desc"==r[e]?-1:1);break t}}e=t.b-n.b}return e})}function rr(t,n){return t=Object(t),er(t,n,function(n,r){ -return r in t})}function er(t,n,r){for(var e=-1,u=n.length,o={};++e<u;){var i=n[e],f=t[i];r(f,i)&&(o[i]=f)}return o}function ur(t){return function(n){return In(n,t)}}function or(t,n,r,e){var u=e?y:d,o=-1,i=n.length,f=t;for(t===n&&(n=Wr(n)),r&&(f=l(t,S(r)));++o<i;)for(var c=0,a=n[o],a=r?r(a):a;-1<(c=u(f,a,c,e));)f!==t&&lo.call(f,c,1),lo.call(t,c,1);return t}function ir(t,n){for(var r=t?n.length:0,e=r-1;r--;){var u=n[r];if(r==e||u!==o){var o=u;if(de(u))lo.call(t,u,1);else if(be(u,t))delete t[Oe(u)];else{ -var u=Ar(u),i=Ae(t,u);null!=i&&delete i[Oe(Ce(u))]}}}}function fr(t,n){return t+po(Ao()*(n-t+1))}function cr(t,n){var r="";if(!t||1>n||9007199254740991<n)return r;do n%2&&(r+=t),(n=po(n/2))&&(t+=t);while(n);return r}function ar(t,n){return n=jo(n===P?t.length-1:n,0),function(){for(var e=arguments,u=-1,o=jo(e.length-n,0),i=Du(o);++u<o;)i[u]=e[n+u];for(u=-1,o=Du(n+1);++u<n;)o[u]=e[u];return o[n]=i,r(t,this,o)}}function lr(t,n,r,e){n=be(n,t)?[n]:Ar(n);for(var u=-1,o=n.length,i=o-1,f=t;null!=f&&++u<o;){ -var c=Oe(n[u]);if(cu(f)){var a=r;if(u!=i){var l=f[c],a=e?e(l,c,f):P;a===P&&(a=null==l?de(n[u+1])?[]:{}:l)}sn(f,c,a)}f=f[c]}return t}function sr(t,n,r){var e=-1,u=t.length;for(0>n&&(n=-n>u?0:u+n),r=r>u?u:r,0>r&&(r+=u),u=n>r?0:r-n>>>0,n>>>=0,r=Du(u);++e<u;)r[e]=t[e+n];return r}function hr(t,n){var r;return Vo(t,function(t,e,u){return r=n(t,e,u),!r}),!!r}function pr(t,n,r){var e=0,u=t?t.length:e;if(typeof n=="number"&&n===n&&2147483647>=u){for(;e<u;){var o=e+u>>>1,i=t[o];null!==i&&!pu(i)&&(r?i<=n:i<n)?e=o+1:u=o; -}return u}return _r(t,n,Wu,r)}function _r(t,n,r,e){n=r(n);for(var u=0,o=t?t.length:0,i=n!==n,f=null===n,c=pu(n),a=n===P;u<o;){var l=po((u+o)/2),s=r(t[l]),h=s!==P,p=null===s,_=s===s,v=pu(s);(i?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=n:s<n)?u=l+1:o=l}return wo(o,4294967294)}function vr(t,n){for(var r=-1,e=t.length,u=0,o=[];++r<e;){var i=t[r],f=n?n(i):i;if(!r||!tu(f,c)){var c=f;o[u++]=0===i?0:i}}return o}function gr(t){return typeof t=="number"?t:pu(t)?q:+t}function dr(t){if(typeof t=="string")return t; -if(pu(t))return qo?qo.call(t):"";var n=t+"";return"0"==n&&1/t==-Z?"-0":n}function yr(t,n,r){var e=-1,u=c,o=t.length,i=true,f=[],l=f;if(r)i=false,u=a;else if(200<=o){if(u=n?null:Qo(t))return $(u);i=false,u=I,l=new Yt}else l=n?[]:f;t:for(;++e<o;){var s=t[e],h=n?n(s):s,s=r||0!==s?s:0;if(i&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue t;n&&l.push(h),f.push(s)}else u(l,h,r)||(l!==f&&l.push(h),f.push(s))}return f}function br(t,n,r,e){for(var u=t.length,o=e?u:-1;(e?o--:++o<u)&&n(t[o],o,t););return r?sr(t,e?0:o,e?o+1:u):sr(t,e?o+1:0,e?u:o); -}function xr(t,n){var r=t;return r instanceof Zt&&(r=r.value()),h(n,function(t,n){return n.func.apply(n.thisArg,s([t],n.args))},r)}function jr(t,n,r){for(var e=-1,u=t.length;++e<u;)var o=o?s(wn(o,t[e],n,r),wn(t[e],o,n,r)):t[e];return o&&o.length?yr(o,n,r):[]}function wr(t,n,r){for(var e=-1,u=t.length,o=n.length,i={};++e<u;)r(i,t[e],e<o?n[e]:P);return i}function mr(t){return eu(t)?t:[]}function Ar(t){return Zi(t)?t:fi(t)}function Or(t,n,r){var e=t.length;return r=r===P?e:r,!n&&r>=e?t:sr(t,n,r)}function kr(t,n){ -if(n)return t.slice();var r=new t.constructor(t.length);return t.copy(r),r}function Er(t){var n=new t.constructor(t.byteLength);return new oo(n).set(new oo(t)),n}function Sr(t,n){if(t!==n){var r=t!==P,e=null===t,u=t===t,o=pu(t),i=n!==P,f=null===n,c=n===n,a=pu(n);if(!f&&!a&&!o&&t>n||o&&i&&c&&!f&&!a||e&&i&&c||!r&&c||!u)return 1;if(!e&&!o&&!a&&t<n||a&&r&&u&&!e&&!o||f&&r&&u||!i&&u||!c)return-1}return 0}function Rr(t,n,r,e){var u=-1,o=t.length,i=r.length,f=-1,c=n.length,a=jo(o-i,0),l=Du(c+a);for(e=!e;++f<c;)l[f]=n[f]; -for(;++u<i;)(e||u<o)&&(l[r[u]]=t[u]);for(;a--;)l[f++]=t[u++];return l}function Ir(t,n,r,e){var u=-1,o=t.length,i=-1,f=r.length,c=-1,a=n.length,l=jo(o-f,0),s=Du(l+a);for(e=!e;++u<l;)s[u]=t[u];for(l=u;++c<a;)s[l+c]=n[c];for(;++i<f;)(e||u<o)&&(s[l+r[i]]=t[u++]);return s}function Wr(t,n){var r=-1,e=t.length;for(n||(n=Du(e));++r<e;)n[r]=t[r];return n}function Br(t,n,r,e){r||(r={});for(var u=-1,o=n.length;++u<o;){var i=n[u],f=e?e(r[i],t[i],i,r,t):P;sn(r,i,f===P?t[i]:f)}return r}function Mr(t,n){return Br(t,ri(t),n); -}function Cr(t,n){return function(r,u){var o=Zi(r)?e:pn,i=n?n():{};return o(r,t,fe(u,2),i)}}function Lr(t){return ar(function(n,r){var e=-1,u=r.length,o=1<u?r[u-1]:P,i=2<u?r[2]:P,o=3<t.length&&typeof o=="function"?(u--,o):P;for(i&&ye(r[0],r[1],i)&&(o=3>u?P:o,u=1),n=Object(n);++e<u;)(i=r[e])&&t(n,i,e,o);return n})}function zr(t,n){return function(r,e){if(null==r)return r;if(!ru(r))return t(r,e);for(var u=r.length,o=n?u:-1,i=Object(r);(n?o--:++o<u)&&false!==e(i[o],o,i););return r}}function Ur(t){return function(n,r,e){ -var u=-1,o=Object(n);e=e(n);for(var i=e.length;i--;){var f=e[t?i:++u];if(false===r(o[f],f,o))break}return n}}function Dr(t,n,r){function e(){return(this&&this!==Vt&&this instanceof e?o:t).apply(u?r:this,arguments)}var u=1&n,o=Tr(t);return e}function $r(t){return function(n){n=xu(n);var r=Lt.test(n)?n.match(Mt):P,e=r?r[0]:n.charAt(0);return n=r?Or(r,1).join(""):n.slice(1),e[t]()+n}}function Fr(t){return function(n){return h(Ru(Su(n).replace(Wt,"")),t,"")}}function Tr(t){return function(){var n=arguments; -switch(n.length){case 0:return new t;case 1:return new t(n[0]);case 2:return new t(n[0],n[1]);case 3:return new t(n[0],n[1],n[2]);case 4:return new t(n[0],n[1],n[2],n[3]);case 5:return new t(n[0],n[1],n[2],n[3],n[4]);case 6:return new t(n[0],n[1],n[2],n[3],n[4],n[5]);case 7:return new t(n[0],n[1],n[2],n[3],n[4],n[5],n[6])}var r=xn(t.prototype),n=t.apply(r,n);return cu(n)?n:r}}function Nr(t,n,e){function u(){for(var i=arguments.length,f=Du(i),c=i,a=ie(u);c--;)f[c]=arguments[c];return c=3>i&&f[0]!==a&&f[i-1]!==a?[]:D(f,a), -i-=c.length,i<e?Xr(t,n,qr,u.placeholder,P,f,c,P,P,e-i):r(this&&this!==Vt&&this instanceof u?o:t,this,f)}var o=Tr(t);return u}function Pr(t){return function(n,r,e){var u=Object(n);if(!ru(n)){var o=fe(r,3);n=mu(n),r=function(t){return o(u[t],t,u)}}return r=t(n,r,e),-1<r?u[o?n[r]:r]:P}}function Zr(t){return ar(function(n){n=kn(n,1);var r=n.length,e=r,u=Tt.prototype.thru;for(t&&n.reverse();e--;){var o=n[e];if(typeof o!="function")throw new Pu("Expected a function");if(u&&!i&&"wrapper"==oe(o))var i=new Tt([],(true)); -}for(e=i?e:r;++e<r;)var o=n[e],u=oe(o),f="wrapper"==u?Xo(o):P,i=f&&xe(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?i[oe(f[0])].apply(i,f[3]):1==o.length&&xe(o)?i[u]():i.thru(o);return function(){var t=arguments,e=t[0];if(i&&1==t.length&&Zi(e)&&200<=e.length)return i.plant(e).value();for(var u=0,t=r?n[u].apply(this,t):e;++u<r;)t=n[u].call(this,t);return t}})}function qr(t,n,r,e,u,o,i,f,c,a){function l(){for(var d=arguments.length,y=Du(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=ie(l),b=y.length;for(x=0;b--;)y[b]===j&&x++; -}if(e&&(y=Rr(y,e,u,_)),o&&(y=Ir(y,o,i,_)),d-=x,_&&d<a)return j=D(y,j),Xr(t,n,qr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[t]:t,d=y.length,f){x=y.length;for(var w=wo(f.length,x),m=Wr(y);w--;){var A=f[w];y[w]=de(A,x)?m[A]:P}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==Vt&&this instanceof l&&(b=g||Tr(b)),b.apply(j,y)}var s=128&n,h=1&n,p=2&n,_=24&n,v=512&n,g=p?P:Tr(t);return l}function Vr(t,n){return function(r,e){return zn(r,t,n(e))}}function Kr(t,n){return function(r,e){ -var u;if(r===P&&e===P)return n;if(r!==P&&(u=r),e!==P){if(u===P)return e;typeof r=="string"||typeof e=="string"?(r=dr(r),e=dr(e)):(r=gr(r),e=gr(e)),u=t(r,e)}return u}}function Gr(t){return ar(function(n){return n=1==n.length&&Zi(n[0])?l(n[0],S(fe())):l(kn(n,1),S(fe())),ar(function(e){var u=this;return t(n,function(t){return r(t,u,e)})})})}function Jr(t,n){n=n===P?" ":dr(n);var r=n.length;return 2>r?r?cr(n,t):n:(r=cr(n,ho(t/T(n))),Lt.test(n)?Or(r.match(Mt),0,t).join(""):r.slice(0,t))}function Yr(t,n,e,u){ -function o(){for(var n=-1,c=arguments.length,a=-1,l=u.length,s=Du(l+c),h=this&&this!==Vt&&this instanceof o?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++n];return r(h,i?e:this,s)}var i=1&n,f=Tr(t);return o}function Hr(t){return function(n,r,e){e&&typeof e!="number"&&ye(n,r,e)&&(r=e=P),n=vu(n),r===P?(r=n,n=0):r=vu(r),e=e===P?n<r?1:-1:vu(e);var u=-1;r=jo(ho((r-n)/(e||1)),0);for(var o=Du(r);r--;)o[t?r:++u]=n,n+=e;return o}}function Qr(t){return function(n,r){return typeof n=="string"&&typeof r=="string"||(n=yu(n), -r=yu(r)),t(n,r)}}function Xr(t,n,r,e,u,o,i,f,c,a){var l=8&n,s=l?i:P;i=l?P:i;var h=l?o:P;return o=l?P:o,n=(n|(l?32:64))&~(l?64:32),4&n||(n&=-4),u=[t,n,u,h,s,o,i,f,c,a],r=r.apply(P,u),xe(t)&&oi(r,u),r.placeholder=e,ii(r,t,n)}function te(t){var n=Tu[t];return function(t,r){if(t=yu(t),r=wo(gu(r),292)){var e=(xu(t)+"e").split("e"),e=n(e[0]+"e"+(+e[1]+r)),e=(xu(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return n(t)}}function ne(t){return function(n){var r=St(n);return"[object Map]"==r?z(n):"[object Set]"==r?F(n):E(n,t(n)); -}}function re(t,n,r,e,u,o,i,f){var c=2&n;if(!c&&typeof t!="function")throw new Pu("Expected a function");var a=e?e.length:0;if(a||(n&=-97,e=u=P),i=i===P?i:jo(gu(i),0),f=f===P?f:gu(f),a-=u?u.length:0,64&n){var l=e,s=u;e=u=P}var h=c?P:Xo(t);return o=[t,n,r,e,u,l,s,o,i,f],h&&(r=o[1],t=h[1],n=r|t,e=128==t&&8==r||128==t&&256==r&&o[7].length<=h[8]||384==t&&h[7].length<=h[8]&&8==r,131>n||e)&&(1&t&&(o[2]=h[2],n|=1&r?0:4),(r=h[3])&&(e=o[3],o[3]=e?Rr(e,r,h[4]):r,o[4]=e?D(o[3],"__lodash_placeholder__"):h[4]), -(r=h[5])&&(e=o[5],o[5]=e?Ir(e,r,h[6]):r,o[6]=e?D(o[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(o[7]=r),128&t&&(o[8]=null==o[8]?h[8]:wo(o[8],h[8])),null==o[9]&&(o[9]=h[9]),o[0]=h[0],o[1]=n),t=o[0],n=o[1],r=o[2],e=o[3],u=o[4],f=o[9]=null==o[9]?c?0:t.length:jo(o[9]-a,0),!f&&24&n&&(n&=-25),ii((h?Ho:oi)(n&&1!=n?8==n||16==n?Nr(t,n,f):32!=n&&33!=n||u.length?qr.apply(P,o):Yr(t,n,r,e):Dr(t,n,r),o),t,n)}function ee(t,n,r,e,u,o){var i=2&u,f=t.length,c=n.length;if(f!=c&&!(i&&c>f))return false;if((c=o.get(t))&&o.get(n))return c==n; -var c=-1,a=true,l=1&u?new Yt:P;for(o.set(t,n),o.set(n,t);++c<f;){var s=t[c],h=n[c];if(e)var p=i?e(h,s,c,n,t,o):e(s,h,c,t,n,o);if(p!==P){if(p)continue;a=false;break}if(l){if(!_(n,function(t,n){if(!l.has(n)&&(s===t||r(s,t,e,u,o)))return l.add(n)})){a=false;break}}else if(s!==h&&!r(s,h,e,u,o)){a=false;break}}return o.delete(t),o.delete(n),a}function ue(t,n,r,e,u,o,i){switch(r){case"[object DataView]":if(t.byteLength!=n.byteLength||t.byteOffset!=n.byteOffset)break;t=t.buffer,n=n.buffer;case"[object ArrayBuffer]": -if(t.byteLength!=n.byteLength||!e(new oo(t),new oo(n)))break;return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return tu(+t,+n);case"[object Error]":return t.name==n.name&&t.message==n.message;case"[object RegExp]":case"[object String]":return t==n+"";case"[object Map]":var f=z;case"[object Set]":if(f||(f=$),t.size!=n.size&&!(2&o))break;return(r=i.get(t))?r==n:(o|=1,i.set(t,n),n=ee(f(t),f(n),e,u,o,i),i.delete(t),n);case"[object Symbol]":if(Zo)return Zo.call(t)==Zo.call(n)} -return false}function oe(t){for(var n=t.name+"",r=Uo[n],e=Yu.call(Uo,n)?r.length:0;e--;){var u=r[e],o=u.func;if(null==o||o==t)return u.name}return n}function ie(t){return(Yu.call(It,"placeholder")?It:t).placeholder}function fe(){var t=It.iteratee||Bu,t=t===Bu?Kn:t;return arguments.length?t(arguments[0],arguments[1]):t}function ce(t,n){var r=t.__data__,e=typeof n;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==n:null===n)?r[typeof n=="string"?"string":"hash"]:r.map}function ae(t){ -for(var n=mu(t),r=n.length;r--;){var e=n[r],u=t[e];n[r]=[e,u,u===u&&!cu(u)]}return n}function le(t,n){var r=null==t?P:t[n];return Pn(r)?r:P}function se(t,n,r){n=be(n,t)?[n]:Ar(n);for(var e,u=-1,o=n.length;++u<o;){var i=Oe(n[u]);if(!(e=null!=t&&r(t,i)))break;t=t[i]}return e?e:(o=t?t.length:0,!!o&&fu(o)&&de(i,o)&&(Zi(t)||hu(t)||nu(t)))}function he(t){var n=t.length,r=t.constructor(n);return n&&"string"==typeof t[0]&&Yu.call(t,"index")&&(r.index=t.index,r.input=t.input),r}function pe(t){return typeof t.constructor!="function"||je(t)?{}:xn(ni(t)); -}function _e(r,e,u,o){var i=r.constructor;switch(e){case"[object ArrayBuffer]":return Er(r);case"[object Boolean]":case"[object Date]":return new i((+r));case"[object DataView]":return e=o?Er(r.buffer):r.buffer,new r.constructor(e,r.byteOffset,r.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]": -return e=o?Er(r.buffer):r.buffer,new r.constructor(e,r.byteOffset,r.length);case"[object Map]":return e=o?u(z(r),true):z(r),h(e,t,new r.constructor);case"[object Number]":case"[object String]":return new i(r);case"[object RegExp]":return e=new r.constructor(r.source,yt.exec(r)),e.lastIndex=r.lastIndex,e;case"[object Set]":return e=o?u($(r),true):$(r),h(e,n,new r.constructor);case"[object Symbol]":return Zo?Object(Zo.call(r)):{}}}function ve(t){var n=t?t.length:P;return fu(n)&&(Zi(t)||hu(t)||nu(t))?k(n,String):null; -}function ge(t){return Zi(t)||nu(t)||!!(so&&t&&t[so])}function de(t,n){return n=null==n?9007199254740991:n,!!n&&(typeof t=="number"||At.test(t))&&-1<t&&0==t%1&&t<n}function ye(t,n,r){if(!cu(r))return false;var e=typeof n;return!!("number"==e?ru(r)&&de(n,r.length):"string"==e&&n in r)&&tu(r[n],t)}function be(t,n){if(Zi(t))return false;var r=typeof t;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!pu(t))||(ut.test(t)||!et.test(t)||null!=n&&t in Object(n))}function xe(t){var n=oe(t),r=It[n];return typeof r=="function"&&n in Zt.prototype&&(t===r||(n=Xo(r), -!!n&&t===n[0]))}function je(t){var n=t&&t.constructor;return t===(typeof n=="function"&&n.prototype||qu)}function we(t,n){return function(r){return null!=r&&(r[t]===n&&(n!==P||t in Object(r)))}}function me(t,n,r,e,u,o){return cu(t)&&cu(n)&&(o.set(n,t),Xn(t,n,P,me,o),o.delete(n)),t}function Ae(t,n){return 1==n.length?t:In(t,sr(n,0,-1))}function Oe(t){if(typeof t=="string"||pu(t))return t;var n=t+"";return"0"==n&&1/t==-Z?"-0":n}function ke(t){if(null!=t){try{return Ju.call(t)}catch(t){}return t+""} -return""}function Ee(t,n){return u(V,function(r){var e="_."+r[0];n&r[1]&&!c(t,e)&&t.push(e)}),t.sort()}function Se(t){if(t instanceof Zt)return t.clone();var n=new Tt(t.__wrapped__,t.__chain__);return n.__actions__=Wr(t.__actions__),n.__index__=t.__index__,n.__values__=t.__values__,n}function Re(t,n,r){var e=t?t.length:0;return e?(n=r||n===P?1:gu(n),sr(t,0>n?0:n,e)):[]}function Ie(t,n,r){var e=t?t.length:0;return e?(n=r||n===P?1:gu(n),n=e-n,sr(t,0,0>n?0:n)):[]}function We(t,n,r){var e=t?t.length:0; -return e?(r=null==r?0:gu(r),0>r&&(r=jo(e+r,0)),g(t,fe(n,3),r)):-1}function Be(t,n,r){var e=t?t.length:0;if(!e)return-1;var u=e-1;return r!==P&&(u=gu(r),u=0>r?jo(e+u,0):wo(u,e-1)),g(t,fe(n,3),u,true)}function Me(t){return t&&t.length?t[0]:P}function Ce(t){var n=t?t.length:0;return n?t[n-1]:P}function Le(t,n){return t&&t.length&&n&&n.length?or(t,n):t}function ze(t){return t?ko.call(t):t}function Ue(t){if(!t||!t.length)return[];var n=0;return t=f(t,function(t){if(eu(t))return n=jo(t.length,n),true}),k(n,function(n){ -return l(t,j(n))})}function De(t,n){if(!t||!t.length)return[];var e=Ue(t);return null==n?e:l(e,function(t){return r(n,P,t)})}function $e(t){return t=It(t),t.__chain__=true,t}function Fe(t,n){return n(t)}function Te(){return this}function Ne(t,n){return(Zi(t)?u:Vo)(t,fe(n,3))}function Pe(t,n){return(Zi(t)?o:Ko)(t,fe(n,3))}function Ze(t,n){return(Zi(t)?l:Yn)(t,fe(n,3))}function qe(t,n,r){var e=-1,u=_u(t),o=u.length,i=o-1;for(n=(r?ye(t,n,r):n===P)?1:gn(gu(n),0,o);++e<n;)t=fr(e,i),r=u[t],u[t]=u[e],u[e]=r; -return u.length=n,u}function Ve(){return $u.now()}function Ke(t,n,r){return n=r?P:n,n=t&&null==n?t.length:n,re(t,128,P,P,P,P,n)}function Ge(t,n){var r;if(typeof n!="function")throw new Pu("Expected a function");return t=gu(t),function(){return 0<--t&&(r=n.apply(this,arguments)),1>=t&&(n=P),r}}function Je(t,n,r){return n=r?P:n,t=re(t,8,P,P,P,P,P,n),t.placeholder=Je.placeholder,t}function Ye(t,n,r){return n=r?P:n,t=re(t,16,P,P,P,P,P,n),t.placeholder=Ye.placeholder,t}function He(t,n,r){function e(n){ -var r=c,e=a;return c=a=P,_=n,s=t.apply(e,r)}function u(t){var r=t-p;return t-=_,p===P||r>=n||0>r||g&&t>=l}function o(){var t=Ve();if(u(t))return i(t);var r;r=t-_,t=n-(t-p),r=g?wo(t,l-r):t,h=Rt(o,r)}function i(t){return h=P,d&&c?e(t):(c=a=P,s)}function f(){var t=Ve(),r=u(t);if(c=arguments,a=this,p=t,r){if(h===P)return _=t=p,h=Rt(o,n),v?e(t):s;if(g)return h=Rt(o,n),e(p)}return h===P&&(h=Rt(o,n)),s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof t!="function")throw new Pu("Expected a function");return n=yu(n)||0, -cu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?jo(yu(r.maxWait)||0,n):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==P&&w.clearTimeout.call(Vt,h),_=0,c=p=a=h=P},f.flush=function(){return h===P?s:i(Ve())},f}function Qe(t,n){function r(){var e=arguments,u=n?n.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=t.apply(this,e),r.cache=o.set(u,e),e)}if(typeof t!="function"||n&&typeof n!="function")throw new Pu("Expected a function");return r.cache=new(Qe.Cache||Gt),r}function Xe(t){if(typeof t!="function")throw new Pu("Expected a function"); -return function(){var n=arguments;switch(n.length){case 0:return!t.call(this);case 1:return!t.call(this,n[0]);case 2:return!t.call(this,n[0],n[1]);case 3:return!t.call(this,n[0],n[1],n[2])}return!t.apply(this,n)}}function tu(t,n){return t===n||t!==t&&n!==n}function nu(t){return eu(t)&&Yu.call(t,"callee")&&(!ao.call(t,"callee")||"[object Arguments]"==Xu.call(t))}function ru(t){return null!=t&&fu(ti(t))&&!ou(t)}function eu(t){return au(t)&&ru(t)}function uu(t){return!!au(t)&&("[object Error]"==Xu.call(t)||typeof t.message=="string"&&typeof t.name=="string"); -}function ou(t){return t=cu(t)?Xu.call(t):"","[object Function]"==t||"[object GeneratorFunction]"==t}function iu(t){return typeof t=="number"&&t==gu(t)}function fu(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t}function cu(t){var n=typeof t;return!!t&&("object"==n||"function"==n)}function au(t){return!!t&&typeof t=="object"}function lu(t){return typeof t=="number"||au(t)&&"[object Number]"==Xu.call(t)}function su(t){return!(!au(t)||"[object Object]"!=Xu.call(t)||C(t))&&(t=ni(t),null===t||(t=Yu.call(t,"constructor")&&t.constructor, -typeof t=="function"&&t instanceof t&&Ju.call(t)==Qu))}function hu(t){return typeof t=="string"||!Zi(t)&&au(t)&&"[object String]"==Xu.call(t)}function pu(t){return typeof t=="symbol"||au(t)&&"[object Symbol]"==Xu.call(t)}function _u(t){if(!t)return[];if(ru(t))return hu(t)?t.match(Mt):Wr(t);if(fo&&t[fo])return L(t[fo]());var n=St(t);return("[object Map]"==n?z:"[object Set]"==n?$:ku)(t)}function vu(t){return t?(t=yu(t),t===Z||t===-Z?1.7976931348623157e308*(0>t?-1:1):t===t?t:0):0===t?t:0}function gu(t){ -t=vu(t);var n=t%1;return t===t?n?t-n:t:0}function du(t){return t?gn(gu(t),0,4294967295):0}function yu(t){if(typeof t=="number")return t;if(pu(t))return q;if(cu(t)&&(t=ou(t.valueOf)?t.valueOf():t,t=cu(t)?t+"":t),typeof t!="string")return 0===t?t:+t;t=t.replace(at,"");var n=jt.test(t);return n||mt.test(t)?Pt(t.slice(2),n?2:8):xt.test(t)?q:+t}function bu(t){return Br(t,Au(t))}function xu(t){return null==t?"":dr(t)}function ju(t,n,r){return t=null==t?P:In(t,n),t===P?r:t}function wu(t,n){return null!=t&&se(t,n,Cn); -}function mu(t){var n=je(t);if(!n&&!ru(t))return Yo(t);var r,e=ve(t),u=!!e,e=e||[],o=e.length;for(r in t)!Mn(t,r)||u&&("length"==r||de(r,o))||n&&"constructor"==r||e.push(r);return e}function Au(t){for(var n=-1,r=je(t),e=Gn(t),u=e.length,o=ve(t),i=!!o,o=o||[],f=o.length;++n<u;){var c=e[n];i&&("length"==c||de(c,f))||"constructor"==c&&(r||!Yu.call(t,c))||o.push(c)}return o}function Ou(t,n){return null==t?{}:er(t,Wn(t,Au,ei),fe(n))}function ku(t){return t?R(t,mu(t)):[]}function Eu(t){return Af(xu(t).toLowerCase()); -}function Su(t){return(t=xu(t))&&t.replace(Ot,en).replace(Bt,"")}function Ru(t,n,r){return t=xu(t),n=r?P:n,n===P&&(n=zt.test(t)?Ct:vt),t.match(n)||[]}function Iu(t){return function(){return t}}function Wu(t){return t}function Bu(t){return Kn(typeof t=="function"?t:dn(t,true))}function Mu(t,n,r){var e=mu(n),o=Rn(n,e);null!=r||cu(n)&&(o.length||!e.length)||(r=n,n=t,t=this,o=Rn(n,mu(n)));var i=!(cu(r)&&"chain"in r&&!r.chain),f=ou(t);return u(o,function(r){var e=n[r];t[r]=e,f&&(t.prototype[r]=function(){ -var n=this.__chain__;if(i||n){var r=t(this.__wrapped__);return(r.__actions__=Wr(this.__actions__)).push({func:e,args:arguments,thisArg:t}),r.__chain__=n,r}return e.apply(t,s([this.value()],arguments))})}),t}function Cu(){}function Lu(t){return be(t)?j(Oe(t)):ur(t)}function zu(){return[]}function Uu(){return false}w=w?fn.defaults({},w,fn.pick(Vt,Ut)):Vt;var Du=w.Array,$u=w.Date,Fu=w.Error,Tu=w.Math,Nu=w.RegExp,Pu=w.TypeError,Zu=w.Array.prototype,qu=w.Object.prototype,Vu=w.String.prototype,Ku=w["__core-js_shared__"],Gu=function(){ -var t=/[^.]+$/.exec(Ku&&Ku.keys&&Ku.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Ju=w.Function.prototype.toString,Yu=qu.hasOwnProperty,Hu=0,Qu=Ju.call(Object),Xu=qu.toString,to=Vt._,no=Nu("^"+Ju.call(Yu).replace(ft,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),ro=Jt?w.Buffer:P,eo=w.Reflect,uo=w.Symbol,oo=w.Uint8Array,io=eo?eo.g:P,fo=uo?uo.iterator:P,co=w.Object.create,ao=qu.propertyIsEnumerable,lo=Zu.splice,so=uo?uo.isConcatSpreadable:P,ho=Tu.ceil,po=Tu.floor,_o=Object.getPrototypeOf,vo=Object.getOwnPropertySymbols,go=ro?ro.isBuffer:P,yo=w.isFinite,bo=Zu.join,xo=Object.keys,jo=Tu.max,wo=Tu.min,mo=w.parseInt,Ao=Tu.random,Oo=Vu.replace,ko=Zu.reverse,Eo=Vu.split,So=le(w,"DataView"),Ro=le(w,"Map"),Io=le(w,"Promise"),Wo=le(w,"Set"),Bo=le(w,"WeakMap"),Mo=le(w.Object,"create"),Co=function(){ -var t=le(w.Object,"defineProperty"),n=le.name;return n&&2<n.length?t:P}(),Lo=Bo&&new Bo,zo=!ao.call({valueOf:1},"valueOf"),Uo={},Do=ke(So),$o=ke(Ro),Fo=ke(Io),To=ke(Wo),No=ke(Bo),Po=uo?uo.prototype:P,Zo=Po?Po.valueOf:P,qo=Po?Po.toString:P;It.templateSettings={escape:tt,evaluate:nt,interpolate:rt,variable:"",imports:{_:It}},It.prototype=Ft.prototype,It.prototype.constructor=It,Tt.prototype=xn(Ft.prototype),Tt.prototype.constructor=Tt,Zt.prototype=xn(Ft.prototype),Zt.prototype.constructor=Zt,qt.prototype.clear=function(){ -this.__data__=Mo?Mo(null):{}},qt.prototype.delete=function(t){return this.has(t)&&delete this.__data__[t]},qt.prototype.get=function(t){var n=this.__data__;return Mo?(t=n[t],"__lodash_hash_undefined__"===t?P:t):Yu.call(n,t)?n[t]:P},qt.prototype.has=function(t){var n=this.__data__;return Mo?n[t]!==P:Yu.call(n,t)},qt.prototype.set=function(t,n){return this.__data__[t]=Mo&&n===P?"__lodash_hash_undefined__":n,this},Kt.prototype.clear=function(){this.__data__=[]},Kt.prototype.delete=function(t){var n=this.__data__; -return t=hn(n,t),!(0>t)&&(t==n.length-1?n.pop():lo.call(n,t,1),true)},Kt.prototype.get=function(t){var n=this.__data__;return t=hn(n,t),0>t?P:n[t][1]},Kt.prototype.has=function(t){return-1<hn(this.__data__,t)},Kt.prototype.set=function(t,n){var r=this.__data__,e=hn(r,t);return 0>e?r.push([t,n]):r[e][1]=n,this},Gt.prototype.clear=function(){this.__data__={hash:new qt,map:new(Ro||Kt),string:new qt}},Gt.prototype.delete=function(t){return ce(this,t).delete(t)},Gt.prototype.get=function(t){return ce(this,t).get(t); -},Gt.prototype.has=function(t){return ce(this,t).has(t)},Gt.prototype.set=function(t,n){return ce(this,t).set(t,n),this},Yt.prototype.add=Yt.prototype.push=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this},Yt.prototype.has=function(t){return this.__data__.has(t)},cn.prototype.clear=function(){this.__data__=new Kt},cn.prototype.delete=function(t){return this.__data__.delete(t)},cn.prototype.get=function(t){return this.__data__.get(t)},cn.prototype.has=function(t){return this.__data__.has(t); -},cn.prototype.set=function(t,n){var r=this.__data__;if(r instanceof Kt){if(r=r.__data__,!Ro||199>r.length)return r.push([t,n]),this;r=this.__data__=new Gt(r)}return r.set(t,n),this};var Vo=zr(En),Ko=zr(Sn,true),Go=Ur(),Jo=Ur(true),Yo=U(xo);io&&!ao.call({valueOf:1},"valueOf")&&(Gn=function(t){return L(io(t))});var Ho=Lo?function(t,n){return Lo.set(t,n),t}:Wu,Qo=Wo&&1/$(new Wo([,-0]))[1]==Z?function(t){return new Wo(t)}:Cu,Xo=Lo?function(t){return Lo.get(t)}:Cu,ti=j("length"),ni=U(_o),ri=vo?U(vo):zu,ei=vo?function(t){ -for(var n=[];t;)s(n,ri(t)),t=ni(t);return n}:zu;(So&&"[object DataView]"!=St(new So(new ArrayBuffer(1)))||Ro&&"[object Map]"!=St(new Ro)||Io&&"[object Promise]"!=St(Io.resolve())||Wo&&"[object Set]"!=St(new Wo)||Bo&&"[object WeakMap]"!=St(new Bo))&&(St=function(t){var n=Xu.call(t);if(t=(t="[object Object]"==n?t.constructor:P)?ke(t):P)switch(t){case Do:return"[object DataView]";case $o:return"[object Map]";case Fo:return"[object Promise]";case To:return"[object Set]";case No:return"[object WeakMap]"; -}return n});var ui=Ku?ou:Uu,oi=function(){var t=0,n=0;return function(r,e){var u=Ve(),o=16-(u-n);if(n=u,0<o){if(150<=++t)return r}else t=0;return Ho(r,e)}}(),ii=Co?function(t,n,r){n+="";var e;e=(e=n.match(pt))?e[1].split(_t):[],r=Ee(e,r),e=r.length;var u=e-1;return r[u]=(1<e?"& ":"")+r[u],r=r.join(2<e?", ":" "),n=n.replace(ht,"{\n/* [wrapped with "+r+"] */\n"),Co(t,"toString",{configurable:true,enumerable:false,value:Iu(n)})}:Wu,fi=Qe(function(t){t=xu(t);var n=[];return ot.test(t)&&n.push(""),t.replace(it,function(t,r,e,u){ -n.push(e?u.replace(gt,"$1"):r||t)}),n}),ci=ar(function(t,n){return eu(t)?wn(t,kn(n,1,eu,true)):[]}),ai=ar(function(t,n){var r=Ce(n);return eu(r)&&(r=P),eu(t)?wn(t,kn(n,1,eu,true),fe(r,2)):[]}),li=ar(function(t,n){var r=Ce(n);return eu(r)&&(r=P),eu(t)?wn(t,kn(n,1,eu,true),P,r):[]}),si=ar(function(t){var n=l(t,mr);return n.length&&n[0]===t[0]?Ln(n):[]}),hi=ar(function(t){var n=Ce(t),r=l(t,mr);return n===Ce(r)?n=P:r.pop(),r.length&&r[0]===t[0]?Ln(r,fe(n,2)):[]}),pi=ar(function(t){var n=Ce(t),r=l(t,mr);return n===Ce(r)?n=P:r.pop(), -r.length&&r[0]===t[0]?Ln(r,P,n):[]}),_i=ar(Le),vi=ar(function(t,n){n=kn(n,1);var r=t?t.length:0,e=vn(t,n);return ir(t,l(n,function(t){return de(t,r)?+t:t}).sort(Sr)),e}),gi=ar(function(t){return yr(kn(t,1,eu,true))}),di=ar(function(t){var n=Ce(t);return eu(n)&&(n=P),yr(kn(t,1,eu,true),fe(n,2))}),yi=ar(function(t){var n=Ce(t);return eu(n)&&(n=P),yr(kn(t,1,eu,true),P,n)}),bi=ar(function(t,n){return eu(t)?wn(t,n):[]}),xi=ar(function(t){return jr(f(t,eu))}),ji=ar(function(t){var n=Ce(t);return eu(n)&&(n=P), -jr(f(t,eu),fe(n,2))}),wi=ar(function(t){var n=Ce(t);return eu(n)&&(n=P),jr(f(t,eu),P,n)}),mi=ar(Ue),Ai=ar(function(t){var n=t.length,n=1<n?t[n-1]:P,n=typeof n=="function"?(t.pop(),n):P;return De(t,n)}),Oi=ar(function(t){function n(n){return vn(n,t)}t=kn(t,1);var r=t.length,e=r?t[0]:0,u=this.__wrapped__;return!(1<r||this.__actions__.length)&&u instanceof Zt&&de(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:Fe,args:[n],thisArg:P}),new Tt(u,this.__chain__).thru(function(t){return r&&!t.length&&t.push(P), -t})):this.thru(n)}),ki=Cr(function(t,n,r){Yu.call(t,r)?++t[r]:t[r]=1}),Ei=Pr(We),Si=Pr(Be),Ri=Cr(function(t,n,r){Yu.call(t,r)?t[r].push(n):t[r]=[n]}),Ii=ar(function(t,n,e){var u=-1,o=typeof n=="function",i=be(n),f=ru(t)?Du(t.length):[];return Vo(t,function(t){var c=o?n:i&&null!=t?t[n]:P;f[++u]=c?r(c,t,e):Un(t,n,e)}),f}),Wi=Cr(function(t,n,r){t[r]=n}),Bi=Cr(function(t,n,r){t[r?0:1].push(n)},function(){return[[],[]]}),Mi=ar(function(t,n){if(null==t)return[];var r=n.length;return 1<r&&ye(t,n[0],n[1])?n=[]:2<r&&ye(n[0],n[1],n[2])&&(n=[n[0]]), -nr(t,kn(n,1),[])}),Ci=ar(function(t,n,r){var e=1;if(r.length)var u=D(r,ie(Ci)),e=32|e;return re(t,e,n,r,u)}),Li=ar(function(t,n,r){var e=3;if(r.length)var u=D(r,ie(Li)),e=32|e;return re(n,e,t,r,u)}),zi=ar(function(t,n){return jn(t,1,n)}),Ui=ar(function(t,n,r){return jn(t,yu(n)||0,r)});Qe.Cache=Gt;var Di=ar(function(t,n){n=1==n.length&&Zi(n[0])?l(n[0],S(fe())):l(kn(n,1),S(fe()));var e=n.length;return ar(function(u){for(var o=-1,i=wo(u.length,e);++o<i;)u[o]=n[o].call(this,u[o]);return r(t,this,u)}); -}),$i=ar(function(t,n){var r=D(n,ie($i));return re(t,32,P,n,r)}),Fi=ar(function(t,n){var r=D(n,ie(Fi));return re(t,64,P,n,r)}),Ti=ar(function(t,n){return re(t,256,P,P,P,kn(n,1))}),Ni=Qr(Bn),Pi=Qr(function(t,n){return t>=n}),Zi=Du.isArray,qi=Ht?S(Ht):Dn,Vi=go||Uu,Ki=Qt?S(Qt):$n,Gi=Xt?S(Xt):Tn,Ji=tn?S(tn):Zn,Yi=nn?S(nn):qn,Hi=rn?S(rn):Vn,Qi=Qr(Jn),Xi=Qr(function(t,n){return t<=n}),tf=Lr(function(t,n){if(zo||je(n)||ru(n))Br(n,mu(n),t);else for(var r in n)Yu.call(n,r)&&sn(t,r,n[r])}),nf=Lr(function(t,n){ -if(zo||je(n)||ru(n))Br(n,Au(n),t);else for(var r in n)sn(t,r,n[r])}),rf=Lr(function(t,n,r,e){Br(n,Au(n),t,e)}),ef=Lr(function(t,n,r,e){Br(n,mu(n),t,e)}),uf=ar(function(t,n){return vn(t,kn(n,1))}),of=ar(function(t){return t.push(P,an),r(rf,P,t)}),ff=ar(function(t){return t.push(P,me),r(hf,P,t)}),cf=Vr(function(t,n,r){t[n]=r},Iu(Wu)),af=Vr(function(t,n,r){Yu.call(t,n)?t[n].push(r):t[n]=[r]},fe),lf=ar(Un),sf=Lr(function(t,n,r){Xn(t,n,r)}),hf=Lr(function(t,n,r,e){Xn(t,n,r,e)}),pf=ar(function(t,n){return null==t?{}:(n=l(kn(n,1),Oe), -rr(t,wn(Wn(t,Au,ei),n)))}),_f=ar(function(t,n){return null==t?{}:rr(t,l(kn(n,1),Oe))}),vf=ne(mu),gf=ne(Au),df=Fr(function(t,n,r){return n=n.toLowerCase(),t+(r?Eu(n):n)}),yf=Fr(function(t,n,r){return t+(r?"-":"")+n.toLowerCase()}),bf=Fr(function(t,n,r){return t+(r?" ":"")+n.toLowerCase()}),xf=$r("toLowerCase"),jf=Fr(function(t,n,r){return t+(r?"_":"")+n.toLowerCase()}),wf=Fr(function(t,n,r){return t+(r?" ":"")+Af(n)}),mf=Fr(function(t,n,r){return t+(r?" ":"")+n.toUpperCase()}),Af=$r("toUpperCase"),Of=ar(function(t,n){ -try{return r(t,P,n)}catch(t){return uu(t)?t:new Fu(t)}}),kf=ar(function(t,n){return u(kn(n,1),function(n){n=Oe(n),t[n]=Ci(t[n],t)}),t}),Ef=Zr(),Sf=Zr(true),Rf=ar(function(t,n){return function(r){return Un(r,t,n)}}),If=ar(function(t,n){return function(r){return Un(t,r,n)}}),Wf=Gr(l),Bf=Gr(i),Mf=Gr(_),Cf=Hr(),Lf=Hr(true),zf=Kr(function(t,n){return t+n},0),Uf=te("ceil"),Df=Kr(function(t,n){return t/n},1),$f=te("floor"),Ff=Kr(function(t,n){return t*n},1),Tf=te("round"),Nf=Kr(function(t,n){return t-n},0);return It.after=function(t,n){ -if(typeof n!="function")throw new Pu("Expected a function");return t=gu(t),function(){if(1>--t)return n.apply(this,arguments)}},It.ary=Ke,It.assign=tf,It.assignIn=nf,It.assignInWith=rf,It.assignWith=ef,It.at=uf,It.before=Ge,It.bind=Ci,It.bindAll=kf,It.bindKey=Li,It.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return Zi(t)?t:[t]},It.chain=$e,It.chunk=function(t,n,r){if(n=(r?ye(t,n,r):n===P)?1:jo(gu(n),0),r=t?t.length:0,!r||1>n)return[];for(var e=0,u=0,o=Du(ho(r/n));e<r;)o[u++]=sr(t,e,e+=n); -return o},It.compact=function(t){for(var n=-1,r=t?t.length:0,e=0,u=[];++n<r;){var o=t[n];o&&(u[e++]=o)}return u},It.concat=function(){for(var t=arguments.length,n=Du(t?t-1:0),r=arguments[0],e=t;e--;)n[e-1]=arguments[e];return t?s(Zi(r)?Wr(r):[r],kn(n,1)):[]},It.cond=function(t){var n=t?t.length:0,e=fe();return t=n?l(t,function(t){if("function"!=typeof t[1])throw new Pu("Expected a function");return[e(t[0]),t[1]]}):[],ar(function(e){for(var u=-1;++u<n;){var o=t[u];if(r(o[0],this,e))return r(o[1],this,e); -}})},It.conforms=function(t){return yn(dn(t,true))},It.constant=Iu,It.countBy=ki,It.create=function(t,n){var r=xn(t);return n?_n(r,n):r},It.curry=Je,It.curryRight=Ye,It.debounce=He,It.defaults=of,It.defaultsDeep=ff,It.defer=zi,It.delay=Ui,It.difference=ci,It.differenceBy=ai,It.differenceWith=li,It.drop=Re,It.dropRight=Ie,It.dropRightWhile=function(t,n){return t&&t.length?br(t,fe(n,3),true,true):[]},It.dropWhile=function(t,n){return t&&t.length?br(t,fe(n,3),true):[]},It.fill=function(t,n,r,e){var u=t?t.length:0; -if(!u)return[];for(r&&typeof r!="number"&&ye(t,n,r)&&(r=0,e=u),u=t.length,r=gu(r),0>r&&(r=-r>u?0:u+r),e=e===P||e>u?u:gu(e),0>e&&(e+=u),e=r>e?0:du(e);r<e;)t[r++]=n;return t},It.filter=function(t,n){return(Zi(t)?f:On)(t,fe(n,3))},It.flatMap=function(t,n){return kn(Ze(t,n),1)},It.flatMapDeep=function(t,n){return kn(Ze(t,n),Z)},It.flatMapDepth=function(t,n,r){return r=r===P?1:gu(r),kn(Ze(t,n),r)},It.flatten=function(t){return t&&t.length?kn(t,1):[]},It.flattenDeep=function(t){return t&&t.length?kn(t,Z):[]; -},It.flattenDepth=function(t,n){return t&&t.length?(n=n===P?1:gu(n),kn(t,n)):[]},It.flip=function(t){return re(t,512)},It.flow=Ef,It.flowRight=Sf,It.fromPairs=function(t){for(var n=-1,r=t?t.length:0,e={};++n<r;){var u=t[n];e[u[0]]=u[1]}return e},It.functions=function(t){return null==t?[]:Rn(t,mu(t))},It.functionsIn=function(t){return null==t?[]:Rn(t,Au(t))},It.groupBy=Ri,It.initial=function(t){return Ie(t,1)},It.intersection=si,It.intersectionBy=hi,It.intersectionWith=pi,It.invert=cf,It.invertBy=af, -It.invokeMap=Ii,It.iteratee=Bu,It.keyBy=Wi,It.keys=mu,It.keysIn=Au,It.map=Ze,It.mapKeys=function(t,n){var r={};return n=fe(n,3),En(t,function(t,e,u){r[n(t,e,u)]=t}),r},It.mapValues=function(t,n){var r={};return n=fe(n,3),En(t,function(t,e,u){r[e]=n(t,e,u)}),r},It.matches=function(t){return Hn(dn(t,true))},It.matchesProperty=function(t,n){return Qn(t,dn(n,true))},It.memoize=Qe,It.merge=sf,It.mergeWith=hf,It.method=Rf,It.methodOf=If,It.mixin=Mu,It.negate=Xe,It.nthArg=function(t){return t=gu(t),ar(function(n){ -return tr(n,t)})},It.omit=pf,It.omitBy=function(t,n){return Ou(t,Xe(fe(n)))},It.once=function(t){return Ge(2,t)},It.orderBy=function(t,n,r,e){return null==t?[]:(Zi(n)||(n=null==n?[]:[n]),r=e?P:r,Zi(r)||(r=null==r?[]:[r]),nr(t,n,r))},It.over=Wf,It.overArgs=Di,It.overEvery=Bf,It.overSome=Mf,It.partial=$i,It.partialRight=Fi,It.partition=Bi,It.pick=_f,It.pickBy=Ou,It.property=Lu,It.propertyOf=function(t){return function(n){return null==t?P:In(t,n)}},It.pull=_i,It.pullAll=Le,It.pullAllBy=function(t,n,r){ -return t&&t.length&&n&&n.length?or(t,n,fe(r,2)):t},It.pullAllWith=function(t,n,r){return t&&t.length&&n&&n.length?or(t,n,P,r):t},It.pullAt=vi,It.range=Cf,It.rangeRight=Lf,It.rearg=Ti,It.reject=function(t,n){return(Zi(t)?f:On)(t,Xe(fe(n,3)))},It.remove=function(t,n){var r=[];if(!t||!t.length)return r;var e=-1,u=[],o=t.length;for(n=fe(n,3);++e<o;){var i=t[e];n(i,e,t)&&(r.push(i),u.push(e))}return ir(t,u),r},It.rest=function(t,n){if(typeof t!="function")throw new Pu("Expected a function");return n=n===P?n:gu(n), -ar(t,n)},It.reverse=ze,It.sampleSize=qe,It.set=function(t,n,r){return null==t?t:lr(t,n,r)},It.setWith=function(t,n,r,e){return e=typeof e=="function"?e:P,null==t?t:lr(t,n,r,e)},It.shuffle=function(t){return qe(t,4294967295)},It.slice=function(t,n,r){var e=t?t.length:0;return e?(r&&typeof r!="number"&&ye(t,n,r)?(n=0,r=e):(n=null==n?0:gu(n),r=r===P?e:gu(r)),sr(t,n,r)):[]},It.sortBy=Mi,It.sortedUniq=function(t){return t&&t.length?vr(t):[]},It.sortedUniqBy=function(t,n){return t&&t.length?vr(t,fe(n,2)):[]; -},It.split=function(t,n,r){return r&&typeof r!="number"&&ye(t,n,r)&&(n=r=P),r=r===P?4294967295:r>>>0,r?(t=xu(t))&&(typeof n=="string"||null!=n&&!Ji(n))&&(n=dr(n),""==n&&Lt.test(t))?Or(t.match(Mt),0,r):Eo.call(t,n,r):[]},It.spread=function(t,n){if(typeof t!="function")throw new Pu("Expected a function");return n=n===P?0:jo(gu(n),0),ar(function(e){var u=e[n];return e=Or(e,0,n),u&&s(e,u),r(t,this,e)})},It.tail=function(t){return Re(t,1)},It.take=function(t,n,r){return t&&t.length?(n=r||n===P?1:gu(n), -sr(t,0,0>n?0:n)):[]},It.takeRight=function(t,n,r){var e=t?t.length:0;return e?(n=r||n===P?1:gu(n),n=e-n,sr(t,0>n?0:n,e)):[]},It.takeRightWhile=function(t,n){return t&&t.length?br(t,fe(n,3),false,true):[]},It.takeWhile=function(t,n){return t&&t.length?br(t,fe(n,3)):[]},It.tap=function(t,n){return n(t),t},It.throttle=function(t,n,r){var e=true,u=true;if(typeof t!="function")throw new Pu("Expected a function");return cu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),He(t,n,{leading:e,maxWait:n, -trailing:u})},It.thru=Fe,It.toArray=_u,It.toPairs=vf,It.toPairsIn=gf,It.toPath=function(t){return Zi(t)?l(t,Oe):pu(t)?[t]:Wr(fi(t))},It.toPlainObject=bu,It.transform=function(t,n,r){var e=Zi(t)||Hi(t);if(n=fe(n,4),null==r)if(e||cu(t)){var o=t.constructor;r=e?Zi(t)?new o:[]:ou(o)?xn(ni(t)):{}}else r={};return(e?u:En)(t,function(t,e,u){return n(r,t,e,u)}),r},It.unary=function(t){return Ke(t,1)},It.union=gi,It.unionBy=di,It.unionWith=yi,It.uniq=function(t){return t&&t.length?yr(t):[]},It.uniqBy=function(t,n){ -return t&&t.length?yr(t,fe(n,2)):[]},It.uniqWith=function(t,n){return t&&t.length?yr(t,P,n):[]},It.unset=function(t,n){var r;if(null==t)r=true;else{r=t;var e=n,e=be(e,r)?[e]:Ar(e);r=Ae(r,e),e=Oe(Ce(e)),r=!(null!=r&&Mn(r,e))||delete r[e]}return r},It.unzip=Ue,It.unzipWith=De,It.update=function(t,n,r){return null==t?t:lr(t,n,(typeof r=="function"?r:Wu)(In(t,n)),void 0)},It.updateWith=function(t,n,r,e){return e=typeof e=="function"?e:P,null!=t&&(t=lr(t,n,(typeof r=="function"?r:Wu)(In(t,n)),e)),t},It.values=ku, -It.valuesIn=function(t){return null==t?[]:R(t,Au(t))},It.without=bi,It.words=Ru,It.wrap=function(t,n){return n=null==n?Wu:n,$i(n,t)},It.xor=xi,It.xorBy=ji,It.xorWith=wi,It.zip=mi,It.zipObject=function(t,n){return wr(t||[],n||[],sn)},It.zipObjectDeep=function(t,n){return wr(t||[],n||[],lr)},It.zipWith=Ai,It.entries=vf,It.entriesIn=gf,It.extend=nf,It.extendWith=rf,Mu(It,It),It.add=zf,It.attempt=Of,It.camelCase=df,It.capitalize=Eu,It.ceil=Uf,It.clamp=function(t,n,r){return r===P&&(r=n,n=P),r!==P&&(r=yu(r), -r=r===r?r:0),n!==P&&(n=yu(n),n=n===n?n:0),gn(yu(t),n,r)},It.clone=function(t){return dn(t,false,true)},It.cloneDeep=function(t){return dn(t,true,true)},It.cloneDeepWith=function(t,n){return dn(t,true,true,n)},It.cloneWith=function(t,n){return dn(t,false,true,n)},It.conformsTo=function(t,n){return null==n||bn(t,n,mu(n))},It.deburr=Su,It.defaultTo=function(t,n){return null==t||t!==t?n:t},It.divide=Df,It.endsWith=function(t,n,r){t=xu(t),n=dr(n);var e=t.length,e=r=r===P?e:gn(gu(r),0,e);return r-=n.length,0<=r&&t.slice(r,e)==n; -},It.eq=tu,It.escape=function(t){return(t=xu(t))&&X.test(t)?t.replace(H,un):t},It.escapeRegExp=function(t){return(t=xu(t))&&ct.test(t)?t.replace(ft,"\\$&"):t},It.every=function(t,n,r){var e=Zi(t)?i:mn;return r&&ye(t,n,r)&&(n=P),e(t,fe(n,3))},It.find=Ei,It.findIndex=We,It.findKey=function(t,n){return v(t,fe(n,3),En)},It.findLast=Si,It.findLastIndex=Be,It.findLastKey=function(t,n){return v(t,fe(n,3),Sn)},It.floor=$f,It.forEach=Ne,It.forEachRight=Pe,It.forIn=function(t,n){return null==t?t:Go(t,fe(n,3),Au); -},It.forInRight=function(t,n){return null==t?t:Jo(t,fe(n,3),Au)},It.forOwn=function(t,n){return t&&En(t,fe(n,3))},It.forOwnRight=function(t,n){return t&&Sn(t,fe(n,3))},It.get=ju,It.gt=Ni,It.gte=Pi,It.has=function(t,n){return null!=t&&se(t,n,Mn)},It.hasIn=wu,It.head=Me,It.identity=Wu,It.includes=function(t,n,r,e){return t=ru(t)?t:ku(t),r=r&&!e?gu(r):0,e=t.length,0>r&&(r=jo(e+r,0)),hu(t)?r<=e&&-1<t.indexOf(n,r):!!e&&-1<d(t,n,r)},It.indexOf=function(t,n,r){var e=t?t.length:0;return e?(r=null==r?0:gu(r), -0>r&&(r=jo(e+r,0)),d(t,n,r)):-1},It.inRange=function(t,n,r){return n=vu(n),r===P?(r=n,n=0):r=vu(r),t=yu(t),t>=wo(n,r)&&t<jo(n,r)},It.invoke=lf,It.isArguments=nu,It.isArray=Zi,It.isArrayBuffer=qi,It.isArrayLike=ru,It.isArrayLikeObject=eu,It.isBoolean=function(t){return true===t||false===t||au(t)&&"[object Boolean]"==Xu.call(t)},It.isBuffer=Vi,It.isDate=Ki,It.isElement=function(t){return!!t&&1===t.nodeType&&au(t)&&!su(t)},It.isEmpty=function(t){if(ru(t)&&(Zi(t)||hu(t)||ou(t.splice)||nu(t)||Vi(t)))return!t.length; -if(au(t)){var n=St(t);if("[object Map]"==n||"[object Set]"==n)return!t.size}for(var r in t)if(Yu.call(t,r))return false;return!(zo&&mu(t).length)},It.isEqual=function(t,n){return Fn(t,n)},It.isEqualWith=function(t,n,r){var e=(r=typeof r=="function"?r:P)?r(t,n):P;return e===P?Fn(t,n,r):!!e},It.isError=uu,It.isFinite=function(t){return typeof t=="number"&&yo(t)},It.isFunction=ou,It.isInteger=iu,It.isLength=fu,It.isMap=Gi,It.isMatch=function(t,n){return t===n||Nn(t,n,ae(n))},It.isMatchWith=function(t,n,r){ -return r=typeof r=="function"?r:P,Nn(t,n,ae(n),r)},It.isNaN=function(t){return lu(t)&&t!=+t},It.isNative=function(t){if(ui(t))throw new Fu("This method is not supported with core-js. Try https://github.com/es-shims.");return Pn(t)},It.isNil=function(t){return null==t},It.isNull=function(t){return null===t},It.isNumber=lu,It.isObject=cu,It.isObjectLike=au,It.isPlainObject=su,It.isRegExp=Ji,It.isSafeInteger=function(t){return iu(t)&&-9007199254740991<=t&&9007199254740991>=t},It.isSet=Yi,It.isString=hu, -It.isSymbol=pu,It.isTypedArray=Hi,It.isUndefined=function(t){return t===P},It.isWeakMap=function(t){return au(t)&&"[object WeakMap]"==St(t)},It.isWeakSet=function(t){return au(t)&&"[object WeakSet]"==Xu.call(t)},It.join=function(t,n){return t?bo.call(t,n):""},It.kebabCase=yf,It.last=Ce,It.lastIndexOf=function(t,n,r){var e=t?t.length:0;if(!e)return-1;var u=e;if(r!==P&&(u=gu(r),u=(0>u?jo(e+u,0):wo(u,e-1))+1),n!==n)return g(t,b,u-1,true);for(;u--;)if(t[u]===n)return u;return-1},It.lowerCase=bf,It.lowerFirst=xf, -It.lt=Qi,It.lte=Xi,It.max=function(t){return t&&t.length?An(t,Wu,Bn):P},It.maxBy=function(t,n){return t&&t.length?An(t,fe(n,2),Bn):P},It.mean=function(t){return x(t,Wu)},It.meanBy=function(t,n){return x(t,fe(n,2))},It.min=function(t){return t&&t.length?An(t,Wu,Jn):P},It.minBy=function(t,n){return t&&t.length?An(t,fe(n,2),Jn):P},It.stubArray=zu,It.stubFalse=Uu,It.stubObject=function(){return{}},It.stubString=function(){return""},It.stubTrue=function(){return true},It.multiply=Ff,It.nth=function(t,n){ -return t&&t.length?tr(t,gu(n)):P},It.noConflict=function(){return Vt._===this&&(Vt._=to),this},It.noop=Cu,It.now=Ve,It.pad=function(t,n,r){t=xu(t);var e=(n=gu(n))?T(t):0;return!n||e>=n?t:(n=(n-e)/2,Jr(po(n),r)+t+Jr(ho(n),r))},It.padEnd=function(t,n,r){t=xu(t);var e=(n=gu(n))?T(t):0;return n&&e<n?t+Jr(n-e,r):t},It.padStart=function(t,n,r){t=xu(t);var e=(n=gu(n))?T(t):0;return n&&e<n?Jr(n-e,r)+t:t},It.parseInt=function(t,n,r){return r||null==n?n=0:n&&(n=+n),t=xu(t).replace(at,""),mo(t,n||(bt.test(t)?16:10)); -},It.random=function(t,n,r){if(r&&typeof r!="boolean"&&ye(t,n,r)&&(n=r=P),r===P&&(typeof n=="boolean"?(r=n,n=P):typeof t=="boolean"&&(r=t,t=P)),t===P&&n===P?(t=0,n=1):(t=vu(t),n===P?(n=t,t=0):n=vu(n)),t>n){var e=t;t=n,n=e}return r||t%1||n%1?(r=Ao(),wo(t+r*(n-t+Nt("1e-"+((r+"").length-1))),n)):fr(t,n)},It.reduce=function(t,n,r){var e=Zi(t)?h:m,u=3>arguments.length;return e(t,fe(n,4),r,u,Vo)},It.reduceRight=function(t,n,r){var e=Zi(t)?p:m,u=3>arguments.length;return e(t,fe(n,4),r,u,Ko)},It.repeat=function(t,n,r){ -return n=(r?ye(t,n,r):n===P)?1:gu(n),cr(xu(t),n)},It.replace=function(){var t=arguments,n=xu(t[0]);return 3>t.length?n:Oo.call(n,t[1],t[2])},It.result=function(t,n,r){n=be(n,t)?[n]:Ar(n);var e=-1,u=n.length;for(u||(t=P,u=1);++e<u;){var o=null==t?P:t[Oe(n[e])];o===P&&(e=u,o=r),t=ou(o)?o.call(t):o}return t},It.round=Tf,It.runInContext=N,It.sample=function(t){t=ru(t)?t:ku(t);var n=t.length;return 0<n?t[fr(0,n-1)]:P},It.size=function(t){if(null==t)return 0;if(ru(t)){var n=t.length;return n&&hu(t)?T(t):n; -}return au(t)&&(n=St(t),"[object Map]"==n||"[object Set]"==n)?t.size:mu(t).length},It.snakeCase=jf,It.some=function(t,n,r){var e=Zi(t)?_:hr;return r&&ye(t,n,r)&&(n=P),e(t,fe(n,3))},It.sortedIndex=function(t,n){return pr(t,n)},It.sortedIndexBy=function(t,n,r){return _r(t,n,fe(r,2))},It.sortedIndexOf=function(t,n){var r=t?t.length:0;if(r){var e=pr(t,n);if(e<r&&tu(t[e],n))return e}return-1},It.sortedLastIndex=function(t,n){return pr(t,n,true)},It.sortedLastIndexBy=function(t,n,r){return _r(t,n,fe(r,2),true); -},It.sortedLastIndexOf=function(t,n){if(t&&t.length){var r=pr(t,n,true)-1;if(tu(t[r],n))return r}return-1},It.startCase=wf,It.startsWith=function(t,n,r){return t=xu(t),r=gn(gu(r),0,t.length),n=dr(n),t.slice(r,r+n.length)==n},It.subtract=Nf,It.sum=function(t){return t&&t.length?O(t,Wu):0},It.sumBy=function(t,n){return t&&t.length?O(t,fe(n,2)):0},It.template=function(t,n,r){var e=It.templateSettings;r&&ye(t,n,r)&&(n=P),t=xu(t),n=rf({},n,e,an),r=rf({},n.imports,e.imports,an);var u,o,i=mu(r),f=R(r,i),c=0; -r=n.interpolate||kt;var a="__p+='";r=Nu((n.escape||kt).source+"|"+r.source+"|"+(r===rt?dt:kt).source+"|"+(n.evaluate||kt).source+"|$","g");var l="sourceURL"in n?"//# sourceURL="+n.sourceURL+"\n":"";if(t.replace(r,function(n,r,e,i,f,l){return e||(e=i),a+=t.slice(c,l).replace(Et,M),r&&(u=true,a+="'+__e("+r+")+'"),f&&(o=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+n.length,n}),a+="';",(n=n.variable)||(a="with(obj){"+a+"}"),a=(o?a.replace(K,""):a).replace(G,"$1").replace(J,"$1;"), -a="function("+(n||"obj")+"){"+(n?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",n=Of(function(){return Function(i,l+"return "+a).apply(P,f)}),n.source=a,uu(n))throw n;return n},It.times=function(t,n){if(t=gu(t),1>t||9007199254740991<t)return[];var r=4294967295,e=wo(t,4294967295);for(n=fe(n),t-=4294967295,e=k(e,n);++r<t;)n(r);return e},It.toFinite=vu,It.toInteger=gu,It.toLength=du,It.toLower=function(t){ -return xu(t).toLowerCase()},It.toNumber=yu,It.toSafeInteger=function(t){return gn(gu(t),-9007199254740991,9007199254740991)},It.toString=xu,It.toUpper=function(t){return xu(t).toUpperCase()},It.trim=function(t,n,r){return(t=xu(t))&&(r||n===P)?t.replace(at,""):t&&(n=dr(n))?(t=t.match(Mt),r=n.match(Mt),n=W(t,r),r=B(t,r)+1,Or(t,n,r).join("")):t},It.trimEnd=function(t,n,r){return(t=xu(t))&&(r||n===P)?t.replace(st,""):t&&(n=dr(n))?(t=t.match(Mt),n=B(t,n.match(Mt))+1,Or(t,0,n).join("")):t},It.trimStart=function(t,n,r){ -return(t=xu(t))&&(r||n===P)?t.replace(lt,""):t&&(n=dr(n))?(t=t.match(Mt),n=W(t,n.match(Mt)),Or(t,n).join("")):t},It.truncate=function(t,n){var r=30,e="...";if(cu(n))var u="separator"in n?n.separator:u,r="length"in n?gu(n.length):r,e="omission"in n?dr(n.omission):e;t=xu(t);var o=t.length;if(Lt.test(t))var i=t.match(Mt),o=i.length;if(r>=o)return t;if(o=r-T(e),1>o)return e;if(r=i?Or(i,0,o).join(""):t.slice(0,o),u===P)return r+e;if(i&&(o+=r.length-o),Ji(u)){if(t.slice(o).search(u)){var f=r;for(u.global||(u=Nu(u.source,xu(yt.exec(u))+"g")), -u.lastIndex=0;i=u.exec(f);)var c=i.index;r=r.slice(0,c===P?o:c)}}else t.indexOf(dr(u),o)!=o&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},It.unescape=function(t){return(t=xu(t))&&Q.test(t)?t.replace(Y,on):t},It.uniqueId=function(t){var n=++Hu;return xu(t)+n},It.upperCase=mf,It.upperFirst=Af,It.each=Ne,It.eachRight=Pe,It.first=Me,Mu(It,function(){var t={};return En(It,function(n,r){Yu.call(It.prototype,r)||(t[r]=n)}),t}(),{chain:false}),It.VERSION="4.14.1",u("bind bindKey curry curryRight partial partialRight".split(" "),function(t){ -It[t].placeholder=It}),u(["drop","take"],function(t,n){Zt.prototype[t]=function(r){var e=this.__filtered__;if(e&&!n)return new Zt(this);r=r===P?1:jo(gu(r),0);var u=this.clone();return e?u.__takeCount__=wo(r,u.__takeCount__):u.__views__.push({size:wo(r,4294967295),type:t+(0>u.__dir__?"Right":"")}),u},Zt.prototype[t+"Right"]=function(n){return this.reverse()[t](n).reverse()}}),u(["filter","map","takeWhile"],function(t,n){var r=n+1,e=1==r||3==r;Zt.prototype[t]=function(t){var n=this.clone();return n.__iteratees__.push({ -iteratee:fe(t,3),type:r}),n.__filtered__=n.__filtered__||e,n}}),u(["head","last"],function(t,n){var r="take"+(n?"Right":"");Zt.prototype[t]=function(){return this[r](1).value()[0]}}),u(["initial","tail"],function(t,n){var r="drop"+(n?"":"Right");Zt.prototype[t]=function(){return this.__filtered__?new Zt(this):this[r](1)}}),Zt.prototype.compact=function(){return this.filter(Wu)},Zt.prototype.find=function(t){return this.filter(t).head()},Zt.prototype.findLast=function(t){return this.reverse().find(t); -},Zt.prototype.invokeMap=ar(function(t,n){return typeof t=="function"?new Zt(this):this.map(function(r){return Un(r,t,n)})}),Zt.prototype.reject=function(t){return this.filter(Xe(fe(t)))},Zt.prototype.slice=function(t,n){t=gu(t);var r=this;return r.__filtered__&&(0<t||0>n)?new Zt(r):(0>t?r=r.takeRight(-t):t&&(r=r.drop(t)),n!==P&&(n=gu(n),r=0>n?r.dropRight(-n):r.take(n-t)),r)},Zt.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},Zt.prototype.toArray=function(){return this.take(4294967295); -},En(Zt.prototype,function(t,n){var r=/^(?:filter|find|map|reject)|While$/.test(n),e=/^(?:head|last)$/.test(n),u=It[e?"take"+("last"==n?"Right":""):n],o=e||/^find/.test(n);u&&(It.prototype[n]=function(){function n(t){return t=u.apply(It,s([t],f)),e&&h?t[0]:t}var i=this.__wrapped__,f=e?[1]:arguments,c=i instanceof Zt,a=f[0],l=c||Zi(i);l&&r&&typeof a=="function"&&1!=a.length&&(c=l=false);var h=this.__chain__,p=!!this.__actions__.length,a=o&&!h,c=c&&!p;return!o&&l?(i=c?i:new Zt(this),i=t.apply(i,f),i.__actions__.push({ -func:Fe,args:[n],thisArg:P}),new Tt(i,h)):a&&c?t.apply(this,f):(i=this.thru(n),a?e?i.value()[0]:i.value():i)})}),u("pop push shift sort splice unshift".split(" "),function(t){var n=Zu[t],r=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",e=/^(?:pop|shift)$/.test(t);It.prototype[t]=function(){var t=arguments;if(e&&!this.__chain__){var u=this.value();return n.apply(Zi(u)?u:[],t)}return this[r](function(r){return n.apply(Zi(r)?r:[],t)})}}),En(Zt.prototype,function(t,n){var r=It[n];if(r){var e=r.name+""; -(Uo[e]||(Uo[e]=[])).push({name:n,func:r})}}),Uo[qr(P,2).name]=[{name:"wrapper",func:P}],Zt.prototype.clone=function(){var t=new Zt(this.__wrapped__);return t.__actions__=Wr(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=Wr(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=Wr(this.__views__),t},Zt.prototype.reverse=function(){if(this.__filtered__){var t=new Zt(this);t.__dir__=-1,t.__filtered__=true}else t=this.clone(),t.__dir__*=-1;return t; -},Zt.prototype.value=function(){var t,n=this.__wrapped__.value(),r=this.__dir__,e=Zi(n),u=0>r,o=e?n.length:0;t=o;for(var i=this.__views__,f=0,c=-1,a=i.length;++c<a;){var l=i[c],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":t-=s;break;case"take":t=wo(t,f+s);break;case"takeRight":f=jo(f,t-s)}}if(t={start:f,end:t},i=t.start,f=t.end,t=f-i,u=u?f:i-1,i=this.__iteratees__,f=i.length,c=0,a=wo(t,this.__takeCount__),!e||200>o||o==t&&a==t)return xr(n,this.__actions__);e=[];t:for(;t--&&c<a;){ -for(u+=r,o=-1,l=n[u];++o<f;){var h=i[o],s=h.type,h=(0,h.iteratee)(l);if(2==s)l=h;else if(!h){if(1==s)continue t;break t}}e[c++]=l}return e},It.prototype.at=Oi,It.prototype.chain=function(){return $e(this)},It.prototype.commit=function(){return new Tt(this.value(),this.__chain__)},It.prototype.next=function(){this.__values__===P&&(this.__values__=_u(this.value()));var t=this.__index__>=this.__values__.length,n=t?P:this.__values__[this.__index__++];return{done:t,value:n}},It.prototype.plant=function(t){ -for(var n,r=this;r instanceof Ft;){var e=Se(r);e.__index__=0,e.__values__=P,n?u.__wrapped__=e:n=e;var u=e,r=r.__wrapped__}return u.__wrapped__=t,n},It.prototype.reverse=function(){var t=this.__wrapped__;return t instanceof Zt?(this.__actions__.length&&(t=new Zt(this)),t=t.reverse(),t.__actions__.push({func:Fe,args:[ze],thisArg:P}),new Tt(t,this.__chain__)):this.thru(ze)},It.prototype.toJSON=It.prototype.valueOf=It.prototype.value=function(){return xr(this.__wrapped__,this.__actions__)},It.prototype.first=It.prototype.head, -fo&&(It.prototype[fo]=Te),It}var P,Z=1/0,q=NaN,V=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],K=/\b__p\+='';/g,G=/\b(__p\+=)''\+/g,J=/(__e\(.*?\)|\b__t\))\+'';/g,Y=/&(?:amp|lt|gt|quot|#39|#96);/g,H=/[&<>"'`]/g,Q=RegExp(Y.source),X=RegExp(H.source),tt=/<%-([\s\S]+?)%>/g,nt=/<%([\s\S]+?)%>/g,rt=/<%=([\s\S]+?)%>/g,et=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,ut=/^\w*$/,ot=/^\./,it=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,ft=/[\\^$.*+?()[\]{}|]/g,ct=RegExp(ft.source),at=/^\s+|\s+$/g,lt=/^\s+/,st=/\s+$/,ht=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,pt=/\{\n\/\* \[wrapped with (.+)\] \*/,_t=/,? & /,vt=/[a-zA-Z0-9]+/g,gt=/\\(\\)?/g,dt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,yt=/\w*$/,bt=/^0x/i,xt=/^[-+]0x[0-9a-f]+$/i,jt=/^0b[01]+$/i,wt=/^\[object .+?Constructor\]$/,mt=/^0o[0-7]+$/i,At=/^(?:0|[1-9]\d*)$/,Ot=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,kt=/($^)/,Et=/['\n\r\u2028\u2029\\]/g,St="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?)*",Rt="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+St,It="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]?|[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",Wt=RegExp("['\u2019]","g"),Bt=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]","g"),Mt=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+It+St,"g"),Ct=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d+",Rt].join("|"),"g"),Lt=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0\\ufe0e\\ufe0f]"),zt=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Ut="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise Reflect RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Dt={}; +return-1}function y(t,n,r,e){--r;for(var u=t.length;++r<u;)if(e(t[r],n))return r;return-1}function b(t){return t!==t}function x(t,n){var r=t?t.length:0;return r?k(t,n)/r:q}function j(t){return function(n){return null==n?P:n[t]}}function w(t){return function(n){return null==t?P:t[n]}}function m(t,n,r,e,u){return u(t,function(t,u,o){r=e?(e=false,t):n(r,t,u,o)}),r}function A(t,n){var r=t.length;for(t.sort(n);r--;)t[r]=t[r].c;return t}function k(t,n){for(var r,e=-1,u=t.length;++e<u;){var o=n(t[e]);o!==P&&(r=r===P?o:r+o); +}return r}function E(t,n){for(var r=-1,e=Array(t);++r<t;)e[r]=n(r);return e}function O(t,n){return l(n,function(n){return[n,t[n]]})}function S(t){return function(n){return t(n)}}function I(t,n){return l(n,function(n){return t[n]})}function R(t,n){return t.has(n)}function W(t,n){for(var r=-1,e=t.length;++r<e&&-1<d(n,t[r],0););return r}function B(t,n){for(var r=t.length;r--&&-1<d(n,t[r],0););return r}function L(t){return"\\"+Ft[t]}function C(t){var n=false;if(null!=t&&typeof t.toString!="function")try{ +n=!!(t+"")}catch(t){}return n}function U(t){var n=-1,r=Array(t.size);return t.forEach(function(t,e){r[++n]=[e,t]}),r}function M(t,n){return function(r){return t(n(r))}}function z(t,n){for(var r=-1,e=t.length,u=0,o=[];++r<e;){var i=t[r];i!==n&&"__lodash_placeholder__"!==i||(t[r]="__lodash_placeholder__",o[u++]=r)}return o}function D(t){var n=-1,r=Array(t.size);return t.forEach(function(t){r[++n]=t}),r}function T(t){var n=-1,r=Array(t.size);return t.forEach(function(t){r[++n]=[t,t]}),r}function $(t){ +if(Ut.test(t)){for(var n=Lt.lastIndex=0;Lt.test(t);)n++;t=n}else t=en(t);return t}function F(t){return Ut.test(t)?t.match(Lt)||[]:t.split("")}function N(w){function St(t){return Hu.call(t)}function It(t){if(ou(t)&&!Fi(t)&&!(t instanceof $t)){if(t instanceof Lt)return t;if(Gu.call(t,"__wrapped__"))return Oe(t)}return new Lt(t)}function Rt(){}function Lt(t,n){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!n,this.__index__=0,this.__values__=P}function $t(t){this.__wrapped__=t,this.__actions__=[], +this.__dir__=1,this.__filtered__=false,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Ft(t){var n=-1,r=t?t.length:0;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Zt(t){var n=-1,r=t?t.length:0;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function qt(t){var n=-1,r=t?t.length:0;for(this.clear();++n<r;){var e=t[n];this.set(e[0],e[1])}}function Kt(t){var n=-1,r=t?t.length:0;for(this.__data__=new qt;++n<r;)this.add(t[n])}function Gt(t){this.__data__=new Zt(t); +}function Yt(t,n){var r,e=Fi(t)||He(t)?E(t.length,Fu):[],u=e.length,o=!!u;for(r in t)!n&&!Gu.call(t,r)||o&&("length"==r||ge(r,u))||e.push(r);return e}function en(t,n,r,e){return t===P||Ye(t,Zu[r])&&!Gu.call(e,r)?n:t}function an(t,n,r){(r===P||Ye(t[n],r))&&(typeof n!="number"||r!==P||n in t)||(t[n]=r)}function ln(t,n,r){var e=t[n];Gu.call(t,n)&&Ye(e,r)&&(r!==P||n in t)||(t[n]=r)}function sn(t,n){for(var r=t.length;r--;)if(Ye(t[r][0],n))return r;return-1}function hn(t,n,r,e){return Po(t,function(t,u,o){ +n(e,t,r(t),o)}),e}function pn(t,n){return t&&Br(n,bu(n),t)}function _n(t,n){for(var r=-1,e=null==t,u=n.length,o=Cu(u);++r<u;)o[r]=e?P:du(t,n[r]);return o}function vn(t,n,r){return t===t&&(r!==P&&(t=t<=r?t:r),n!==P&&(t=t>=n?t:n)),t}function gn(t,n,r,e,o,i,f){var c;if(e&&(c=i?e(t,o,i,f):e(t)),c!==P)return c;if(!uu(t))return t;if(o=Fi(t)){if(c=he(t),!n)return Wr(t,c)}else{var a=St(t),l="[object Function]"==a||"[object GeneratorFunction]"==a;if(Pi(t))return Er(t,n);if("[object Object]"==a||"[object Arguments]"==a||l&&!i){ +if(C(t))return i?t:{};if(c=pe(l?{}:t),!n)return Lr(t,pn(c,t))}else{if(!Tt[a])return i?t:{};c=_e(t,a,gn,n)}}if(f||(f=new Gt),i=f.get(t))return i;if(f.set(t,c),!o)var s=r?Rn(t,bu,Ho):bu(t);return u(s||t,function(u,o){s&&(o=u,u=t[o]),ln(c,o,gn(u,n,r,e,o,t,f))}),c}function dn(t){var n=bu(t);return function(r){return yn(r,t,n)}}function yn(t,n,r){var e=r.length;if(null==t)return!e;for(t=Tu(t);e--;){var u=r[e],o=n[u],i=t[u];if(i===P&&!(u in t)||!o(i))return false}return true}function bn(t){return uu(t)?oo(t):{}; +}function xn(t,n,r){if(typeof t!="function")throw new Nu("Expected a function");return ni(function(){t.apply(P,r)},n)}function jn(t,n,r,e){var u=-1,o=c,i=true,f=t.length,s=[],h=n.length;if(!f)return s;r&&(n=l(n,S(r))),e?(o=a,i=false):200<=n.length&&(o=R,i=false,n=new Kt(n));t:for(;++u<f;){var p=t[u],_=r?r(p):p,p=e||0!==p?p:0;if(i&&_===_){for(var v=h;v--;)if(n[v]===_)continue t;s.push(p)}else o(n,_,e)||s.push(p)}return s}function wn(t,n){var r=true;return Po(t,function(t,e,u){return r=!!n(t,e,u)}),r}function mn(t,n,r){ +for(var e=-1,u=t.length;++e<u;){var o=t[e],i=n(o);if(null!=i&&(f===P?i===i&&!au(i):r(i,f)))var f=i,c=o}return c}function An(t,n){var r=[];return Po(t,function(t,e,u){n(t,e,u)&&r.push(t)}),r}function kn(t,n,r,e,u){var o=-1,i=t.length;for(r||(r=ve),u||(u=[]);++o<i;){var f=t[o];0<n&&r(f)?1<n?kn(f,n-1,r,e,u):s(u,f):e||(u[u.length]=f)}return u}function En(t,n){return t&&qo(t,n,bu)}function On(t,n){return t&&Vo(t,n,bu)}function Sn(t,n){return f(n,function(n){return nu(t[n])})}function In(t,n){n=ye(n,t)?[n]:Ar(n); +for(var r=0,e=n.length;null!=t&&r<e;)t=t[Ae(n[r++])];return r&&r==e?t:P}function Rn(t,n,r){return n=n(t),Fi(t)?n:s(n,r(t))}function Wn(t,n){return t>n}function Bn(t,n){return null!=t&&Gu.call(t,n)}function Ln(t,n){return null!=t&&n in Tu(t)}function Cn(t,n,r){for(var e=r?a:c,u=t[0].length,o=t.length,i=o,f=Cu(o),s=1/0,h=[];i--;){var p=t[i];i&&n&&(p=l(p,S(n))),s=jo(p.length,s),f[i]=!r&&(n||120<=u&&120<=p.length)?new Kt(i&&p):P}var p=t[0],_=-1,v=f[0];t:for(;++_<u&&h.length<s;){var g=p[_],d=n?n(g):g,g=r||0!==g?g:0; +if(v?!R(v,d):!e(h,d,r)){for(i=o;--i;){var y=f[i];if(y?!R(y,d):!e(t[i],d,r))continue t}v&&v.push(d),h.push(g)}}return h}function Un(t,n,r){var e={};return En(t,function(t,u,o){n(e,r(t),u,o)}),e}function Mn(t,n,e){return ye(n,t)||(n=Ar(n),t=me(t,n),n=We(n)),n=null==t?t:t[Ae(n)],null==n?P:r(n,t,e)}function zn(t){return ou(t)&&"[object ArrayBuffer]"==Hu.call(t)}function Dn(t){return ou(t)&&"[object Date]"==Hu.call(t)}function Tn(t,n,r,e,u){if(t===n)n=true;else if(null==t||null==n||!uu(t)&&!ou(n))n=t!==t&&n!==n;else t:{ +var o=Fi(t),i=Fi(n),f="[object Array]",c="[object Array]";o||(f=St(t),f="[object Arguments]"==f?"[object Object]":f),i||(c=St(n),c="[object Arguments]"==c?"[object Object]":c);var a="[object Object]"==f&&!C(t),i="[object Object]"==c&&!C(n);if((c=f==c)&&!a)u||(u=new Gt),n=o||Gi(t)?ee(t,n,Tn,r,e,u):ue(t,n,f,Tn,r,e,u);else{if(!(2&e)&&(o=a&&Gu.call(t,"__wrapped__"),f=i&&Gu.call(n,"__wrapped__"),o||f)){t=o?t.value():t,n=f?n.value():n,u||(u=new Gt),n=Tn(t,n,r,e,u);break t}if(c)n:if(u||(u=new Gt),o=2&e, +f=bu(t),i=f.length,c=bu(n).length,i==c||o){for(a=i;a--;){var l=f[a];if(!(o?l in n:Gu.call(n,l))){n=false;break n}}if((c=u.get(t))&&u.get(n))n=c==n;else{c=true,u.set(t,n),u.set(n,t);for(var s=o;++a<i;){var l=f[a],h=t[l],p=n[l];if(r)var _=o?r(p,h,l,n,t,u):r(h,p,l,t,n,u);if(_===P?h!==p&&!Tn(h,p,r,e,u):!_){c=false;break}s||(s="constructor"==l)}c&&!s&&(r=t.constructor,e=n.constructor,r!=e&&"constructor"in t&&"constructor"in n&&!(typeof r=="function"&&r instanceof r&&typeof e=="function"&&e instanceof e)&&(c=false)), +u.delete(t),u.delete(n),n=c}}else n=false;else n=false}}return n}function $n(t){return ou(t)&&"[object Map]"==St(t)}function Fn(t,n,r,e){var u=r.length,o=u,i=!e;if(null==t)return!o;for(t=Tu(t);u--;){var f=r[u];if(i&&f[2]?f[1]!==t[f[0]]:!(f[0]in t))return false}for(;++u<o;){var f=r[u],c=f[0],a=t[c],l=f[1];if(i&&f[2]){if(a===P&&!(c in t))return false}else{if(f=new Gt,e)var s=e(a,l,c,t,n,f);if(s===P?!Tn(l,a,e,3,f):!s)return false}}return true}function Nn(t){return!(!uu(t)||Vu&&Vu in t)&&(nu(t)||C(t)?Xu:wt).test(ke(t))}function Pn(t){ +return uu(t)&&"[object RegExp]"==Hu.call(t)}function Zn(t){return ou(t)&&"[object Set]"==St(t)}function qn(t){return ou(t)&&eu(t.length)&&!!Dt[Hu.call(t)]}function Vn(t){return typeof t=="function"?t:null==t?Ou:typeof t=="object"?Fi(t)?Qn(t[0],t[1]):Hn(t):Wu(t)}function Kn(t){if(!xe(t))return bo(t);var n,r=[];for(n in Tu(t))Gu.call(t,n)&&"constructor"!=n&&r.push(n);return r}function Gn(t){if(!uu(t)){var n=[];if(null!=t)for(var r in Tu(t))n.push(r);return n}r=xe(t);var e=[];for(n in t)("constructor"!=n||!r&&Gu.call(t,n))&&e.push(n); +return e}function Jn(t,n){return t<n}function Yn(t,n){var r=-1,e=Qe(t)?Cu(t.length):[];return Po(t,function(t,u,o){e[++r]=n(t,u,o)}),e}function Hn(t){var n=ae(t);return 1==n.length&&n[0][2]?je(n[0][0],n[0][1]):function(r){return r===t||Fn(r,t,n)}}function Qn(t,n){return ye(t)&&n===n&&!uu(n)?je(Ae(t),n):function(r){var e=du(r,t);return e===P&&e===n?yu(r,t):Tn(n,e,P,3)}}function Xn(t,n,r,e,o){if(t!==n){if(!Fi(n)&&!Gi(n))var i=Gn(n);u(i||n,function(u,f){if(i&&(f=u,u=n[f]),uu(u)){o||(o=new Gt);var c=f,a=o,l=t[c],s=n[c],h=a.get(s); +if(h)an(t,c,h);else{var h=e?e(l,s,c+"",t,n,a):P,p=h===P;p&&(h=s,Fi(s)||Gi(s)?Fi(l)?h=l:Xe(l)?h=Wr(l):(p=false,h=gn(s,true)):fu(s)||He(s)?He(l)?h=vu(l):!uu(l)||r&&nu(l)?(p=false,h=gn(s,true)):h=l:p=false),p&&(a.set(s,h),Xn(h,s,r,e,a),a.delete(s)),an(t,c,h)}}else c=e?e(t[f],u,f+"",t,n,o):P,c===P&&(c=u),an(t,f,c)})}}function tr(t,n){var r=t.length;if(r)return n+=0>n?r:0,ge(n,r)?t[n]:P}function nr(t,n,r){var e=-1;return n=l(n.length?n:[Ou],S(fe())),t=Yn(t,function(t){return{a:l(n,function(n){return n(t)}),b:++e,c:t +}}),A(t,function(t,n){var e;t:{e=-1;for(var u=t.a,o=n.a,i=u.length,f=r.length;++e<i;){var c=Sr(u[e],o[e]);if(c){e=e>=f?c:c*("desc"==r[e]?-1:1);break t}}e=t.b-n.b}return e})}function rr(t,n){return t=Tu(t),er(t,n,function(n,r){return r in t})}function er(t,n,r){for(var e=-1,u=n.length,o={};++e<u;){var i=n[e],f=t[i];r(f,i)&&(o[i]=f)}return o}function ur(t){return function(n){return In(n,t)}}function or(t,n,r,e){var u=e?y:d,o=-1,i=n.length,f=t;for(t===n&&(n=Wr(n)),r&&(f=l(t,S(r)));++o<i;)for(var c=0,a=n[o],a=r?r(a):a;-1<(c=u(f,a,c,e));)f!==t&&fo.call(f,c,1), +fo.call(t,c,1);return t}function ir(t,n){for(var r=t?n.length:0,e=r-1;r--;){var u=n[r];if(r==e||u!==o){var o=u;if(ge(u))fo.call(t,u,1);else if(ye(u,t))delete t[Ae(u)];else{var u=Ar(u),i=me(t,u);null!=i&&delete i[Ae(We(u))]}}}}function fr(t,n){return t+po(mo()*(n-t+1))}function cr(t,n){var r="";if(!t||1>n||9007199254740991<n)return r;do n%2&&(r+=t),(n=po(n/2))&&(t+=t);while(n);return r}function ar(t,n){return n=xo(n===P?t.length-1:n,0),function(){for(var e=arguments,u=-1,o=xo(e.length-n,0),i=Cu(o);++u<o;)i[u]=e[n+u]; +for(u=-1,o=Cu(n+1);++u<n;)o[u]=e[u];return o[n]=i,r(t,this,o)}}function lr(t,n,r,e){if(!uu(t))return t;n=ye(n,t)?[n]:Ar(n);for(var u=-1,o=n.length,i=o-1,f=t;null!=f&&++u<o;){var c=Ae(n[u]),a=r;if(u!=i){var l=f[c],a=e?e(l,c,f):P;a===P&&(a=uu(l)?l:ge(n[u+1])?[]:{})}ln(f,c,a),f=f[c]}return t}function sr(t,n,r){var e=-1,u=t.length;for(0>n&&(n=-n>u?0:u+n),r=r>u?u:r,0>r&&(r+=u),u=n>r?0:r-n>>>0,n>>>=0,r=Cu(u);++e<u;)r[e]=t[e+n];return r}function hr(t,n){var r;return Po(t,function(t,e,u){return r=n(t,e,u), +!r}),!!r}function pr(t,n,r){var e=0,u=t?t.length:e;if(typeof n=="number"&&n===n&&2147483647>=u){for(;e<u;){var o=e+u>>>1,i=t[o];null!==i&&!au(i)&&(r?i<=n:i<n)?e=o+1:u=o}return u}return _r(t,n,Ou,r)}function _r(t,n,r,e){n=r(n);for(var u=0,o=t?t.length:0,i=n!==n,f=null===n,c=au(n),a=n===P;u<o;){var l=po((u+o)/2),s=r(t[l]),h=s!==P,p=null===s,_=s===s,v=au(s);(i?e||_:a?_&&(e||h):f?_&&h&&(e||!p):c?_&&h&&!p&&(e||!v):p||v?0:e?s<=n:s<n)?u=l+1:o=l}return jo(o,4294967294)}function vr(t,n){for(var r=-1,e=t.length,u=0,o=[];++r<e;){ +var i=t[r],f=n?n(i):i;if(!r||!Ye(f,c)){var c=f;o[u++]=0===i?0:i}}return o}function gr(t){return typeof t=="number"?t:au(t)?q:+t}function dr(t){if(typeof t=="string")return t;if(au(t))return No?No.call(t):"";var n=t+"";return"0"==n&&1/t==-Z?"-0":n}function yr(t,n,r){var e=-1,u=c,o=t.length,i=true,f=[],l=f;if(r)i=false,u=a;else if(200<=o){if(u=n?null:Jo(t))return D(u);i=false,u=R,l=new Kt}else l=n?[]:f;t:for(;++e<o;){var s=t[e],h=n?n(s):s,s=r||0!==s?s:0;if(i&&h===h){for(var p=l.length;p--;)if(l[p]===h)continue t; +n&&l.push(h),f.push(s)}else u(l,h,r)||(l!==f&&l.push(h),f.push(s))}return f}function br(t,n,r,e){for(var u=t.length,o=e?u:-1;(e?o--:++o<u)&&n(t[o],o,t););return r?sr(t,e?0:o,e?o+1:u):sr(t,e?o+1:0,e?u:o)}function xr(t,n){var r=t;return r instanceof $t&&(r=r.value()),h(n,function(t,n){return n.func.apply(n.thisArg,s([t],n.args))},r)}function jr(t,n,r){for(var e=-1,u=t.length;++e<u;)var o=o?s(jn(o,t[e],n,r),jn(t[e],o,n,r)):t[e];return o&&o.length?yr(o,n,r):[]}function wr(t,n,r){for(var e=-1,u=t.length,o=n.length,i={};++e<u;)r(i,t[e],e<o?n[e]:P); +return i}function mr(t){return Xe(t)?t:[]}function Ar(t){return Fi(t)?t:ei(t)}function kr(t,n,r){var e=t.length;return r=r===P?e:r,!n&&r>=e?t:sr(t,n,r)}function Er(t,n){if(n)return t.slice();var r=new t.constructor(t.length);return t.copy(r),r}function Or(t){var n=new t.constructor(t.byteLength);return new ro(n).set(new ro(t)),n}function Sr(t,n){if(t!==n){var r=t!==P,e=null===t,u=t===t,o=au(t),i=n!==P,f=null===n,c=n===n,a=au(n);if(!f&&!a&&!o&&t>n||o&&i&&c&&!f&&!a||e&&i&&c||!r&&c||!u)return 1;if(!e&&!o&&!a&&t<n||a&&r&&u&&!e&&!o||f&&r&&u||!i&&u||!c)return-1; +}return 0}function Ir(t,n,r,e){var u=-1,o=t.length,i=r.length,f=-1,c=n.length,a=xo(o-i,0),l=Cu(c+a);for(e=!e;++f<c;)l[f]=n[f];for(;++u<i;)(e||u<o)&&(l[r[u]]=t[u]);for(;a--;)l[f++]=t[u++];return l}function Rr(t,n,r,e){var u=-1,o=t.length,i=-1,f=r.length,c=-1,a=n.length,l=xo(o-f,0),s=Cu(l+a);for(e=!e;++u<l;)s[u]=t[u];for(l=u;++c<a;)s[l+c]=n[c];for(;++i<f;)(e||u<o)&&(s[l+r[i]]=t[u++]);return s}function Wr(t,n){var r=-1,e=t.length;for(n||(n=Cu(e));++r<e;)n[r]=t[r];return n}function Br(t,n,r,e){r||(r={}); +for(var u=-1,o=n.length;++u<o;){var i=n[u],f=e?e(r[i],t[i],i,r,t):P;ln(r,i,f===P?t[i]:f)}return r}function Lr(t,n){return Br(t,Ho(t),n)}function Cr(t,n){return function(r,u){var o=Fi(r)?e:hn,i=n?n():{};return o(r,t,fe(u,2),i)}}function Ur(t){return ar(function(n,r){var e=-1,u=r.length,o=1<u?r[u-1]:P,i=2<u?r[2]:P,o=3<t.length&&typeof o=="function"?(u--,o):P;for(i&&de(r[0],r[1],i)&&(o=3>u?P:o,u=1),n=Tu(n);++e<u;)(i=r[e])&&t(n,i,e,o);return n})}function Mr(t,n){return function(r,e){if(null==r)return r; +if(!Qe(r))return t(r,e);for(var u=r.length,o=n?u:-1,i=Tu(r);(n?o--:++o<u)&&false!==e(i[o],o,i););return r}}function zr(t){return function(n,r,e){var u=-1,o=Tu(n);e=e(n);for(var i=e.length;i--;){var f=e[t?i:++u];if(false===r(o[f],f,o))break}return n}}function Dr(t,n,r){function e(){return(this&&this!==Vt&&this instanceof e?o:t).apply(u?r:this,arguments)}var u=1&n,o=Fr(t);return e}function Tr(t){return function(n){n=gu(n);var r=Ut.test(n)?F(n):P,e=r?r[0]:n.charAt(0);return n=r?kr(r,1).join(""):n.slice(1), +e[t]()+n}}function $r(t){return function(n){return h(ku(Au(n).replace(Wt,"")),t,"")}}function Fr(t){return function(){var n=arguments;switch(n.length){case 0:return new t;case 1:return new t(n[0]);case 2:return new t(n[0],n[1]);case 3:return new t(n[0],n[1],n[2]);case 4:return new t(n[0],n[1],n[2],n[3]);case 5:return new t(n[0],n[1],n[2],n[3],n[4]);case 6:return new t(n[0],n[1],n[2],n[3],n[4],n[5]);case 7:return new t(n[0],n[1],n[2],n[3],n[4],n[5],n[6])}var r=bn(t.prototype),n=t.apply(r,n);return uu(n)?n:r; +}}function Nr(t,n,e){function u(){for(var i=arguments.length,f=Cu(i),c=i,a=ie(u);c--;)f[c]=arguments[c];return c=3>i&&f[0]!==a&&f[i-1]!==a?[]:z(f,a),i-=c.length,i<e?Xr(t,n,qr,u.placeholder,P,f,c,P,P,e-i):r(this&&this!==Vt&&this instanceof u?o:t,this,f)}var o=Fr(t);return u}function Pr(t){return function(n,r,e){var u=Tu(n);if(!Qe(n)){var o=fe(r,3);n=bu(n),r=function(t){return o(u[t],t,u)}}return r=t(n,r,e),-1<r?u[o?n[r]:r]:P}}function Zr(t){return ar(function(n){n=kn(n,1);var r=n.length,e=r,u=Lt.prototype.thru; +for(t&&n.reverse();e--;){var o=n[e];if(typeof o!="function")throw new Nu("Expected a function");if(u&&!i&&"wrapper"==oe(o))var i=new Lt([],(true))}for(e=i?e:r;++e<r;)var o=n[e],u=oe(o),f="wrapper"==u?Yo(o):P,i=f&&be(f[0])&&424==f[1]&&!f[4].length&&1==f[9]?i[oe(f[0])].apply(i,f[3]):1==o.length&&be(o)?i[u]():i.thru(o);return function(){var t=arguments,e=t[0];if(i&&1==t.length&&Fi(e)&&200<=e.length)return i.plant(e).value();for(var u=0,t=r?n[u].apply(this,t):e;++u<r;)t=n[u].call(this,t);return t}})}function qr(t,n,r,e,u,o,i,f,c,a){ +function l(){for(var d=arguments.length,y=Cu(d),b=d;b--;)y[b]=arguments[b];if(_){var x,j=ie(l),b=y.length;for(x=0;b--;)y[b]===j&&x++}if(e&&(y=Ir(y,e,u,_)),o&&(y=Rr(y,o,i,_)),d-=x,_&&d<a)return j=z(y,j),Xr(t,n,qr,l.placeholder,r,y,j,f,c,a-d);if(j=h?r:this,b=p?j[t]:t,d=y.length,f){x=y.length;for(var w=jo(f.length,x),m=Wr(y);w--;){var A=f[w];y[w]=ge(A,x)?m[A]:P}}else v&&1<d&&y.reverse();return s&&c<d&&(y.length=c),this&&this!==Vt&&this instanceof l&&(b=g||Fr(b)),b.apply(j,y)}var s=128&n,h=1&n,p=2&n,_=24&n,v=512&n,g=p?P:Fr(t); +return l}function Vr(t,n){return function(r,e){return Un(r,t,n(e))}}function Kr(t,n){return function(r,e){var u;if(r===P&&e===P)return n;if(r!==P&&(u=r),e!==P){if(u===P)return e;typeof r=="string"||typeof e=="string"?(r=dr(r),e=dr(e)):(r=gr(r),e=gr(e)),u=t(r,e)}return u}}function Gr(t){return ar(function(n){return n=1==n.length&&Fi(n[0])?l(n[0],S(fe())):l(kn(n,1),S(fe())),ar(function(e){var u=this;return t(n,function(t){return r(t,u,e)})})})}function Jr(t,n){n=n===P?" ":dr(n);var r=n.length;return 2>r?r?cr(n,t):n:(r=cr(n,ho(t/$(n))), +Ut.test(n)?kr(F(r),0,t).join(""):r.slice(0,t))}function Yr(t,n,e,u){function o(){for(var n=-1,c=arguments.length,a=-1,l=u.length,s=Cu(l+c),h=this&&this!==Vt&&this instanceof o?f:t;++a<l;)s[a]=u[a];for(;c--;)s[a++]=arguments[++n];return r(h,i?e:this,s)}var i=1&n,f=Fr(t);return o}function Hr(t){return function(n,r,e){e&&typeof e!="number"&&de(n,r,e)&&(r=e=P),n=su(n),r===P?(r=n,n=0):r=su(r),e=e===P?n<r?1:-1:su(e);var u=-1;r=xo(ho((r-n)/(e||1)),0);for(var o=Cu(r);r--;)o[t?r:++u]=n,n+=e;return o}}function Qr(t){ +return function(n,r){return typeof n=="string"&&typeof r=="string"||(n=_u(n),r=_u(r)),t(n,r)}}function Xr(t,n,r,e,u,o,i,f,c,a){var l=8&n,s=l?i:P;i=l?P:i;var h=l?o:P;return o=l?P:o,n=(n|(l?32:64))&~(l?64:32),4&n||(n&=-4),u=[t,n,u,h,s,o,i,f,c,a],r=r.apply(P,u),be(t)&&ti(r,u),r.placeholder=e,ri(r,t,n)}function te(t){var n=Du[t];return function(t,r){if(t=_u(t),r=jo(hu(r),292)){var e=(gu(t)+"e").split("e"),e=n(e[0]+"e"+(+e[1]+r)),e=(gu(e)+"e").split("e");return+(e[0]+"e"+(+e[1]-r))}return n(t)}}function ne(t){ +return function(n){var r=St(n);return"[object Map]"==r?U(n):"[object Set]"==r?T(n):O(n,t(n))}}function re(t,n,r,e,u,o,i,f){var c=2&n;if(!c&&typeof t!="function")throw new Nu("Expected a function");var a=e?e.length:0;if(a||(n&=-97,e=u=P),i=i===P?i:xo(hu(i),0),f=f===P?f:hu(f),a-=u?u.length:0,64&n){var l=e,s=u;e=u=P}var h=c?P:Yo(t);return o=[t,n,r,e,u,l,s,o,i,f],h&&(r=o[1],t=h[1],n=r|t,e=128==t&&8==r||128==t&&256==r&&o[7].length<=h[8]||384==t&&h[7].length<=h[8]&&8==r,131>n||e)&&(1&t&&(o[2]=h[2],n|=1&r?0:4), +(r=h[3])&&(e=o[3],o[3]=e?Ir(e,r,h[4]):r,o[4]=e?z(o[3],"__lodash_placeholder__"):h[4]),(r=h[5])&&(e=o[5],o[5]=e?Rr(e,r,h[6]):r,o[6]=e?z(o[5],"__lodash_placeholder__"):h[6]),(r=h[7])&&(o[7]=r),128&t&&(o[8]=null==o[8]?h[8]:jo(o[8],h[8])),null==o[9]&&(o[9]=h[9]),o[0]=h[0],o[1]=n),t=o[0],n=o[1],r=o[2],e=o[3],u=o[4],f=o[9]=null==o[9]?c?0:t.length:xo(o[9]-a,0),!f&&24&n&&(n&=-25),ri((h?Ko:ti)(n&&1!=n?8==n||16==n?Nr(t,n,f):32!=n&&33!=n||u.length?qr.apply(P,o):Yr(t,n,r,e):Dr(t,n,r),o),t,n)}function ee(t,n,r,e,u,o){ +var i=2&u,f=t.length,c=n.length;if(f!=c&&!(i&&c>f))return false;if((c=o.get(t))&&o.get(n))return c==n;var c=-1,a=true,l=1&u?new Kt:P;for(o.set(t,n),o.set(n,t);++c<f;){var s=t[c],h=n[c];if(e)var p=i?e(h,s,c,n,t,o):e(s,h,c,t,n,o);if(p!==P){if(p)continue;a=false;break}if(l){if(!_(n,function(t,n){if(!l.has(n)&&(s===t||r(s,t,e,u,o)))return l.add(n)})){a=false;break}}else if(s!==h&&!r(s,h,e,u,o)){a=false;break}}return o.delete(t),o.delete(n),a}function ue(t,n,r,e,u,o,i){switch(r){case"[object DataView]":if(t.byteLength!=n.byteLength||t.byteOffset!=n.byteOffset)break; +t=t.buffer,n=n.buffer;case"[object ArrayBuffer]":if(t.byteLength!=n.byteLength||!e(new ro(t),new ro(n)))break;return true;case"[object Boolean]":case"[object Date]":case"[object Number]":return Ye(+t,+n);case"[object Error]":return t.name==n.name&&t.message==n.message;case"[object RegExp]":case"[object String]":return t==n+"";case"[object Map]":var f=U;case"[object Set]":if(f||(f=D),t.size!=n.size&&!(2&o))break;return(r=i.get(t))?r==n:(o|=1,i.set(t,n),n=ee(f(t),f(n),e,u,o,i),i.delete(t),n);case"[object Symbol]": +if(Fo)return Fo.call(t)==Fo.call(n)}return false}function oe(t){for(var n=t.name+"",r=Co[n],e=Gu.call(Co,n)?r.length:0;e--;){var u=r[e],o=u.func;if(null==o||o==t)return u.name}return n}function ie(t){return(Gu.call(It,"placeholder")?It:t).placeholder}function fe(){var t=It.iteratee||Su,t=t===Su?Vn:t;return arguments.length?t(arguments[0],arguments[1]):t}function ce(t,n){var r=t.__data__,e=typeof n;return("string"==e||"number"==e||"symbol"==e||"boolean"==e?"__proto__"!==n:null===n)?r[typeof n=="string"?"string":"hash"]:r.map; +}function ae(t){for(var n=bu(t),r=n.length;r--;){var e=n[r],u=t[e];n[r]=[e,u,u===u&&!uu(u)]}return n}function le(t,n){var r=null==t?P:t[n];return Nn(r)?r:P}function se(t,n,r){n=ye(n,t)?[n]:Ar(n);for(var e,u=-1,o=n.length;++u<o;){var i=Ae(n[u]);if(!(e=null!=t&&r(t,i)))break;t=t[i]}return e?e:(o=t?t.length:0,!!o&&eu(o)&&ge(i,o)&&(Fi(t)||He(t)))}function he(t){var n=t.length,r=t.constructor(n);return n&&"string"==typeof t[0]&&Gu.call(t,"index")&&(r.index=t.index,r.input=t.input),r}function pe(t){return typeof t.constructor!="function"||xe(t)?{}:bn(eo(t)); +}function _e(r,e,u,o){var i=r.constructor;switch(e){case"[object ArrayBuffer]":return Or(r);case"[object Boolean]":case"[object Date]":return new i((+r));case"[object DataView]":return e=o?Or(r.buffer):r.buffer,new r.constructor(e,r.byteOffset,r.byteLength);case"[object Float32Array]":case"[object Float64Array]":case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[object Uint16Array]":case"[object Uint32Array]": +return e=o?Or(r.buffer):r.buffer,new r.constructor(e,r.byteOffset,r.length);case"[object Map]":return e=o?u(U(r),true):U(r),h(e,t,new r.constructor);case"[object Number]":case"[object String]":return new i(r);case"[object RegExp]":return e=new r.constructor(r.source,yt.exec(r)),e.lastIndex=r.lastIndex,e;case"[object Set]":return e=o?u(D(r),true):D(r),h(e,n,new r.constructor);case"[object Symbol]":return Fo?Tu(Fo.call(r)):{}}}function ve(t){return Fi(t)||He(t)||!!(co&&t&&t[co])}function ge(t,n){return n=null==n?9007199254740991:n, +!!n&&(typeof t=="number"||At.test(t))&&-1<t&&0==t%1&&t<n}function de(t,n,r){if(!uu(r))return false;var e=typeof n;return!!("number"==e?Qe(r)&&ge(n,r.length):"string"==e&&n in r)&&Ye(r[n],t)}function ye(t,n){if(Fi(t))return false;var r=typeof t;return!("number"!=r&&"symbol"!=r&&"boolean"!=r&&null!=t&&!au(t))||(ut.test(t)||!et.test(t)||null!=n&&t in Tu(n))}function be(t){var n=oe(t),r=It[n];return typeof r=="function"&&n in $t.prototype&&(t===r||(n=Yo(r),!!n&&t===n[0]))}function xe(t){var n=t&&t.constructor; +return t===(typeof n=="function"&&n.prototype||Zu)}function je(t,n){return function(r){return null!=r&&(r[t]===n&&(n!==P||t in Tu(r)))}}function we(t,n,r,e,u,o){return uu(t)&&uu(n)&&(o.set(n,t),Xn(t,n,P,we,o),o.delete(n)),t}function me(t,n){return 1==n.length?t:In(t,sr(n,0,-1))}function Ae(t){if(typeof t=="string"||au(t))return t;var n=t+"";return"0"==n&&1/t==-Z?"-0":n}function ke(t){if(null!=t){try{return Ku.call(t)}catch(t){}return t+""}return""}function Ee(t,n){return u(V,function(r){var e="_."+r[0]; +n&r[1]&&!c(t,e)&&t.push(e)}),t.sort()}function Oe(t){if(t instanceof $t)return t.clone();var n=new Lt(t.__wrapped__,t.__chain__);return n.__actions__=Wr(t.__actions__),n.__index__=t.__index__,n.__values__=t.__values__,n}function Se(t,n,r){var e=t?t.length:0;return e?(r=null==r?0:hu(r),0>r&&(r=xo(e+r,0)),g(t,fe(n,3),r)):-1}function Ie(t,n,r){var e=t?t.length:0;if(!e)return-1;var u=e-1;return r!==P&&(u=hu(r),u=0>r?xo(e+u,0):jo(u,e-1)),g(t,fe(n,3),u,true)}function Re(t){return t&&t.length?t[0]:P}function We(t){ +var n=t?t.length:0;return n?t[n-1]:P}function Be(t,n){return t&&t.length&&n&&n.length?or(t,n):t}function Le(t){return t?Ao.call(t):t}function Ce(t){if(!t||!t.length)return[];var n=0;return t=f(t,function(t){if(Xe(t))return n=xo(t.length,n),true}),E(n,function(n){return l(t,j(n))})}function Ue(t,n){if(!t||!t.length)return[];var e=Ce(t);return null==n?e:l(e,function(t){return r(n,P,t)})}function Me(t){return t=It(t),t.__chain__=true,t}function ze(t,n){return n(t)}function De(){return this}function Te(t,n){ +return(Fi(t)?u:Po)(t,fe(n,3))}function $e(t,n){return(Fi(t)?o:Zo)(t,fe(n,3))}function Fe(t,n){return(Fi(t)?l:Yn)(t,fe(n,3))}function Ne(t,n,r){var e=-1,u=lu(t),o=u.length,i=o-1;for(n=(r?de(t,n,r):n===P)?1:vn(hu(n),0,o);++e<n;)t=fr(e,i),r=u[t],u[t]=u[e],u[e]=r;return u.length=n,u}function Pe(t,n,r){return n=r?P:n,n=t&&null==n?t.length:n,re(t,128,P,P,P,P,n)}function Ze(t,n){var r;if(typeof n!="function")throw new Nu("Expected a function");return t=hu(t),function(){return 0<--t&&(r=n.apply(this,arguments)), +1>=t&&(n=P),r}}function qe(t,n,r){return n=r?P:n,t=re(t,8,P,P,P,P,P,n),t.placeholder=qe.placeholder,t}function Ve(t,n,r){return n=r?P:n,t=re(t,16,P,P,P,P,P,n),t.placeholder=Ve.placeholder,t}function Ke(t,n,r){function e(n){var r=c,e=a;return c=a=P,_=n,s=t.apply(e,r)}function u(t){var r=t-p;return t-=_,p===P||r>=n||0>r||g&&t>=l}function o(){var t=Ri();if(u(t))return i(t);var r,e=ni;r=t-_,t=n-(t-p),r=g?jo(t,l-r):t,h=e(o,r)}function i(t){return h=P,d&&c?e(t):(c=a=P,s)}function f(){var t=Ri(),r=u(t);if(c=arguments, +a=this,p=t,r){if(h===P)return _=t=p,h=ni(o,n),v?e(t):s;if(g)return h=ni(o,n),e(p)}return h===P&&(h=ni(o,n)),s}var c,a,l,s,h,p,_=0,v=false,g=false,d=true;if(typeof t!="function")throw new Nu("Expected a function");return n=_u(n)||0,uu(r)&&(v=!!r.leading,l=(g="maxWait"in r)?xo(_u(r.maxWait)||0,n):l,d="trailing"in r?!!r.trailing:d),f.cancel=function(){h!==P&&Go(h),_=0,c=p=a=h=P},f.flush=function(){return h===P?s:i(Ri())},f}function Ge(t,n){function r(){var e=arguments,u=n?n.apply(this,e):e[0],o=r.cache;return o.has(u)?o.get(u):(e=t.apply(this,e), +r.cache=o.set(u,e),e)}if(typeof t!="function"||n&&typeof n!="function")throw new Nu("Expected a function");return r.cache=new(Ge.Cache||qt),r}function Je(t){if(typeof t!="function")throw new Nu("Expected a function");return function(){var n=arguments;switch(n.length){case 0:return!t.call(this);case 1:return!t.call(this,n[0]);case 2:return!t.call(this,n[0],n[1]);case 3:return!t.call(this,n[0],n[1],n[2])}return!t.apply(this,n)}}function Ye(t,n){return t===n||t!==t&&n!==n}function He(t){return Xe(t)&&Gu.call(t,"callee")&&(!io.call(t,"callee")||"[object Arguments]"==Hu.call(t)); +}function Qe(t){return null!=t&&eu(t.length)&&!nu(t)}function Xe(t){return ou(t)&&Qe(t)}function tu(t){return!!ou(t)&&("[object Error]"==Hu.call(t)||typeof t.message=="string"&&typeof t.name=="string")}function nu(t){return t=uu(t)?Hu.call(t):"","[object Function]"==t||"[object GeneratorFunction]"==t}function ru(t){return typeof t=="number"&&t==hu(t)}function eu(t){return typeof t=="number"&&-1<t&&0==t%1&&9007199254740991>=t}function uu(t){var n=typeof t;return!!t&&("object"==n||"function"==n)}function ou(t){ +return!!t&&typeof t=="object"}function iu(t){return typeof t=="number"||ou(t)&&"[object Number]"==Hu.call(t)}function fu(t){return!(!ou(t)||"[object Object]"!=Hu.call(t)||C(t))&&(t=eo(t),null===t||(t=Gu.call(t,"constructor")&&t.constructor,typeof t=="function"&&t instanceof t&&Ku.call(t)==Yu))}function cu(t){return typeof t=="string"||!Fi(t)&&ou(t)&&"[object String]"==Hu.call(t)}function au(t){return typeof t=="symbol"||ou(t)&&"[object Symbol]"==Hu.call(t)}function lu(t){if(!t)return[];if(Qe(t))return cu(t)?F(t):Wr(t); +if(uo&&t[uo]){t=t[uo]();for(var n,r=[];!(n=t.next()).done;)r.push(n.value);return r}return n=St(t),("[object Map]"==n?U:"[object Set]"==n?D:wu)(t)}function su(t){return t?(t=_u(t),t===Z||t===-Z?1.7976931348623157e308*(0>t?-1:1):t===t?t:0):0===t?t:0}function hu(t){t=su(t);var n=t%1;return t===t?n?t-n:t:0}function pu(t){return t?vn(hu(t),0,4294967295):0}function _u(t){if(typeof t=="number")return t;if(au(t))return q;if(uu(t)&&(t=typeof t.valueOf=="function"?t.valueOf():t,t=uu(t)?t+"":t),typeof t!="string")return 0===t?t:+t; +t=t.replace(at,"");var n=jt.test(t);return n||mt.test(t)?Pt(t.slice(2),n?2:8):xt.test(t)?q:+t}function vu(t){return Br(t,xu(t))}function gu(t){return null==t?"":dr(t)}function du(t,n,r){return t=null==t?P:In(t,n),t===P?r:t}function yu(t,n){return null!=t&&se(t,n,Ln)}function bu(t){return Qe(t)?Yt(t):Kn(t)}function xu(t){return Qe(t)?Yt(t,true):Gn(t)}function ju(t,n){return null==t?{}:er(t,Rn(t,xu,Qo),fe(n))}function wu(t){return t?I(t,bu(t)):[]}function mu(t){return jf(gu(t).toLowerCase())}function Au(t){ +return(t=gu(t))&&t.replace(kt,un).replace(Bt,"")}function ku(t,n,r){return t=gu(t),n=r?P:n,n===P?Mt.test(t)?t.match(Ct)||[]:t.match(vt)||[]:t.match(n)||[]}function Eu(t){return function(){return t}}function Ou(t){return t}function Su(t){return Vn(typeof t=="function"?t:gn(t,true))}function Iu(t,n,r){var e=bu(n),o=Sn(n,e);null!=r||uu(n)&&(o.length||!e.length)||(r=n,n=t,t=this,o=Sn(n,bu(n)));var i=!(uu(r)&&"chain"in r&&!r.chain),f=nu(t);return u(o,function(r){var e=n[r];t[r]=e,f&&(t.prototype[r]=function(){ +var n=this.__chain__;if(i||n){var r=t(this.__wrapped__);return(r.__actions__=Wr(this.__actions__)).push({func:e,args:arguments,thisArg:t}),r.__chain__=n,r}return e.apply(t,s([this.value()],arguments))})}),t}function Ru(){}function Wu(t){return ye(t)?j(Ae(t)):ur(t)}function Bu(){return[]}function Lu(){return false}w=w?cn.defaults(Vt.Object(),w,cn.pick(Vt,zt)):Vt;var Cu=w.Array,Uu=w.Date,Mu=w.Error,zu=w.Function,Du=w.Math,Tu=w.Object,$u=w.RegExp,Fu=w.String,Nu=w.TypeError,Pu=Cu.prototype,Zu=Tu.prototype,qu=w["__core-js_shared__"],Vu=function(){ +var t=/[^.]+$/.exec(qu&&qu.keys&&qu.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""}(),Ku=zu.prototype.toString,Gu=Zu.hasOwnProperty,Ju=0,Yu=Ku.call(Tu),Hu=Zu.toString,Qu=Vt._,Xu=$u("^"+Ku.call(Gu).replace(ft,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),to=Jt?w.Buffer:P,no=w.Symbol,ro=w.Uint8Array,eo=M(Tu.getPrototypeOf,Tu),uo=no?no.iterator:P,oo=Tu.create,io=Zu.propertyIsEnumerable,fo=Pu.splice,co=no?no.isConcatSpreadable:P,ao=w.clearTimeout!==Vt.clearTimeout&&w.clearTimeout,lo=Uu&&Uu.now!==Vt.Date.now&&Uu.now,so=w.setTimeout!==Vt.setTimeout&&w.setTimeout,ho=Du.ceil,po=Du.floor,_o=Tu.getOwnPropertySymbols,vo=to?to.isBuffer:P,go=w.isFinite,yo=Pu.join,bo=M(Tu.keys,Tu),xo=Du.max,jo=Du.min,wo=w.parseInt,mo=Du.random,Ao=Pu.reverse,ko=le(w,"DataView"),Eo=le(w,"Map"),Oo=le(w,"Promise"),So=le(w,"Set"),Io=le(w,"WeakMap"),Ro=le(Tu,"create"),Wo=function(){ +var t=le(Tu,"defineProperty"),n=le.name;return n&&2<n.length?t:P}(),Bo=Io&&new Io,Lo=!io.call({valueOf:1},"valueOf"),Co={},Uo=ke(ko),Mo=ke(Eo),zo=ke(Oo),Do=ke(So),To=ke(Io),$o=no?no.prototype:P,Fo=$o?$o.valueOf:P,No=$o?$o.toString:P;It.templateSettings={escape:tt,evaluate:nt,interpolate:rt,variable:"",imports:{_:It}},It.prototype=Rt.prototype,It.prototype.constructor=It,Lt.prototype=bn(Rt.prototype),Lt.prototype.constructor=Lt,$t.prototype=bn(Rt.prototype),$t.prototype.constructor=$t,Ft.prototype.clear=function(){ +this.__data__=Ro?Ro(null):{}},Ft.prototype.delete=function(t){return this.has(t)&&delete this.__data__[t]},Ft.prototype.get=function(t){var n=this.__data__;return Ro?(t=n[t],"__lodash_hash_undefined__"===t?P:t):Gu.call(n,t)?n[t]:P},Ft.prototype.has=function(t){var n=this.__data__;return Ro?n[t]!==P:Gu.call(n,t)},Ft.prototype.set=function(t,n){return this.__data__[t]=Ro&&n===P?"__lodash_hash_undefined__":n,this},Zt.prototype.clear=function(){this.__data__=[]},Zt.prototype.delete=function(t){var n=this.__data__; +return t=sn(n,t),!(0>t)&&(t==n.length-1?n.pop():fo.call(n,t,1),true)},Zt.prototype.get=function(t){var n=this.__data__;return t=sn(n,t),0>t?P:n[t][1]},Zt.prototype.has=function(t){return-1<sn(this.__data__,t)},Zt.prototype.set=function(t,n){var r=this.__data__,e=sn(r,t);return 0>e?r.push([t,n]):r[e][1]=n,this},qt.prototype.clear=function(){this.__data__={hash:new Ft,map:new(Eo||Zt),string:new Ft}},qt.prototype.delete=function(t){return ce(this,t).delete(t)},qt.prototype.get=function(t){return ce(this,t).get(t); +},qt.prototype.has=function(t){return ce(this,t).has(t)},qt.prototype.set=function(t,n){return ce(this,t).set(t,n),this},Kt.prototype.add=Kt.prototype.push=function(t){return this.__data__.set(t,"__lodash_hash_undefined__"),this},Kt.prototype.has=function(t){return this.__data__.has(t)},Gt.prototype.clear=function(){this.__data__=new Zt},Gt.prototype.delete=function(t){return this.__data__.delete(t)},Gt.prototype.get=function(t){return this.__data__.get(t)},Gt.prototype.has=function(t){return this.__data__.has(t); +},Gt.prototype.set=function(t,n){var r=this.__data__;if(r instanceof Zt){if(r=r.__data__,!Eo||199>r.length)return r.push([t,n]),this;r=this.__data__=new qt(r)}return r.set(t,n),this};var Po=Mr(En),Zo=Mr(On,true),qo=zr(),Vo=zr(true),Ko=Bo?function(t,n){return Bo.set(t,n),t}:Ou,Go=ao||function(t){return Vt.clearTimeout(t)},Jo=So&&1/D(new So([,-0]))[1]==Z?function(t){return new So(t)}:Ru,Yo=Bo?function(t){return Bo.get(t)}:Ru,Ho=_o?M(_o,Tu):Bu,Qo=_o?function(t){for(var n=[];t;)s(n,Ho(t)),t=eo(t);return n; +}:Bu;(ko&&"[object DataView]"!=St(new ko(new ArrayBuffer(1)))||Eo&&"[object Map]"!=St(new Eo)||Oo&&"[object Promise]"!=St(Oo.resolve())||So&&"[object Set]"!=St(new So)||Io&&"[object WeakMap]"!=St(new Io))&&(St=function(t){var n=Hu.call(t);if(t=(t="[object Object]"==n?t.constructor:P)?ke(t):P)switch(t){case Uo:return"[object DataView]";case Mo:return"[object Map]";case zo:return"[object Promise]";case Do:return"[object Set]";case To:return"[object WeakMap]"}return n});var Xo=qu?nu:Lu,ti=function(){ +var t=0,n=0;return function(r,e){var u=Ri(),o=16-(u-n);if(n=u,0<o){if(150<=++t)return r}else t=0;return Ko(r,e)}}(),ni=so||function(t,n){return Vt.setTimeout(t,n)},ri=Wo?function(t,n,r){n+="";var e;e=(e=n.match(pt))?e[1].split(_t):[],r=Ee(e,r),e=r.length;var u=e-1;return r[u]=(1<e?"& ":"")+r[u],r=r.join(2<e?", ":" "),n=n.replace(ht,"{\n/* [wrapped with "+r+"] */\n"),Wo(t,"toString",{configurable:true,enumerable:false,value:Eu(n)})}:Ou,ei=Ge(function(t){t=gu(t);var n=[];return ot.test(t)&&n.push(""),t.replace(it,function(t,r,e,u){ +n.push(e?u.replace(gt,"$1"):r||t)}),n}),ui=ar(function(t,n){return Xe(t)?jn(t,kn(n,1,Xe,true)):[]}),oi=ar(function(t,n){var r=We(n);return Xe(r)&&(r=P),Xe(t)?jn(t,kn(n,1,Xe,true),fe(r,2)):[]}),ii=ar(function(t,n){var r=We(n);return Xe(r)&&(r=P),Xe(t)?jn(t,kn(n,1,Xe,true),P,r):[]}),fi=ar(function(t){var n=l(t,mr);return n.length&&n[0]===t[0]?Cn(n):[]}),ci=ar(function(t){var n=We(t),r=l(t,mr);return n===We(r)?n=P:r.pop(),r.length&&r[0]===t[0]?Cn(r,fe(n,2)):[]}),ai=ar(function(t){var n=We(t),r=l(t,mr);return n===We(r)?n=P:r.pop(), +r.length&&r[0]===t[0]?Cn(r,P,n):[]}),li=ar(Be),si=ar(function(t,n){n=kn(n,1);var r=t?t.length:0,e=_n(t,n);return ir(t,l(n,function(t){return ge(t,r)?+t:t}).sort(Sr)),e}),hi=ar(function(t){return yr(kn(t,1,Xe,true))}),pi=ar(function(t){var n=We(t);return Xe(n)&&(n=P),yr(kn(t,1,Xe,true),fe(n,2))}),_i=ar(function(t){var n=We(t);return Xe(n)&&(n=P),yr(kn(t,1,Xe,true),P,n)}),vi=ar(function(t,n){return Xe(t)?jn(t,n):[]}),gi=ar(function(t){return jr(f(t,Xe))}),di=ar(function(t){var n=We(t);return Xe(n)&&(n=P), +jr(f(t,Xe),fe(n,2))}),yi=ar(function(t){var n=We(t);return Xe(n)&&(n=P),jr(f(t,Xe),P,n)}),bi=ar(Ce),xi=ar(function(t){var n=t.length,n=1<n?t[n-1]:P,n=typeof n=="function"?(t.pop(),n):P;return Ue(t,n)}),ji=ar(function(t){function n(n){return _n(n,t)}t=kn(t,1);var r=t.length,e=r?t[0]:0,u=this.__wrapped__;return!(1<r||this.__actions__.length)&&u instanceof $t&&ge(e)?(u=u.slice(e,+e+(r?1:0)),u.__actions__.push({func:ze,args:[n],thisArg:P}),new Lt(u,this.__chain__).thru(function(t){return r&&!t.length&&t.push(P), +t})):this.thru(n)}),wi=Cr(function(t,n,r){Gu.call(t,r)?++t[r]:t[r]=1}),mi=Pr(Se),Ai=Pr(Ie),ki=Cr(function(t,n,r){Gu.call(t,r)?t[r].push(n):t[r]=[n]}),Ei=ar(function(t,n,e){var u=-1,o=typeof n=="function",i=ye(n),f=Qe(t)?Cu(t.length):[];return Po(t,function(t){var c=o?n:i&&null!=t?t[n]:P;f[++u]=c?r(c,t,e):Mn(t,n,e)}),f}),Oi=Cr(function(t,n,r){t[r]=n}),Si=Cr(function(t,n,r){t[r?0:1].push(n)},function(){return[[],[]]}),Ii=ar(function(t,n){if(null==t)return[];var r=n.length;return 1<r&&de(t,n[0],n[1])?n=[]:2<r&&de(n[0],n[1],n[2])&&(n=[n[0]]), +nr(t,kn(n,1),[])}),Ri=lo||function(){return Vt.Date.now()},Wi=ar(function(t,n,r){var e=1;if(r.length)var u=z(r,ie(Wi)),e=32|e;return re(t,e,n,r,u)}),Bi=ar(function(t,n,r){var e=3;if(r.length)var u=z(r,ie(Bi)),e=32|e;return re(n,e,t,r,u)}),Li=ar(function(t,n){return xn(t,1,n)}),Ci=ar(function(t,n,r){return xn(t,_u(n)||0,r)});Ge.Cache=qt;var Ui=ar(function(t,n){n=1==n.length&&Fi(n[0])?l(n[0],S(fe())):l(kn(n,1),S(fe()));var e=n.length;return ar(function(u){for(var o=-1,i=jo(u.length,e);++o<i;)u[o]=n[o].call(this,u[o]); +return r(t,this,u)})}),Mi=ar(function(t,n){var r=z(n,ie(Mi));return re(t,32,P,n,r)}),zi=ar(function(t,n){var r=z(n,ie(zi));return re(t,64,P,n,r)}),Di=ar(function(t,n){return re(t,256,P,P,P,kn(n,1))}),Ti=Qr(Wn),$i=Qr(function(t,n){return t>=n}),Fi=Cu.isArray,Ni=Ht?S(Ht):zn,Pi=vo||Lu,Zi=Qt?S(Qt):Dn,qi=Xt?S(Xt):$n,Vi=tn?S(tn):Pn,Ki=nn?S(nn):Zn,Gi=rn?S(rn):qn,Ji=Qr(Jn),Yi=Qr(function(t,n){return t<=n}),Hi=Ur(function(t,n){if(Lo||xe(n)||Qe(n))Br(n,bu(n),t);else for(var r in n)Gu.call(n,r)&&ln(t,r,n[r]); +}),Qi=Ur(function(t,n){Br(n,xu(n),t)}),Xi=Ur(function(t,n,r,e){Br(n,xu(n),t,e)}),tf=Ur(function(t,n,r,e){Br(n,bu(n),t,e)}),nf=ar(function(t,n){return _n(t,kn(n,1))}),rf=ar(function(t){return t.push(P,en),r(Xi,P,t)}),ef=ar(function(t){return t.push(P,we),r(af,P,t)}),uf=Vr(function(t,n,r){t[n]=r},Eu(Ou)),of=Vr(function(t,n,r){Gu.call(t,n)?t[n].push(r):t[n]=[r]},fe),ff=ar(Mn),cf=Ur(function(t,n,r){Xn(t,n,r)}),af=Ur(function(t,n,r,e){Xn(t,n,r,e)}),lf=ar(function(t,n){return null==t?{}:(n=l(kn(n,1),Ae), +rr(t,jn(Rn(t,xu,Qo),n)))}),sf=ar(function(t,n){return null==t?{}:rr(t,l(kn(n,1),Ae))}),hf=ne(bu),pf=ne(xu),_f=$r(function(t,n,r){return n=n.toLowerCase(),t+(r?mu(n):n)}),vf=$r(function(t,n,r){return t+(r?"-":"")+n.toLowerCase()}),gf=$r(function(t,n,r){return t+(r?" ":"")+n.toLowerCase()}),df=Tr("toLowerCase"),yf=$r(function(t,n,r){return t+(r?"_":"")+n.toLowerCase()}),bf=$r(function(t,n,r){return t+(r?" ":"")+jf(n)}),xf=$r(function(t,n,r){return t+(r?" ":"")+n.toUpperCase()}),jf=Tr("toUpperCase"),wf=ar(function(t,n){ +try{return r(t,P,n)}catch(t){return tu(t)?t:new Mu(t)}}),mf=ar(function(t,n){return u(kn(n,1),function(n){n=Ae(n),t[n]=Wi(t[n],t)}),t}),Af=Zr(),kf=Zr(true),Ef=ar(function(t,n){return function(r){return Mn(r,t,n)}}),Of=ar(function(t,n){return function(r){return Mn(t,r,n)}}),Sf=Gr(l),If=Gr(i),Rf=Gr(_),Wf=Hr(),Bf=Hr(true),Lf=Kr(function(t,n){return t+n},0),Cf=te("ceil"),Uf=Kr(function(t,n){return t/n},1),Mf=te("floor"),zf=Kr(function(t,n){return t*n},1),Df=te("round"),Tf=Kr(function(t,n){return t-n},0);return It.after=function(t,n){ +if(typeof n!="function")throw new Nu("Expected a function");return t=hu(t),function(){if(1>--t)return n.apply(this,arguments)}},It.ary=Pe,It.assign=Hi,It.assignIn=Qi,It.assignInWith=Xi,It.assignWith=tf,It.at=nf,It.before=Ze,It.bind=Wi,It.bindAll=mf,It.bindKey=Bi,It.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return Fi(t)?t:[t]},It.chain=Me,It.chunk=function(t,n,r){if(n=(r?de(t,n,r):n===P)?1:xo(hu(n),0),r=t?t.length:0,!r||1>n)return[];for(var e=0,u=0,o=Cu(ho(r/n));e<r;)o[u++]=sr(t,e,e+=n); +return o},It.compact=function(t){for(var n=-1,r=t?t.length:0,e=0,u=[];++n<r;){var o=t[n];o&&(u[e++]=o)}return u},It.concat=function(){for(var t=arguments.length,n=Cu(t?t-1:0),r=arguments[0],e=t;e--;)n[e-1]=arguments[e];return t?s(Fi(r)?Wr(r):[r],kn(n,1)):[]},It.cond=function(t){var n=t?t.length:0,e=fe();return t=n?l(t,function(t){if("function"!=typeof t[1])throw new Nu("Expected a function");return[e(t[0]),t[1]]}):[],ar(function(e){for(var u=-1;++u<n;){var o=t[u];if(r(o[0],this,e))return r(o[1],this,e); +}})},It.conforms=function(t){return dn(gn(t,true))},It.constant=Eu,It.countBy=wi,It.create=function(t,n){var r=bn(t);return n?pn(r,n):r},It.curry=qe,It.curryRight=Ve,It.debounce=Ke,It.defaults=rf,It.defaultsDeep=ef,It.defer=Li,It.delay=Ci,It.difference=ui,It.differenceBy=oi,It.differenceWith=ii,It.drop=function(t,n,r){var e=t?t.length:0;return e?(n=r||n===P?1:hu(n),sr(t,0>n?0:n,e)):[]},It.dropRight=function(t,n,r){var e=t?t.length:0;return e?(n=r||n===P?1:hu(n),n=e-n,sr(t,0,0>n?0:n)):[]},It.dropRightWhile=function(t,n){ +return t&&t.length?br(t,fe(n,3),true,true):[]},It.dropWhile=function(t,n){return t&&t.length?br(t,fe(n,3),true):[]},It.fill=function(t,n,r,e){var u=t?t.length:0;if(!u)return[];for(r&&typeof r!="number"&&de(t,n,r)&&(r=0,e=u),u=t.length,r=hu(r),0>r&&(r=-r>u?0:u+r),e=e===P||e>u?u:hu(e),0>e&&(e+=u),e=r>e?0:pu(e);r<e;)t[r++]=n;return t},It.filter=function(t,n){return(Fi(t)?f:An)(t,fe(n,3))},It.flatMap=function(t,n){return kn(Fe(t,n),1)},It.flatMapDeep=function(t,n){return kn(Fe(t,n),Z)},It.flatMapDepth=function(t,n,r){ +return r=r===P?1:hu(r),kn(Fe(t,n),r)},It.flatten=function(t){return t&&t.length?kn(t,1):[]},It.flattenDeep=function(t){return t&&t.length?kn(t,Z):[]},It.flattenDepth=function(t,n){return t&&t.length?(n=n===P?1:hu(n),kn(t,n)):[]},It.flip=function(t){return re(t,512)},It.flow=Af,It.flowRight=kf,It.fromPairs=function(t){for(var n=-1,r=t?t.length:0,e={};++n<r;){var u=t[n];e[u[0]]=u[1]}return e},It.functions=function(t){return null==t?[]:Sn(t,bu(t))},It.functionsIn=function(t){return null==t?[]:Sn(t,xu(t)); +},It.groupBy=ki,It.initial=function(t){return t&&t.length?sr(t,0,-1):[]},It.intersection=fi,It.intersectionBy=ci,It.intersectionWith=ai,It.invert=uf,It.invertBy=of,It.invokeMap=Ei,It.iteratee=Su,It.keyBy=Oi,It.keys=bu,It.keysIn=xu,It.map=Fe,It.mapKeys=function(t,n){var r={};return n=fe(n,3),En(t,function(t,e,u){r[n(t,e,u)]=t}),r},It.mapValues=function(t,n){var r={};return n=fe(n,3),En(t,function(t,e,u){r[e]=n(t,e,u)}),r},It.matches=function(t){return Hn(gn(t,true))},It.matchesProperty=function(t,n){ +return Qn(t,gn(n,true))},It.memoize=Ge,It.merge=cf,It.mergeWith=af,It.method=Ef,It.methodOf=Of,It.mixin=Iu,It.negate=Je,It.nthArg=function(t){return t=hu(t),ar(function(n){return tr(n,t)})},It.omit=lf,It.omitBy=function(t,n){return ju(t,Je(fe(n)))},It.once=function(t){return Ze(2,t)},It.orderBy=function(t,n,r,e){return null==t?[]:(Fi(n)||(n=null==n?[]:[n]),r=e?P:r,Fi(r)||(r=null==r?[]:[r]),nr(t,n,r))},It.over=Sf,It.overArgs=Ui,It.overEvery=If,It.overSome=Rf,It.partial=Mi,It.partialRight=zi,It.partition=Si, +It.pick=sf,It.pickBy=ju,It.property=Wu,It.propertyOf=function(t){return function(n){return null==t?P:In(t,n)}},It.pull=li,It.pullAll=Be,It.pullAllBy=function(t,n,r){return t&&t.length&&n&&n.length?or(t,n,fe(r,2)):t},It.pullAllWith=function(t,n,r){return t&&t.length&&n&&n.length?or(t,n,P,r):t},It.pullAt=si,It.range=Wf,It.rangeRight=Bf,It.rearg=Di,It.reject=function(t,n){return(Fi(t)?f:An)(t,Je(fe(n,3)))},It.remove=function(t,n){var r=[];if(!t||!t.length)return r;var e=-1,u=[],o=t.length;for(n=fe(n,3);++e<o;){ +var i=t[e];n(i,e,t)&&(r.push(i),u.push(e))}return ir(t,u),r},It.rest=function(t,n){if(typeof t!="function")throw new Nu("Expected a function");return n=n===P?n:hu(n),ar(t,n)},It.reverse=Le,It.sampleSize=Ne,It.set=function(t,n,r){return null==t?t:lr(t,n,r)},It.setWith=function(t,n,r,e){return e=typeof e=="function"?e:P,null==t?t:lr(t,n,r,e)},It.shuffle=function(t){return Ne(t,4294967295)},It.slice=function(t,n,r){var e=t?t.length:0;return e?(r&&typeof r!="number"&&de(t,n,r)?(n=0,r=e):(n=null==n?0:hu(n), +r=r===P?e:hu(r)),sr(t,n,r)):[]},It.sortBy=Ii,It.sortedUniq=function(t){return t&&t.length?vr(t):[]},It.sortedUniqBy=function(t,n){return t&&t.length?vr(t,fe(n,2)):[]},It.split=function(t,n,r){return r&&typeof r!="number"&&de(t,n,r)&&(n=r=P),r=r===P?4294967295:r>>>0,r?(t=gu(t))&&(typeof n=="string"||null!=n&&!Vi(n))&&(n=dr(n),!n&&Ut.test(t))?kr(F(t),0,r):t.split(n,r):[]},It.spread=function(t,n){if(typeof t!="function")throw new Nu("Expected a function");return n=n===P?0:xo(hu(n),0),ar(function(e){ +var u=e[n];return e=kr(e,0,n),u&&s(e,u),r(t,this,e)})},It.tail=function(t){var n=t?t.length:0;return n?sr(t,1,n):[]},It.take=function(t,n,r){return t&&t.length?(n=r||n===P?1:hu(n),sr(t,0,0>n?0:n)):[]},It.takeRight=function(t,n,r){var e=t?t.length:0;return e?(n=r||n===P?1:hu(n),n=e-n,sr(t,0>n?0:n,e)):[]},It.takeRightWhile=function(t,n){return t&&t.length?br(t,fe(n,3),false,true):[]},It.takeWhile=function(t,n){return t&&t.length?br(t,fe(n,3)):[]},It.tap=function(t,n){return n(t),t},It.throttle=function(t,n,r){ +var e=true,u=true;if(typeof t!="function")throw new Nu("Expected a function");return uu(r)&&(e="leading"in r?!!r.leading:e,u="trailing"in r?!!r.trailing:u),Ke(t,n,{leading:e,maxWait:n,trailing:u})},It.thru=ze,It.toArray=lu,It.toPairs=hf,It.toPairsIn=pf,It.toPath=function(t){return Fi(t)?l(t,Ae):au(t)?[t]:Wr(ei(t))},It.toPlainObject=vu,It.transform=function(t,n,r){var e=Fi(t)||Gi(t);if(n=fe(n,4),null==r)if(e||uu(t)){var o=t.constructor;r=e?Fi(t)?new o:[]:nu(o)?bn(eo(t)):{}}else r={};return(e?u:En)(t,function(t,e,u){ +return n(r,t,e,u)}),r},It.unary=function(t){return Pe(t,1)},It.union=hi,It.unionBy=pi,It.unionWith=_i,It.uniq=function(t){return t&&t.length?yr(t):[]},It.uniqBy=function(t,n){return t&&t.length?yr(t,fe(n,2)):[]},It.uniqWith=function(t,n){return t&&t.length?yr(t,P,n):[]},It.unset=function(t,n){var r;if(null==t)r=true;else{r=t;var e=n,e=ye(e,r)?[e]:Ar(e);r=me(r,e),e=Ae(We(e)),r=!(null!=r&&Gu.call(r,e))||delete r[e]}return r},It.unzip=Ce,It.unzipWith=Ue,It.update=function(t,n,r){return null==t?t:lr(t,n,(typeof r=="function"?r:Ou)(In(t,n)),void 0); +},It.updateWith=function(t,n,r,e){return e=typeof e=="function"?e:P,null!=t&&(t=lr(t,n,(typeof r=="function"?r:Ou)(In(t,n)),e)),t},It.values=wu,It.valuesIn=function(t){return null==t?[]:I(t,xu(t))},It.without=vi,It.words=ku,It.wrap=function(t,n){return n=null==n?Ou:n,Mi(n,t)},It.xor=gi,It.xorBy=di,It.xorWith=yi,It.zip=bi,It.zipObject=function(t,n){return wr(t||[],n||[],ln)},It.zipObjectDeep=function(t,n){return wr(t||[],n||[],lr)},It.zipWith=xi,It.entries=hf,It.entriesIn=pf,It.extend=Qi,It.extendWith=Xi, +Iu(It,It),It.add=Lf,It.attempt=wf,It.camelCase=_f,It.capitalize=mu,It.ceil=Cf,It.clamp=function(t,n,r){return r===P&&(r=n,n=P),r!==P&&(r=_u(r),r=r===r?r:0),n!==P&&(n=_u(n),n=n===n?n:0),vn(_u(t),n,r)},It.clone=function(t){return gn(t,false,true)},It.cloneDeep=function(t){return gn(t,true,true)},It.cloneDeepWith=function(t,n){return gn(t,true,true,n)},It.cloneWith=function(t,n){return gn(t,false,true,n)},It.conformsTo=function(t,n){return null==n||yn(t,n,bu(n))},It.deburr=Au,It.defaultTo=function(t,n){return null==t||t!==t?n:t; +},It.divide=Uf,It.endsWith=function(t,n,r){t=gu(t),n=dr(n);var e=t.length,e=r=r===P?e:vn(hu(r),0,e);return r-=n.length,0<=r&&t.slice(r,e)==n},It.eq=Ye,It.escape=function(t){return(t=gu(t))&&X.test(t)?t.replace(H,on):t},It.escapeRegExp=function(t){return(t=gu(t))&&ct.test(t)?t.replace(ft,"\\$&"):t},It.every=function(t,n,r){var e=Fi(t)?i:wn;return r&&de(t,n,r)&&(n=P),e(t,fe(n,3))},It.find=mi,It.findIndex=Se,It.findKey=function(t,n){return v(t,fe(n,3),En)},It.findLast=Ai,It.findLastIndex=Ie,It.findLastKey=function(t,n){ +return v(t,fe(n,3),On)},It.floor=Mf,It.forEach=Te,It.forEachRight=$e,It.forIn=function(t,n){return null==t?t:qo(t,fe(n,3),xu)},It.forInRight=function(t,n){return null==t?t:Vo(t,fe(n,3),xu)},It.forOwn=function(t,n){return t&&En(t,fe(n,3))},It.forOwnRight=function(t,n){return t&&On(t,fe(n,3))},It.get=du,It.gt=Ti,It.gte=$i,It.has=function(t,n){return null!=t&&se(t,n,Bn)},It.hasIn=yu,It.head=Re,It.identity=Ou,It.includes=function(t,n,r,e){return t=Qe(t)?t:wu(t),r=r&&!e?hu(r):0,e=t.length,0>r&&(r=xo(e+r,0)), +cu(t)?r<=e&&-1<t.indexOf(n,r):!!e&&-1<d(t,n,r)},It.indexOf=function(t,n,r){var e=t?t.length:0;return e?(r=null==r?0:hu(r),0>r&&(r=xo(e+r,0)),d(t,n,r)):-1},It.inRange=function(t,n,r){return n=su(n),r===P?(r=n,n=0):r=su(r),t=_u(t),t>=jo(n,r)&&t<xo(n,r)},It.invoke=ff,It.isArguments=He,It.isArray=Fi,It.isArrayBuffer=Ni,It.isArrayLike=Qe,It.isArrayLikeObject=Xe,It.isBoolean=function(t){return true===t||false===t||ou(t)&&"[object Boolean]"==Hu.call(t)},It.isBuffer=Pi,It.isDate=Zi,It.isElement=function(t){return!!t&&1===t.nodeType&&ou(t)&&!fu(t); +},It.isEmpty=function(t){if(Qe(t)&&(Fi(t)||typeof t=="string"||typeof t.splice=="function"||Pi(t)||He(t)))return!t.length;var n=St(t);if("[object Map]"==n||"[object Set]"==n)return!t.size;if(Lo||xe(t))return!bo(t).length;for(var r in t)if(Gu.call(t,r))return false;return true},It.isEqual=function(t,n){return Tn(t,n)},It.isEqualWith=function(t,n,r){var e=(r=typeof r=="function"?r:P)?r(t,n):P;return e===P?Tn(t,n,r):!!e},It.isError=tu,It.isFinite=function(t){return typeof t=="number"&&go(t)},It.isFunction=nu, +It.isInteger=ru,It.isLength=eu,It.isMap=qi,It.isMatch=function(t,n){return t===n||Fn(t,n,ae(n))},It.isMatchWith=function(t,n,r){return r=typeof r=="function"?r:P,Fn(t,n,ae(n),r)},It.isNaN=function(t){return iu(t)&&t!=+t},It.isNative=function(t){if(Xo(t))throw new Mu("This method is not supported with core-js. Try https://github.com/es-shims.");return Nn(t)},It.isNil=function(t){return null==t},It.isNull=function(t){return null===t},It.isNumber=iu,It.isObject=uu,It.isObjectLike=ou,It.isPlainObject=fu, +It.isRegExp=Vi,It.isSafeInteger=function(t){return ru(t)&&-9007199254740991<=t&&9007199254740991>=t},It.isSet=Ki,It.isString=cu,It.isSymbol=au,It.isTypedArray=Gi,It.isUndefined=function(t){return t===P},It.isWeakMap=function(t){return ou(t)&&"[object WeakMap]"==St(t)},It.isWeakSet=function(t){return ou(t)&&"[object WeakSet]"==Hu.call(t)},It.join=function(t,n){return t?yo.call(t,n):""},It.kebabCase=vf,It.last=We,It.lastIndexOf=function(t,n,r){var e=t?t.length:0;if(!e)return-1;var u=e;if(r!==P&&(u=hu(r), +u=(0>u?xo(e+u,0):jo(u,e-1))+1),n!==n)return g(t,b,u-1,true);for(;u--;)if(t[u]===n)return u;return-1},It.lowerCase=gf,It.lowerFirst=df,It.lt=Ji,It.lte=Yi,It.max=function(t){return t&&t.length?mn(t,Ou,Wn):P},It.maxBy=function(t,n){return t&&t.length?mn(t,fe(n,2),Wn):P},It.mean=function(t){return x(t,Ou)},It.meanBy=function(t,n){return x(t,fe(n,2))},It.min=function(t){return t&&t.length?mn(t,Ou,Jn):P},It.minBy=function(t,n){return t&&t.length?mn(t,fe(n,2),Jn):P},It.stubArray=Bu,It.stubFalse=Lu,It.stubObject=function(){ +return{}},It.stubString=function(){return""},It.stubTrue=function(){return true},It.multiply=zf,It.nth=function(t,n){return t&&t.length?tr(t,hu(n)):P},It.noConflict=function(){return Vt._===this&&(Vt._=Qu),this},It.noop=Ru,It.now=Ri,It.pad=function(t,n,r){t=gu(t);var e=(n=hu(n))?$(t):0;return!n||e>=n?t:(n=(n-e)/2,Jr(po(n),r)+t+Jr(ho(n),r))},It.padEnd=function(t,n,r){t=gu(t);var e=(n=hu(n))?$(t):0;return n&&e<n?t+Jr(n-e,r):t},It.padStart=function(t,n,r){t=gu(t);var e=(n=hu(n))?$(t):0;return n&&e<n?Jr(n-e,r)+t:t; +},It.parseInt=function(t,n,r){return r||null==n?n=0:n&&(n=+n),t=gu(t).replace(at,""),wo(t,n||(bt.test(t)?16:10))},It.random=function(t,n,r){if(r&&typeof r!="boolean"&&de(t,n,r)&&(n=r=P),r===P&&(typeof n=="boolean"?(r=n,n=P):typeof t=="boolean"&&(r=t,t=P)),t===P&&n===P?(t=0,n=1):(t=su(t),n===P?(n=t,t=0):n=su(n)),t>n){var e=t;t=n,n=e}return r||t%1||n%1?(r=mo(),jo(t+r*(n-t+Nt("1e-"+((r+"").length-1))),n)):fr(t,n)},It.reduce=function(t,n,r){var e=Fi(t)?h:m,u=3>arguments.length;return e(t,fe(n,4),r,u,Po); +},It.reduceRight=function(t,n,r){var e=Fi(t)?p:m,u=3>arguments.length;return e(t,fe(n,4),r,u,Zo)},It.repeat=function(t,n,r){return n=(r?de(t,n,r):n===P)?1:hu(n),cr(gu(t),n)},It.replace=function(){var t=arguments,n=gu(t[0]);return 3>t.length?n:n.replace(t[1],t[2])},It.result=function(t,n,r){n=ye(n,t)?[n]:Ar(n);var e=-1,u=n.length;for(u||(t=P,u=1);++e<u;){var o=null==t?P:t[Ae(n[e])];o===P&&(e=u,o=r),t=nu(o)?o.call(t):o}return t},It.round=Df,It.runInContext=N,It.sample=function(t){t=Qe(t)?t:wu(t);var n=t.length; +return 0<n?t[fr(0,n-1)]:P},It.size=function(t){if(null==t)return 0;if(Qe(t))return cu(t)?$(t):t.length;var n=St(t);return"[object Map]"==n||"[object Set]"==n?t.size:Kn(t).length},It.snakeCase=yf,It.some=function(t,n,r){var e=Fi(t)?_:hr;return r&&de(t,n,r)&&(n=P),e(t,fe(n,3))},It.sortedIndex=function(t,n){return pr(t,n)},It.sortedIndexBy=function(t,n,r){return _r(t,n,fe(r,2))},It.sortedIndexOf=function(t,n){var r=t?t.length:0;if(r){var e=pr(t,n);if(e<r&&Ye(t[e],n))return e}return-1},It.sortedLastIndex=function(t,n){ +return pr(t,n,true)},It.sortedLastIndexBy=function(t,n,r){return _r(t,n,fe(r,2),true)},It.sortedLastIndexOf=function(t,n){if(t&&t.length){var r=pr(t,n,true)-1;if(Ye(t[r],n))return r}return-1},It.startCase=bf,It.startsWith=function(t,n,r){return t=gu(t),r=vn(hu(r),0,t.length),n=dr(n),t.slice(r,r+n.length)==n},It.subtract=Tf,It.sum=function(t){return t&&t.length?k(t,Ou):0},It.sumBy=function(t,n){return t&&t.length?k(t,fe(n,2)):0},It.template=function(t,n,r){var e=It.templateSettings;r&&de(t,n,r)&&(n=P),t=gu(t), +n=Xi({},n,e,en),r=Xi({},n.imports,e.imports,en);var u,o,i=bu(r),f=I(r,i),c=0;r=n.interpolate||Et;var a="__p+='";r=$u((n.escape||Et).source+"|"+r.source+"|"+(r===rt?dt:Et).source+"|"+(n.evaluate||Et).source+"|$","g");var l="sourceURL"in n?"//# sourceURL="+n.sourceURL+"\n":"";if(t.replace(r,function(n,r,e,i,f,l){return e||(e=i),a+=t.slice(c,l).replace(Ot,L),r&&(u=true,a+="'+__e("+r+")+'"),f&&(o=true,a+="';"+f+";\n__p+='"),e&&(a+="'+((__t=("+e+"))==null?'':__t)+'"),c=l+n.length,n}),a+="';",(n=n.variable)||(a="with(obj){"+a+"}"), +a=(o?a.replace(K,""):a).replace(G,"$1").replace(J,"$1;"),a="function("+(n||"obj")+"){"+(n?"":"obj||(obj={});")+"var __t,__p=''"+(u?",__e=_.escape":"")+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+a+"return __p}",n=wf(function(){return zu(i,l+"return "+a).apply(P,f)}),n.source=a,tu(n))throw n;return n},It.times=function(t,n){if(t=hu(t),1>t||9007199254740991<t)return[];var r=4294967295,e=jo(t,4294967295);for(n=fe(n),t-=4294967295,e=E(e,n);++r<t;)n(r);return e},It.toFinite=su, +It.toInteger=hu,It.toLength=pu,It.toLower=function(t){return gu(t).toLowerCase()},It.toNumber=_u,It.toSafeInteger=function(t){return vn(hu(t),-9007199254740991,9007199254740991)},It.toString=gu,It.toUpper=function(t){return gu(t).toUpperCase()},It.trim=function(t,n,r){return(t=gu(t))&&(r||n===P)?t.replace(at,""):t&&(n=dr(n))?(t=F(t),r=F(n),n=W(t,r),r=B(t,r)+1,kr(t,n,r).join("")):t},It.trimEnd=function(t,n,r){return(t=gu(t))&&(r||n===P)?t.replace(st,""):t&&(n=dr(n))?(t=F(t),n=B(t,F(n))+1,kr(t,0,n).join("")):t; +},It.trimStart=function(t,n,r){return(t=gu(t))&&(r||n===P)?t.replace(lt,""):t&&(n=dr(n))?(t=F(t),n=W(t,F(n)),kr(t,n).join("")):t},It.truncate=function(t,n){var r=30,e="...";if(uu(n))var u="separator"in n?n.separator:u,r="length"in n?hu(n.length):r,e="omission"in n?dr(n.omission):e;t=gu(t);var o=t.length;if(Ut.test(t))var i=F(t),o=i.length;if(r>=o)return t;if(o=r-$(e),1>o)return e;if(r=i?kr(i,0,o).join(""):t.slice(0,o),u===P)return r+e;if(i&&(o+=r.length-o),Vi(u)){if(t.slice(o).search(u)){var f=r;for(u.global||(u=$u(u.source,gu(yt.exec(u))+"g")), +u.lastIndex=0;i=u.exec(f);)var c=i.index;r=r.slice(0,c===P?o:c)}}else t.indexOf(dr(u),o)!=o&&(u=r.lastIndexOf(u),-1<u&&(r=r.slice(0,u)));return r+e},It.unescape=function(t){return(t=gu(t))&&Q.test(t)?t.replace(Y,fn):t},It.uniqueId=function(t){var n=++Ju;return gu(t)+n},It.upperCase=xf,It.upperFirst=jf,It.each=Te,It.eachRight=$e,It.first=Re,Iu(It,function(){var t={};return En(It,function(n,r){Gu.call(It.prototype,r)||(t[r]=n)}),t}(),{chain:false}),It.VERSION="4.15.0",u("bind bindKey curry curryRight partial partialRight".split(" "),function(t){ +It[t].placeholder=It}),u(["drop","take"],function(t,n){$t.prototype[t]=function(r){var e=this.__filtered__;if(e&&!n)return new $t(this);r=r===P?1:xo(hu(r),0);var u=this.clone();return e?u.__takeCount__=jo(r,u.__takeCount__):u.__views__.push({size:jo(r,4294967295),type:t+(0>u.__dir__?"Right":"")}),u},$t.prototype[t+"Right"]=function(n){return this.reverse()[t](n).reverse()}}),u(["filter","map","takeWhile"],function(t,n){var r=n+1,e=1==r||3==r;$t.prototype[t]=function(t){var n=this.clone();return n.__iteratees__.push({ +iteratee:fe(t,3),type:r}),n.__filtered__=n.__filtered__||e,n}}),u(["head","last"],function(t,n){var r="take"+(n?"Right":"");$t.prototype[t]=function(){return this[r](1).value()[0]}}),u(["initial","tail"],function(t,n){var r="drop"+(n?"":"Right");$t.prototype[t]=function(){return this.__filtered__?new $t(this):this[r](1)}}),$t.prototype.compact=function(){return this.filter(Ou)},$t.prototype.find=function(t){return this.filter(t).head()},$t.prototype.findLast=function(t){return this.reverse().find(t); +},$t.prototype.invokeMap=ar(function(t,n){return typeof t=="function"?new $t(this):this.map(function(r){return Mn(r,t,n)})}),$t.prototype.reject=function(t){return this.filter(Je(fe(t)))},$t.prototype.slice=function(t,n){t=hu(t);var r=this;return r.__filtered__&&(0<t||0>n)?new $t(r):(0>t?r=r.takeRight(-t):t&&(r=r.drop(t)),n!==P&&(n=hu(n),r=0>n?r.dropRight(-n):r.take(n-t)),r)},$t.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},$t.prototype.toArray=function(){return this.take(4294967295); +},En($t.prototype,function(t,n){var r=/^(?:filter|find|map|reject)|While$/.test(n),e=/^(?:head|last)$/.test(n),u=It[e?"take"+("last"==n?"Right":""):n],o=e||/^find/.test(n);u&&(It.prototype[n]=function(){function n(t){return t=u.apply(It,s([t],f)),e&&h?t[0]:t}var i=this.__wrapped__,f=e?[1]:arguments,c=i instanceof $t,a=f[0],l=c||Fi(i);l&&r&&typeof a=="function"&&1!=a.length&&(c=l=false);var h=this.__chain__,p=!!this.__actions__.length,a=o&&!h,c=c&&!p;return!o&&l?(i=c?i:new $t(this),i=t.apply(i,f),i.__actions__.push({ +func:ze,args:[n],thisArg:P}),new Lt(i,h)):a&&c?t.apply(this,f):(i=this.thru(n),a?e?i.value()[0]:i.value():i)})}),u("pop push shift sort splice unshift".split(" "),function(t){var n=Pu[t],r=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",e=/^(?:pop|shift)$/.test(t);It.prototype[t]=function(){var t=arguments;if(e&&!this.__chain__){var u=this.value();return n.apply(Fi(u)?u:[],t)}return this[r](function(r){return n.apply(Fi(r)?r:[],t)})}}),En($t.prototype,function(t,n){var r=It[n];if(r){var e=r.name+""; +(Co[e]||(Co[e]=[])).push({name:n,func:r})}}),Co[qr(P,2).name]=[{name:"wrapper",func:P}],$t.prototype.clone=function(){var t=new $t(this.__wrapped__);return t.__actions__=Wr(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=Wr(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=Wr(this.__views__),t},$t.prototype.reverse=function(){if(this.__filtered__){var t=new $t(this);t.__dir__=-1,t.__filtered__=true}else t=this.clone(),t.__dir__*=-1;return t; +},$t.prototype.value=function(){var t,n=this.__wrapped__.value(),r=this.__dir__,e=Fi(n),u=0>r,o=e?n.length:0;t=o;for(var i=this.__views__,f=0,c=-1,a=i.length;++c<a;){var l=i[c],s=l.size;switch(l.type){case"drop":f+=s;break;case"dropRight":t-=s;break;case"take":t=jo(t,f+s);break;case"takeRight":f=xo(f,t-s)}}if(t={start:f,end:t},i=t.start,f=t.end,t=f-i,u=u?f:i-1,i=this.__iteratees__,f=i.length,c=0,a=jo(t,this.__takeCount__),!e||200>o||o==t&&a==t)return xr(n,this.__actions__);e=[];t:for(;t--&&c<a;){ +for(u+=r,o=-1,l=n[u];++o<f;){var h=i[o],s=h.type,h=(0,h.iteratee)(l);if(2==s)l=h;else if(!h){if(1==s)continue t;break t}}e[c++]=l}return e},It.prototype.at=ji,It.prototype.chain=function(){return Me(this)},It.prototype.commit=function(){return new Lt(this.value(),this.__chain__)},It.prototype.next=function(){this.__values__===P&&(this.__values__=lu(this.value()));var t=this.__index__>=this.__values__.length,n=t?P:this.__values__[this.__index__++];return{done:t,value:n}},It.prototype.plant=function(t){ +for(var n,r=this;r instanceof Rt;){var e=Oe(r);e.__index__=0,e.__values__=P,n?u.__wrapped__=e:n=e;var u=e,r=r.__wrapped__}return u.__wrapped__=t,n},It.prototype.reverse=function(){var t=this.__wrapped__;return t instanceof $t?(this.__actions__.length&&(t=new $t(this)),t=t.reverse(),t.__actions__.push({func:ze,args:[Le],thisArg:P}),new Lt(t,this.__chain__)):this.thru(Le)},It.prototype.toJSON=It.prototype.valueOf=It.prototype.value=function(){return xr(this.__wrapped__,this.__actions__)},It.prototype.first=It.prototype.head, +uo&&(It.prototype[uo]=De),It}var P,Z=1/0,q=NaN,V=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],K=/\b__p\+='';/g,G=/\b(__p\+=)''\+/g,J=/(__e\(.*?\)|\b__t\))\+'';/g,Y=/&(?:amp|lt|gt|quot|#39|#96);/g,H=/[&<>"'`]/g,Q=RegExp(Y.source),X=RegExp(H.source),tt=/<%-([\s\S]+?)%>/g,nt=/<%([\s\S]+?)%>/g,rt=/<%=([\s\S]+?)%>/g,et=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,ut=/^\w*$/,ot=/^\./,it=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,ft=/[\\^$.*+?()[\]{}|]/g,ct=RegExp(ft.source),at=/^\s+|\s+$/g,lt=/^\s+/,st=/\s+$/,ht=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,pt=/\{\n\/\* \[wrapped with (.+)\] \*/,_t=/,? & /,vt=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,gt=/\\(\\)?/g,dt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,yt=/\w*$/,bt=/^0x/i,xt=/^[-+]0x[0-9a-f]+$/i,jt=/^0b[01]+$/i,wt=/^\[object .+?Constructor\]$/,mt=/^0o[0-7]+$/i,At=/^(?:0|[1-9]\d*)$/,kt=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Et=/($^)/,Ot=/['\n\r\u2028\u2029\\]/g,St="[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?(?:\\u200d(?:[^\\ud800-\\udfff]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|\\ud83c[\\udffb-\\udfff])?)*",It="(?:[\\u2700-\\u27bf]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff])"+St,Rt="(?:[^\\ud800-\\udfff][\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]?|[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|(?:\\ud83c[\\udde6-\\uddff]){2}|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff])",Wt=RegExp("['\u2019]","g"),Bt=RegExp("[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]","g"),Lt=RegExp("\\ud83c[\\udffb-\\udfff](?=\\ud83c[\\udffb-\\udfff])|"+Rt+St,"g"),Ct=RegExp(["[A-Z\\xc0-\\xd6\\xd8-\\xde]?[a-z\\xdf-\\xf6\\xf8-\\xff]+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde]|$)|(?:[A-Z\\xc0-\\xd6\\xd8-\\xde]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?=[\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000]|[A-Z\\xc0-\\xd6\\xd8-\\xde](?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])|$)|[A-Z\\xc0-\\xd6\\xd8-\\xde]?(?:[a-z\\xdf-\\xf6\\xf8-\\xff]|[^\\ud800-\\udfff\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000\\d+\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde])+(?:['\u2019](?:d|ll|m|re|s|t|ve))?|[A-Z\\xc0-\\xd6\\xd8-\\xde]+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?|\\d+",It].join("|"),"g"),Ut=RegExp("[\\u200d\\ud800-\\udfff\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0\\ufe0e\\ufe0f]"),Mt=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,zt="Array Buffer DataView Date Error Float32Array Float64Array Function Int8Array Int16Array Int32Array Map Math Object Promise RegExp Set String Symbol TypeError Uint8Array Uint8ClampedArray Uint16Array Uint32Array WeakMap _ clearTimeout isFinite parseInt setTimeout".split(" "),Dt={}; Dt["[object Float32Array]"]=Dt["[object Float64Array]"]=Dt["[object Int8Array]"]=Dt["[object Int16Array]"]=Dt["[object Int32Array]"]=Dt["[object Uint8Array]"]=Dt["[object Uint8ClampedArray]"]=Dt["[object Uint16Array]"]=Dt["[object Uint32Array]"]=true,Dt["[object Arguments]"]=Dt["[object Array]"]=Dt["[object ArrayBuffer]"]=Dt["[object Boolean]"]=Dt["[object DataView]"]=Dt["[object Date]"]=Dt["[object Error]"]=Dt["[object Function]"]=Dt["[object Map]"]=Dt["[object Number]"]=Dt["[object Object]"]=Dt["[object RegExp]"]=Dt["[object Set]"]=Dt["[object String]"]=Dt["[object WeakMap]"]=false; -var $t={};$t["[object Arguments]"]=$t["[object Array]"]=$t["[object ArrayBuffer]"]=$t["[object DataView]"]=$t["[object Boolean]"]=$t["[object Date]"]=$t["[object Float32Array]"]=$t["[object Float64Array]"]=$t["[object Int8Array]"]=$t["[object Int16Array]"]=$t["[object Int32Array]"]=$t["[object Map]"]=$t["[object Number]"]=$t["[object Object]"]=$t["[object RegExp]"]=$t["[object Set]"]=$t["[object String]"]=$t["[object Symbol]"]=$t["[object Uint8Array]"]=$t["[object Uint8ClampedArray]"]=$t["[object Uint16Array]"]=$t["[object Uint32Array]"]=true, -$t["[object Error]"]=$t["[object Function]"]=$t["[object WeakMap]"]=false;var Ft,Tt={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Nt=parseFloat,Pt=parseInt,Zt=typeof global=="object"&&global&&global.Object===Object&&global,qt=typeof self=="object"&&self&&self.Object===Object&&self,Vt=Zt||qt||Function("return this")(),Kt=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Gt=Kt&&typeof module=="object"&&module&&!module.nodeType&&module,Jt=Gt&&Gt.exports===Kt,Yt=Jt&&Zt.h; -t:{try{Ft=Yt&&Yt.f("util");break t}catch(t){}Ft=void 0}var Ht=Ft&&Ft.isArrayBuffer,Qt=Ft&&Ft.isDate,Xt=Ft&&Ft.isMap,tn=Ft&&Ft.isRegExp,nn=Ft&&Ft.isSet,rn=Ft&&Ft.isTypedArray,en=w({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i", -"\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss"}),un=w({"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"}),on=w({"&":"&","<":"<",">":">",""":'"',"'":"'", -"`":"`"}),fn=N();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Vt._=fn, define(function(){return fn})):Gt?((Gt.exports=fn)._=fn,Kt._=fn):Vt._=fn}).call(this);
\ No newline at end of file +var Tt={};Tt["[object Arguments]"]=Tt["[object Array]"]=Tt["[object ArrayBuffer]"]=Tt["[object DataView]"]=Tt["[object Boolean]"]=Tt["[object Date]"]=Tt["[object Float32Array]"]=Tt["[object Float64Array]"]=Tt["[object Int8Array]"]=Tt["[object Int16Array]"]=Tt["[object Int32Array]"]=Tt["[object Map]"]=Tt["[object Number]"]=Tt["[object Object]"]=Tt["[object RegExp]"]=Tt["[object Set]"]=Tt["[object String]"]=Tt["[object Symbol]"]=Tt["[object Uint8Array]"]=Tt["[object Uint8ClampedArray]"]=Tt["[object Uint16Array]"]=Tt["[object Uint32Array]"]=true, +Tt["[object Error]"]=Tt["[object Function]"]=Tt["[object WeakMap]"]=false;var $t,Ft={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Nt=parseFloat,Pt=parseInt,Zt=typeof global=="object"&&global&&global.Object===Object&&global,qt=typeof self=="object"&&self&&self.Object===Object&&self,Vt=Zt||qt||Function("return this")(),Kt=typeof exports=="object"&&exports&&!exports.nodeType&&exports,Gt=Kt&&typeof module=="object"&&module&&!module.nodeType&&module,Jt=Gt&&Gt.exports===Kt,Yt=Jt&&Zt.g; +t:{try{$t=Yt&&Yt.f("util");break t}catch(t){}$t=void 0}var Ht=$t&&$t.isArrayBuffer,Qt=$t&&$t.isDate,Xt=$t&&$t.isMap,tn=$t&&$t.isRegExp,nn=$t&&$t.isSet,rn=$t&&$t.isTypedArray,en=j("length"),un=w({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I", +"\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C", +"\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i", +"\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S", +"\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n", +"\u017f":"ss"}),on=w({"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"}),fn=w({"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"}),cn=N();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(Vt._=cn, define(function(){return cn})):Gt?((Gt.exports=cn)._=cn,Kt._=cn):Vt._=cn}).call(this);
\ No newline at end of file diff --git a/tools/eslint/node_modules/lodash/matches.js b/tools/eslint/node_modules/lodash/matches.js index 834d4729b2..d34e98e9bb 100644 --- a/tools/eslint/node_modules/lodash/matches.js +++ b/tools/eslint/node_modules/lodash/matches.js @@ -6,8 +6,12 @@ var baseClone = require('./_baseClone'), * object and `source`, returning `true` if the given object has equivalent * property values, else `false`. * - * **Note:** The created function supports comparing the same values as - * `_.isEqual` is equivalent to `_.isMatch` with `source` partially applied. + * **Note:** The created function is equivalent to `_.isMatch` with `source` + * partially applied. + * + * Partial comparisons will match empty array and empty object `source` + * values against any array or object value, respectively. See `_.isEqual` + * for a list of supported value comparisons. * * @static * @memberOf _ diff --git a/tools/eslint/node_modules/lodash/matchesProperty.js b/tools/eslint/node_modules/lodash/matchesProperty.js index 4496442cb2..ff8f2dffcd 100644 --- a/tools/eslint/node_modules/lodash/matchesProperty.js +++ b/tools/eslint/node_modules/lodash/matchesProperty.js @@ -6,7 +6,9 @@ var baseClone = require('./_baseClone'), * value at `path` of a given object to `srcValue`, returning `true` if the * object value is equivalent, else `false`. * - * **Note:** This method supports comparing the same values as `_.isEqual`. + * **Note:** Partial comparisons will match empty array and empty object + * `srcValue` values against any array or object value, respectively. See + * `_.isEqual` for a list of supported value comparisons. * * @static * @memberOf _ diff --git a/tools/eslint/node_modules/lodash/memoize.js b/tools/eslint/node_modules/lodash/memoize.js index 54e461400f..97aa182852 100644 --- a/tools/eslint/node_modules/lodash/memoize.js +++ b/tools/eslint/node_modules/lodash/memoize.js @@ -13,7 +13,7 @@ var FUNC_ERROR_TEXT = 'Expected a function'; * **Note:** The cache is exposed as the `cache` property on the memoized * function. Its creation may be customized by replacing the `_.memoize.Cache` * constructor with one whose instances implement the - * [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object) + * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) * method interface of `delete`, `get`, `has`, and `set`. * * @static diff --git a/tools/eslint/node_modules/lodash/now.js b/tools/eslint/node_modules/lodash/now.js index 5ad305033b..44a05623f2 100644 --- a/tools/eslint/node_modules/lodash/now.js +++ b/tools/eslint/node_modules/lodash/now.js @@ -1,3 +1,5 @@ +var root = require('./_root'); + /** * Gets the timestamp of the number of milliseconds that have elapsed since * the Unix epoch (1 January 1970 00:00:00 UTC). @@ -14,8 +16,8 @@ * }, _.now()); * // => Logs the number of milliseconds it took for the deferred invocation. */ -function now() { - return Date.now(); -} +var now = function() { + return root.Date.now(); +}; module.exports = now; diff --git a/tools/eslint/node_modules/lodash/package.json b/tools/eslint/node_modules/lodash/package.json index cd7116e4c7..589764db20 100644 --- a/tools/eslint/node_modules/lodash/package.json +++ b/tools/eslint/node_modules/lodash/package.json @@ -14,20 +14,20 @@ ] ], "_from": "lodash@>=4.0.0 <5.0.0", - "_id": "lodash@4.14.1", + "_id": "lodash@4.15.0", "_inCache": true, "_installable": true, "_location": "/lodash", - "_nodeVersion": "4.2.4", + "_nodeVersion": "4.4.7", "_npmOperationalInternal": { "host": "packages-16-east.internal.npmjs.com", - "tmp": "tmp/lodash-4.14.1.tgz_1469803745646_0.5584656686987728" + "tmp": "tmp/lodash-4.15.0.tgz_1471012765624_0.7570270872674882" }, "_npmUser": { "name": "jdalton", "email": "john.david.dalton@gmail.com" }, - "_npmVersion": "2.15.9", + "_npmVersion": "2.15.10", "_phantomChildren": {}, "_requested": { "raw": "lodash@^4.0.0", @@ -43,8 +43,8 @@ "/inquirer", "/table" ], - "_resolved": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz", - "_shasum": "5b5d0a516ad3d46e12012d7f59ad66a5659bf408", + "_resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "_shasum": "3162391d8f0140aa22cf8f6b3c34d6b7f63d3aa9", "_shrinkwrap": null, "_spec": "lodash@^4.0.0", "_where": "/Users/trott/io.js/tools/node_modules/eslint", @@ -78,8 +78,8 @@ "devDependencies": {}, "directories": {}, "dist": { - "shasum": "5b5d0a516ad3d46e12012d7f59ad66a5659bf408", - "tarball": "https://registry.npmjs.org/lodash/-/lodash-4.14.1.tgz" + "shasum": "3162391d8f0140aa22cf8f6b3c34d6b7f63d3aa9", + "tarball": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz" }, "homepage": "https://lodash.com/", "icon": "https://lodash.com/icon.svg", @@ -114,5 +114,5 @@ "scripts": { "test": "echo \"See https://travis-ci.org/lodash/lodash-cli for testing details.\"" }, - "version": "4.14.1" + "version": "4.15.0" } diff --git a/tools/eslint/node_modules/lodash/pull.js b/tools/eslint/node_modules/lodash/pull.js index c136c06e84..a2efcb5e10 100644 --- a/tools/eslint/node_modules/lodash/pull.js +++ b/tools/eslint/node_modules/lodash/pull.js @@ -3,7 +3,7 @@ var baseRest = require('./_baseRest'), /** * Removes all given values from `array` using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` diff --git a/tools/eslint/node_modules/lodash/replace.js b/tools/eslint/node_modules/lodash/replace.js index 1d113e70a9..6e26ecd827 100644 --- a/tools/eslint/node_modules/lodash/replace.js +++ b/tools/eslint/node_modules/lodash/replace.js @@ -1,11 +1,5 @@ var toString = require('./toString'); -/** Used for built-in method references. */ -var stringProto = String.prototype; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeReplace = stringProto.replace; - /** * Replaces matches for `pattern` in `string` with `replacement`. * @@ -29,7 +23,7 @@ function replace() { var args = arguments, string = toString(args[0]); - return args.length < 3 ? string : nativeReplace.call(string, args[1], args[2]); + return args.length < 3 ? string : string.replace(args[1], args[2]); } module.exports = replace; diff --git a/tools/eslint/node_modules/lodash/size.js b/tools/eslint/node_modules/lodash/size.js index 2e414ab47e..3561fc1010 100644 --- a/tools/eslint/node_modules/lodash/size.js +++ b/tools/eslint/node_modules/lodash/size.js @@ -1,8 +1,7 @@ -var getTag = require('./_getTag'), +var baseKeys = require('./_baseKeys'), + getTag = require('./_getTag'), isArrayLike = require('./isArrayLike'), - isObjectLike = require('./isObjectLike'), isString = require('./isString'), - keys = require('./keys'), stringSize = require('./_stringSize'); /** `Object#toString` result references. */ @@ -17,7 +16,7 @@ var mapTag = '[object Map]', * @memberOf _ * @since 0.1.0 * @category Collection - * @param {Array|Object} collection The collection to inspect. + * @param {Array|Object|string} collection The collection to inspect. * @returns {number} Returns the collection size. * @example * @@ -35,16 +34,13 @@ function size(collection) { return 0; } if (isArrayLike(collection)) { - var result = collection.length; - return (result && isString(collection)) ? stringSize(collection) : result; + return isString(collection) ? stringSize(collection) : collection.length; } - if (isObjectLike(collection)) { - var tag = getTag(collection); - if (tag == mapTag || tag == setTag) { - return collection.size; - } + var tag = getTag(collection); + if (tag == mapTag || tag == setTag) { + return collection.size; } - return keys(collection).length; + return baseKeys(collection).length; } module.exports = size; diff --git a/tools/eslint/node_modules/lodash/sortedIndexOf.js b/tools/eslint/node_modules/lodash/sortedIndexOf.js index 72d65d8aab..731c59f4b7 100644 --- a/tools/eslint/node_modules/lodash/sortedIndexOf.js +++ b/tools/eslint/node_modules/lodash/sortedIndexOf.js @@ -9,7 +9,7 @@ var baseSortedIndex = require('./_baseSortedIndex'), * @memberOf _ * @since 4.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example diff --git a/tools/eslint/node_modules/lodash/sortedLastIndexOf.js b/tools/eslint/node_modules/lodash/sortedLastIndexOf.js index 5ff351d688..3635a7f984 100644 --- a/tools/eslint/node_modules/lodash/sortedLastIndexOf.js +++ b/tools/eslint/node_modules/lodash/sortedLastIndexOf.js @@ -9,7 +9,7 @@ var baseSortedIndex = require('./_baseSortedIndex'), * @memberOf _ * @since 4.0.0 * @category Array - * @param {Array} array The array to search. + * @param {Array} array The array to inspect. * @param {*} value The value to search for. * @returns {number} Returns the index of the matched value, else `-1`. * @example diff --git a/tools/eslint/node_modules/lodash/split.js b/tools/eslint/node_modules/lodash/split.js index a789e01de2..956b48a15a 100644 --- a/tools/eslint/node_modules/lodash/split.js +++ b/tools/eslint/node_modules/lodash/split.js @@ -1,20 +1,14 @@ var baseToString = require('./_baseToString'), castSlice = require('./_castSlice'), + hasUnicode = require('./_hasUnicode'), isIterateeCall = require('./_isIterateeCall'), isRegExp = require('./isRegExp'), - reHasComplexSymbol = require('./_reHasComplexSymbol'), stringToArray = require('./_stringToArray'), toString = require('./toString'); /** Used as references for the maximum length and index of an array. */ var MAX_ARRAY_LENGTH = 4294967295; -/** Used for built-in method references. */ -var stringProto = String.prototype; - -/* Built-in method references for those with the same name as other `lodash` methods. */ -var nativeSplit = stringProto.split; - /** * Splits `string` by `separator`. * @@ -48,11 +42,11 @@ function split(string, separator, limit) { (separator != null && !isRegExp(separator)) )) { separator = baseToString(separator); - if (separator == '' && reHasComplexSymbol.test(string)) { + if (!separator && hasUnicode(string)) { return castSlice(stringToArray(string), 0, limit); } } - return nativeSplit.call(string, separator, limit); + return string.split(separator, limit); } module.exports = split; diff --git a/tools/eslint/node_modules/lodash/spread.js b/tools/eslint/node_modules/lodash/spread.js index c537dfa9bc..9b70db6cc3 100644 --- a/tools/eslint/node_modules/lodash/spread.js +++ b/tools/eslint/node_modules/lodash/spread.js @@ -13,7 +13,7 @@ var nativeMax = Math.max; /** * Creates a function that invokes `func` with the `this` binding of the * create function and an array of arguments much like - * [`Function#apply`](http://www.ecma-international.org/ecma-262/6.0/#sec-function.prototype.apply). + * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). * * **Note:** This method is based on the * [spread operator](https://mdn.io/spread_operator). diff --git a/tools/eslint/node_modules/lodash/startsWith.js b/tools/eslint/node_modules/lodash/startsWith.js index 04509f05dc..359e5ad78f 100644 --- a/tools/eslint/node_modules/lodash/startsWith.js +++ b/tools/eslint/node_modules/lodash/startsWith.js @@ -10,7 +10,7 @@ var baseClamp = require('./_baseClamp'), * @memberOf _ * @since 3.0.0 * @category String - * @param {string} [string=''] The string to search. + * @param {string} [string=''] The string to inspect. * @param {string} [target] The string to search for. * @param {number} [position=0] The position to search from. * @returns {boolean} Returns `true` if `string` starts with `target`, diff --git a/tools/eslint/node_modules/lodash/tail.js b/tools/eslint/node_modules/lodash/tail.js index 459a8a3793..9964be528a 100644 --- a/tools/eslint/node_modules/lodash/tail.js +++ b/tools/eslint/node_modules/lodash/tail.js @@ -1,4 +1,4 @@ -var drop = require('./drop'); +var baseSlice = require('./_baseSlice'); /** * Gets all but the first element of `array`. @@ -15,7 +15,8 @@ var drop = require('./drop'); * // => [2, 3] */ function tail(array) { - return drop(array, 1); + var length = array ? array.length : 0; + return length ? baseSlice(array, 1, length) : []; } module.exports = tail; diff --git a/tools/eslint/node_modules/lodash/template.js b/tools/eslint/node_modules/lodash/template.js index 03d20e591a..c1a523c575 100644 --- a/tools/eslint/node_modules/lodash/template.js +++ b/tools/eslint/node_modules/lodash/template.js @@ -17,7 +17,7 @@ var reEmptyStringLeading = /\b__p \+= '';/g, /** * Used to match - * [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). + * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). */ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; diff --git a/tools/eslint/node_modules/lodash/toInteger.js b/tools/eslint/node_modules/lodash/toInteger.js index 49fd28dc71..c6aadf8f94 100644 --- a/tools/eslint/node_modules/lodash/toInteger.js +++ b/tools/eslint/node_modules/lodash/toInteger.js @@ -4,7 +4,7 @@ var toFinite = require('./toFinite'); * Converts `value` to an integer. * * **Note:** This method is loosely based on - * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger). + * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). * * @static * @memberOf _ diff --git a/tools/eslint/node_modules/lodash/toLength.js b/tools/eslint/node_modules/lodash/toLength.js index 9aac9f6d5f..be8f2a7446 100644 --- a/tools/eslint/node_modules/lodash/toLength.js +++ b/tools/eslint/node_modules/lodash/toLength.js @@ -9,7 +9,7 @@ var MAX_ARRAY_LENGTH = 4294967295; * array-like object. * * **Note:** This method is based on - * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength). + * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). * * @static * @memberOf _ diff --git a/tools/eslint/node_modules/lodash/toNumber.js b/tools/eslint/node_modules/lodash/toNumber.js index d95821170b..b0f72de302 100644 --- a/tools/eslint/node_modules/lodash/toNumber.js +++ b/tools/eslint/node_modules/lodash/toNumber.js @@ -1,5 +1,4 @@ -var isFunction = require('./isFunction'), - isObject = require('./isObject'), +var isObject = require('./isObject'), isSymbol = require('./isSymbol'); /** Used as references for various `Number` constants. */ @@ -51,7 +50,7 @@ function toNumber(value) { return NAN; } if (isObject(value)) { - var other = isFunction(value.valueOf) ? value.valueOf() : value; + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; } if (typeof value != 'string') { diff --git a/tools/eslint/node_modules/lodash/truncate.js b/tools/eslint/node_modules/lodash/truncate.js index 4290315483..21fcdfef6e 100644 --- a/tools/eslint/node_modules/lodash/truncate.js +++ b/tools/eslint/node_modules/lodash/truncate.js @@ -1,8 +1,8 @@ var baseToString = require('./_baseToString'), castSlice = require('./_castSlice'), + hasUnicode = require('./_hasUnicode'), isObject = require('./isObject'), isRegExp = require('./isRegExp'), - reHasComplexSymbol = require('./_reHasComplexSymbol'), stringSize = require('./_stringSize'), stringToArray = require('./_stringToArray'), toInteger = require('./toInteger'), @@ -64,7 +64,7 @@ function truncate(string, options) { string = toString(string); var strLength = string.length; - if (reHasComplexSymbol.test(string)) { + if (hasUnicode(string)) { var strSymbols = stringToArray(string); strLength = strSymbols.length; } diff --git a/tools/eslint/node_modules/lodash/union.js b/tools/eslint/node_modules/lodash/union.js index d448d8be20..e676dfe493 100644 --- a/tools/eslint/node_modules/lodash/union.js +++ b/tools/eslint/node_modules/lodash/union.js @@ -5,7 +5,7 @@ var baseFlatten = require('./_baseFlatten'), /** * Creates an array of unique values, in order, from all given arrays using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * @static diff --git a/tools/eslint/node_modules/lodash/uniq.js b/tools/eslint/node_modules/lodash/uniq.js index 0e99ee932b..52e5d512ad 100644 --- a/tools/eslint/node_modules/lodash/uniq.js +++ b/tools/eslint/node_modules/lodash/uniq.js @@ -2,7 +2,7 @@ var baseUniq = require('./_baseUniq'); /** * Creates a duplicate-free version of an array, using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons, in which only the first occurrence of each * element is kept. * diff --git a/tools/eslint/node_modules/lodash/without.js b/tools/eslint/node_modules/lodash/without.js index 13cc11fc0f..3a28e8ae4c 100644 --- a/tools/eslint/node_modules/lodash/without.js +++ b/tools/eslint/node_modules/lodash/without.js @@ -4,7 +4,7 @@ var baseDifference = require('./_baseDifference'), /** * Creates an array excluding all given values using - * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero) + * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) * for equality comparisons. * * **Note:** Unlike `_.pull`, this method returns a new array. diff --git a/tools/eslint/node_modules/lodash/words.js b/tools/eslint/node_modules/lodash/words.js index 786d14d039..6d7cdd1857 100644 --- a/tools/eslint/node_modules/lodash/words.js +++ b/tools/eslint/node_modules/lodash/words.js @@ -1,61 +1,7 @@ -var toString = require('./toString'); - -/** Used to match non-compound words composed of alphanumeric characters. */ -var reBasicWord = /[a-zA-Z0-9]+/g; - -/** Used to compose unicode character classes. */ -var rsAstralRange = '\\ud800-\\udfff', - rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23', - rsComboSymbolsRange = '\\u20d0-\\u20f0', - rsDingbatRange = '\\u2700-\\u27bf', - rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', - rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', - rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', - rsPunctuationRange = '\\u2000-\\u206f', - rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', - rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', - rsVarRange = '\\ufe0e\\ufe0f', - rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; - -/** Used to compose unicode capture groups. */ -var rsApos = "['\u2019]", - rsBreak = '[' + rsBreakRange + ']', - rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']', - rsDigits = '\\d+', - rsDingbat = '[' + rsDingbatRange + ']', - rsLower = '[' + rsLowerRange + ']', - rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', - rsFitz = '\\ud83c[\\udffb-\\udfff]', - rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', - rsNonAstral = '[^' + rsAstralRange + ']', - rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', - rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', - rsUpper = '[' + rsUpperRange + ']', - rsZWJ = '\\u200d'; - -/** Used to compose unicode regexes. */ -var rsLowerMisc = '(?:' + rsLower + '|' + rsMisc + ')', - rsUpperMisc = '(?:' + rsUpper + '|' + rsMisc + ')', - rsOptLowerContr = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', - rsOptUpperContr = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', - reOptMod = rsModifier + '?', - rsOptVar = '[' + rsVarRange + ']?', - rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', - rsSeq = rsOptVar + reOptMod + rsOptJoin, - rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq; - -/** Used to match complex or compound words. */ -var reComplexWord = RegExp([ - rsUpper + '?' + rsLower + '+' + rsOptLowerContr + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', - rsUpperMisc + '+' + rsOptUpperContr + '(?=' + [rsBreak, rsUpper + rsLowerMisc, '$'].join('|') + ')', - rsUpper + '?' + rsLowerMisc + '+' + rsOptLowerContr, - rsUpper + '+' + rsOptUpperContr, - rsDigits, - rsEmoji -].join('|'), 'g'); - -/** Used to detect strings that need a more robust regexp to match words. */ -var reHasComplexWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; +var asciiWords = require('./_asciiWords'), + hasUnicodeWord = require('./_hasUnicodeWord'), + toString = require('./toString'), + unicodeWords = require('./_unicodeWords'); /** * Splits `string` into an array of its words. @@ -81,7 +27,7 @@ function words(string, pattern, guard) { pattern = guard ? undefined : pattern; if (pattern === undefined) { - pattern = reHasComplexWord.test(string) ? reComplexWord : reBasicWord; + return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); } return string.match(pattern) || []; } diff --git a/tools/eslint/node_modules/minimatch/minimatch.js b/tools/eslint/node_modules/minimatch/minimatch.js index 830a27246c..5b5f8cf444 100644 --- a/tools/eslint/node_modules/minimatch/minimatch.js +++ b/tools/eslint/node_modules/minimatch/minimatch.js @@ -9,6 +9,14 @@ try { var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} var expand = require('brace-expansion') +var plTypes = { + '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, + '?': { open: '(?:', close: ')?' }, + '+': { open: '(?:', close: ')+' }, + '*': { open: '(?:', close: ')*' }, + '@': { open: '(?:', close: ')' } +} + // any single thing other than / // don't need to escape / when using new RegExp() var qmark = '[^/]' @@ -277,7 +285,6 @@ function parse (pattern, isSub) { // ? => one single character var patternListStack = [] var negativeLists = [] - var plType var stateChar var inClass = false var reClassStart = -1 @@ -376,11 +383,12 @@ function parse (pattern, isSub) { continue } - plType = stateChar patternListStack.push({ - type: plType, + type: stateChar, start: i - 1, - reStart: re.length + reStart: re.length, + open: plTypes[stateChar].open, + close: plTypes[stateChar].close }) // negation is (?:(?!js)[^/]*) re += stateChar === '!' ? '(?:(?!(?:' : '(?:' @@ -396,24 +404,14 @@ function parse (pattern, isSub) { clearStateChar() hasMagic = true - re += ')' var pl = patternListStack.pop() - plType = pl.type // negation is (?:(?!js)[^/]*) // The others are (?:<pattern>)<type> - switch (plType) { - case '!': - negativeLists.push(pl) - re += ')[^/]*?)' - pl.reEnd = re.length - break - case '?': - case '+': - case '*': - re += plType - break - case '@': break // the default anyway + re += pl.close + if (pl.type === '!') { + negativeLists.push(pl) } + pl.reEnd = re.length continue case '|': @@ -520,7 +518,8 @@ function parse (pattern, isSub) { // Go through and escape them, taking care not to double-escape any // | chars that were already escaped. for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { - var tail = re.slice(pl.reStart + 3) + var tail = re.slice(pl.reStart + pl.open.length) + this.debug('setting tail', re, pl) // maybe some even number of \, then maybe 1 \, followed by a | tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { if (!$2) { @@ -537,7 +536,7 @@ function parse (pattern, isSub) { return $1 + $1 + $2 + '|' }) - this.debug('tail=%j\n %s', tail, tail) + this.debug('tail=%j\n %s', tail, tail, pl, re) var t = pl.type === '*' ? star : pl.type === '?' ? qmark : '\\' + pl.type diff --git a/tools/eslint/node_modules/minimatch/package.json b/tools/eslint/node_modules/minimatch/package.json index dc28942686..1b832f6ff8 100644 --- a/tools/eslint/node_modules/minimatch/package.json +++ b/tools/eslint/node_modules/minimatch/package.json @@ -14,20 +14,20 @@ ] ], "_from": "minimatch@>=3.0.2 <4.0.0", - "_id": "minimatch@3.0.2", + "_id": "minimatch@3.0.3", "_inCache": true, "_installable": true, "_location": "/minimatch", "_nodeVersion": "4.4.4", "_npmOperationalInternal": { - "host": "packages-16-east.internal.npmjs.com", - "tmp": "tmp/minimatch-3.0.2.tgz_1466194379770_0.11417287751100957" + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/minimatch-3.0.3.tgz_1470678322731_0.1892083385027945" }, "_npmUser": { "name": "isaacs", "email": "i@izs.me" }, - "_npmVersion": "3.9.1", + "_npmVersion": "3.10.6", "_phantomChildren": {}, "_requested": { "raw": "minimatch@^3.0.2", @@ -41,8 +41,8 @@ "_requiredBy": [ "/glob" ], - "_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz", - "_shasum": "0f398a7300ea441e9c348c83d98ab8c9dbf9c40a", + "_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "_shasum": "2a4e4090b96b2db06a9d7df01055a62a77c9b774", "_shrinkwrap": null, "_spec": "minimatch@^3.0.2", "_where": "/Users/trott/io.js/tools/node_modules/glob", @@ -64,8 +64,8 @@ }, "directories": {}, "dist": { - "shasum": "0f398a7300ea441e9c348c83d98ab8c9dbf9c40a", - "tarball": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.2.tgz" + "shasum": "2a4e4090b96b2db06a9d7df01055a62a77c9b774", + "tarball": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz" }, "engines": { "node": "*" @@ -73,7 +73,7 @@ "files": [ "minimatch.js" ], - "gitHead": "81edb7c763abd31ba981c87ec5e835f178786be0", + "gitHead": "eed89491bd4a4e6bc463aac0dfb5c29ef0d1dc13", "homepage": "https://github.com/isaacs/minimatch#readme", "license": "ISC", "main": "minimatch.js", @@ -94,5 +94,5 @@ "posttest": "standard minimatch.js test/*.js", "test": "tap test/*.js" }, - "version": "3.0.2" + "version": "3.0.3" } diff --git a/tools/eslint/node_modules/natural-compare/README.md b/tools/eslint/node_modules/natural-compare/README.md new file mode 100644 index 0000000000..c85dfdf98c --- /dev/null +++ b/tools/eslint/node_modules/natural-compare/README.md @@ -0,0 +1,125 @@ + +[Build]: http://img.shields.io/travis/litejs/natural-compare-lite.png +[Coverage]: http://img.shields.io/coveralls/litejs/natural-compare-lite.png +[1]: https://travis-ci.org/litejs/natural-compare-lite +[2]: https://coveralls.io/r/litejs/natural-compare-lite +[npm package]: https://npmjs.org/package/natural-compare-lite +[GitHub repo]: https://github.com/litejs/natural-compare-lite + + + + @version 1.4.0 + @date 2015-10-26 + @stability 3 - Stable + + +Natural Compare – [![Build][]][1] [![Coverage][]][2] +=============== + +Compare strings containing a mix of letters and numbers +in the way a human being would in sort order. +This is described as a "natural ordering". + +```text +Standard sorting: Natural order sorting: + img1.png img1.png + img10.png img2.png + img12.png img10.png + img2.png img12.png +``` + +String.naturalCompare returns a number indicating +whether a reference string comes before or after or is the same +as the given string in sort order. +Use it with builtin sort() function. + + + +### Installation + +- In browser + +```html +<script src=min.natural-compare.js></script> +``` + +- In node.js: `npm install natural-compare-lite` + +```javascript +require("natural-compare-lite") +``` + +### Usage + +```javascript +// Simple case sensitive example +var a = ["z1.doc", "z10.doc", "z17.doc", "z2.doc", "z23.doc", "z3.doc"]; +a.sort(String.naturalCompare); +// ["z1.doc", "z2.doc", "z3.doc", "z10.doc", "z17.doc", "z23.doc"] + +// Use wrapper function for case insensitivity +a.sort(function(a, b){ + return String.naturalCompare(a.toLowerCase(), b.toLowerCase()); +}) + +// In most cases we want to sort an array of objects +var a = [ {"street":"350 5th Ave", "room":"A-1021"} + , {"street":"350 5th Ave", "room":"A-21046-b"} ]; + +// sort by street, then by room +a.sort(function(a, b){ + return String.naturalCompare(a.street, b.street) || String.naturalCompare(a.room, b.room); +}) + +// When text transformation is needed (eg toLowerCase()), +// it is best for performance to keep +// transformed key in that object. +// There are no need to do text transformation +// on each comparision when sorting. +var a = [ {"make":"Audi", "model":"A6"} + , {"make":"Kia", "model":"Rio"} ]; + +// sort by make, then by model +a.map(function(car){ + car.sort_key = (car.make + " " + car.model).toLowerCase(); +}) +a.sort(function(a, b){ + return String.naturalCompare(a.sort_key, b.sort_key); +}) +``` + +- Works well with dates in ISO format eg "Rev 2012-07-26.doc". + + +### Custom alphabet + +It is possible to configure a custom alphabet +to achieve a desired order. + +```javascript +// Estonian alphabet +String.alphabet = "ABDEFGHIJKLMNOPRSÅ ZŽTUVĆĆĆĆXYabdefghijklmnoprsÅ”zžtuvĆµĆ¤Ć¶Ć¼xy" +["t", "z", "x", "Ƶ"].sort(String.naturalCompare) +// ["z", "t", "Ƶ", "x"] + +// Russian alphabet +String.alphabet = "ŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠŠ Š”Š¢Š£Š¤Š„Š¦Š§ŠØŠ©ŠŖŠ«Š¬ŠŠ®ŠÆŠ°Š±Š²Š³Š“ŠµŃŠ¶Š·ŠøŠ¹ŠŗŠ»Š¼Š½Š¾ŠæŃŃŃŃŃŃ
ŃŃŃŃŃŃŃŃŃŃ" +["Š", "Š", "Š"].sort(String.naturalCompare) +// ["Š", "Š", "Š"] +``` + + +External links +-------------- + +- [GitHub repo][https://github.com/litejs/natural-compare-lite] +- [jsperf test](http://jsperf.com/natural-sort-2/12) + + +Licence +------- + +Copyright (c) 2012-2015 Lauri Rooden <lauri@rooden.ee> +[The MIT License](http://lauri.rooden.ee/mit-license.txt) + + diff --git a/tools/eslint/node_modules/natural-compare/index.js b/tools/eslint/node_modules/natural-compare/index.js new file mode 100644 index 0000000000..e705d49f5f --- /dev/null +++ b/tools/eslint/node_modules/natural-compare/index.js @@ -0,0 +1,57 @@ + + + +/* + * @version 1.4.0 + * @date 2015-10-26 + * @stability 3 - Stable + * @author Lauri Rooden (https://github.com/litejs/natural-compare-lite) + * @license MIT License + */ + + +var naturalCompare = function(a, b) { + var i, codeA + , codeB = 1 + , posA = 0 + , posB = 0 + , alphabet = String.alphabet + + function getCode(str, pos, code) { + if (code) { + for (i = pos; code = getCode(str, i), code < 76 && code > 65;) ++i; + return +str.slice(pos - 1, i) + } + code = alphabet && alphabet.indexOf(str.charAt(pos)) + return code > -1 ? code + 76 : ((code = str.charCodeAt(pos) || 0), code < 45 || code > 127) ? code + : code < 46 ? 65 // - + : code < 48 ? code - 1 + : code < 58 ? code + 18 // 0-9 + : code < 65 ? code - 11 + : code < 91 ? code + 11 // A-Z + : code < 97 ? code - 37 + : code < 123 ? code + 5 // a-z + : code - 63 + } + + + if ((a+="") != (b+="")) for (;codeB;) { + codeA = getCode(a, posA++) + codeB = getCode(b, posB++) + + if (codeA < 76 && codeB < 76 && codeA > 66 && codeB > 66) { + codeA = getCode(a, posA, posA) + codeB = getCode(b, posB, posA = i) + posB = i + } + + if (codeA != codeB) return (codeA < codeB) ? -1 : 1 + } + return 0 +} + +try { + module.exports = naturalCompare; +} catch (e) { + String.naturalCompare = naturalCompare; +} diff --git a/tools/eslint/node_modules/natural-compare/package.json b/tools/eslint/node_modules/natural-compare/package.json new file mode 100644 index 0000000000..0057d2d5b5 --- /dev/null +++ b/tools/eslint/node_modules/natural-compare/package.json @@ -0,0 +1,110 @@ +{ + "_args": [ + [ + { + "raw": "natural-compare@^1.4.0", + "scope": null, + "escapedName": "natural-compare", + "name": "natural-compare", + "rawSpec": "^1.4.0", + "spec": ">=1.4.0 <2.0.0", + "type": "range" + }, + "/Users/trott/io.js/tools/node_modules/eslint" + ] + ], + "_from": "natural-compare@>=1.4.0 <2.0.0", + "_id": "natural-compare@1.4.0", + "_inCache": true, + "_installable": true, + "_location": "/natural-compare", + "_nodeVersion": "6.2.2", + "_npmOperationalInternal": { + "host": "packages-12-west.internal.npmjs.com", + "tmp": "tmp/natural-compare-1.4.0.tgz_1469220490086_0.1379237591754645" + }, + "_npmUser": { + "name": "megawac", + "email": "megawac@gmail.com" + }, + "_npmVersion": "3.9.5", + "_phantomChildren": {}, + "_requested": { + "raw": "natural-compare@^1.4.0", + "scope": null, + "escapedName": "natural-compare", + "name": "natural-compare", + "rawSpec": "^1.4.0", + "spec": ">=1.4.0 <2.0.0", + "type": "range" + }, + "_requiredBy": [ + "/eslint" + ], + "_resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "_shasum": "4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7", + "_shrinkwrap": null, + "_spec": "natural-compare@^1.4.0", + "_where": "/Users/trott/io.js/tools/node_modules/eslint", + "author": { + "name": "Lauri Rooden", + "url": "https://github.com/litejs/natural-compare-lite" + }, + "bugs": { + "url": "https://github.com/litejs/natural-compare-lite/issues" + }, + "buildman": { + "dist/index-min.js": { + "banner": "/*! litejs.com/MIT-LICENSE.txt */", + "input": "index.js" + } + }, + "dependencies": {}, + "description": "Compare strings containing a mix of letters and numbers in the way a human being would in sort order.", + "devDependencies": { + "buildman": "*", + "testman": "*" + }, + "directories": {}, + "dist": { + "shasum": "4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7", + "tarball": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + }, + "files": [ + "index.js" + ], + "gitHead": "eec83eee67cfac84d6db30cdd65363f155673770", + "homepage": "https://github.com/litejs/natural-compare-lite#readme", + "keywords": [ + "string", + "natural", + "order", + "sort", + "natsort", + "natcmp", + "compare", + "alphanum", + "litejs" + ], + "license": "MIT", + "main": "index.js", + "maintainers": [ + { + "name": "megawac", + "email": "megawac@gmail.com" + } + ], + "name": "natural-compare", + "optionalDependencies": {}, + "readme": "ERROR: No README data found!", + "repository": { + "type": "git", + "url": "git://github.com/litejs/natural-compare-lite.git" + }, + "scripts": { + "build": "node node_modules/buildman/index.js --all", + "test": "node tests/index.js" + }, + "stability": 3, + "version": "1.4.0" +} diff --git a/tools/eslint/node_modules/shelljs/build/output.js b/tools/eslint/node_modules/shelljs/build/output.js deleted file mode 100644 index 1b778b9318..0000000000 --- a/tools/eslint/node_modules/shelljs/build/output.js +++ /dev/null @@ -1,2411 +0,0 @@ -var common = require('./common'); -var fs = require('fs'); - -//@ -//@ ### cat(file [, file ...]) -//@ ### cat(file_array) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var str = cat('file*.txt'); -//@ var str = cat('file1', 'file2'); -//@ var str = cat(['file1', 'file2']); // same as above -//@ ``` -//@ -//@ Returns a string containing the given file, or a concatenated string -//@ containing the files if more than one file is given (a new line character is -//@ introduced between each file). Wildcard `*` accepted. -function _cat(options, files) { - var cat = ''; - - if (!files) - common.error('no paths given'); - - if (typeof files === 'string') - files = [].slice.call(arguments, 1); - // if it's array leave it as it is - - files = common.expand(files); - - files.forEach(function(file) { - if (!fs.existsSync(file)) - common.error('no such file or directory: ' + file); - - cat += fs.readFileSync(file, 'utf8'); - }); - - return common.ShellString(cat); -} -module.exports = _cat; - -var fs = require('fs'); -var common = require('./common'); - -//@ -//@ ### cd([dir]) -//@ Changes to directory `dir` for the duration of the script. Changes to home -//@ directory if no argument is supplied. -function _cd(options, dir) { - if (!dir) - dir = common.getUserHome(); - - if (dir === '-') { - if (!common.state.previousDir) - common.error('could not find previous directory'); - else - dir = common.state.previousDir; - } - - if (!fs.existsSync(dir)) - common.error('no such file or directory: ' + dir); - - if (!fs.statSync(dir).isDirectory()) - common.error('not a directory: ' + dir); - - common.state.previousDir = process.cwd(); - process.chdir(dir); -} -module.exports = _cd; - -var common = require('./common'); -var fs = require('fs'); -var path = require('path'); - -var PERMS = (function (base) { - return { - OTHER_EXEC : base.EXEC, - OTHER_WRITE : base.WRITE, - OTHER_READ : base.READ, - - GROUP_EXEC : base.EXEC << 3, - GROUP_WRITE : base.WRITE << 3, - GROUP_READ : base.READ << 3, - - OWNER_EXEC : base.EXEC << 6, - OWNER_WRITE : base.WRITE << 6, - OWNER_READ : base.READ << 6, - - // Literal octal numbers are apparently not allowed in "strict" javascript. Using parseInt is - // the preferred way, else a jshint warning is thrown. - STICKY : parseInt('01000', 8), - SETGID : parseInt('02000', 8), - SETUID : parseInt('04000', 8), - - TYPE_MASK : parseInt('0770000', 8) - }; -})({ - EXEC : 1, - WRITE : 2, - READ : 4 -}); - -//@ -//@ ### chmod(octal_mode || octal_string, file) -//@ ### chmod(symbolic_mode, file) -//@ -//@ Available options: -//@ -//@ + `-v`: output a diagnostic for every file processed//@ -//@ + `-c`: like verbose but report only when a change is made//@ -//@ + `-R`: change files and directories recursively//@ -//@ -//@ Examples: -//@ -//@ ```javascript -//@ chmod(755, '/Users/brandon'); -//@ chmod('755', '/Users/brandon'); // same as above -//@ chmod('u+x', '/Users/brandon'); -//@ ``` -//@ -//@ Alters the permissions of a file or directory by either specifying the -//@ absolute permissions in octal form or expressing the changes in symbols. -//@ This command tries to mimic the POSIX behavior as much as possible. -//@ Notable exceptions: -//@ -//@ + In symbolic modes, 'a-r' and '-r' are identical. No consideration is -//@ given to the umask. -//@ + There is no "quiet" option since default behavior is to run silent. -function _chmod(options, mode, filePattern) { - if (!filePattern) { - if (options.length > 0 && options.charAt(0) === '-') { - // Special case where the specified file permissions started with - to subtract perms, which - // get picked up by the option parser as command flags. - // If we are down by one argument and options starts with -, shift everything over. - filePattern = mode; - mode = options; - options = ''; - } - else { - common.error('You must specify a file.'); - } - } - - options = common.parseOptions(options, { - 'R': 'recursive', - 'c': 'changes', - 'v': 'verbose' - }); - - if (typeof filePattern === 'string') { - filePattern = [ filePattern ]; - } - - var files; - - if (options.recursive) { - files = []; - common.expand(filePattern).forEach(function addFile(expandedFile) { - var stat = fs.lstatSync(expandedFile); - - if (!stat.isSymbolicLink()) { - files.push(expandedFile); - - if (stat.isDirectory()) { // intentionally does not follow symlinks. - fs.readdirSync(expandedFile).forEach(function (child) { - addFile(expandedFile + '/' + child); - }); - } - } - }); - } - else { - files = common.expand(filePattern); - } - - files.forEach(function innerChmod(file) { - file = path.resolve(file); - if (!fs.existsSync(file)) { - common.error('File not found: ' + file); - } - - // When recursing, don't follow symlinks. - if (options.recursive && fs.lstatSync(file).isSymbolicLink()) { - return; - } - - var stat = fs.statSync(file); - var isDir = stat.isDirectory(); - var perms = stat.mode; - var type = perms & PERMS.TYPE_MASK; - - var newPerms = perms; - - if (isNaN(parseInt(mode, 8))) { - // parse options - mode.split(',').forEach(function (symbolicMode) { - /*jshint regexdash:true */ - var pattern = /([ugoa]*)([=\+-])([rwxXst]*)/i; - var matches = pattern.exec(symbolicMode); - - if (matches) { - var applyTo = matches[1]; - var operator = matches[2]; - var change = matches[3]; - - var changeOwner = applyTo.indexOf('u') != -1 || applyTo === 'a' || applyTo === ''; - var changeGroup = applyTo.indexOf('g') != -1 || applyTo === 'a' || applyTo === ''; - var changeOther = applyTo.indexOf('o') != -1 || applyTo === 'a' || applyTo === ''; - - var changeRead = change.indexOf('r') != -1; - var changeWrite = change.indexOf('w') != -1; - var changeExec = change.indexOf('x') != -1; - var changeExecDir = change.indexOf('X') != -1; - var changeSticky = change.indexOf('t') != -1; - var changeSetuid = change.indexOf('s') != -1; - - if (changeExecDir && isDir) - changeExec = true; - - var mask = 0; - if (changeOwner) { - mask |= (changeRead ? PERMS.OWNER_READ : 0) + (changeWrite ? PERMS.OWNER_WRITE : 0) + (changeExec ? PERMS.OWNER_EXEC : 0) + (changeSetuid ? PERMS.SETUID : 0); - } - if (changeGroup) { - mask |= (changeRead ? PERMS.GROUP_READ : 0) + (changeWrite ? PERMS.GROUP_WRITE : 0) + (changeExec ? PERMS.GROUP_EXEC : 0) + (changeSetuid ? PERMS.SETGID : 0); - } - if (changeOther) { - mask |= (changeRead ? PERMS.OTHER_READ : 0) + (changeWrite ? PERMS.OTHER_WRITE : 0) + (changeExec ? PERMS.OTHER_EXEC : 0); - } - - // Sticky bit is special - it's not tied to user, group or other. - if (changeSticky) { - mask |= PERMS.STICKY; - } - - switch (operator) { - case '+': - newPerms |= mask; - break; - - case '-': - newPerms &= ~mask; - break; - - case '=': - newPerms = type + mask; - - // According to POSIX, when using = to explicitly set the permissions, setuid and setgid can never be cleared. - if (fs.statSync(file).isDirectory()) { - newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; - } - break; - } - - if (options.verbose) { - console.log(file + ' -> ' + newPerms.toString(8)); - } - - if (perms != newPerms) { - if (!options.verbose && options.changes) { - console.log(file + ' -> ' + newPerms.toString(8)); - } - fs.chmodSync(file, newPerms); - perms = newPerms; // for the next round of changes! - } - } - else { - common.error('Invalid symbolic mode change: ' + symbolicMode); - } - }); - } - else { - // they gave us a full number - newPerms = type + parseInt(mode, 8); - - // POSIX rules are that setuid and setgid can only be added using numeric form, but not cleared. - if (fs.statSync(file).isDirectory()) { - newPerms |= (PERMS.SETUID + PERMS.SETGID) & perms; - } - - fs.chmodSync(file, newPerms); - } - }); -} -module.exports = _chmod; - -var os = require('os'); -var fs = require('fs'); -var _ls = require('./ls'); - -// Module globals -var config = { - silent: false, - fatal: false, - verbose: false, -}; -exports.config = config; - -var state = { - error: null, - currentCmd: 'shell.js', - previousDir: null, - tempDir: null -}; -exports.state = state; - -var platform = os.type().match(/^Win/) ? 'win' : 'unix'; -exports.platform = platform; - -function log() { - if (!config.silent) - console.error.apply(console, arguments); -} -exports.log = log; - -// Shows error message. Throws unless _continue or config.fatal are true -function error(msg, _continue) { - if (state.error === null) - state.error = ''; - var log_entry = state.currentCmd + ': ' + msg; - if (state.error === '') - state.error = log_entry; - else - state.error += '\n' + log_entry; - - if (msg.length > 0) - log(log_entry); - - if (config.fatal) - process.exit(1); - - if (!_continue) - throw ''; -} -exports.error = error; - -// In the future, when Proxies are default, we can add methods like `.to()` to primitive strings. -// For now, this is a dummy function to bookmark places we need such strings -function ShellString(str) { - return str; -} -exports.ShellString = ShellString; - -// Return the home directory in a platform-agnostic way, with consideration for -// older versions of node -function getUserHome() { - var result; - if (os.homedir) - result = os.homedir(); // node 3+ - else - result = process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME']; - return result; -} -exports.getUserHome = getUserHome; - -// Returns {'alice': true, 'bob': false} when passed a dictionary, e.g.: -// parseOptions('-a', {'a':'alice', 'b':'bob'}); -function parseOptions(str, map) { - if (!map) - error('parseOptions() internal error: no map given'); - - // All options are false by default - var options = {}; - for (var letter in map) { - if (!map[letter].match('^!')) - options[map[letter]] = false; - } - - if (!str) - return options; // defaults - - if (typeof str !== 'string') - error('parseOptions() internal error: wrong str'); - - // e.g. match[1] = 'Rf' for str = '-Rf' - var match = str.match(/^\-(.+)/); - if (!match) - return options; - - // e.g. chars = ['R', 'f'] - var chars = match[1].split(''); - - var opt; - chars.forEach(function(c) { - if (c in map) { - opt = map[c]; - if (opt.match('^!')) - options[opt.slice(1, opt.length-1)] = false; - else - options[opt] = true; - } else { - error('option not recognized: '+c); - } - }); - - return options; -} -exports.parseOptions = parseOptions; - -// Expands wildcards with matching (ie. existing) file names. -// For example: -// expand(['file*.js']) = ['file1.js', 'file2.js', ...] -// (if the files 'file1.js', 'file2.js', etc, exist in the current dir) -function expand(list) { - var expanded = []; - list.forEach(function(listEl) { - // Wildcard present on directory names ? - if(listEl.search(/\*[^\/]*\//) > -1 || listEl.search(/\*\*[^\/]*\//) > -1) { - var match = listEl.match(/^([^*]+\/|)(.*)/); - var root = match[1]; - var rest = match[2]; - var restRegex = rest.replace(/\*\*/g, ".*").replace(/\*/g, "[^\\/]*"); - restRegex = new RegExp(restRegex); - - _ls('-R', root).filter(function (e) { - return restRegex.test(e); - }).forEach(function(file) { - expanded.push(file); - }); - } - // Wildcard present on file names ? - else if (listEl.search(/\*/) > -1) { - _ls('', listEl).forEach(function(file) { - expanded.push(file); - }); - } else { - expanded.push(listEl); - } - }); - return expanded; -} -exports.expand = expand; - -// Normalizes _unlinkSync() across platforms to match Unix behavior, i.e. -// file can be unlinked even if it's read-only, see https://github.com/joyent/node/issues/3006 -function unlinkSync(file) { - try { - fs.unlinkSync(file); - } catch(e) { - // Try to override file permission - if (e.code === 'EPERM') { - fs.chmodSync(file, '0666'); - fs.unlinkSync(file); - } else { - throw e; - } - } -} -exports.unlinkSync = unlinkSync; - -// e.g. 'shelljs_a5f185d0443ca...' -function randomFileName() { - function randomHash(count) { - if (count === 1) - return parseInt(16*Math.random(), 10).toString(16); - else { - var hash = ''; - for (var i=0; i<count; i++) - hash += randomHash(1); - return hash; - } - } - - return 'shelljs_'+randomHash(20); -} -exports.randomFileName = randomFileName; - -// extend(target_obj, source_obj1 [, source_obj2 ...]) -// Shallow extend, e.g.: -// extend({A:1}, {b:2}, {c:3}) returns {A:1, b:2, c:3} -function extend(target) { - var sources = [].slice.call(arguments, 1); - sources.forEach(function(source) { - for (var key in source) - target[key] = source[key]; - }); - - return target; -} -exports.extend = extend; - -// Common wrapper for all Unix-like commands -function wrap(cmd, fn, options) { - return function() { - var retValue = null; - - state.currentCmd = cmd; - state.error = null; - - try { - var args = [].slice.call(arguments, 0); - - if (config.verbose) { - args.unshift(cmd); - console.log.apply(console, args); - args.shift(); - } - - if (options && options.notUnix) { - retValue = fn.apply(this, args); - } else { - if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-') - args.unshift(''); // only add dummy option if '-option' not already present - // Expand the '~' if appropriate - var homeDir = getUserHome(); - args = args.map(function(arg) { - if (typeof arg === 'string' && arg.slice(0, 2) === '~/' || arg === '~') - return arg.replace(/^~/, homeDir); - else - return arg; - }); - retValue = fn.apply(this, args); - } - } catch (e) { - if (!state.error) { - // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug... - console.log('shell.js: internal error'); - console.log(e.stack || e); - process.exit(1); - } - if (config.fatal) - throw e; - } - - state.currentCmd = 'shell.js'; - return retValue; - }; -} // wrap -exports.wrap = wrap; - -var fs = require('fs'); -var path = require('path'); -var common = require('./common'); -var os = require('os'); - -// Buffered file copy, synchronous -// (Using readFileSync() + writeFileSync() could easily cause a memory overflow -// with large files) -function copyFileSync(srcFile, destFile) { - if (!fs.existsSync(srcFile)) - common.error('copyFileSync: no such file or directory: ' + srcFile); - - var BUF_LENGTH = 64*1024, - buf = new Buffer(BUF_LENGTH), - bytesRead = BUF_LENGTH, - pos = 0, - fdr = null, - fdw = null; - - try { - fdr = fs.openSync(srcFile, 'r'); - } catch(e) { - common.error('copyFileSync: could not read src file ('+srcFile+')'); - } - - try { - fdw = fs.openSync(destFile, 'w'); - } catch(e) { - common.error('copyFileSync: could not write to dest file (code='+e.code+'):'+destFile); - } - - while (bytesRead === BUF_LENGTH) { - bytesRead = fs.readSync(fdr, buf, 0, BUF_LENGTH, pos); - fs.writeSync(fdw, buf, 0, bytesRead); - pos += bytesRead; - } - - fs.closeSync(fdr); - fs.closeSync(fdw); - - fs.chmodSync(destFile, fs.statSync(srcFile).mode); -} - -// Recursively copies 'sourceDir' into 'destDir' -// Adapted from https://github.com/ryanmcgrath/wrench-js -// -// Copyright (c) 2010 Ryan McGrath -// Copyright (c) 2012 Artur Adib -// -// Licensed under the MIT License -// http://www.opensource.org/licenses/mit-license.php -function cpdirSyncRecursive(sourceDir, destDir, opts) { - if (!opts) opts = {}; - - /* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */ - var checkDir = fs.statSync(sourceDir); - try { - fs.mkdirSync(destDir, checkDir.mode); - } catch (e) { - //if the directory already exists, that's okay - if (e.code !== 'EEXIST') throw e; - } - - var files = fs.readdirSync(sourceDir); - - for (var i = 0; i < files.length; i++) { - var srcFile = sourceDir + "/" + files[i]; - var destFile = destDir + "/" + files[i]; - var srcFileStat = fs.lstatSync(srcFile); - - if (srcFileStat.isDirectory()) { - /* recursion this thing right on back. */ - cpdirSyncRecursive(srcFile, destFile, opts); - } else if (srcFileStat.isSymbolicLink()) { - var symlinkFull = fs.readlinkSync(srcFile); - fs.symlinkSync(symlinkFull, destFile, os.platform() === "win32" ? "junction" : null); - } else { - /* At this point, we've hit a file actually worth copying... so copy it on over. */ - if (fs.existsSync(destFile) && opts.no_force) { - common.log('skipping existing file: ' + files[i]); - } else { - copyFileSync(srcFile, destFile); - } - } - - } // for files -} // cpdirSyncRecursive - - -//@ -//@ ### cp([options,] source [, source ...], dest) -//@ ### cp([options,] source_array, dest) -//@ Available options: -//@ -//@ + `-f`: force (default behavior) -//@ + `-n`: no-clobber -//@ + `-r, -R`: recursive -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cp('file1', 'dir1'); -//@ cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp'); -//@ cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above -//@ ``` -//@ -//@ Copies files. The wildcard `*` is accepted. -function _cp(options, sources, dest) { - options = common.parseOptions(options, { - 'f': '!no_force', - 'n': 'no_force', - 'R': 'recursive', - 'r': 'recursive' - }); - - // Get sources, dest - if (arguments.length < 3) { - common.error('missing <source> and/or <dest>'); - } else if (arguments.length > 3) { - sources = [].slice.call(arguments, 1, arguments.length - 1); - dest = arguments[arguments.length - 1]; - } else if (typeof sources === 'string') { - sources = [sources]; - } else if ('length' in sources) { - sources = sources; // no-op for array - } else { - common.error('invalid arguments'); - } - - var exists = fs.existsSync(dest), - stats = exists && fs.statSync(dest); - - // Dest is not existing dir, but multiple sources given - if ((!exists || !stats.isDirectory()) && sources.length > 1) - common.error('dest is not a directory (too many sources)'); - - // Dest is an existing file, but no -f given - if (exists && stats.isFile() && options.no_force) - common.error('dest file already exists: ' + dest); - - if (options.recursive) { - // Recursive allows the shortcut syntax "sourcedir/" for "sourcedir/*" - // (see Github issue #15) - sources.forEach(function(src, i) { - if (src[src.length - 1] === '/') { - sources[i] += '*'; - // If src is a directory and dest doesn't exist, 'cp -r src dest' should copy src/* into dest - } else if (fs.statSync(src).isDirectory() && !exists) { - sources[i] += '/*'; - } - }); - - // Create dest - try { - fs.mkdirSync(dest, parseInt('0777', 8)); - } catch (e) { - // like Unix's cp, keep going even if we can't create dest dir - } - } - - sources = common.expand(sources); - - sources.forEach(function(src) { - if (!fs.existsSync(src)) { - common.error('no such file or directory: '+src, true); - return; // skip file - } - - // If here, src exists - if (fs.statSync(src).isDirectory()) { - if (!options.recursive) { - // Non-Recursive - common.log(src + ' is a directory (not copied)'); - } else { - // Recursive - // 'cp /a/source dest' should create 'source' in 'dest' - var newDest = path.join(dest, path.basename(src)), - checkDir = fs.statSync(src); - try { - fs.mkdirSync(newDest, checkDir.mode); - } catch (e) { - //if the directory already exists, that's okay - if (e.code !== 'EEXIST') { - common.error('dest file no such file or directory: ' + newDest, true); - throw e; - } - } - - cpdirSyncRecursive(src, newDest, {no_force: options.no_force}); - } - return; // done with dir - } - - // If here, src is a file - - // When copying to '/path/dir': - // thisDest = '/path/dir/file1' - var thisDest = dest; - if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) - thisDest = path.normalize(dest + '/' + path.basename(src)); - - if (fs.existsSync(thisDest) && options.no_force) { - common.error('dest file already exists: ' + thisDest, true); - return; // skip file - } - - copyFileSync(src, thisDest); - }); // forEach(src) -} -module.exports = _cp; - -var common = require('./common'); -var _cd = require('./cd'); -var path = require('path'); - -// Pushd/popd/dirs internals -var _dirStack = []; - -function _isStackIndex(index) { - return (/^[\-+]\d+$/).test(index); -} - -function _parseStackIndex(index) { - if (_isStackIndex(index)) { - if (Math.abs(index) < _dirStack.length + 1) { // +1 for pwd - return (/^-/).test(index) ? Number(index) - 1 : Number(index); - } else { - common.error(index + ': directory stack index out of range'); - } - } else { - common.error(index + ': invalid number'); - } -} - -function _actualDirStack() { - return [process.cwd()].concat(_dirStack); -} - -//@ -//@ ### pushd([options,] [dir | '-N' | '+N']) -//@ -//@ Available options: -//@ -//@ + `-n`: Suppresses the normal change of directory when adding directories to the stack, so that only the stack is manipulated. -//@ -//@ Arguments: -//@ -//@ + `dir`: Makes the current working directory be the top of the stack, and then executes the equivalent of `cd dir`. -//@ + `+N`: Brings the Nth directory (counting from the left of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. -//@ + `-N`: Brings the Nth directory (counting from the right of the list printed by dirs, starting with zero) to the top of the list by rotating the stack. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ // process.cwd() === '/usr' -//@ pushd('/etc'); // Returns /etc /usr -//@ pushd('+1'); // Returns /usr /etc -//@ ``` -//@ -//@ Save the current directory on the top of the directory stack and then cd to `dir`. With no arguments, pushd exchanges the top two directories. Returns an array of paths in the stack. -function _pushd(options, dir) { - if (_isStackIndex(options)) { - dir = options; - options = ''; - } - - options = common.parseOptions(options, { - 'n' : 'no-cd' - }); - - var dirs = _actualDirStack(); - - if (dir === '+0') { - return dirs; // +0 is a noop - } else if (!dir) { - if (dirs.length > 1) { - dirs = dirs.splice(1, 1).concat(dirs); - } else { - return common.error('no other directory'); - } - } else if (_isStackIndex(dir)) { - var n = _parseStackIndex(dir); - dirs = dirs.slice(n).concat(dirs.slice(0, n)); - } else { - if (options['no-cd']) { - dirs.splice(1, 0, dir); - } else { - dirs.unshift(dir); - } - } - - if (options['no-cd']) { - dirs = dirs.slice(1); - } else { - dir = path.resolve(dirs.shift()); - _cd('', dir); - } - - _dirStack = dirs; - return _dirs(''); -} -exports.pushd = _pushd; - -//@ -//@ ### popd([options,] ['-N' | '+N']) -//@ -//@ Available options: -//@ -//@ + `-n`: Suppresses the normal change of directory when removing directories from the stack, so that only the stack is manipulated. -//@ -//@ Arguments: -//@ -//@ + `+N`: Removes the Nth directory (counting from the left of the list printed by dirs), starting with zero. -//@ + `-N`: Removes the Nth directory (counting from the right of the list printed by dirs), starting with zero. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ echo(process.cwd()); // '/usr' -//@ pushd('/etc'); // '/etc /usr' -//@ echo(process.cwd()); // '/etc' -//@ popd(); // '/usr' -//@ echo(process.cwd()); // '/usr' -//@ ``` -//@ -//@ When no arguments are given, popd removes the top directory from the stack and performs a cd to the new top directory. The elements are numbered from 0 starting at the first directory listed with dirs; i.e., popd is equivalent to popd +0. Returns an array of paths in the stack. -function _popd(options, index) { - if (_isStackIndex(options)) { - index = options; - options = ''; - } - - options = common.parseOptions(options, { - 'n' : 'no-cd' - }); - - if (!_dirStack.length) { - return common.error('directory stack empty'); - } - - index = _parseStackIndex(index || '+0'); - - if (options['no-cd'] || index > 0 || _dirStack.length + index === 0) { - index = index > 0 ? index - 1 : index; - _dirStack.splice(index, 1); - } else { - var dir = path.resolve(_dirStack.shift()); - _cd('', dir); - } - - return _dirs(''); -} -exports.popd = _popd; - -//@ -//@ ### dirs([options | '+N' | '-N']) -//@ -//@ Available options: -//@ -//@ + `-c`: Clears the directory stack by deleting all of the elements. -//@ -//@ Arguments: -//@ -//@ + `+N`: Displays the Nth directory (counting from the left of the list printed by dirs when invoked without options), starting with zero. -//@ + `-N`: Displays the Nth directory (counting from the right of the list printed by dirs when invoked without options), starting with zero. -//@ -//@ Display the list of currently remembered directories. Returns an array of paths in the stack, or a single path if +N or -N was specified. -//@ -//@ See also: pushd, popd -function _dirs(options, index) { - if (_isStackIndex(options)) { - index = options; - options = ''; - } - - options = common.parseOptions(options, { - 'c' : 'clear' - }); - - if (options['clear']) { - _dirStack = []; - return _dirStack; - } - - var stack = _actualDirStack(); - - if (index) { - index = _parseStackIndex(index); - - if (index < 0) { - index = stack.length + index; - } - - common.log(stack[index]); - return stack[index]; - } - - common.log(stack.join(' ')); - - return stack; -} -exports.dirs = _dirs; - -var common = require('./common'); - -//@ -//@ ### echo(string [, string ...]) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ echo('hello world'); -//@ var str = echo('hello world'); -//@ ``` -//@ -//@ Prints string to stdout, and returns string with additional utility methods -//@ like `.to()`. -function _echo() { - var messages = [].slice.call(arguments, 0); - console.log.apply(console, messages); - return common.ShellString(messages.join(' ')); -} -module.exports = _echo; - -var common = require('./common'); - -//@ -//@ ### error() -//@ Tests if error occurred in the last command. Returns `null` if no error occurred, -//@ otherwise returns string explaining the error -function error() { - return common.state.error; -} -module.exports = error; - -var common = require('./common'); -var _tempDir = require('./tempdir'); -var _pwd = require('./pwd'); -var path = require('path'); -var fs = require('fs'); -var child = require('child_process'); - -// Hack to run child_process.exec() synchronously (sync avoids callback hell) -// Uses a custom wait loop that checks for a flag file, created when the child process is done. -// (Can't do a wait loop that checks for internal Node variables/messages as -// Node is single-threaded; callbacks and other internal state changes are done in the -// event loop). -function execSync(cmd, opts) { - var tempDir = _tempDir(); - var stdoutFile = path.resolve(tempDir+'/'+common.randomFileName()), - stderrFile = path.resolve(tempDir+'/'+common.randomFileName()), - codeFile = path.resolve(tempDir+'/'+common.randomFileName()), - scriptFile = path.resolve(tempDir+'/'+common.randomFileName()), - sleepFile = path.resolve(tempDir+'/'+common.randomFileName()); - - var options = common.extend({ - silent: common.config.silent - }, opts); - - var previousStdoutContent = '', - previousStderrContent = ''; - // Echoes stdout and stderr changes from running process, if not silent - function updateStream(streamFile) { - if (options.silent || !fs.existsSync(streamFile)) - return; - - var previousStreamContent, - proc_stream; - if (streamFile === stdoutFile) { - previousStreamContent = previousStdoutContent; - proc_stream = process.stdout; - } else { // assume stderr - previousStreamContent = previousStderrContent; - proc_stream = process.stderr; - } - - var streamContent = fs.readFileSync(streamFile, 'utf8'); - // No changes since last time? - if (streamContent.length <= previousStreamContent.length) - return; - - proc_stream.write(streamContent.substr(previousStreamContent.length)); - previousStreamContent = streamContent; - } - - function escape(str) { - return (str+'').replace(/([\\"'])/g, "\\$1").replace(/\0/g, "\\0"); - } - - if (fs.existsSync(scriptFile)) common.unlinkSync(scriptFile); - if (fs.existsSync(stdoutFile)) common.unlinkSync(stdoutFile); - if (fs.existsSync(stderrFile)) common.unlinkSync(stderrFile); - if (fs.existsSync(codeFile)) common.unlinkSync(codeFile); - - var execCommand = '"'+process.execPath+'" '+scriptFile; - var execOptions = { - env: process.env, - cwd: _pwd(), - maxBuffer: 20*1024*1024 - }; - - var script; - - if (typeof child.execSync === 'function') { - script = [ - "var child = require('child_process')", - " , fs = require('fs');", - "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {", - " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');", - "});", - "var stdoutStream = fs.createWriteStream('"+escape(stdoutFile)+"');", - "var stderrStream = fs.createWriteStream('"+escape(stderrFile)+"');", - "childProcess.stdout.pipe(stdoutStream, {end: false});", - "childProcess.stderr.pipe(stderrStream, {end: false});", - "childProcess.stdout.pipe(process.stdout);", - "childProcess.stderr.pipe(process.stderr);", - "var stdoutEnded = false, stderrEnded = false;", - "function tryClosingStdout(){ if(stdoutEnded){ stdoutStream.end(); } }", - "function tryClosingStderr(){ if(stderrEnded){ stderrStream.end(); } }", - "childProcess.stdout.on('end', function(){ stdoutEnded = true; tryClosingStdout(); });", - "childProcess.stderr.on('end', function(){ stderrEnded = true; tryClosingStderr(); });" - ].join('\n'); - - fs.writeFileSync(scriptFile, script); - - if (options.silent) { - execOptions.stdio = 'ignore'; - } else { - execOptions.stdio = [0, 1, 2]; - } - - // Welcome to the future - child.execSync(execCommand, execOptions); - } else { - cmd += ' > '+stdoutFile+' 2> '+stderrFile; // works on both win/unix - - script = [ - "var child = require('child_process')", - " , fs = require('fs');", - "var childProcess = child.exec('"+escape(cmd)+"', {env: process.env, maxBuffer: 20*1024*1024}, function(err) {", - " fs.writeFileSync('"+escape(codeFile)+"', err ? err.code.toString() : '0');", - "});" - ].join('\n'); - - fs.writeFileSync(scriptFile, script); - - child.exec(execCommand, execOptions); - - // The wait loop - // sleepFile is used as a dummy I/O op to mitigate unnecessary CPU usage - // (tried many I/O sync ops, writeFileSync() seems to be only one that is effective in reducing - // CPU usage, though apparently not so much on Windows) - while (!fs.existsSync(codeFile)) { updateStream(stdoutFile); fs.writeFileSync(sleepFile, 'a'); } - while (!fs.existsSync(stdoutFile)) { updateStream(stdoutFile); fs.writeFileSync(sleepFile, 'a'); } - while (!fs.existsSync(stderrFile)) { updateStream(stderrFile); fs.writeFileSync(sleepFile, 'a'); } - } - - // At this point codeFile exists, but it's not necessarily flushed yet. - // Keep reading it until it is. - var code = parseInt('', 10); - while (isNaN(code)) { - code = parseInt(fs.readFileSync(codeFile, 'utf8'), 10); - } - - var stdout = fs.readFileSync(stdoutFile, 'utf8'); - var stderr = fs.readFileSync(stderrFile, 'utf8'); - - // No biggie if we can't erase the files now -- they're in a temp dir anyway - try { common.unlinkSync(scriptFile); } catch(e) {} - try { common.unlinkSync(stdoutFile); } catch(e) {} - try { common.unlinkSync(stderrFile); } catch(e) {} - try { common.unlinkSync(codeFile); } catch(e) {} - try { common.unlinkSync(sleepFile); } catch(e) {} - - // some shell return codes are defined as errors, per http://tldp.org/LDP/abs/html/exitcodes.html - if (code === 1 || code === 2 || code >= 126) { - common.error('', true); // unix/shell doesn't really give an error message after non-zero exit codes - } - // True if successful, false if not - var obj = { - code: code, - output: stdout, // deprecated - stdout: stdout, - stderr: stderr - }; - return obj; -} // execSync() - -// Wrapper around exec() to enable echoing output to console in real time -function execAsync(cmd, opts, callback) { - var stdout = ''; - var stderr = ''; - - var options = common.extend({ - silent: common.config.silent - }, opts); - - var c = child.exec(cmd, {env: process.env, maxBuffer: 20*1024*1024}, function(err) { - if (callback) - callback(err ? err.code : 0, stdout, stderr); - }); - - c.stdout.on('data', function(data) { - stdout += data; - if (!options.silent) - process.stdout.write(data); - }); - - c.stderr.on('data', function(data) { - stderr += data; - if (!options.silent) - process.stderr.write(data); - }); - - return c; -} - -//@ -//@ ### exec(command [, options] [, callback]) -//@ Available options (all `false` by default): -//@ -//@ + `async`: Asynchronous execution. If a callback is provided, it will be set to -//@ `true`, regardless of the passed value. -//@ + `silent`: Do not echo program output to console. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var version = exec('node --version', {silent:true}).stdout; -//@ -//@ var child = exec('some_long_running_process', {async:true}); -//@ child.stdout.on('data', function(data) { -//@ /* ... do something with data ... */ -//@ }); -//@ -//@ exec('some_long_running_process', function(code, stdout, stderr) { -//@ console.log('Exit code:', code); -//@ console.log('Program output:', stdout); -//@ console.log('Program stderr:', stderr); -//@ }); -//@ ``` -//@ -//@ Executes the given `command` _synchronously_, unless otherwise specified. When in synchronous -//@ mode returns the object `{ code:..., stdout:... , stderr:... }`, containing the program's -//@ `stdout`, `stderr`, and its exit `code`. Otherwise returns the child process object, -//@ and the `callback` gets the arguments `(code, stdout, stderr)`. -//@ -//@ **Note:** For long-lived processes, it's best to run `exec()` asynchronously as -//@ the current synchronous implementation uses a lot of CPU. This should be getting -//@ fixed soon. -function _exec(command, options, callback) { - if (!command) - common.error('must specify command'); - - // Callback is defined instead of options. - if (typeof options === 'function') { - callback = options; - options = { async: true }; - } - - // Callback is defined with options. - if (typeof options === 'object' && typeof callback === 'function') { - options.async = true; - } - - options = common.extend({ - silent: common.config.silent, - async: false - }, options); - - if (options.async) - return execAsync(command, options, callback); - else - return execSync(command, options); -} -module.exports = _exec; - -var fs = require('fs'); -var common = require('./common'); -var _ls = require('./ls'); - -//@ -//@ ### find(path [, path ...]) -//@ ### find(path_array) -//@ Examples: -//@ -//@ ```javascript -//@ find('src', 'lib'); -//@ find(['src', 'lib']); // same as above -//@ find('.').filter(function(file) { return file.match(/\.js$/); }); -//@ ``` -//@ -//@ Returns array of all files (however deep) in the given paths. -//@ -//@ The main difference from `ls('-R', path)` is that the resulting file names -//@ include the base directories, e.g. `lib/resources/file1` instead of just `file1`. -function _find(options, paths) { - if (!paths) - common.error('no path specified'); - else if (typeof paths === 'object') - paths = paths; // assume array - else if (typeof paths === 'string') - paths = [].slice.call(arguments, 1); - - var list = []; - - function pushFile(file) { - if (common.platform === 'win') - file = file.replace(/\\/g, '/'); - list.push(file); - } - - // why not simply do ls('-R', paths)? because the output wouldn't give the base dirs - // to get the base dir in the output, we need instead ls('-R', 'dir/*') for every directory - - paths.forEach(function(file) { - pushFile(file); - - if (fs.statSync(file).isDirectory()) { - _ls('-RA', file+'/*').forEach(function(subfile) { - pushFile(subfile); - }); - } - }); - - return list; -} -module.exports = _find; - -var common = require('./common'); -var fs = require('fs'); - -//@ -//@ ### grep([options,] regex_filter, file [, file ...]) -//@ ### grep([options,] regex_filter, file_array) -//@ Available options: -//@ -//@ + `-v`: Inverse the sense of the regex and print the lines not matching the criteria. -//@ -//@ Examples: -//@ -//@ ```javascript -//@ grep('-v', 'GLOBAL_VARIABLE', '*.js'); -//@ grep('GLOBAL_VARIABLE', '*.js'); -//@ ``` -//@ -//@ Reads input string from given files and returns a string containing all lines of the -//@ file that match the given `regex_filter`. Wildcard `*` accepted. -function _grep(options, regex, files) { - options = common.parseOptions(options, { - 'v': 'inverse' - }); - - if (!files) - common.error('no paths given'); - - if (typeof files === 'string') - files = [].slice.call(arguments, 2); - // if it's array leave it as it is - - files = common.expand(files); - - var grep = ''; - files.forEach(function(file) { - if (!fs.existsSync(file)) { - common.error('no such file or directory: ' + file, true); - return; - } - - var contents = fs.readFileSync(file, 'utf8'), - lines = contents.split(/\r*\n/); - lines.forEach(function(line) { - var matched = line.match(regex); - if ((options.inverse && !matched) || (!options.inverse && matched)) - grep += line + '\n'; - }); - }); - - return common.ShellString(grep); -} -module.exports = _grep; - -var fs = require('fs'); -var path = require('path'); -var common = require('./common'); - -//@ -//@ ### ln([options,] source, dest) -//@ Available options: -//@ -//@ + `-s`: symlink -//@ + `-f`: force -//@ -//@ Examples: -//@ -//@ ```javascript -//@ ln('file', 'newlink'); -//@ ln('-sf', 'file', 'existing'); -//@ ``` -//@ -//@ Links source to dest. Use -f to force the link, should dest already exist. -function _ln(options, source, dest) { - options = common.parseOptions(options, { - 's': 'symlink', - 'f': 'force' - }); - - if (!source || !dest) { - common.error('Missing <source> and/or <dest>'); - } - - source = String(source); - var sourcePath = path.normalize(source).replace(RegExp(path.sep + '$'), ''); - var isAbsolute = (path.resolve(source) === sourcePath); - dest = path.resolve(process.cwd(), String(dest)); - - if (fs.existsSync(dest)) { - if (!options.force) { - common.error('Destination file exists', true); - } - - fs.unlinkSync(dest); - } - - if (options.symlink) { - var isWindows = common.platform === 'win'; - var linkType = isWindows ? 'file' : null; - var resolvedSourcePath = isAbsolute ? sourcePath : path.resolve(process.cwd(), path.dirname(dest), source); - if (!fs.existsSync(resolvedSourcePath)) { - common.error('Source file does not exist', true); - } else if (isWindows && fs.statSync(resolvedSourcePath).isDirectory()) { - linkType = 'junction'; - } - - try { - fs.symlinkSync(linkType === 'junction' ? resolvedSourcePath: source, dest, linkType); - } catch (err) { - common.error(err.message); - } - } else { - if (!fs.existsSync(source)) { - common.error('Source file does not exist', true); - } - try { - fs.linkSync(source, dest); - } catch (err) { - common.error(err.message); - } - } -} -module.exports = _ln; - -var path = require('path'); -var fs = require('fs'); -var common = require('./common'); -var _cd = require('./cd'); -var _pwd = require('./pwd'); - -//@ -//@ ### ls([options,] [path, ...]) -//@ ### ls([options,] path_array) -//@ Available options: -//@ -//@ + `-R`: recursive -//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) -//@ + `-d`: list directories themselves, not their contents -//@ + `-l`: list objects representing each file, each with fields containing `ls -//@ -l` output fields. See -//@ [fs.Stats](https://nodejs.org/api/fs.html#fs_class_fs_stats) -//@ for more info -//@ -//@ Examples: -//@ -//@ ```javascript -//@ ls('projs/*.js'); -//@ ls('-R', '/users/me', '/tmp'); -//@ ls('-R', ['/users/me', '/tmp']); // same as above -//@ ls('-l', 'file.txt'); // { name: 'file.txt', mode: 33188, nlink: 1, ...} -//@ ``` -//@ -//@ Returns array of files in the given path, or in current directory if no path provided. -function _ls(options, paths) { - options = common.parseOptions(options, { - 'R': 'recursive', - 'A': 'all', - 'a': 'all_deprecated', - 'd': 'directory', - 'l': 'long' - }); - - if (options.all_deprecated) { - // We won't support the -a option as it's hard to image why it's useful - // (it includes '.' and '..' in addition to '.*' files) - // For backwards compatibility we'll dump a deprecated message and proceed as before - common.log('ls: Option -a is deprecated. Use -A instead'); - options.all = true; - } - - if (!paths) - paths = ['.']; - else if (typeof paths === 'object') - paths = paths; // assume array - else if (typeof paths === 'string') - paths = [].slice.call(arguments, 1); - - var list = []; - - // Conditionally pushes file to list - returns true if pushed, false otherwise - // (e.g. prevents hidden files to be included unless explicitly told so) - function pushFile(file, query) { - var name = file.name || file; - // hidden file? - if (path.basename(name)[0] === '.') { - // not explicitly asking for hidden files? - if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1)) - return false; - } - - if (common.platform === 'win') - name = name.replace(/\\/g, '/'); - - if (file.name) { - file.name = name; - } else { - file = name; - } - list.push(file); - return true; - } - - paths.forEach(function(p) { - if (fs.existsSync(p)) { - var stats = ls_stat(p); - // Simple file? - if (stats.isFile()) { - if (options.long) { - pushFile(stats, p); - } else { - pushFile(p, p); - } - return; // continue - } - - // Simple dir? - if (options.directory) { - pushFile(p, p); - return; - } else if (stats.isDirectory()) { - // Iterate over p contents - fs.readdirSync(p).forEach(function(file) { - var orig_file = file; - if (options.long) - file = ls_stat(path.join(p, file)); - if (!pushFile(file, p)) - return; - - // Recursive? - if (options.recursive) { - var oldDir = _pwd(); - _cd('', p); - if (fs.statSync(orig_file).isDirectory()) - list = list.concat(_ls('-R'+(options.all?'A':''), orig_file+'/*')); - _cd('', oldDir); - } - }); - return; // continue - } - } - - // p does not exist - possible wildcard present - - var basename = path.basename(p); - var dirname = path.dirname(p); - // Wildcard present on an existing dir? (e.g. '/tmp/*.js') - if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) { - // Escape special regular expression chars - var regexp = basename.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1'); - // Translates wildcard into regex - regexp = '^' + regexp.replace(/\*/g, '.*') + '$'; - // Iterate over directory contents - fs.readdirSync(dirname).forEach(function(file) { - if (file.match(new RegExp(regexp))) { - var file_path = path.join(dirname, file); - file_path = options.long ? ls_stat(file_path) : file_path; - if (file_path.name) - file_path.name = path.normalize(file_path.name); - else - file_path = path.normalize(file_path); - if (!pushFile(file_path, basename)) - return; - - // Recursive? - if (options.recursive) { - var pp = dirname + '/' + file; - if (fs.lstatSync(pp).isDirectory()) - list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*')); - } // recursive - } // if file matches - }); // forEach - return; - } - - common.error('no such file or directory: ' + p, true); - }); - - return list; -} -module.exports = _ls; - - -function ls_stat(path) { - var stats = fs.statSync(path); - // Note: this object will contain more information than .toString() returns - stats.name = path; - stats.toString = function() { - // Return a string resembling unix's `ls -l` format - return [this.mode, this.nlink, this.uid, this.gid, this.size, this.mtime, this.name].join(' '); - }; - return stats; -} - -var common = require('./common'); -var fs = require('fs'); -var path = require('path'); - -// Recursively creates 'dir' -function mkdirSyncRecursive(dir) { - var baseDir = path.dirname(dir); - - // Base dir exists, no recursion necessary - if (fs.existsSync(baseDir)) { - fs.mkdirSync(dir, parseInt('0777', 8)); - return; - } - - // Base dir does not exist, go recursive - mkdirSyncRecursive(baseDir); - - // Base dir created, can create dir - fs.mkdirSync(dir, parseInt('0777', 8)); -} - -//@ -//@ ### mkdir([options,] dir [, dir ...]) -//@ ### mkdir([options,] dir_array) -//@ Available options: -//@ -//@ + `-p`: full path (will create intermediate dirs if necessary) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ mkdir('-p', '/tmp/a/b/c/d', '/tmp/e/f/g'); -//@ mkdir('-p', ['/tmp/a/b/c/d', '/tmp/e/f/g']); // same as above -//@ ``` -//@ -//@ Creates directories. -function _mkdir(options, dirs) { - options = common.parseOptions(options, { - 'p': 'fullpath' - }); - if (!dirs) - common.error('no paths given'); - - if (typeof dirs === 'string') - dirs = [].slice.call(arguments, 1); - // if it's array leave it as it is - - dirs.forEach(function(dir) { - if (fs.existsSync(dir)) { - if (!options.fullpath) - common.error('path already exists: ' + dir, true); - return; // skip dir - } - - // Base dir does not exist, and no -p option given - var baseDir = path.dirname(dir); - if (!fs.existsSync(baseDir) && !options.fullpath) { - common.error('no such file or directory: ' + baseDir, true); - return; // skip dir - } - - if (options.fullpath) - mkdirSyncRecursive(dir); - else - fs.mkdirSync(dir, parseInt('0777', 8)); - }); -} // mkdir -module.exports = _mkdir; - -var fs = require('fs'); -var path = require('path'); -var common = require('./common'); - -//@ -//@ ### mv([options ,] source [, source ...], dest') -//@ ### mv([options ,] source_array, dest') -//@ Available options: -//@ -//@ + `-f`: force (default behavior) -//@ + `-n`: no-clobber -//@ -//@ Examples: -//@ -//@ ```javascript -//@ mv('-n', 'file', 'dir/'); -//@ mv('file1', 'file2', 'dir/'); -//@ mv(['file1', 'file2'], 'dir/'); // same as above -//@ ``` -//@ -//@ Moves files. The wildcard `*` is accepted. -function _mv(options, sources, dest) { - options = common.parseOptions(options, { - 'f': '!no_force', - 'n': 'no_force' - }); - - // Get sources, dest - if (arguments.length < 3) { - common.error('missing <source> and/or <dest>'); - } else if (arguments.length > 3) { - sources = [].slice.call(arguments, 1, arguments.length - 1); - dest = arguments[arguments.length - 1]; - } else if (typeof sources === 'string') { - sources = [sources]; - } else if ('length' in sources) { - sources = sources; // no-op for array - } else { - common.error('invalid arguments'); - } - - sources = common.expand(sources); - - var exists = fs.existsSync(dest), - stats = exists && fs.statSync(dest); - - // Dest is not existing dir, but multiple sources given - if ((!exists || !stats.isDirectory()) && sources.length > 1) - common.error('dest is not a directory (too many sources)'); - - // Dest is an existing file, but no -f given - if (exists && stats.isFile() && options.no_force) - common.error('dest file already exists: ' + dest); - - sources.forEach(function(src) { - if (!fs.existsSync(src)) { - common.error('no such file or directory: '+src, true); - return; // skip file - } - - // If here, src exists - - // When copying to '/path/dir': - // thisDest = '/path/dir/file1' - var thisDest = dest; - if (fs.existsSync(dest) && fs.statSync(dest).isDirectory()) - thisDest = path.normalize(dest + '/' + path.basename(src)); - - if (fs.existsSync(thisDest) && options.no_force) { - common.error('dest file already exists: ' + thisDest, true); - return; // skip file - } - - if (path.resolve(src) === path.dirname(path.resolve(thisDest))) { - common.error('cannot move to self: '+src, true); - return; // skip file - } - - fs.renameSync(src, thisDest); - }); // forEach(src) -} // mv -module.exports = _mv; - -// see dirs.js -// see dirs.js -var path = require('path'); -var common = require('./common'); - -//@ -//@ ### pwd() -//@ Returns the current directory. -function _pwd() { - var pwd = path.resolve(process.cwd()); - return common.ShellString(pwd); -} -module.exports = _pwd; - -var common = require('./common'); -var fs = require('fs'); - -// Recursively removes 'dir' -// Adapted from https://github.com/ryanmcgrath/wrench-js -// -// Copyright (c) 2010 Ryan McGrath -// Copyright (c) 2012 Artur Adib -// -// Licensed under the MIT License -// http://www.opensource.org/licenses/mit-license.php -function rmdirSyncRecursive(dir, force) { - var files; - - files = fs.readdirSync(dir); - - // Loop through and delete everything in the sub-tree after checking it - for(var i = 0; i < files.length; i++) { - var file = dir + "/" + files[i], - currFile = fs.lstatSync(file); - - if(currFile.isDirectory()) { // Recursive function back to the beginning - rmdirSyncRecursive(file, force); - } - - else if(currFile.isSymbolicLink()) { // Unlink symlinks - if (force || isWriteable(file)) { - try { - common.unlinkSync(file); - } catch (e) { - common.error('could not remove file (code '+e.code+'): ' + file, true); - } - } - } - - else // Assume it's a file - perhaps a try/catch belongs here? - if (force || isWriteable(file)) { - try { - common.unlinkSync(file); - } catch (e) { - common.error('could not remove file (code '+e.code+'): ' + file, true); - } - } - } - - // Now that we know everything in the sub-tree has been deleted, we can delete the main directory. - // Huzzah for the shopkeep. - - var result; - try { - // Retry on windows, sometimes it takes a little time before all the files in the directory are gone - var start = Date.now(); - while (true) { - try { - result = fs.rmdirSync(dir); - if (fs.existsSync(dir)) throw { code: "EAGAIN" }; - break; - } catch(er) { - // In addition to error codes, also check if the directory still exists and loop again if true - if (process.platform === "win32" && (er.code === "ENOTEMPTY" || er.code === "EBUSY" || er.code === "EPERM" || er.code === "EAGAIN")) { - if (Date.now() - start > 1000) throw er; - } else if (er.code === "ENOENT") { - // Directory did not exist, deletion was successful - break; - } else { - throw er; - } - } - } - } catch(e) { - common.error('could not remove directory (code '+e.code+'): ' + dir, true); - } - - return result; -} // rmdirSyncRecursive - -// Hack to determine if file has write permissions for current user -// Avoids having to check user, group, etc, but it's probably slow -function isWriteable(file) { - var writePermission = true; - try { - var __fd = fs.openSync(file, 'a'); - fs.closeSync(__fd); - } catch(e) { - writePermission = false; - } - - return writePermission; -} - -//@ -//@ ### rm([options,] file [, file ...]) -//@ ### rm([options,] file_array) -//@ Available options: -//@ -//@ + `-f`: force -//@ + `-r, -R`: recursive -//@ -//@ Examples: -//@ -//@ ```javascript -//@ rm('-rf', '/tmp/*'); -//@ rm('some_file.txt', 'another_file.txt'); -//@ rm(['some_file.txt', 'another_file.txt']); // same as above -//@ ``` -//@ -//@ Removes files. The wildcard `*` is accepted. -function _rm(options, files) { - options = common.parseOptions(options, { - 'f': 'force', - 'r': 'recursive', - 'R': 'recursive' - }); - if (!files) - common.error('no paths given'); - - if (typeof files === 'string') - files = [].slice.call(arguments, 1); - // if it's array leave it as it is - - files = common.expand(files); - - files.forEach(function(file) { - if (!fs.existsSync(file)) { - // Path does not exist, no force flag given - if (!options.force) - common.error('no such file or directory: '+file, true); - - return; // skip file - } - - // If here, path exists - - var stats = fs.lstatSync(file); - if (stats.isFile() || stats.isSymbolicLink()) { - - // Do not check for file writing permissions - if (options.force) { - common.unlinkSync(file); - return; - } - - if (isWriteable(file)) - common.unlinkSync(file); - else - common.error('permission denied: '+file, true); - - return; - } // simple file - - // Path is an existing directory, but no -r flag given - if (stats.isDirectory() && !options.recursive) { - common.error('path is a directory', true); - return; // skip path - } - - // Recursively remove existing directory - if (stats.isDirectory() && options.recursive) { - rmdirSyncRecursive(file, options.force); - } - }); // forEach(file) -} // rm -module.exports = _rm; - -var common = require('./common'); -var fs = require('fs'); - -//@ -//@ ### sed([options,] search_regex, replacement, file [, file ...]) -//@ ### sed([options,] search_regex, replacement, file_array) -//@ Available options: -//@ -//@ + `-i`: Replace contents of 'file' in-place. _Note that no backups will be created!_ -//@ -//@ Examples: -//@ -//@ ```javascript -//@ sed('-i', 'PROGRAM_VERSION', 'v0.1.3', 'source.js'); -//@ sed(/.*DELETE_THIS_LINE.*\n/, '', 'source.js'); -//@ ``` -//@ -//@ Reads an input string from `files` and performs a JavaScript `replace()` on the input -//@ using the given search regex and replacement string or function. Returns the new string after replacement. -function _sed(options, regex, replacement, files) { - options = common.parseOptions(options, { - 'i': 'inplace' - }); - - if (typeof replacement === 'string' || typeof replacement === 'function') - replacement = replacement; // no-op - else if (typeof replacement === 'number') - replacement = replacement.toString(); // fallback - else - common.error('invalid replacement string'); - - // Convert all search strings to RegExp - if (typeof regex === 'string') - regex = RegExp(regex); - - if (!files) - common.error('no files given'); - - if (typeof files === 'string') - files = [].slice.call(arguments, 3); - // if it's array leave it as it is - - files = common.expand(files); - - var sed = []; - files.forEach(function(file) { - if (!fs.existsSync(file)) { - common.error('no such file or directory: ' + file, true); - return; - } - - var result = fs.readFileSync(file, 'utf8').split('\n').map(function (line) { - return line.replace(regex, replacement); - }).join('\n'); - - sed.push(result); - - if (options.inplace) - fs.writeFileSync(file, result, 'utf8'); - }); - - return common.ShellString(sed.join('\n')); -} -module.exports = _sed; - -var common = require('./common'); - -//@ -//@ ### set(options) -//@ Available options: -//@ -//@ + `+/-e`: exit upon error (`config.fatal`) -//@ + `+/-v`: verbose: show all commands (`config.verbose`) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ set('-e'); // exit upon first error -//@ set('+e'); // this undoes a "set('-e')" -//@ ``` -//@ -//@ Sets global configuration variables -function _set(options) { - if (!options) { - var args = [].slice.call(arguments, 0); - if (args.length < 2) - common.error('must provide an argument'); - options = args[1]; - } - var negate = (options[0] === '+'); - if (negate) { - options = '-' + options.slice(1); // parseOptions needs a '-' prefix - } - options = common.parseOptions(options, { - 'e': 'fatal', - 'v': 'verbose' - }); - - var key; - if (negate) { - for (key in options) - options[key] = !options[key]; - } - - for (key in options) { - // Only change the global config if `negate` is false and the option is true - // or if `negate` is true and the option is false (aka negate !== option) - if (negate !== options[key]) { - common.config[key] = options[key]; - } - } - return; -} -module.exports = _set; - -var common = require('./common'); -var os = require('os'); -var fs = require('fs'); - -// Returns false if 'dir' is not a writeable directory, 'dir' otherwise -function writeableDir(dir) { - if (!dir || !fs.existsSync(dir)) - return false; - - if (!fs.statSync(dir).isDirectory()) - return false; - - var testFile = dir+'/'+common.randomFileName(); - try { - fs.writeFileSync(testFile, ' '); - common.unlinkSync(testFile); - return dir; - } catch (e) { - return false; - } -} - - -//@ -//@ ### tempdir() -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var tmp = tempdir(); // "/tmp" for most *nix platforms -//@ ``` -//@ -//@ Searches and returns string containing a writeable, platform-dependent temporary directory. -//@ Follows Python's [tempfile algorithm](http://docs.python.org/library/tempfile.html#tempfile.tempdir). -function _tempDir() { - var state = common.state; - if (state.tempDir) - return state.tempDir; // from cache - - state.tempDir = writeableDir(os.tmpdir && os.tmpdir()) || // node 0.10+ - writeableDir(os.tmpDir && os.tmpDir()) || // node 0.8+ - writeableDir(process.env['TMPDIR']) || - writeableDir(process.env['TEMP']) || - writeableDir(process.env['TMP']) || - writeableDir(process.env['Wimp$ScrapDir']) || // RiscOS - writeableDir('C:\\TEMP') || // Windows - writeableDir('C:\\TMP') || // Windows - writeableDir('\\TEMP') || // Windows - writeableDir('\\TMP') || // Windows - writeableDir('/tmp') || - writeableDir('/var/tmp') || - writeableDir('/usr/tmp') || - writeableDir('.'); // last resort - - return state.tempDir; -} -module.exports = _tempDir; - -var common = require('./common'); -var fs = require('fs'); - -//@ -//@ ### test(expression) -//@ Available expression primaries: -//@ -//@ + `'-b', 'path'`: true if path is a block device -//@ + `'-c', 'path'`: true if path is a character device -//@ + `'-d', 'path'`: true if path is a directory -//@ + `'-e', 'path'`: true if path exists -//@ + `'-f', 'path'`: true if path is a regular file -//@ + `'-L', 'path'`: true if path is a symbolic link -//@ + `'-p', 'path'`: true if path is a pipe (FIFO) -//@ + `'-S', 'path'`: true if path is a socket -//@ -//@ Examples: -//@ -//@ ```javascript -//@ if (test('-d', path)) { /* do something with dir */ }; -//@ if (!test('-f', path)) continue; // skip if it's a regular file -//@ ``` -//@ -//@ Evaluates expression using the available primaries and returns corresponding value. -function _test(options, path) { - if (!path) - common.error('no path given'); - - // hack - only works with unary primaries - options = common.parseOptions(options, { - 'b': 'block', - 'c': 'character', - 'd': 'directory', - 'e': 'exists', - 'f': 'file', - 'L': 'link', - 'p': 'pipe', - 'S': 'socket' - }); - - var canInterpret = false; - for (var key in options) - if (options[key] === true) { - canInterpret = true; - break; - } - - if (!canInterpret) - common.error('could not interpret expression'); - - if (options.link) { - try { - return fs.lstatSync(path).isSymbolicLink(); - } catch(e) { - return false; - } - } - - if (!fs.existsSync(path)) - return false; - - if (options.exists) - return true; - - var stats = fs.statSync(path); - - if (options.block) - return stats.isBlockDevice(); - - if (options.character) - return stats.isCharacterDevice(); - - if (options.directory) - return stats.isDirectory(); - - if (options.file) - return stats.isFile(); - - if (options.pipe) - return stats.isFIFO(); - - if (options.socket) - return stats.isSocket(); -} // test -module.exports = _test; - -var common = require('./common'); -var fs = require('fs'); -var path = require('path'); - -//@ -//@ ### 'string'.to(file) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cat('input.txt').to('output.txt'); -//@ ``` -//@ -//@ Analogous to the redirection operator `>` in Unix, but works with JavaScript strings (such as -//@ those returned by `cat`, `grep`, etc). _Like Unix redirections, `to()` will overwrite any existing file!_ -function _to(options, file) { - if (!file) - common.error('wrong arguments'); - - if (!fs.existsSync( path.dirname(file) )) - common.error('no such file or directory: ' + path.dirname(file)); - - try { - fs.writeFileSync(file, this.toString(), 'utf8'); - return this; - } catch(e) { - common.error('could not write to file (code '+e.code+'): '+file, true); - } -} -module.exports = _to; - -var common = require('./common'); -var fs = require('fs'); -var path = require('path'); - -//@ -//@ ### 'string'.toEnd(file) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ cat('input.txt').toEnd('output.txt'); -//@ ``` -//@ -//@ Analogous to the redirect-and-append operator `>>` in Unix, but works with JavaScript strings (such as -//@ those returned by `cat`, `grep`, etc). -function _toEnd(options, file) { - if (!file) - common.error('wrong arguments'); - - if (!fs.existsSync( path.dirname(file) )) - common.error('no such file or directory: ' + path.dirname(file)); - - try { - fs.appendFileSync(file, this.toString(), 'utf8'); - return this; - } catch(e) { - common.error('could not append to file (code '+e.code+'): '+file, true); - } -} -module.exports = _toEnd; - -var common = require('./common'); -var fs = require('fs'); - -//@ -//@ ### touch([options,] file) -//@ Available options: -//@ -//@ + `-a`: Change only the access time -//@ + `-c`: Do not create any files -//@ + `-m`: Change only the modification time -//@ + `-d DATE`: Parse DATE and use it instead of current time -//@ + `-r FILE`: Use FILE's times instead of current time -//@ -//@ Examples: -//@ -//@ ```javascript -//@ touch('source.js'); -//@ touch('-c', '/path/to/some/dir/source.js'); -//@ touch({ '-r': FILE }, '/path/to/some/dir/source.js'); -//@ ``` -//@ -//@ Update the access and modification times of each FILE to the current time. -//@ A FILE argument that does not exist is created empty, unless -c is supplied. -//@ This is a partial implementation of *[touch(1)](http://linux.die.net/man/1/touch)*. -function _touch(opts, files) { - opts = common.parseOptions(opts, { - 'a': 'atime_only', - 'c': 'no_create', - 'd': 'date', - 'm': 'mtime_only', - 'r': 'reference', - }); - - if (!files) { - common.error('no paths given'); - } - - - if (Array.isArray(files)) { - files.forEach(function(f) { - touchFile(opts, f); - }); - } else if (typeof files === 'string') { - touchFile(opts, files); - } else { - common.error('file arg should be a string file path or an Array of string file paths'); - } - -} - -function touchFile(opts, file) { - var stat = tryStatFile(file); - - if (stat && stat.isDirectory()) { - // don't error just exit - return; - } - - // if the file doesn't already exist and the user has specified --no-create then - // this script is finished - if (!stat && opts.no_create) { - return; - } - - // open the file and then close it. this will create it if it doesn't exist but will - // not truncate the file - fs.closeSync(fs.openSync(file, 'a')); - - // - // Set timestamps - // - - // setup some defaults - var now = new Date(); - var mtime = opts.date || now; - var atime = opts.date || now; - - // use reference file - if (opts.reference) { - var refStat = tryStatFile(opts.reference); - if (!refStat) { - common.error('failed to get attributess of ' + opts.reference); - } - mtime = refStat.mtime; - atime = refStat.atime; - } else if (opts.date) { - mtime = opts.date; - atime = opts.date; - } - - if (opts.atime_only && opts.mtime_only) { - // keep the new values of mtime and atime like GNU - } else if (opts.atime_only) { - mtime = stat.mtime; - } else if (opts.mtime_only) { - atime = stat.atime; - } - - fs.utimesSync(file, atime, mtime); -} - -module.exports = _touch; - -function tryStatFile(filePath) { - try { - return fs.statSync(filePath); - } catch (e) { - return null; - } -} - -var common = require('./common'); -var fs = require('fs'); -var path = require('path'); - -// XP's system default value for PATHEXT system variable, just in case it's not -// set on Windows. -var XP_DEFAULT_PATHEXT = '.com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh'; - -// Cross-platform method for splitting environment PATH variables -function splitPath(p) { - if (!p) - return []; - - if (common.platform === 'win') - return p.split(';'); - else - return p.split(':'); -} - -function checkPath(path) { - return fs.existsSync(path) && !fs.statSync(path).isDirectory(); -} - -//@ -//@ ### which(command) -//@ -//@ Examples: -//@ -//@ ```javascript -//@ var nodeExec = which('node'); -//@ ``` -//@ -//@ Searches for `command` in the system's PATH. On Windows, this uses the -//@ `PATHEXT` variable to append the extension if it's not already executable. -//@ Returns string containing the absolute path to the command. -function _which(options, cmd) { - if (!cmd) - common.error('must specify command'); - - var pathEnv = process.env.path || process.env.Path || process.env.PATH, - pathArray = splitPath(pathEnv), - where = null; - - // No relative/absolute paths provided? - if (cmd.search(/\//) === -1) { - // Search for command in PATH - pathArray.forEach(function(dir) { - if (where) - return; // already found it - - var attempt = path.resolve(dir, cmd); - - if (common.platform === 'win') { - attempt = attempt.toUpperCase(); - - // In case the PATHEXT variable is somehow not set (e.g. - // child_process.spawn with an empty environment), use the XP default. - var pathExtEnv = process.env.PATHEXT || XP_DEFAULT_PATHEXT; - var pathExtArray = splitPath(pathExtEnv.toUpperCase()); - var i; - - // If the extension is already in PATHEXT, just return that. - for (i = 0; i < pathExtArray.length; i++) { - var ext = pathExtArray[i]; - if (attempt.slice(-ext.length) === ext && checkPath(attempt)) { - where = attempt; - return; - } - } - - // Cycle through the PATHEXT variable - var baseAttempt = attempt; - for (i = 0; i < pathExtArray.length; i++) { - attempt = baseAttempt + pathExtArray[i]; - if (checkPath(attempt)) { - where = attempt; - return; - } - } - } else { - // Assume it's Unix-like - if (checkPath(attempt)) { - where = attempt; - return; - } - } - }); - } - - // Command not found anywhere? - if (!checkPath(cmd) && !where) - return null; - - where = where || path.resolve(cmd); - - return common.ShellString(where); -} -module.exports = _which; diff --git a/tools/eslint/node_modules/shelljs/package.json b/tools/eslint/node_modules/shelljs/package.json index b3928ac932..5bf5252a8b 100644 --- a/tools/eslint/node_modules/shelljs/package.json +++ b/tools/eslint/node_modules/shelljs/package.json @@ -14,20 +14,20 @@ ] ], "_from": "shelljs@>=0.6.0 <0.7.0", - "_id": "shelljs@0.6.0", + "_id": "shelljs@0.6.1", "_inCache": true, "_installable": true, "_location": "/shelljs", - "_nodeVersion": "5.4.0", + "_nodeVersion": "6.0.0", "_npmOperationalInternal": { - "host": "packages-6-west.internal.npmjs.com", - "tmp": "tmp/shelljs-0.6.0.tgz_1454632811074_0.5800695188809186" + "host": "packages-16-east.internal.npmjs.com", + "tmp": "tmp/shelljs-0.6.1.tgz_1470519555022_0.9348916830495" }, "_npmUser": { - "name": "ariporad", - "email": "ari@ariporad.com" + "name": "nfischer", + "email": "ntfschr@gmail.com" }, - "_npmVersion": "3.6.0", + "_npmVersion": "3.5.2", "_phantomChildren": {}, "_requested": { "raw": "shelljs@^0.6.0", @@ -41,8 +41,8 @@ "_requiredBy": [ "/eslint" ], - "_resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz", - "_shasum": "ce1ed837b4b0e55b5ec3dab84251ab9dbdc0c7ec", + "_resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", + "_shasum": "ec6211bed1920442088fe0f70b2837232ed2c8a8", "_shrinkwrap": null, "_spec": "shelljs@^0.6.0", "_where": "/Users/trott/io.js/tools/node_modules/eslint", @@ -75,13 +75,13 @@ }, "directories": {}, "dist": { - "shasum": "ce1ed837b4b0e55b5ec3dab84251ab9dbdc0c7ec", - "tarball": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.0.tgz" + "shasum": "ec6211bed1920442088fe0f70b2837232ed2c8a8", + "tarball": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz" }, "engines": { "node": ">=0.10.0" }, - "gitHead": "fe06baf1173ec6f0a70cd58ddb7d373f4c6446f5", + "gitHead": "a5b9e2a64ffdf9f837d6ceb15d7f42221875542b", "homepage": "http://github.com/shelljs/shelljs", "keywords": [ "unix", @@ -117,5 +117,5 @@ "scripts": { "test": "node scripts/run-tests" }, - "version": "0.6.0" + "version": "0.6.1" } diff --git a/tools/eslint/node_modules/wordwrap/package.json b/tools/eslint/node_modules/wordwrap/package.json index 30966fe226..3121a6ed03 100644 --- a/tools/eslint/node_modules/wordwrap/package.json +++ b/tools/eslint/node_modules/wordwrap/package.json @@ -62,7 +62,7 @@ }, "dist": { "shasum": "27584810891456a4171c8d0226441ade90cbcaeb", - "tarball": "http://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" + "tarball": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz" }, "gitHead": "9f02667e901f2f10d87c33f7093fcf94788ab2f8", "homepage": "https://github.com/substack/node-wordwrap#readme", diff --git a/tools/eslint/package.json b/tools/eslint/package.json index 720d9454a9..0041730965 100644 --- a/tools/eslint/package.json +++ b/tools/eslint/package.json @@ -14,20 +14,20 @@ ] ], "_from": "eslint@latest", - "_id": "eslint@3.2.2", + "_id": "eslint@3.3.0", "_inCache": true, "_installable": true, "_location": "/eslint", - "_nodeVersion": "4.4.2", + "_nodeVersion": "4.4.7", "_npmOperationalInternal": { "host": "packages-12-west.internal.npmjs.com", - "tmp": "tmp/eslint-3.2.2.tgz_1470077896026_0.7558055422268808" + "tmp": "tmp/eslint-3.3.0.tgz_1471027082338_0.7748861608561128" }, "_npmUser": { - "name": "nzakas", - "email": "nicholas@nczconsulting.com" + "name": "eslint", + "email": "nicholas+eslint@nczconsulting.com" }, - "_npmVersion": "2.15.0", + "_npmVersion": "2.15.8", "_phantomChildren": {}, "_requested": { "raw": "eslint", @@ -41,8 +41,8 @@ "_requiredBy": [ "#USER" ], - "_resolved": "https://registry.npmjs.org/eslint/-/eslint-3.2.2.tgz", - "_shasum": "47226f6b0e709f23f6acd06c5cc9e97b39574c7c", + "_resolved": "https://registry.npmjs.org/eslint/-/eslint-3.3.0.tgz", + "_shasum": "9524700cf94f90f0447f34152e68e99d39034f57", "_shrinkwrap": null, "_spec": "eslint", "_where": "/Users/trott/io.js/tools", @@ -78,6 +78,7 @@ "levn": "^0.3.0", "lodash": "^4.0.0", "mkdirp": "^0.5.0", + "natural-compare": "^1.4.0", "optionator": "^0.8.1", "path-is-inside": "^1.0.1", "pluralize": "^1.2.1", @@ -103,7 +104,8 @@ "coveralls": "2.11.4", "dateformat": "^1.0.8", "ejs": "^2.3.3", - "eslint-release": "^0.5.0", + "eslint-plugin-node": "^2.0.0", + "eslint-release": "^0.10.0", "esprima": "^2.4.1", "esprima-fb": "^15001.1001.0-dev-harmony-fb", "gh-got": "^2.2.0", @@ -122,7 +124,7 @@ "mock-fs": "^3.10.0", "npm-license": "^0.3.2", "phantomjs-prebuilt": "^2.1.7", - "proxyquire": ">=1.0.0 <1.7.5", + "proxyquire": "^1.7.10", "semver": "^5.0.3", "shelljs-nodecli": "~0.1.0", "sinon": "^1.17.2", @@ -131,8 +133,8 @@ }, "directories": {}, "dist": { - "shasum": "47226f6b0e709f23f6acd06c5cc9e97b39574c7c", - "tarball": "https://registry.npmjs.org/eslint/-/eslint-3.2.2.tgz" + "shasum": "9524700cf94f90f0447f34152e68e99d39034f57", + "tarball": "https://registry.npmjs.org/eslint/-/eslint-3.3.0.tgz" }, "engines": { "node": ">=4" @@ -145,7 +147,7 @@ "lib", "messages" ], - "gitHead": "cc4559c9d7b07ee82d73030c5f593968ddf7e0c8", + "gitHead": "c66bcfec9fe0d166a5ed7b9910eb8cc802ff94d7", "homepage": "http://eslint.org", "keywords": [ "ast", @@ -182,6 +184,7 @@ "betarelease": "node Makefile.js prerelease -- beta", "browserify": "node Makefile.js browserify", "check-commit": "node Makefile.js checkGitCommit", + "ci-release": "node Makefile.js ciRelease", "coveralls": "cat ./coverage/lcov.info | coveralls", "docs": "node Makefile.js docs", "gensite": "node Makefile.js gensite", @@ -191,5 +194,5 @@ "release": "node Makefile.js release", "test": "node Makefile.js test" }, - "version": "3.2.2" + "version": "3.3.0" } |