Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build(deps): bump eslint from 8.53.0 to 8.54.0 #1657

Merged
merged 1 commit into from
Nov 20, 2023

Conversation

dependabot[bot]
Copy link
Contributor

@dependabot dependabot bot commented on behalf of github Nov 20, 2023

Bumps eslint from 8.53.0 to 8.54.0.

Release notes

Sourced from eslint's releases.

v8.54.0

Features

  • a7a883b feat: for-direction rule add check for condition in reverse order (#17755) (Angelo Annunziata)
  • 1452dc9 feat: Add suggestions to no-console (#17680) (Joel Mathew Koshy)
  • 21ebf8a feat: update no-array-constructor rule (#17711) (Francesco Trotta)

Bug Fixes

  • 98926e6 fix: Ensure that extra data is not accidentally stored in the cache file (#17760) (Milos Djermanovic)
  • e8cf9f6 fix: Make dark scroll bar in dark theme (#17753) (Pavel)
  • 3cbeaad fix: Use cwd constructor option as config basePath in Linter (#17705) (Milos Djermanovic)

Documentation

  • becfdd3 docs: Make clear when rules are removed (#17728) (Nicholas C. Zakas)
  • 05d6e99 docs: update "Submit a Pull Request" page (#17712) (Francesco Trotta)
  • eb2279e docs: display info about deprecated rules (#17749) (Percy Ma)
  • d245326 docs: Correct working in migrating plugin docs (#17722) (Filip Tammergård)

Chores

  • d644de9 chore: upgrade @​eslint/js@​8.54.0 (#17773) (Milos Djermanovic)
  • 1e6e314 chore: package.json update for @​eslint/js release (Jenkins)
  • 6fb8805 chore: Fixed grammar in issue_templates/rule_change (#17770) (Joel Mathew Koshy)
  • 85db724 chore: upgrade markdownlint to 0.31.1 (#17754) (Nitin Kumar)
  • 6d470d2 chore: update dependency recast to ^0.23.0 (#17736) (renovate[bot])
  • b7121b5 chore: update dependency markdownlint-cli to ^0.37.0 (#17735) (renovate[bot])
  • 633b9a1 chore: update dependency regenerator-runtime to ^0.14.0 (#17739) (renovate[bot])
  • acac16f chore: update dependency vite-plugin-commonjs to ^0.10.0 (#17740) (renovate[bot])
  • ba8ca7e chore: add .github/renovate.json5 (#17567) (Josh Goldberg ✨)
Changelog

Sourced from eslint's changelog.

v8.54.0 - November 17, 2023

  • d644de9 chore: upgrade @​eslint/js@​8.54.0 (#17773) (Milos Djermanovic)
  • 1e6e314 chore: package.json update for @​eslint/js release (Jenkins)
  • 98926e6 fix: Ensure that extra data is not accidentally stored in the cache file (#17760) (Milos Djermanovic)
  • a7a883b feat: for-direction rule add check for condition in reverse order (#17755) (Angelo Annunziata)
  • 1452dc9 feat: Add suggestions to no-console (#17680) (Joel Mathew Koshy)
  • 6fb8805 chore: Fixed grammar in issue_templates/rule_change (#17770) (Joel Mathew Koshy)
  • becfdd3 docs: Make clear when rules are removed (#17728) (Nicholas C. Zakas)
  • e8cf9f6 fix: Make dark scroll bar in dark theme (#17753) (Pavel)
  • 85db724 chore: upgrade markdownlint to 0.31.1 (#17754) (Nitin Kumar)
  • 21ebf8a feat: update no-array-constructor rule (#17711) (Francesco Trotta)
  • 05d6e99 docs: update "Submit a Pull Request" page (#17712) (Francesco Trotta)
  • eb2279e docs: display info about deprecated rules (#17749) (Percy Ma)
  • 6d470d2 chore: update dependency recast to ^0.23.0 (#17736) (renovate[bot])
  • b7121b5 chore: update dependency markdownlint-cli to ^0.37.0 (#17735) (renovate[bot])
  • 633b9a1 chore: update dependency regenerator-runtime to ^0.14.0 (#17739) (renovate[bot])
  • acac16f chore: update dependency vite-plugin-commonjs to ^0.10.0 (#17740) (renovate[bot])
  • ba8ca7e chore: add .github/renovate.json5 (#17567) (Josh Goldberg ✨)
  • 3cbeaad fix: Use cwd constructor option as config basePath in Linter (#17705) (Milos Djermanovic)
  • d245326 docs: Correct working in migrating plugin docs (#17722) (Filip Tammergård)
  • 5454c22 Revert "chore: remove metascraper (#17707)" (#17708) (Milos Djermanovic)
Commits

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot merge will merge this PR after your CI passes on it
  • @dependabot squash and merge will squash and merge this PR after your CI passes on it
  • @dependabot cancel merge will cancel a previously requested merge and block automerging
  • @dependabot reopen will reopen this PR if it is closed
  • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore <dependency name> major version will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
  • @dependabot ignore <dependency name> minor version will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
  • @dependabot ignore <dependency name> will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
  • @dependabot unignore <dependency name> will remove all of the ignore conditions of the specified dependency
  • @dependabot unignore <dependency name> <ignore condition> will remove the ignore condition of the specified dependency and ignore conditions

@dependabot dependabot bot added dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code labels Nov 20, 2023
@github-actions github-actions bot enabled auto-merge (squash) November 20, 2023 03:04
Copy link
Contributor

Diff between eslint 8.53.0 and 8.54.0
diff --git a/lib/rules/utils/ast-utils.js b/lib/rules/utils/ast-utils.js
index v8.53.0..v8.54.0 100644
--- a/lib/rules/utils/ast-utils.js
+++ b/lib/rules/utils/ast-utils.js
@@ -1016,4 +1016,112 @@
 }
 
+/**
+ * Tests if a node appears at the beginning of an ancestor ExpressionStatement node.
+ * @param {ASTNode} node The node to check.
+ * @returns {boolean} Whether the node appears at the beginning of an ancestor ExpressionStatement node.
+ */
+function isStartOfExpressionStatement(node) {
+    const start = node.range[0];
+    let ancestor = node;
+
+    while ((ancestor = ancestor.parent) && ancestor.range[0] === start) {
+        if (ancestor.type === "ExpressionStatement") {
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * Determines whether an opening parenthesis `(`, bracket `[` or backtick ``` ` ``` needs to be preceded by a semicolon.
+ * This opening parenthesis or bracket should be at the start of an `ExpressionStatement` or at the start of the body of an `ArrowFunctionExpression`.
+ * @type {(sourceCode: SourceCode, node: ASTNode) => boolean}
+ * @param {SourceCode} sourceCode The source code object.
+ * @param {ASTNode} node A node at the position where an opening parenthesis or bracket will be inserted.
+ * @returns {boolean} Whether a semicolon is required before the opening parenthesis or braket.
+ */
+let needsPrecedingSemicolon;
+
+{
+    const BREAK_OR_CONTINUE = new Set(["BreakStatement", "ContinueStatement"]);
+
+    // Declaration types that must contain a string Literal node at the end.
+    const DECLARATIONS = new Set(["ExportAllDeclaration", "ExportNamedDeclaration", "ImportDeclaration"]);
+
+    const IDENTIFIER_OR_KEYWORD = new Set(["Identifier", "Keyword"]);
+
+    // Keywords that can immediately precede an ExpressionStatement node, mapped to the their node types.
+    const NODE_TYPES_BY_KEYWORD = {
+        __proto__: null,
+        break: "BreakStatement",
+        continue: "ContinueStatement",
+        debugger: "DebuggerStatement",
+        do: "DoWhileStatement",
+        else: "IfStatement",
+        return: "ReturnStatement",
+        yield: "YieldExpression"
+    };
+
+    /*
+     * Before an opening parenthesis, postfix `++` and `--` always trigger ASI;
+     * the tokens `:`, `;`, `{` and `=>` don't expect a semicolon, as that would count as an empty statement.
+     */
+    const PUNCTUATORS = new Set([":", ";", "{", "=>", "++", "--"]);
+
+    /*
+     * Statements that can contain an `ExpressionStatement` after a closing parenthesis.
+     * DoWhileStatement is an exception in that it always triggers ASI after the closing parenthesis.
+     */
+    const STATEMENTS = new Set([
+        "DoWhileStatement",
+        "ForInStatement",
+        "ForOfStatement",
+        "ForStatement",
+        "IfStatement",
+        "WhileStatement",
+        "WithStatement"
+    ]);
+
+    needsPrecedingSemicolon =
+    function(sourceCode, node) {
+        const prevToken = sourceCode.getTokenBefore(node);
+
+        if (!prevToken || prevToken.type === "Punctuator" && PUNCTUATORS.has(prevToken.value)) {
+            return false;
+        }
+
+        const prevNode = sourceCode.getNodeByRangeIndex(prevToken.range[0]);
+
+        if (isClosingParenToken(prevToken)) {
+            return !STATEMENTS.has(prevNode.type);
+        }
+
+        if (isClosingBraceToken(prevToken)) {
+            return (
+                prevNode.type === "BlockStatement" && prevNode.parent.type === "FunctionExpression" ||
+                prevNode.type === "ClassBody" && prevNode.parent.type === "ClassExpression" ||
+                prevNode.type === "ObjectExpression"
+            );
+        }
+
+        if (IDENTIFIER_OR_KEYWORD.has(prevToken.type)) {
+            if (BREAK_OR_CONTINUE.has(prevNode.parent.type)) {
+                return false;
+            }
+
+            const keyword = prevToken.value;
+            const nodeType = NODE_TYPES_BY_KEYWORD[keyword];
+
+            return prevNode.type !== nodeType;
+        }
+
+        if (prevToken.type === "String") {
+            return !DECLARATIONS.has(prevNode.parent.type);
+        }
+
+        return true;
+    };
+}
+
 //------------------------------------------------------------------------------
 // Public Interface
@@ -2169,4 +2277,6 @@
     isConstant,
     isTopLevelExpressionStatement,
-    isDirective
+    isDirective,
+    isStartOfExpressionStatement,
+    needsPrecedingSemicolon
 };
diff --git a/lib/rules/for-direction.js b/lib/rules/for-direction.js
index v8.53.0..v8.54.0 100644
--- a/lib/rules/for-direction.js
+++ b/lib/rules/for-direction.js
@@ -102,28 +102,35 @@
             return 0;
         }
+
         return {
             ForStatement(node) {
 
-                if (node.test && node.test.type === "BinaryExpression" && node.test.left.type === "Identifier" && node.update) {
-                    const counter = node.test.left.name;
-                    const operator = node.test.operator;
-                    const update = node.update;
+                if (node.test && node.test.type === "BinaryExpression" && node.update) {
+                    for (const counterPosition of ["left", "right"]) {
+                        if (node.test[counterPosition].type !== "Identifier") {
+                            continue;
+                        }
 
-                    let wrongDirection;
+                        const counter = node.test[counterPosition].name;
+                        const operator = node.test.operator;
+                        const update = node.update;
 
-                    if (operator === "<" || operator === "<=") {
-                        wrongDirection = -1;
-                    } else if (operator === ">" || operator === ">=") {
-                        wrongDirection = 1;
-                    } else {
-                        return;
-                    }
+                        let wrongDirection;
 
-                    if (update.type === "UpdateExpression") {
-                        if (getUpdateDirection(update, counter) === wrongDirection) {
+                        if (operator === "<" || operator === "<=") {
+                            wrongDirection = counterPosition === "left" ? -1 : 1;
+                        } else if (operator === ">" || operator === ">=") {
+                            wrongDirection = counterPosition === "left" ? 1 : -1;
+                        } else {
+                            return;
+                        }
+
+                        if (update.type === "UpdateExpression") {
+                            if (getUpdateDirection(update, counter) === wrongDirection) {
+                                report(node);
+                            }
+                        } else if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) === wrongDirection) {
                             report(node);
                         }
-                    } else if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) === wrongDirection) {
-                        report(node);
                     }
                 }
diff --git a/lib/cli-engine/lint-result-cache.js b/lib/cli-engine/lint-result-cache.js
index v8.53.0..v8.54.0 100644
--- a/lib/cli-engine/lint-result-cache.js
+++ b/lib/cli-engine/lint-result-cache.js
@@ -129,14 +129,26 @@
         }
 
+        const cachedResults = fileDescriptor.meta.results;
+
+        // Just in case, not sure if this can ever happen.
+        if (!cachedResults) {
+            return cachedResults;
+        }
+
+        /*
+         * Shallow clone the object to ensure that any properties added or modified afterwards
+         * will not be accidentally stored in the cache file when `reconcile()` is called.
+         * https://github.com/eslint/eslint/issues/13507
+         * All intentional changes to the cache file must be done through `setCachedLintResults()`.
+         */
+        const results = { ...cachedResults };
+
         // If source is present but null, need to reread the file from the filesystem.
-        if (
-            fileDescriptor.meta.results &&
-            fileDescriptor.meta.results.source === null
-        ) {
+        if (results.source === null) {
             debug(`Rereading cached result source from filesystem: ${filePath}`);
-            fileDescriptor.meta.results.source = fs.readFileSync(filePath, "utf-8");
+            results.source = fs.readFileSync(filePath, "utf-8");
         }
 
-        return fileDescriptor.meta.results;
+        return results;
     }
 
diff --git a/lib/linter/linter.js b/lib/linter/linter.js
index v8.53.0..v8.54.0 100644
--- a/lib/linter/linter.js
+++ b/lib/linter/linter.js
@@ -1423,5 +1423,5 @@
         debug("Verify");
 
-        const { configType } = internalSlotsMap.get(this);
+        const { configType, cwd } = internalSlotsMap.get(this);
 
         const options = typeof filenameOrOptions === "string"
@@ -1442,5 +1442,5 @@
 
                 if (!Array.isArray(config) || typeof config.getConfig !== "function") {
-                    configArray = new FlatConfigArray(config);
+                    configArray = new FlatConfigArray(config, { basePath: cwd });
                     configArray.normalizeSync();
                 }
diff --git a/lib/rules/no-array-constructor.js b/lib/rules/no-array-constructor.js
index v8.53.0..v8.54.0 100644
--- a/lib/rules/no-array-constructor.js
+++ b/lib/rules/no-array-constructor.js
@@ -7,4 +7,16 @@
 
 //------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const {
+    getVariableByName,
+    isClosingParenToken,
+    isOpeningParenToken,
+    isStartOfExpressionStatement,
+    needsPrecedingSemicolon
+} = require("./utils/ast-utils");
+
+//------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -21,8 +33,12 @@
         },
 
+        hasSuggestions: true,
+
         schema: [],
 
         messages: {
-            preferLiteral: "The array literal notation [] is preferable."
+            preferLiteral: "The array literal notation [] is preferable.",
+            useLiteral: "Replace with an array literal.",
+            useLiteralAfterSemicolon: "Replace with an array literal, add preceding semicolon."
         }
     },
@@ -30,5 +46,31 @@
     create(context) {
 
+        const sourceCode = context.sourceCode;
+
         /**
+         * Gets the text between the calling parentheses of a CallExpression or NewExpression.
+         * @param {ASTNode} node A CallExpression or NewExpression node.
+         * @returns {string} The text between the calling parentheses, or an empty string if there are none.
+         */
+        function getArgumentsText(node) {
+            const lastToken = sourceCode.getLastToken(node);
+
+            if (!isClosingParenToken(lastToken)) {
+                return "";
+            }
+
+            let firstToken = node.callee;
+
+            do {
+                firstToken = sourceCode.getTokenAfter(firstToken);
+                if (!firstToken || firstToken === lastToken) {
+                    return "";
+                }
+            } while (!isOpeningParenToken(firstToken));
+
+            return sourceCode.text.slice(firstToken.range[1], lastToken.range[0]);
+        }
+
+        /**
          * Disallow construction of dense arrays using the Array constructor
          * @param {ASTNode} node node to evaluate
@@ -38,10 +80,47 @@
         function check(node) {
             if (
-                node.arguments.length !== 1 &&
-                node.callee.type === "Identifier" &&
-                node.callee.name === "Array"
-            ) {
-                context.report({ node, messageId: "preferLiteral" });
+                node.callee.type !== "Identifier" ||
+                node.callee.name !== "Array" ||
+                node.arguments.length === 1 &&
+                node.arguments[0].type !== "SpreadElement") {
+                return;
             }
+
+            const variable = getVariableByName(sourceCode.getScope(node), "Array");
+
+            /*
+             * Check if `Array` is a predefined global variable: predefined globals have no declarations,
+             * meaning that the `identifiers` list of the variable object is empty.
+             */
+            if (variable && variable.identifiers.length === 0) {
+                const argsText = getArgumentsText(node);
+                let fixText;
+                let messageId;
+
+                /*
+                 * Check if the suggested change should include a preceding semicolon or not.
+                 * Due to JavaScript's ASI rules, a missing semicolon may be inserted automatically
+                 * before an expression like `Array()` or `new Array()`, but not when the expression
+                 * is changed into an array literal like `[]`.
+                 */
+                if (isStartOfExpressionStatement(node) && needsPrecedingSemicolon(sourceCode, node)) {
+                    fixText = `;[${argsText}]`;
+                    messageId = "useLiteralAfterSemicolon";
+                } else {
+                    fixText = `[${argsText}]`;
+                    messageId = "useLiteral";
+                }
+
+                context.report({
+                    node,
+                    messageId: "preferLiteral",
+                    suggest: [
+                        {
+                            messageId,
+                            fix: fixer => fixer.replaceText(node, fixText)
+                        }
+                    ]
+                });
+            }
         }
 
diff --git a/lib/rules/no-console.js b/lib/rules/no-console.js
index v8.53.0..v8.54.0 100644
--- a/lib/rules/no-console.js
+++ b/lib/rules/no-console.js
@@ -44,6 +44,9 @@
         ],
 
+        hasSuggestions: true,
+
         messages: {
-            unexpected: "Unexpected console statement."
+            unexpected: "Unexpected console statement.",
+            removeConsole: "Remove the console.{{ propertyName }}()."
         }
     },
@@ -96,4 +99,62 @@
 
         /**
+         * Checks if removing the ExpressionStatement node will cause ASI to
+         * break.
+         * eg.
+         * foo()
+         * console.log();
+         * [1, 2, 3].forEach(a => doSomething(a))
+         *
+         * Removing the console.log(); statement should leave two statements, but
+         * here the two statements will become one because [ causes continuation after
+         * foo().
+         * @param {ASTNode} node The ExpressionStatement node to check.
+         * @returns {boolean} `true` if ASI will break after removing the ExpressionStatement
+         *      node.
+         */
+        function maybeAsiHazard(node) {
+            const SAFE_TOKENS_BEFORE = /^[:;{]$/u; // One of :;{
+            const UNSAFE_CHARS_AFTER = /^[-[(/+`]/u; // One of [(/+-`
+
+            const tokenBefore = sourceCode.getTokenBefore(node);
+            const tokenAfter = sourceCode.getTokenAfter(node);
+
+            return (
+                Boolean(tokenAfter) &&
+                UNSAFE_CHARS_AFTER.test(tokenAfter.value) &&
+                tokenAfter.value !== "++" &&
+                tokenAfter.value !== "--" &&
+                Boolean(tokenBefore) &&
+                !SAFE_TOKENS_BEFORE.test(tokenBefore.value)
+            );
+        }
+
+        /**
+         * Checks if the MemberExpression node's parent.parent.parent is a
+         * Program, BlockStatement, StaticBlock, or SwitchCase node. This check
+         * is necessary to avoid providing a suggestion that might cause a syntax error.
+         *
+         * eg. if (a) console.log(b), removing console.log() here will lead to a
+         *     syntax error.
+         *     if (a) { console.log(b) }, removing console.log() here is acceptable.
+         *
+         * Additionally, it checks if the callee of the CallExpression node is
+         * the node itself.
+         *
+         * eg. foo(console.log), cannot provide a suggestion here.
+         * @param {ASTNode} node The MemberExpression node to check.
+         * @returns {boolean} `true` if a suggestion can be provided for a node.
+         */
+        function canProvideSuggestions(node) {
+            return (
+                node.parent.type === "CallExpression" &&
+                node.parent.callee === node &&
+                node.parent.parent.type === "ExpressionStatement" &&
+                astUtils.STATEMENT_LIST_PARENTS.has(node.parent.parent.parent.type) &&
+                !maybeAsiHazard(node.parent.parent)
+            );
+        }
+
+        /**
          * Reports the given reference as a violation.
          * @param {eslint-scope.Reference} reference The reference to report.
@@ -103,8 +164,19 @@
             const node = reference.identifier.parent;
 
+            const propertyName = astUtils.getStaticPropertyName(node);
+
             context.report({
                 node,
                 loc: node.loc,
-                messageId: "unexpected"
+                messageId: "unexpected",
+                suggest: canProvideSuggestions(node)
+                    ? [{
+                        messageId: "removeConsole",
+                        data: { propertyName },
+                        fix(fixer) {
+                            return fixer.remove(node.parent.parent);
+                        }
+                    }]
+                    : []
             });
         }
diff --git a/lib/rules/no-object-constructor.js b/lib/rules/no-object-constructor.js
index v8.53.0..v8.54.0 100644
--- a/lib/rules/no-object-constructor.js
+++ b/lib/rules/no-object-constructor.js
@@ -10,67 +10,12 @@
 //------------------------------------------------------------------------------
 
-const { getVariableByName, isArrowToken, isClosingBraceToken, isClosingParenToken } = require("./utils/ast-utils");
+const {
+    getVariableByName,
+    isArrowToken,
+    isStartOfExpressionStatement,
+    needsPrecedingSemicolon
+} = require("./utils/ast-utils");
 
 //------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-const BREAK_OR_CONTINUE = new Set(["BreakStatement", "ContinueStatement"]);
-
-// Declaration types that must contain a string Literal node at the end.
-const DECLARATIONS = new Set(["ExportAllDeclaration", "ExportNamedDeclaration", "ImportDeclaration"]);
-
-const IDENTIFIER_OR_KEYWORD = new Set(["Identifier", "Keyword"]);
-
-// Keywords that can immediately precede an ExpressionStatement node, mapped to the their node types.
-const NODE_TYPES_BY_KEYWORD = {
-    __proto__: null,
-    break: "BreakStatement",
-    continue: "ContinueStatement",
-    debugger: "DebuggerStatement",
-    do: "DoWhileStatement",
-    else: "IfStatement",
-    return: "ReturnStatement",
-    yield: "YieldExpression"
-};
-
-/*
- * Before an opening parenthesis, postfix `++` and `--` always trigger ASI;
- * the tokens `:`, `;`, `{` and `=>` don't expect a semicolon, as that would count as an empty statement.
- */
-const PUNCTUATORS = new Set([":", ";", "{", "=>", "++", "--"]);
-
-/*
- * Statements that can contain an `ExpressionStatement` after a closing parenthesis.
- * DoWhileStatement is an exception in that it always triggers ASI after the closing parenthesis.
- */
-const STATEMENTS = new Set([
-    "DoWhileStatement",
-    "ForInStatement",
-    "ForOfStatement",
-    "ForStatement",
-    "IfStatement",
-    "WhileStatement",
-    "WithStatement"
-]);
-
-/**
- * Tests if a node appears at the beginning of an ancestor ExpressionStatement node.
- * @param {ASTNode} node The node to check.
- * @returns {boolean} Whether the node appears at the beginning of an ancestor ExpressionStatement node.
- */
-function isStartOfExpressionStatement(node) {
-    const start = node.range[0];
-    let ancestor = node;
-
-    while ((ancestor = ancestor.parent) && ancestor.range[0] === start) {
-        if (ancestor.type === "ExpressionStatement") {
-            return true;
-        }
-    }
-    return false;
-}
-
-//------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -122,48 +67,4 @@
 
         /**
-         * Determines whether a parenthesized object literal that replaces a specified node needs to be preceded by a semicolon.
-         * @param {ASTNode} node The node to be replaced. This node should be at the start of an `ExpressionStatement` or at the start of the body of an `ArrowFunctionExpression`.
-         * @returns {boolean} Whether a semicolon is required before the parenthesized object literal.
-         */
-        function needsSemicolon(node) {
-            const prevToken = sourceCode.getTokenBefore(node);
-
-            if (!prevToken || prevToken.type === "Punctuator" && PUNCTUATORS.has(prevToken.value)) {
-                return false;
-            }
-
-            const prevNode = sourceCode.getNodeByRangeIndex(prevToken.range[0]);
-
-            if (isClosingParenToken(prevToken)) {
-                return !STATEMENTS.has(prevNode.type);
-            }
-
-            if (isClosingBraceToken(prevToken)) {
-                return (
-                    prevNode.type === "BlockStatement" && prevNode.parent.type === "FunctionExpression" ||
-                    prevNode.type === "ClassBody" && prevNode.parent.type === "ClassExpression" ||
-                    prevNode.type === "ObjectExpression"
-                );
-            }
-
-            if (IDENTIFIER_OR_KEYWORD.has(prevToken.type)) {
-                if (BREAK_OR_CONTINUE.has(prevNode.parent.type)) {
-                    return false;
-                }
-
-                const keyword = prevToken.value;
-                const nodeType = NODE_TYPES_BY_KEYWORD[keyword];
-
-                return prevNode.type !== nodeType;
-            }
-
-            if (prevToken.type === "String") {
-                return !DECLARATIONS.has(prevNode.parent.type);
-            }
-
-            return true;
-        }
-
-        /**
          * Reports on nodes where the `Object` constructor is called without arguments.
          * @param {ASTNode} node The node to evaluate.
@@ -184,5 +85,5 @@
                 if (needsParentheses(node)) {
                     replacement = "({})";
-                    if (needsSemicolon(node)) {
+                    if (needsPrecedingSemicolon(sourceCode, node)) {
                         fixText = ";({})";
                         messageId = "useLiteralAfterSemicolon";
diff --git a/package.json b/package.json
index v8.53.0..v8.54.0 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
 {
   "name": "eslint",
-  "version": "8.53.0",
+  "version": "8.54.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
@@ -42,4 +42,8 @@
       "git add packages/js/src/configs/eslint-all.js"
     ],
+    "docs/src/rules/*.md": [
+      "node tools/fetch-docs-links.js",
+      "git add docs/src/_data/further_reading_links.json"
+    ],
     "docs/**/*.svg": "npx svgo -r --multipass"
   },
@@ -60,5 +64,5 @@
     "@eslint-community/regexpp": "^4.6.1",
     "@eslint/eslintrc": "^2.1.3",
-    "@eslint/js": "8.53.0",
+    "@eslint/js": "8.54.0",
     "@humanwhocodes/config-array": "^0.11.13",
     "@humanwhocodes/module-importer": "^1.0.1",
@@ -129,8 +133,14 @@
     "lint-staged": "^11.0.0",
     "load-perf": "^0.2.0",
-    "markdownlint": "^0.25.1",
-    "markdownlint-cli": "^0.31.1",
+    "markdownlint": "^0.31.1",
+    "markdownlint-cli": "^0.37.0",
     "marked": "^4.0.8",
     "memfs": "^3.0.1",
+    "metascraper": "^5.25.7",
+    "metascraper-description": "^5.25.7",
+    "metascraper-image": "^5.29.3",
+    "metascraper-logo": "^5.25.7",
+    "metascraper-logo-favicon": "^5.25.7",
+    "metascraper-title": "^5.25.7",
     "mocha": "^8.3.2",
     "mocha-junit-reporter": "^2.0.0",
@@ -140,11 +150,11 @@
     "progress": "^2.0.3",
     "proxyquire": "^2.0.1",
-    "recast": "^0.20.4",
-    "regenerator-runtime": "^0.13.2",
+    "recast": "^0.23.0",
+    "regenerator-runtime": "^0.14.0",
     "rollup-plugin-node-polyfills": "^0.2.1",
     "semver": "^7.5.3",
     "shelljs": "^0.8.2",
     "sinon": "^11.0.0",
-    "vite-plugin-commonjs": "^0.8.2",
+    "vite-plugin-commonjs": "^0.10.0",
     "webdriverio": "^8.14.6",
     "webpack": "^5.23.0",
Size Files
2.9 MB → 2.9 MB (+7.3 KB 🟡) 407 → 407 (±0 🟢)
Command details
npm diff --diff=eslint@8.53.0 --diff=eslint@8.54.0 --diff-unified=2

See also the npm diff document.

Reported by ybiquitous/npm-diff-action@v1.5.0 (Node.js 20.9.0 and npm 10.2.4)

@dependabot dependabot bot force-pushed the dependabot/npm_and_yarn/eslint-8.54.0 branch from aaa22f9 to d2bc8cf Compare November 20, 2023 03:07
Bumps [eslint](https://github.com/eslint/eslint) from 8.53.0 to 8.54.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](eslint/eslint@v8.53.0...v8.54.0)

---
updated-dependencies:
- dependency-name: eslint
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot bot force-pushed the dependabot/npm_and_yarn/eslint-8.54.0 branch from d2bc8cf to 1f9fc22 Compare November 20, 2023 03:10
@github-actions github-actions bot merged commit 954d715 into main Nov 20, 2023
5 checks passed
@github-actions github-actions bot deleted the dependabot/npm_and_yarn/eslint-8.54.0 branch November 20, 2023 03:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

0 participants