diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json index 8bb9e1b057..a72ec4eb8a 100644 --- a/node_modules/.package-lock.json +++ b/node_modules/.package-lock.json @@ -448,9 +448,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", - "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -934,21 +934,21 @@ } }, "node_modules/@types/uuid": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.4.tgz", - "integrity": "sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==" + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", + "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.3.tgz", - "integrity": "sha512-vntq452UHNltxsaaN+L9WyuMch8bMd9CqJ3zhzTPXXidwbf5mqqKCVXEuvRZUqLJSTLeWE65lQwyXsRGnXkCTA==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.5.tgz", + "integrity": "sha512-JhtAwTRhOUcP96D0Y6KYnwig/MRQbOoLGXTON2+LlyB/N35SP9j1boai2zzwXb7ypKELXMx3DVk9UTaEq1vHEw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/type-utils": "6.7.3", - "@typescript-eslint/utils": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/type-utils": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -974,15 +974,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.3.tgz", - "integrity": "sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.5.tgz", + "integrity": "sha512-bIZVSGx2UME/lmhLcjdVc7ePBwn7CLqKarUBL4me1C5feOd663liTGjMBGVcGr+BhnSLeP4SgwdvNnnkbIdkCw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/typescript-estree": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4" }, "engines": { @@ -1002,13 +1002,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.3.tgz", - "integrity": "sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.5.tgz", + "integrity": "sha512-GAlk3eQIwWOJeb9F7MKQ6Jbah/vx1zETSDw8likab/eFcqkjSD7BI75SDAeC5N2L0MmConMoPvTsmkrg71+B1A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1019,13 +1019,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.3.tgz", - "integrity": "sha512-Fc68K0aTDrKIBvLnKTZ5Pf3MXK495YErrbHb1R6aTpfK5OdSFj0rVN7ib6Tx6ePrZ2gsjLqr0s98NG7l96KSQw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.5.tgz", + "integrity": "sha512-Gs0qos5wqxnQrvpYv+pf3XfcRXW6jiAn9zE/K+DlmYf6FcpxeNYN0AIETaPR7rHO4K2UY+D0CIbDP9Ut0U4m1g==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.3", - "@typescript-eslint/utils": "6.7.3", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/utils": "6.7.5", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1046,9 +1046,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.3.tgz", - "integrity": "sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.5.tgz", + "integrity": "sha512-WboQBlOXtdj1tDFPyIthpKrUb+kZf2VroLZhxKa/VlwLlLyqv/PwUNgL30BlTVZV1Wu4Asu2mMYPqarSO4L5ZQ==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1059,13 +1059,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.3.tgz", - "integrity": "sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.5.tgz", + "integrity": "sha512-NhJiJ4KdtwBIxrKl0BqG1Ur+uw7FiOnOThcYx9DpOGJ/Abc9z2xNzLeirCG02Ig3vkvrc2qFLmYSSsaITbKjlg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1086,17 +1086,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.3.tgz", - "integrity": "sha512-vzLkVder21GpWRrmSR9JxGZ5+ibIUSudXlW52qeKpzUEQhRSmyZiVDDj3crAth7+5tmN1ulvgKaCU2f/bPRCzg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.5.tgz", + "integrity": "sha512-pfRRrH20thJbzPPlPc4j0UNGvH1PjPlhlCMq4Yx7EGjV7lvEeGX0U6MJYe8+SyFutWgSHsdbJ3BXzZccYggezA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/typescript-estree": "6.7.3", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", "semver": "^7.5.4" }, "engines": { @@ -1111,12 +1111,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.3.tgz", - "integrity": "sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.5.tgz", + "integrity": "sha512-3MaWdDZtLlsexZzDSdQWsFQ9l9nL8B80Z4fImSpyllFC/KLqWQRdEcB+gGGO+N3Q2uL40EsG66wZLsohPxNXvg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.3", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2470,15 +2470,15 @@ } }, "node_modules/eslint": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", - "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.50.0", + "@eslint/js": "8.51.0", "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5445,9 +5445,9 @@ "dev": true }, "node_modules/sinon": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.0.0.tgz", - "integrity": "sha512-B8AaZZm9CT5pqe4l4uWJztfD/mOTa7dL8Qo0W4+s+t74xECOgSZDDQCBjNgIK3+n4kyxQrSTv2V5ul8K25qkiQ==", + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.0.tgz", + "integrity": "sha512-ZSgzF0vwmoa8pq0GEynqfdnpEDyP1PkYmEChnkjW0Vyh8IDlyFEJ+fkMhCP0il6d5cJjPl2PUsnUSAuP5sttOQ==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", diff --git a/node_modules/@eslint/js/package.json b/node_modules/@eslint/js/package.json index fc5fb50fcb..7e43db7f2e 100644 --- a/node_modules/@eslint/js/package.json +++ b/node_modules/@eslint/js/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/js", - "version": "8.50.0", + "version": "8.51.0", "description": "ESLint JavaScript language implementation", "main": "./src/index.js", "scripts": {}, diff --git a/node_modules/@types/uuid/README.md b/node_modules/@types/uuid/README.md index d80f82d2d6..7d13368388 100644 --- a/node_modules/@types/uuid/README.md +++ b/node_modules/@types/uuid/README.md @@ -8,7 +8,7 @@ This package contains type definitions for uuid (https://github.com/uuidjs/uuid) Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/uuid. ### Additional Details - * Last updated: Thu, 14 Sep 2023 14:21:18 GMT + * Last updated: Fri, 06 Oct 2023 23:05:45 GMT * Dependencies: none * Global values: none diff --git a/node_modules/@types/uuid/index.d.mts b/node_modules/@types/uuid/index.d.mts index f4061e020b..247c8b0dc0 100644 --- a/node_modules/@types/uuid/index.d.mts +++ b/node_modules/@types/uuid/index.d.mts @@ -1,4 +1,4 @@ -import uuid from './index.js'; +import uuid from "./index.js"; export import v1 = uuid.v1; export import v3 = uuid.v3; export import v4 = uuid.v4; @@ -7,4 +7,4 @@ export import NIL = uuid.NIL; export import version = uuid.version; export import validate = uuid.validate; export import stringify = uuid.stringify; -export import parse = uuid.parse; \ No newline at end of file +export import parse = uuid.parse; diff --git a/node_modules/@types/uuid/package.json b/node_modules/@types/uuid/package.json index e81ac07d96..7ab6914bc0 100644 --- a/node_modules/@types/uuid/package.json +++ b/node_modules/@types/uuid/package.json @@ -1,6 +1,6 @@ { "name": "@types/uuid", - "version": "9.0.4", + "version": "9.0.5", "description": "TypeScript definitions for uuid", "homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/uuid", "license": "MIT", @@ -40,7 +40,7 @@ }, "scripts": {}, "dependencies": {}, - "typesPublisherContentHash": "bce6069b94fc3e504545efe5646f5e5d0ccbb6a2cfaf3d36698b945952fa4fec", + "typesPublisherContentHash": "321106d7a0649dc4bbe8cbc573e0812a78e7208fb095cae5b3497341fad32196", "typeScriptVersion": "4.5", "exports": { "./package.json": "./package.json", diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js index 9f62a3d536..79f0ba8c61 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js @@ -117,19 +117,17 @@ exports.default = (0, util_1.createRule)({ evaluatedLength.value === evaluatedString.value.length); } /** - * Check if a given node is a negative index expression - * - * E.g. `s.slice(- )`, `s.substring(s.length - )` - * - * @param node The node to check. - * @param expectedIndexedNode The node which is expected as the receiver of index expression. + * Returns true if `node` is `-substring.length` or + * `parentString.length - substring.length` */ - function isNegativeIndexExpression(node, expectedIndexedNode) { + function isLengthAheadOfEnd(node, substring, parentString) { return ((node.type === utils_1.AST_NODE_TYPES.UnaryExpression && - node.operator === '-') || + node.operator === '-' && + isLengthExpression(node.argument, substring)) || (node.type === utils_1.AST_NODE_TYPES.BinaryExpression && node.operator === '-' && - isLengthExpression(node.left, expectedIndexedNode))); + isLengthExpression(node.left, parentString) && + isLengthExpression(node.right, substring))); } /** * Check if a given node is the expression of the last index. @@ -405,14 +403,34 @@ exports.default = (0, util_1.createRule)({ if (!isEqualityComparison(parentNode) || !isStringType(node.object)) { return; } - const isEndsWith = (callNode.arguments.length === 1 || - (callNode.arguments.length === 2 && - isLengthExpression(callNode.arguments[1], node.object))) && - isNegativeIndexExpression(callNode.arguments[0], node.object); - const isStartsWith = !isEndsWith && - callNode.arguments.length === 2 && + let isEndsWith = false; + let isStartsWith = false; + if (callNode.arguments.length === 1) { + if ( + // foo.slice(-bar.length) === bar + // foo.slice(foo.length - bar.length) === bar + isLengthAheadOfEnd(callNode.arguments[0], parentNode.right, node.object)) { + isEndsWith = true; + } + } + else if (callNode.arguments.length === 2) { + if ( + // foo.slice(0, bar.length) === bar isNumber(callNode.arguments[0], 0) && - !isNegativeIndexExpression(callNode.arguments[1], node.object); + isLengthExpression(callNode.arguments[1], parentNode.right)) { + isStartsWith = true; + } + else if ( + // foo.slice(foo.length - bar.length, foo.length) === bar + // foo.slice(foo.length - bar.length, 0) === bar + // foo.slice(-bar.length, foo.length) === bar + // foo.slice(-bar.length, 0) === bar + (isLengthExpression(callNode.arguments[1], node.object) || + isNumber(callNode.arguments[1], 0)) && + isLengthAheadOfEnd(callNode.arguments[0], parentNode.right, node.object)) { + isEndsWith = true; + } + } if (!isStartsWith && !isEndsWith) { return; } diff --git a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js.map b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js.map index d49a5ade7f..dceadbc60b 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js.map +++ b/node_modules/@typescript-eslint/eslint-plugin/dist/rules/prefer-string-starts-ends-with.js.map @@ -1 +1 @@ -{"version":3,"file":"prefer-string-starts-ends-with.js","sourceRoot":"","sources":["../../src/rules/prefer-string-starts-ends-with.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"prefer-string-starts-ends-with.js","sourceRoot":"","sources":["../../src/rules/prefer-string-starts-ends-with.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-optional-chain.md b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-optional-chain.md index 6efb88b17a..4168281948 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-optional-chain.md +++ b/node_modules/@typescript-eslint/eslint-plugin/docs/rules/prefer-optional-chain.md @@ -76,7 +76,7 @@ declare function acceptsBoolean(arg: boolean): void; acceptsBoolean(foo != null && foo.bar); // ❌ typechecks UNSUCCESSFULLY as the expression returns `boolean | undefined` -acceptsBoolean(foo != null && foo.bar); +acceptsBoolean(foo?.bar); ``` This style of code isn't super common - which means having this option set to `true` _should_ be safe in most codebases. However we default it to `false` due to its unsafe nature. We have provided this option for convenience because it increases the autofix cases covered by the rule. If you set option to `true` the onus is entirely on you and your team to ensure that each fix is correct and safe and that it does not break the build. diff --git a/node_modules/@typescript-eslint/eslint-plugin/package.json b/node_modules/@typescript-eslint/eslint-plugin/package.json index d908762f7c..85e3c08993 100644 --- a/node_modules/@typescript-eslint/eslint-plugin/package.json +++ b/node_modules/@typescript-eslint/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "6.7.3", + "version": "6.7.5", "description": "TypeScript plugin for ESLint", "files": [ "dist", @@ -57,10 +57,10 @@ }, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/type-utils": "6.7.3", - "@typescript-eslint/utils": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/type-utils": "6.7.5", + "@typescript-eslint/utils": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -73,8 +73,8 @@ "@types/marked": "*", "@types/natural-compare": "*", "@types/prettier": "*", - "@typescript-eslint/rule-schema-to-typescript-types": "6.7.3", - "@typescript-eslint/rule-tester": "6.7.3", + "@typescript-eslint/rule-schema-to-typescript-types": "6.7.5", + "@typescript-eslint/rule-tester": "6.7.5", "ajv": "^6.12.6", "chalk": "^5.3.0", "cross-fetch": "*", @@ -103,5 +103,5 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/@typescript-eslint/parser/package.json b/node_modules/@typescript-eslint/parser/package.json index 2507495246..3ca18dd8e0 100644 --- a/node_modules/@typescript-eslint/parser/package.json +++ b/node_modules/@typescript-eslint/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "6.7.3", + "version": "6.7.5", "description": "An ESLint custom parser which leverages TypeScript ESTree", "files": [ "dist", @@ -51,10 +51,10 @@ "eslint": "^7.0.0 || ^8.0.0" }, "dependencies": { - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/typescript-estree": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4" }, "devDependencies": { @@ -82,5 +82,5 @@ ] } }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/@typescript-eslint/scope-manager/package.json b/node_modules/@typescript-eslint/scope-manager/package.json index cf392b2e05..9bead40edd 100644 --- a/node_modules/@typescript-eslint/scope-manager/package.json +++ b/node_modules/@typescript-eslint/scope-manager/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/scope-manager", - "version": "6.7.3", + "version": "6.7.5", "description": "TypeScript scope analyser for ESLint", "files": [ "dist", @@ -44,12 +44,12 @@ "typecheck": "nx typecheck" }, "dependencies": { - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3" + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5" }, "devDependencies": { "@types/glob": "*", - "@typescript-eslint/typescript-estree": "6.7.3", + "@typescript-eslint/typescript-estree": "6.7.5", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", @@ -67,5 +67,5 @@ ] } }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/@typescript-eslint/type-utils/package.json b/node_modules/@typescript-eslint/type-utils/package.json index 4bb5be1d79..96143b109a 100644 --- a/node_modules/@typescript-eslint/type-utils/package.json +++ b/node_modules/@typescript-eslint/type-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/type-utils", - "version": "6.7.3", + "version": "6.7.5", "description": "Type utilities for working with TypeScript + ESLint together", "files": [ "dist", @@ -45,13 +45,13 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.3", - "@typescript-eslint/utils": "6.7.3", + "@typescript-eslint/typescript-estree": "6.7.5", + "@typescript-eslint/utils": "6.7.5", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, "devDependencies": { - "@typescript-eslint/parser": "6.7.3", + "@typescript-eslint/parser": "6.7.5", "ajv": "^6.10.0", "downlevel-dts": "*", "jest": "29.7.0", @@ -78,5 +78,5 @@ ] } }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/@typescript-eslint/types/package.json b/node_modules/@typescript-eslint/types/package.json index 520161ed05..92cda7ad09 100644 --- a/node_modules/@typescript-eslint/types/package.json +++ b/node_modules/@typescript-eslint/types/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/types", - "version": "6.7.3", + "version": "6.7.5", "description": "Types for the TypeScript-ESTree AST spec", "files": [ "dist", @@ -90,5 +90,5 @@ ] } }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/@typescript-eslint/typescript-estree/package.json b/node_modules/@typescript-eslint/typescript-estree/package.json index 21da563c78..1669885923 100644 --- a/node_modules/@typescript-eslint/typescript-estree/package.json +++ b/node_modules/@typescript-eslint/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "6.7.3", + "version": "6.7.5", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "files": [ "dist", @@ -52,8 +52,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/visitor-keys": "6.7.5", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -88,5 +88,5 @@ ] } }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/@typescript-eslint/utils/package.json b/node_modules/@typescript-eslint/utils/package.json index db26216b4f..ddd197fbf9 100644 --- a/node_modules/@typescript-eslint/utils/package.json +++ b/node_modules/@typescript-eslint/utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/utils", - "version": "6.7.3", + "version": "6.7.5", "description": "Utilities for working with TypeScript + ESLint together", "files": [ "dist", @@ -68,16 +68,16 @@ "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/typescript-estree": "6.7.3", + "@typescript-eslint/scope-manager": "6.7.5", + "@typescript-eslint/types": "6.7.5", + "@typescript-eslint/typescript-estree": "6.7.5", "semver": "^7.5.4" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0" }, "devDependencies": { - "@typescript-eslint/parser": "6.7.3", + "@typescript-eslint/parser": "6.7.5", "downlevel-dts": "*", "jest": "29.7.0", "prettier": "^2.8.4", @@ -95,5 +95,5 @@ ] } }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/@typescript-eslint/visitor-keys/package.json b/node_modules/@typescript-eslint/visitor-keys/package.json index 9c0eb2dd3a..8450d757ae 100644 --- a/node_modules/@typescript-eslint/visitor-keys/package.json +++ b/node_modules/@typescript-eslint/visitor-keys/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/visitor-keys", - "version": "6.7.3", + "version": "6.7.5", "description": "Visitor keys used to help traverse the TypeScript-ESTree AST", "files": [ "dist", @@ -45,7 +45,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "6.7.3", + "@typescript-eslint/types": "6.7.5", "eslint-visitor-keys": "^3.4.1" }, "devDependencies": { @@ -67,5 +67,5 @@ ] } }, - "gitHead": "91a3e0c85a8fb2001ad808362b437df0b90cce04" + "gitHead": "36aecb6a836eb01307c35b42ca60f5a78496c339" } diff --git a/node_modules/eslint/README.md b/node_modules/eslint/README.md index 0b82961932..7aa4019ed8 100644 --- a/node_modules/eslint/README.md +++ b/node_modules/eslint/README.md @@ -288,8 +288,8 @@ The following companies, organizations, and individuals support ESLint's ongoing

Platinum Sponsors

Chrome Frameworks Fund Automattic

Gold Sponsors

Salesforce Airbnb

Silver Sponsors

-

Sentry Liftoff Siemens American Express

Bronze Sponsors

-

ThemeIsle Nx (by Nrwl) Anagram Solver Icons8 Discord Transloadit Ignition HeroCoders QuickBooks Tool hub

+

Liftoff Siemens American Express

Bronze Sponsors

+

ThemeIsle Anagram Solver Icons8 Discord Transloadit Ignition HeroCoders QuickBooks Tool hub

## Technology Sponsors diff --git a/node_modules/eslint/bin/eslint.js b/node_modules/eslint/bin/eslint.js index 7094ac77bc..5c7972cc08 100755 --- a/node_modules/eslint/bin/eslint.js +++ b/node_modules/eslint/bin/eslint.js @@ -92,6 +92,14 @@ function getErrorMessage(error) { return util.format("%o", error); } +/** + * Tracks error messages that are shown to the user so we only ever show the + * same message once. + * @type {Set} + */ + +const displayedErrors = new Set(); + /** * Catch and report unexpected error. * @param {any} error The thrown error object. @@ -101,14 +109,17 @@ function onFatalError(error) { process.exitCode = 2; const { version } = require("../package.json"); - const message = getErrorMessage(error); - - console.error(` + const message = ` Oops! Something went wrong! :( ESLint: ${version} -${message}`); +${getErrorMessage(error)}`; + + if (!displayedErrors.has(message)) { + console.error(message); + displayedErrors.add(message); + } } //------------------------------------------------------------------------------ diff --git a/node_modules/eslint/lib/cli.js b/node_modules/eslint/lib/cli.js index a14930e9b0..807d28a0d1 100644 --- a/node_modules/eslint/lib/cli.js +++ b/node_modules/eslint/lib/cli.js @@ -91,7 +91,8 @@ async function translateOptions({ reportUnusedDisableDirectives, resolvePluginsRelativeTo, rule, - rulesdir + rulesdir, + warnIgnored }, configType) { let overrideConfig, overrideConfigFile; @@ -182,6 +183,7 @@ async function translateOptions({ if (configType === "flat") { options.ignorePatterns = ignorePattern; + options.warnIgnored = warnIgnored; } else { options.resolvePluginsRelativeTo = resolvePluginsRelativeTo; options.rulePaths = rulesdir; @@ -385,7 +387,9 @@ const cli = { if (useStdin) { results = await engine.lintText(text, { filePath: options.stdinFilename, - warnIgnored: true + + // flatConfig respects CLI flag and constructor warnIgnored, eslintrc forces true for backwards compatibility + warnIgnored: usingFlatConfig ? void 0 : true }); } else { results = await engine.lintFiles(files); diff --git a/node_modules/eslint/lib/config/flat-config-schema.js b/node_modules/eslint/lib/config/flat-config-schema.js index a79c02d663..df850995d8 100644 --- a/node_modules/eslint/lib/config/flat-config-schema.js +++ b/node_modules/eslint/lib/config/flat-config-schema.js @@ -179,9 +179,7 @@ class InvalidRuleSeverityError extends Error { * @throws {InvalidRuleSeverityError} If the value isn't a valid rule severity. */ function assertIsRuleSeverity(ruleId, value) { - const severity = typeof value === "string" - ? ruleSeverities.get(value.toLowerCase()) - : ruleSeverities.get(value); + const severity = ruleSeverities.get(value); if (typeof severity === "undefined") { throw new InvalidRuleSeverityError(ruleId, value); diff --git a/node_modules/eslint/lib/eslint/eslint-helpers.js b/node_modules/eslint/lib/eslint/eslint-helpers.js index e25b10e8bc..72828363c3 100644 --- a/node_modules/eslint/lib/eslint/eslint-helpers.js +++ b/node_modules/eslint/lib/eslint/eslint-helpers.js @@ -594,9 +594,9 @@ function createIgnoreResult(filePath, baseDir) { const isInNodeModules = baseDir && path.dirname(path.relative(baseDir, filePath)).split(path.sep).includes("node_modules"); if (isInNodeModules) { - message = "File ignored by default because it is located under the node_modules directory. Use ignore pattern \"!**/node_modules/\" to override."; + message = "File ignored by default because it is located under the node_modules directory. Use ignore pattern \"!**/node_modules/\" to disable file ignore settings or use \"--no-warn-ignored\" to suppress this warning."; } else { - message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override."; + message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to disable file ignore settings or use \"--no-warn-ignored\" to suppress this warning."; } return { @@ -676,6 +676,7 @@ function processOptions({ overrideConfigFile = null, plugins = {}, reportUnusedDisableDirectives = null, // ← should be null by default because if it's a string then it overrides the 'reportUnusedDisableDirectives' setting in config files. And we cannot use `overrideConfig.reportUnusedDisableDirectives` instead because we cannot configure the `error` severity with that. + warnIgnored = true, ...unknownOptions }) { const errors = []; @@ -781,6 +782,9 @@ function processOptions({ ) { errors.push("'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null."); } + if (typeof warnIgnored !== "boolean") { + errors.push("'warnIgnored' must be a boolean."); + } if (errors.length > 0) { throw new ESLintInvalidOptionsError(errors); } @@ -802,7 +806,8 @@ function processOptions({ globInputPaths, ignore, ignorePatterns, - reportUnusedDisableDirectives + reportUnusedDisableDirectives, + warnIgnored }; } diff --git a/node_modules/eslint/lib/eslint/flat-eslint.js b/node_modules/eslint/lib/eslint/flat-eslint.js index 4ef3861136..306c80de1d 100644 --- a/node_modules/eslint/lib/eslint/flat-eslint.js +++ b/node_modules/eslint/lib/eslint/flat-eslint.js @@ -84,6 +84,7 @@ const LintResultCache = require("../cli-engine/lint-result-cache"); * when a string. * @property {Record} [plugins] An array of plugin implementations. * @property {"error" | "warn" | "off"} [reportUnusedDisableDirectives] the severity to report unused eslint-disable directives. + * @property {boolean} warnIgnored Show warnings when the file list includes ignored files */ //------------------------------------------------------------------------------ @@ -749,7 +750,8 @@ class FlatESLint { fixTypes, reportUnusedDisableDirectives, globInputPaths, - errorOnUnmatchedPattern + errorOnUnmatchedPattern, + warnIgnored } = eslintOptions; const startTime = Date.now(); const fixTypesSet = fixTypes ? new Set(fixTypes) : null; @@ -795,7 +797,11 @@ class FlatESLint { * pattern, then notify the user. */ if (ignored) { - return createIgnoreResult(filePath, cwd); + if (warnIgnored) { + return createIgnoreResult(filePath, cwd); + } + + return void 0; } const config = configs.getConfig(filePath); @@ -908,7 +914,7 @@ class FlatESLint { const { filePath, - warnIgnored = false, + warnIgnored, ...unknownOptions } = options || {}; @@ -922,7 +928,7 @@ class FlatESLint { throw new Error("'options.filePath' must be a non-empty string or undefined"); } - if (typeof warnIgnored !== "boolean") { + if (typeof warnIgnored !== "boolean" && typeof warnIgnored !== "undefined") { throw new Error("'options.warnIgnored' must be a boolean or undefined"); } @@ -937,7 +943,8 @@ class FlatESLint { allowInlineConfig, cwd, fix, - reportUnusedDisableDirectives + reportUnusedDisableDirectives, + warnIgnored: constructorWarnIgnored } = eslintOptions; const results = []; const startTime = Date.now(); @@ -945,7 +952,9 @@ class FlatESLint { // Clear the last used config arrays. if (resolvedFilename && await this.isPathIgnored(resolvedFilename)) { - if (warnIgnored) { + const shouldWarnIgnored = typeof warnIgnored === "boolean" ? warnIgnored : constructorWarnIgnored; + + if (shouldWarnIgnored) { results.push(createIgnoreResult(resolvedFilename, cwd)); } } else { diff --git a/node_modules/eslint/lib/linter/apply-disable-directives.js b/node_modules/eslint/lib/linter/apply-disable-directives.js index 13ced990ff..55f7683f3f 100644 --- a/node_modules/eslint/lib/linter/apply-disable-directives.js +++ b/node_modules/eslint/lib/linter/apply-disable-directives.js @@ -87,7 +87,7 @@ function createIndividualDirectivesRemoval(directives, commentToken) { return directives.map(directive => { const { ruleId } = directive; - const regex = new RegExp(String.raw`(?:^|\s*,\s*)${escapeRegExp(ruleId)}(?:\s*,\s*|$)`, "u"); + const regex = new RegExp(String.raw`(?:^|\s*,\s*)(?['"]?)${escapeRegExp(ruleId)}\k(?:\s*,\s*|$)`, "u"); const match = regex.exec(listText); const matchedText = match[0]; const matchStartOffset = listStartOffset + match.index; diff --git a/node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js b/node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js index d187297d32..2b0dc2bfca 100644 --- a/node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js +++ b/node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js @@ -12,13 +12,622 @@ const CodePathSegment = require("./code-path-segment"), ForkContext = require("./fork-context"); +//----------------------------------------------------------------------------- +// Contexts +//----------------------------------------------------------------------------- + +/** + * Represents the context in which a `break` statement can be used. + * + * A `break` statement without a label is only valid in a few places in + * JavaScript: any type of loop or a `switch` statement. Otherwise, `break` + * without a label causes a syntax error. For these contexts, `breakable` is + * set to `true` to indicate that a `break` without a label is valid. + * + * However, a `break` statement with a label is also valid inside of a labeled + * statement. For example, this is valid: + * + * a : { + * break a; + * } + * + * The `breakable` property is set false for labeled statements to indicate + * that `break` without a label is invalid. + */ +class BreakContext { + + /** + * Creates a new instance. + * @param {BreakContext} upperContext The previous `BreakContext`. + * @param {boolean} breakable Indicates if we are inside a statement where + * `break` without a label will exit the statement. + * @param {string|null} label The label for the statement. + * @param {ForkContext} forkContext The current fork context. + */ + constructor(upperContext, breakable, label, forkContext) { + + /** + * The previous `BreakContext` + * @type {BreakContext} + */ + this.upper = upperContext; + + /** + * Indicates if we are inside a statement where `break` without a label + * will exit the statement. + * @type {boolean} + */ + this.breakable = breakable; + + /** + * The label associated with the statement. + * @type {string|null} + */ + this.label = label; + + /** + * The fork context for the `break`. + * @type {ForkContext} + */ + this.brokenForkContext = ForkContext.newEmpty(forkContext); + } +} + +/** + * Represents the context for `ChainExpression` nodes. + */ +class ChainContext { + + /** + * Creates a new instance. + * @param {ChainContext} upperContext The previous `ChainContext`. + */ + constructor(upperContext) { + + /** + * The previous `ChainContext` + * @type {ChainContext} + */ + this.upper = upperContext; + + /** + * The number of choice contexts inside of the `ChainContext`. + * @type {number} + */ + this.choiceContextCount = 0; + + } +} + +/** + * Represents a choice in the code path. + * + * Choices are created by logical operators such as `&&`, loops, conditionals, + * and `if` statements. This is the point at which the code path has a choice of + * which direction to go. + * + * The result of a choice might be in the left (test) expression of another choice, + * and in that case, may create a new fork. For example, `a || b` is a choice + * but does not create a new fork because the result of the expression is + * not used as the test expression in another expression. In this case, + * `isForkingAsResult` is false. In the expression `a || b || c`, the `a || b` + * expression appears as the test expression for `|| c`, so the + * result of `a || b` creates a fork because execution may or may not + * continue to `|| c`. `isForkingAsResult` for `a || b` in this case is true + * while `isForkingAsResult` for `|| c` is false. (`isForkingAsResult` is always + * false for `if` statements, conditional expressions, and loops.) + * + * All of the choices except one (`??`) operate on a true/false fork, meaning if + * true go one way and if false go the other (tracked by `trueForkContext` and + * `falseForkContext`). The `??` operator doesn't operate on true/false because + * the left expression is evaluated to be nullish or not, so only if nullish do + * we fork to the right expression (tracked by `nullishForkContext`). + */ +class ChoiceContext { + + /** + * Creates a new instance. + * @param {ChoiceContext} upperContext The previous `ChoiceContext`. + * @param {string} kind The kind of choice. If it's a logical or assignment expression, this + * is `"&&"` or `"||"` or `"??"`; if it's an `if` statement or + * conditional expression, this is `"test"`; otherwise, this is `"loop"`. + * @param {boolean} isForkingAsResult Indicates if the result of the choice + * creates a fork. + * @param {ForkContext} forkContext The containing `ForkContext`. + */ + constructor(upperContext, kind, isForkingAsResult, forkContext) { + + /** + * The previous `ChoiceContext` + * @type {ChoiceContext} + */ + this.upper = upperContext; + + /** + * The kind of choice. If it's a logical or assignment expression, this + * is `"&&"` or `"||"` or `"??"`; if it's an `if` statement or + * conditional expression, this is `"test"`; otherwise, this is `"loop"`. + * @type {string} + */ + this.kind = kind; + + /** + * Indicates if the result of the choice forks the code path. + * @type {boolean} + */ + this.isForkingAsResult = isForkingAsResult; + + /** + * The fork context for the `true` path of the choice. + * @type {ForkContext} + */ + this.trueForkContext = ForkContext.newEmpty(forkContext); + + /** + * The fork context for the `false` path of the choice. + * @type {ForkContext} + */ + this.falseForkContext = ForkContext.newEmpty(forkContext); + + /** + * The fork context for when the choice result is `null` or `undefined`. + * @type {ForkContext} + */ + this.nullishForkContext = ForkContext.newEmpty(forkContext); + + /** + * Indicates if any of `trueForkContext`, `falseForkContext`, or + * `nullishForkContext` have been updated with segments from a child context. + * @type {boolean} + */ + this.processed = false; + } + +} + +/** + * Base class for all loop contexts. + */ +class LoopContextBase { + + /** + * Creates a new instance. + * @param {LoopContext|null} upperContext The previous `LoopContext`. + * @param {string} type The AST node's `type` for the loop. + * @param {string|null} label The label for the loop from an enclosing `LabeledStatement`. + * @param {BreakContext} breakContext The context for breaking the loop. + */ + constructor(upperContext, type, label, breakContext) { + + /** + * The previous `LoopContext`. + * @type {LoopContext} + */ + this.upper = upperContext; + + /** + * The AST node's `type` for the loop. + * @type {string} + */ + this.type = type; + + /** + * The label for the loop from an enclosing `LabeledStatement`. + * @type {string|null} + */ + this.label = label; + + /** + * The fork context for when `break` is encountered. + * @type {ForkContext} + */ + this.brokenForkContext = breakContext.brokenForkContext; + } +} + +/** + * Represents the context for a `while` loop. + */ +class WhileLoopContext extends LoopContextBase { + + /** + * Creates a new instance. + * @param {LoopContext|null} upperContext The previous `LoopContext`. + * @param {string|null} label The label for the loop from an enclosing `LabeledStatement`. + * @param {BreakContext} breakContext The context for breaking the loop. + */ + constructor(upperContext, label, breakContext) { + super(upperContext, "WhileStatement", label, breakContext); + + /** + * The hardcoded literal boolean test condition for + * the loop. Used to catch infinite or skipped loops. + * @type {boolean|undefined} + */ + this.test = void 0; + + /** + * The segments representing the test condition where `continue` will + * jump to. The test condition will typically have just one segment but + * it's possible for there to be more than one. + * @type {Array|null} + */ + this.continueDestSegments = null; + } +} + +/** + * Represents the context for a `do-while` loop. + */ +class DoWhileLoopContext extends LoopContextBase { + + /** + * Creates a new instance. + * @param {LoopContext|null} upperContext The previous `LoopContext`. + * @param {string|null} label The label for the loop from an enclosing `LabeledStatement`. + * @param {BreakContext} breakContext The context for breaking the loop. + * @param {ForkContext} forkContext The enclosing fork context. + */ + constructor(upperContext, label, breakContext, forkContext) { + super(upperContext, "DoWhileStatement", label, breakContext); + + /** + * The hardcoded literal boolean test condition for + * the loop. Used to catch infinite or skipped loops. + * @type {boolean|undefined} + */ + this.test = void 0; + + /** + * The segments at the start of the loop body. This is the only loop + * where the test comes at the end, so the first iteration always + * happens and we need a reference to the first statements. + * @type {Array|null} + */ + this.entrySegments = null; + + /** + * The fork context to follow when a `continue` is found. + * @type {ForkContext} + */ + this.continueForkContext = ForkContext.newEmpty(forkContext); + } +} + +/** + * Represents the context for a `for` loop. + */ +class ForLoopContext extends LoopContextBase { + + /** + * Creates a new instance. + * @param {LoopContext|null} upperContext The previous `LoopContext`. + * @param {string|null} label The label for the loop from an enclosing `LabeledStatement`. + * @param {BreakContext} breakContext The context for breaking the loop. + */ + constructor(upperContext, label, breakContext) { + super(upperContext, "ForStatement", label, breakContext); + + /** + * The hardcoded literal boolean test condition for + * the loop. Used to catch infinite or skipped loops. + * @type {boolean|undefined} + */ + this.test = void 0; + + /** + * The end of the init expression. This may change during the lifetime + * of the instance as we traverse the loop because some loops don't have + * an init expression. + * @type {Array|null} + */ + this.endOfInitSegments = null; + + /** + * The start of the test expression. This may change during the lifetime + * of the instance as we traverse the loop because some loops don't have + * a test expression. + * @type {Array|null} + */ + this.testSegments = null; + + /** + * The end of the test expression. This may change during the lifetime + * of the instance as we traverse the loop because some loops don't have + * a test expression. + * @type {Array|null} + */ + this.endOfTestSegments = null; + + /** + * The start of the update expression. This may change during the lifetime + * of the instance as we traverse the loop because some loops don't have + * an update expression. + * @type {Array|null} + */ + this.updateSegments = null; + + /** + * The end of the update expresion. This may change during the lifetime + * of the instance as we traverse the loop because some loops don't have + * an update expression. + * @type {Array|null} + */ + this.endOfUpdateSegments = null; + + /** + * The segments representing the test condition where `continue` will + * jump to. The test condition will typically have just one segment but + * it's possible for there to be more than one. This may change during the + * lifetime of the instance as we traverse the loop because some loops + * don't have an update expression. When there is an update expression, this + * will end up pointing to that expression; otherwise it will end up pointing + * to the test expression. + * @type {Array|null} + */ + this.continueDestSegments = null; + } +} + +/** + * Represents the context for a `for-in` loop. + * + * Terminology: + * - "left" means the part of the loop to the left of the `in` keyword. For + * example, in `for (var x in y)`, the left is `var x`. + * - "right" means the part of the loop to the right of the `in` keyword. For + * example, in `for (var x in y)`, the right is `y`. + */ +class ForInLoopContext extends LoopContextBase { + + /** + * Creates a new instance. + * @param {LoopContext|null} upperContext The previous `LoopContext`. + * @param {string|null} label The label for the loop from an enclosing `LabeledStatement`. + * @param {BreakContext} breakContext The context for breaking the loop. + */ + constructor(upperContext, label, breakContext) { + super(upperContext, "ForInStatement", label, breakContext); + + /** + * The segments that came immediately before the start of the loop. + * This allows you to traverse backwards out of the loop into the + * surrounding code. This is necessary to evaluate the right expression + * correctly, as it must be evaluated in the same way as the left + * expression, but the pointer to these segments would otherwise be + * lost if not stored on the instance. Once the right expression has + * been evaluated, this property is no longer used. + * @type {Array|null} + */ + this.prevSegments = null; + + /** + * Segments representing the start of everything to the left of the + * `in` keyword. This can be used to move forward towards + * `endOfLeftSegments`. `leftSegments` and `endOfLeftSegments` are + * effectively the head and tail of a doubly-linked list. + * @type {Array|null} + */ + this.leftSegments = null; + + /** + * Segments representing the end of everything to the left of the + * `in` keyword. This can be used to move backward towards `leftSegments`. + * `leftSegments` and `endOfLeftSegments` are effectively the head + * and tail of a doubly-linked list. + * @type {Array|null} + */ + this.endOfLeftSegments = null; + + /** + * The segments representing the left expression where `continue` will + * jump to. In `for-in` loops, `continue` must always re-execute the + * left expression each time through the loop. This contains the same + * segments as `leftSegments`, but is duplicated here so each loop + * context has the same property pointing to where `continue` should + * end up. + * @type {Array|null} + */ + this.continueDestSegments = null; + } +} + +/** + * Represents the context for a `for-of` loop. + */ +class ForOfLoopContext extends LoopContextBase { + + /** + * Creates a new instance. + * @param {LoopContext|null} upperContext The previous `LoopContext`. + * @param {string|null} label The label for the loop from an enclosing `LabeledStatement`. + * @param {BreakContext} breakContext The context for breaking the loop. + */ + constructor(upperContext, label, breakContext) { + super(upperContext, "ForOfStatement", label, breakContext); + + /** + * The segments that came immediately before the start of the loop. + * This allows you to traverse backwards out of the loop into the + * surrounding code. This is necessary to evaluate the right expression + * correctly, as it must be evaluated in the same way as the left + * expression, but the pointer to these segments would otherwise be + * lost if not stored on the instance. Once the right expression has + * been evaluated, this property is no longer used. + * @type {Array|null} + */ + this.prevSegments = null; + + /** + * Segments representing the start of everything to the left of the + * `of` keyword. This can be used to move forward towards + * `endOfLeftSegments`. `leftSegments` and `endOfLeftSegments` are + * effectively the head and tail of a doubly-linked list. + * @type {Array|null} + */ + this.leftSegments = null; + + /** + * Segments representing the end of everything to the left of the + * `of` keyword. This can be used to move backward towards `leftSegments`. + * `leftSegments` and `endOfLeftSegments` are effectively the head + * and tail of a doubly-linked list. + * @type {Array|null} + */ + this.endOfLeftSegments = null; + + /** + * The segments representing the left expression where `continue` will + * jump to. In `for-in` loops, `continue` must always re-execute the + * left expression each time through the loop. This contains the same + * segments as `leftSegments`, but is duplicated here so each loop + * context has the same property pointing to where `continue` should + * end up. + * @type {Array|null} + */ + this.continueDestSegments = null; + } +} + +/** + * Represents the context for any loop. + * @typedef {WhileLoopContext|DoWhileLoopContext|ForLoopContext|ForInLoopContext|ForOfLoopContext} LoopContext + */ + +/** + * Represents the context for a `switch` statement. + */ +class SwitchContext { + + /** + * Creates a new instance. + * @param {SwitchContext} upperContext The previous context. + * @param {boolean} hasCase Indicates if there is at least one `case` statement. + * `default` doesn't count. + */ + constructor(upperContext, hasCase) { + + /** + * The previous context. + * @type {SwitchContext} + */ + this.upper = upperContext; + + /** + * Indicates if there is at least one `case` statement. `default` doesn't count. + * @type {boolean} + */ + this.hasCase = hasCase; + + /** + * The `default` keyword. + * @type {Array|null} + */ + this.defaultSegments = null; + + /** + * The default case body starting segments. + * @type {Array|null} + */ + this.defaultBodySegments = null; + + /** + * Indicates if a `default` case and is empty exists. + * @type {boolean} + */ + this.foundEmptyDefault = false; + + /** + * Indicates that a `default` exists and is the last case. + * @type {boolean} + */ + this.lastIsDefault = false; + + /** + * The number of fork contexts created. This is equivalent to the + * number of `case` statements plus a `default` statement (if present). + * @type {number} + */ + this.forkCount = 0; + } +} + +/** + * Represents the context for a `try` statement. + */ +class TryContext { + + /** + * Creates a new instance. + * @param {TryContext} upperContext The previous context. + * @param {boolean} hasFinalizer Indicates if the `try` statement has a + * `finally` block. + * @param {ForkContext} forkContext The enclosing fork context. + */ + constructor(upperContext, hasFinalizer, forkContext) { + + /** + * The previous context. + * @type {TryContext} + */ + this.upper = upperContext; + + /** + * Indicates if the `try` statement has a `finally` block. + * @type {boolean} + */ + this.hasFinalizer = hasFinalizer; + + /** + * Tracks the traversal position inside of the `try` statement. This is + * used to help determine the context necessary to create paths because + * a `try` statement may or may not have `catch` or `finally` blocks, + * and code paths behave differently in those blocks. + * @type {"try"|"catch"|"finally"} + */ + this.position = "try"; + + /** + * If the `try` statement has a `finally` block, this affects how a + * `return` statement behaves in the `try` block. Without `finally`, + * `return` behaves as usual and doesn't require a fork; with `finally`, + * `return` forks into the `finally` block, so we need a fork context + * to track it. + * @type {ForkContext|null} + */ + this.returnedForkContext = hasFinalizer + ? ForkContext.newEmpty(forkContext) + : null; + + /** + * When a `throw` occurs inside of a `try` block, the code path forks + * into the `catch` or `finally` blocks, and this fork context tracks + * that path. + * @type {ForkContext} + */ + this.thrownForkContext = ForkContext.newEmpty(forkContext); + + /** + * Indicates if the last segment in the `try` block is reachable. + * @type {boolean} + */ + this.lastOfTryIsReachable = false; + + /** + * Indicates if the last segment in the `catch` block is reachable. + * @type {boolean} + */ + this.lastOfCatchIsReachable = false; + } +} + //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ /** * Adds given segments into the `dest` array. - * If the `others` array does not includes the given segments, adds to the `all` + * If the `others` array does not include the given segments, adds to the `all` * array as well. * * This adds only reachable and used segments. @@ -40,9 +649,9 @@ function addToReturnedOrThrown(dest, others, all, segments) { } /** - * Gets a loop-context for a `continue` statement. - * @param {CodePathState} state A state to get. - * @param {string} label The label of a `continue` statement. + * Gets a loop context for a `continue` statement based on a given label. + * @param {CodePathState} state The state to search within. + * @param {string|null} label The label of a `continue` statement. * @returns {LoopContext} A loop-context for a `continue` statement. */ function getContinueContext(state, label) { @@ -65,9 +674,9 @@ function getContinueContext(state, label) { /** * Gets a context for a `break` statement. - * @param {CodePathState} state A state to get. - * @param {string} label The label of a `break` statement. - * @returns {LoopContext|SwitchContext} A context for a `break` statement. + * @param {CodePathState} state The state to search within. + * @param {string|null} label The label of a `break` statement. + * @returns {BreakContext} A context for a `break` statement. */ function getBreakContext(state, label) { let context = state.breakContext; @@ -84,8 +693,10 @@ function getBreakContext(state, label) { } /** - * Gets a context for a `return` statement. - * @param {CodePathState} state A state to get. + * Gets a context for a `return` statement. There is just one special case: + * if there is a `try` statement with a `finally` block, because that alters + * how `return` behaves; otherwise, this just passes through the given state. + * @param {CodePathState} state The state to search within * @returns {TryContext|CodePathState} A context for a `return` statement. */ function getReturnContext(state) { @@ -102,8 +713,11 @@ function getReturnContext(state) { } /** - * Gets a context for a `throw` statement. - * @param {CodePathState} state A state to get. + * Gets a context for a `throw` statement. There is just one special case: + * if there is a `try` statement with a `finally` block and we are inside of + * a `catch` because that changes how `throw` behaves; otherwise, this just + * passes through the given state. + * @param {CodePathState} state The state to search within. * @returns {TryContext|CodePathState} A context for a `throw` statement. */ function getThrowContext(state) { @@ -122,13 +736,13 @@ function getThrowContext(state) { } /** - * Removes a given element from a given array. - * @param {any[]} xs An array to remove the specific element. - * @param {any} x An element to be removed. + * Removes a given value from a given array. + * @param {any[]} elements An array to remove the specific element. + * @param {any} value The value to be removed. * @returns {void} */ -function remove(xs, x) { - xs.splice(xs.indexOf(x), 1); +function removeFromArray(elements, value) { + elements.splice(elements.indexOf(value), 1); } /** @@ -141,48 +755,77 @@ function remove(xs, x) { * @param {CodePathSegment[]} nextSegments Backward segments to disconnect. * @returns {void} */ -function removeConnection(prevSegments, nextSegments) { +function disconnectSegments(prevSegments, nextSegments) { for (let i = 0; i < prevSegments.length; ++i) { const prevSegment = prevSegments[i]; const nextSegment = nextSegments[i]; - remove(prevSegment.nextSegments, nextSegment); - remove(prevSegment.allNextSegments, nextSegment); - remove(nextSegment.prevSegments, prevSegment); - remove(nextSegment.allPrevSegments, prevSegment); + removeFromArray(prevSegment.nextSegments, nextSegment); + removeFromArray(prevSegment.allNextSegments, nextSegment); + removeFromArray(nextSegment.prevSegments, prevSegment); + removeFromArray(nextSegment.allPrevSegments, prevSegment); } } /** - * Creates looping path. - * @param {CodePathState} state The instance. + * Creates looping path between two arrays of segments, ensuring that there are + * paths going between matching segments in the arrays. + * @param {CodePathState} state The state to operate on. * @param {CodePathSegment[]} unflattenedFromSegments Segments which are source. * @param {CodePathSegment[]} unflattenedToSegments Segments which are destination. * @returns {void} */ function makeLooped(state, unflattenedFromSegments, unflattenedToSegments) { + const fromSegments = CodePathSegment.flattenUnusedSegments(unflattenedFromSegments); const toSegments = CodePathSegment.flattenUnusedSegments(unflattenedToSegments); - const end = Math.min(fromSegments.length, toSegments.length); + /* + * This loop effectively updates a doubly-linked list between two collections + * of segments making sure that segments in the same array indices are + * combined to create a path. + */ for (let i = 0; i < end; ++i) { + + // get the segments in matching array indices const fromSegment = fromSegments[i]; const toSegment = toSegments[i]; + /* + * If the destination segment is reachable, then create a path from the + * source segment to the destination segment. + */ if (toSegment.reachable) { fromSegment.nextSegments.push(toSegment); } + + /* + * If the source segment is reachable, then create a path from the + * destination segment back to the source segment. + */ if (fromSegment.reachable) { toSegment.prevSegments.push(fromSegment); } + + /* + * Also update the arrays that don't care if the segments are reachable + * or not. This should always happen regardless of anything else. + */ fromSegment.allNextSegments.push(toSegment); toSegment.allPrevSegments.push(fromSegment); + /* + * If the destination segment has at least two previous segments in its + * path then that means there was one previous segment before this iteration + * of the loop was executed. So, we need to mark the source segment as + * looped. + */ if (toSegment.allPrevSegments.length >= 2) { CodePathSegment.markPrevSegmentAsLooped(toSegment, fromSegment); } + // let the code path analyzer know that there's been a loop created state.notifyLooped(fromSegment, toSegment); } } @@ -198,15 +841,27 @@ function makeLooped(state, unflattenedFromSegments, unflattenedToSegments) { * @returns {void} */ function finalizeTestSegmentsOfFor(context, choiceContext, head) { + + /* + * If this choice context doesn't already contain paths from a + * child context, then add the current head to each potential path. + */ if (!choiceContext.processed) { choiceContext.trueForkContext.add(head); choiceContext.falseForkContext.add(head); - choiceContext.qqForkContext.add(head); + choiceContext.nullishForkContext.add(head); } + /* + * If the test condition isn't a hardcoded truthy value, then `break` + * must follow the same path as if the test condition is false. To represent + * that, we append the path for when the loop test is false (represented by + * `falseForkContext`) to the `brokenForkContext`. + */ if (context.test !== true) { context.brokenForkContext.addAll(choiceContext.falseForkContext); } + context.endOfTestSegments = choiceContext.trueForkContext.makeNext(0, -1); } @@ -220,35 +875,124 @@ function finalizeTestSegmentsOfFor(context, choiceContext, head) { class CodePathState { /** + * Creates a new instance. * @param {IdGenerator} idGenerator An id generator to generate id for code * path segments. * @param {Function} onLooped A callback function to notify looping. */ constructor(idGenerator, onLooped) { + + /** + * The ID generator to use when creating new segments. + * @type {IdGenerator} + */ this.idGenerator = idGenerator; + + /** + * A callback function to call when there is a loop. + * @type {Function} + */ this.notifyLooped = onLooped; + + /** + * The root fork context for this state. + * @type {ForkContext} + */ this.forkContext = ForkContext.newRoot(idGenerator); + + /** + * Context for logical expressions, conditional expressions, `if` statements, + * and loops. + * @type {ChoiceContext} + */ this.choiceContext = null; + + /** + * Context for `switch` statements. + * @type {SwitchContext} + */ this.switchContext = null; + + /** + * Context for `try` statements. + * @type {TryContext} + */ this.tryContext = null; + + /** + * Context for loop statements. + * @type {LoopContext} + */ this.loopContext = null; + + /** + * Context for `break` statements. + * @type {BreakContext} + */ this.breakContext = null; + + /** + * Context for `ChainExpression` nodes. + * @type {ChainContext} + */ this.chainContext = null; + /** + * An array that tracks the current segments in the state. The array + * starts empty and segments are added with each `onCodePathSegmentStart` + * event and removed with each `onCodePathSegmentEnd` event. Effectively, + * this is tracking the code path segment traversal as the state is + * modified. + * @type {Array} + */ this.currentSegments = []; + + /** + * Tracks the starting segment for this path. This value never changes. + * @type {CodePathSegment} + */ this.initialSegment = this.forkContext.head[0]; - // returnedSegments and thrownSegments push elements into finalSegments also. - const final = this.finalSegments = []; - const returned = this.returnedForkContext = []; - const thrown = this.thrownForkContext = []; + /** + * The final segments of the code path which are either `return` or `throw`. + * This is a union of the segments in `returnedForkContext` and `thrownForkContext`. + * @type {Array} + */ + this.finalSegments = []; + + /** + * The final segments of the code path which are `return`. These + * segments are also contained in `finalSegments`. + * @type {Array} + */ + this.returnedForkContext = []; + + /** + * The final segments of the code path which are `throw`. These + * segments are also contained in `finalSegments`. + * @type {Array} + */ + this.thrownForkContext = []; + + /* + * We add an `add` method so that these look more like fork contexts and + * can be used interchangeably when a fork context is needed to add more + * segments to a path. + * + * Ultimately, we want anything added to `returned` or `thrown` to also + * be added to `final`. We only add reachable and used segments to these + * arrays. + */ + 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); } /** - * The head segments. + * A passthrough property exposing the current pointer as part of the API. * @type {CodePathSegment[]} */ get headSegments() { @@ -341,77 +1085,72 @@ class CodePathState { * If the new context is LogicalExpression's or AssignmentExpression's, this is `"&&"` or `"||"` or `"??"`. * If it's IfStatement's or ConditionalExpression's, this is `"test"`. * Otherwise, this is `"loop"`. - * @param {boolean} isForkingAsResult A flag that shows that goes different - * paths between `true` and `false`. + * @param {boolean} isForkingAsResult Indicates if the result of the choice + * creates a fork. * @returns {void} */ pushChoiceContext(kind, isForkingAsResult) { - this.choiceContext = { - upper: this.choiceContext, - kind, - isForkingAsResult, - trueForkContext: ForkContext.newEmpty(this.forkContext), - falseForkContext: ForkContext.newEmpty(this.forkContext), - qqForkContext: ForkContext.newEmpty(this.forkContext), - processed: false - }; + this.choiceContext = new ChoiceContext(this.choiceContext, kind, isForkingAsResult, this.forkContext); } /** * Pops the last choice context and finalizes it. + * This is called upon leaving a node that represents a choice. * @throws {Error} (Unreachable.) * @returns {ChoiceContext} The popped context. */ popChoiceContext() { - const context = this.choiceContext; - - this.choiceContext = context.upper; - + const poppedChoiceContext = this.choiceContext; const forkContext = this.forkContext; - const headSegments = forkContext.head; + const head = forkContext.head; + + this.choiceContext = poppedChoiceContext.upper; - switch (context.kind) { + switch (poppedChoiceContext.kind) { case "&&": case "||": case "??": /* - * If any result were not transferred from child contexts, - * this sets the head segments to both cases. - * The head segments are the path of the right-hand operand. + * The `head` are the path of the right-hand operand. + * If we haven't previously added segments from child contexts, + * then we add these segments to all possible forks. */ - if (!context.processed) { - context.trueForkContext.add(headSegments); - context.falseForkContext.add(headSegments); - context.qqForkContext.add(headSegments); + if (!poppedChoiceContext.processed) { + poppedChoiceContext.trueForkContext.add(head); + poppedChoiceContext.falseForkContext.add(head); + poppedChoiceContext.nullishForkContext.add(head); } /* - * Transfers results to upper context if this context is in - * test chunk. + * If this context is the left (test) expression for another choice + * context, such as `a || b` in the expression `a || b || c`, + * then we take the segments for this context and move them up + * to the parent context. */ - if (context.isForkingAsResult) { + if (poppedChoiceContext.isForkingAsResult) { const parentContext = this.choiceContext; - parentContext.trueForkContext.addAll(context.trueForkContext); - parentContext.falseForkContext.addAll(context.falseForkContext); - parentContext.qqForkContext.addAll(context.qqForkContext); + parentContext.trueForkContext.addAll(poppedChoiceContext.trueForkContext); + parentContext.falseForkContext.addAll(poppedChoiceContext.falseForkContext); + parentContext.nullishForkContext.addAll(poppedChoiceContext.nullishForkContext); parentContext.processed = true; - return context; + // Exit early so we don't collapse all paths into one. + return poppedChoiceContext; } break; case "test": - if (!context.processed) { + if (!poppedChoiceContext.processed) { /* * The head segments are the path of the `if` block here. * Updates the `true` path with the end of the `if` block. */ - context.trueForkContext.clear(); - context.trueForkContext.add(headSegments); + poppedChoiceContext.trueForkContext.clear(); + poppedChoiceContext.trueForkContext.add(head); } else { /* @@ -419,8 +1158,8 @@ class CodePathState { * Updates the `false` path with the end of the `else` * block. */ - context.falseForkContext.clear(); - context.falseForkContext.add(headSegments); + poppedChoiceContext.falseForkContext.clear(); + poppedChoiceContext.falseForkContext.add(head); } break; @@ -428,82 +1167,129 @@ class CodePathState { case "loop": /* - * Loops are addressed in popLoopContext(). - * This is called from popLoopContext(). + * Loops are addressed in `popLoopContext()` so just return + * the context without modification. */ - return context; + return poppedChoiceContext; /* c8 ignore next */ default: throw new Error("unreachable"); } - // Merges all paths. - const prevForkContext = context.trueForkContext; + /* + * Merge the true path with the false path to create a single path. + */ + const combinedForkContext = poppedChoiceContext.trueForkContext; - prevForkContext.addAll(context.falseForkContext); - forkContext.replaceHead(prevForkContext.makeNext(0, -1)); + combinedForkContext.addAll(poppedChoiceContext.falseForkContext); + forkContext.replaceHead(combinedForkContext.makeNext(0, -1)); - return context; + return poppedChoiceContext; } /** - * Makes a code path segment of the right-hand operand of a logical + * Creates a code path segment to represent right-hand operand of a logical * expression. + * This is called in the preprocessing phase when entering a node. * @throws {Error} (Unreachable.) * @returns {void} */ makeLogicalRight() { - const context = this.choiceContext; + const currentChoiceContext = this.choiceContext; const forkContext = this.forkContext; - if (context.processed) { + if (currentChoiceContext.processed) { /* - * This got segments already from the child choice context. - * Creates the next path from own true/false fork context. + * This context was already assigned segments from a child + * choice context. In this case, we are concerned only about + * the path that does not short-circuit and so ends up on the + * right-hand operand of the logical expression. */ let prevForkContext; - switch (context.kind) { + switch (currentChoiceContext.kind) { case "&&": // if true then go to the right-hand side. - prevForkContext = context.trueForkContext; + prevForkContext = currentChoiceContext.trueForkContext; break; case "||": // if false then go to the right-hand side. - prevForkContext = context.falseForkContext; + prevForkContext = currentChoiceContext.falseForkContext; break; - case "??": // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's qqForkContext. - prevForkContext = context.qqForkContext; + case "??": // Both true/false can short-circuit, so needs the third path to go to the right-hand side. That's nullishForkContext. + prevForkContext = currentChoiceContext.nullishForkContext; break; default: throw new Error("unreachable"); } + /* + * Create the segment for the right-hand operand of the logical expression + * and adjust the fork context pointer to point there. The right-hand segment + * is added at the end of all segments in `prevForkContext`. + */ forkContext.replaceHead(prevForkContext.makeNext(0, -1)); + + /* + * We no longer need this list of segments. + * + * Reset `processed` because we've removed the segments from the child + * choice context. This allows `popChoiceContext()` to continue adding + * segments later. + */ prevForkContext.clear(); - context.processed = false; + currentChoiceContext.processed = false; + } else { /* - * This did not get segments from the child choice context. - * So addresses the head segments. - * The head segments are the path of the left-hand operand. + * This choice context was not assigned segments from a child + * choice context, which means that it's a terminal logical + * expression. + * + * `head` is the segments for the left-hand operand of the + * logical expression. + * + * Each of the fork contexts below are empty at this point. We choose + * the path(s) that will short-circuit and add the segment for the + * left-hand operand to it. Ultimately, this will be the only segment + * in that path due to the short-circuting, so we are just seeding + * these paths to start. */ - switch (context.kind) { - case "&&": // the false path can short-circuit. - context.falseForkContext.add(forkContext.head); + switch (currentChoiceContext.kind) { + case "&&": + + /* + * In most contexts, when a && expression evaluates to false, + * it short circuits, so we need to account for that by setting + * the `falseForkContext` to the left operand. + * + * When a && expression is the left-hand operand for a ?? + * expression, such as `(a && b) ?? c`, a nullish value will + * also short-circuit in a different way than a false value, + * so we also set the `nullishForkContext` to the left operand. + * This path is only used with a ?? expression and is thrown + * away for any other type of logical expression, so it's safe + * to always add. + */ + currentChoiceContext.falseForkContext.add(forkContext.head); + currentChoiceContext.nullishForkContext.add(forkContext.head); break; case "||": // the true path can short-circuit. - context.trueForkContext.add(forkContext.head); + currentChoiceContext.trueForkContext.add(forkContext.head); break; case "??": // both can short-circuit. - context.trueForkContext.add(forkContext.head); - context.falseForkContext.add(forkContext.head); + currentChoiceContext.trueForkContext.add(forkContext.head); + currentChoiceContext.falseForkContext.add(forkContext.head); break; default: throw new Error("unreachable"); } + /* + * Create the segment for the right-hand operand of the logical expression + * and adjust the fork context pointer to point there. + */ forkContext.replaceHead(forkContext.makeNext(-1, -1)); } } @@ -524,7 +1310,7 @@ class CodePathState { if (!context.processed) { context.trueForkContext.add(forkContext.head); context.falseForkContext.add(forkContext.head); - context.qqForkContext.add(forkContext.head); + context.nullishForkContext.add(forkContext.head); } context.processed = false; @@ -562,22 +1348,20 @@ class CodePathState { //-------------------------------------------------------------------------- /** - * Push a new `ChainExpression` context to the stack. - * This method is called on entering to each `ChainExpression` node. - * This context is used to count forking in the optional chain then merge them on the exiting from the `ChainExpression` node. + * Pushes a new `ChainExpression` context to the stack. This method is + * called when entering a `ChainExpression` node. A chain context is used to + * count forking in the optional chain then merge them on the exiting from the + * `ChainExpression` node. * @returns {void} */ pushChainContext() { - this.chainContext = { - upper: this.chainContext, - countChoiceContexts: 0 - }; + this.chainContext = new ChainContext(this.chainContext); } /** - * Pop a `ChainExpression` context from the stack. - * This method is called on exiting from each `ChainExpression` node. - * This merges all forks of the last optional chaining. + * Pop a `ChainExpression` context from the stack. This method is called on + * exiting from each `ChainExpression` node. This merges all forks of the + * last optional chaining. * @returns {void} */ popChainContext() { @@ -586,7 +1370,7 @@ class CodePathState { this.chainContext = context.upper; // pop all choice contexts of this. - for (let i = context.countChoiceContexts; i > 0; --i) { + for (let i = context.choiceContextCount; i > 0; --i) { this.popChoiceContext(); } } @@ -599,7 +1383,7 @@ class CodePathState { */ makeOptionalNode() { if (this.chainContext) { - this.chainContext.countChoiceContexts += 1; + this.chainContext.choiceContextCount += 1; this.pushChoiceContext("??", false); } } @@ -627,16 +1411,7 @@ class CodePathState { * @returns {void} */ pushSwitchContext(hasCase, label) { - this.switchContext = { - upper: this.switchContext, - hasCase, - defaultSegments: null, - defaultBodySegments: null, - foundDefault: false, - lastIsDefault: false, - countForks: 0 - }; - + this.switchContext = new SwitchContext(this.switchContext, hasCase); this.pushBreakContext(true, label); } @@ -657,7 +1432,7 @@ class CodePathState { const forkContext = this.forkContext; const brokenForkContext = this.popBreakContext().brokenForkContext; - if (context.countForks === 0) { + if (context.forkCount === 0) { /* * When there is only one `default` chunk and there is one or more @@ -684,47 +1459,54 @@ class CodePathState { brokenForkContext.add(lastSegments); /* - * A path which is failed in all case test should be connected to path - * of `default` chunk. + * Any value that doesn't match a `case` test should flow to the default + * case. That happens normally when the default case is last in the `switch`, + * but if it's not, we need to rewire some of the paths to be correct. */ if (!context.lastIsDefault) { if (context.defaultBodySegments) { /* - * Remove a link from `default` label to its chunk. - * It's false route. + * There is a non-empty default case, so remove the path from the `default` + * label to its body for an accurate representation. + */ + disconnectSegments(context.defaultSegments, context.defaultBodySegments); + + /* + * Connect the path from the last non-default case to the body of the + * default case. */ - removeConnection(context.defaultSegments, context.defaultBodySegments); makeLooped(this, lastCaseSegments, context.defaultBodySegments); + } else { /* - * It handles the last case body as broken if `default` chunk - * does not exist. + * There is no default case, so we treat this as if the last case + * had a `break` in it. */ brokenForkContext.add(lastCaseSegments); } } - // Pops the segment context stack until the entry segment. - for (let i = 0; i < context.countForks; ++i) { + // Traverse up to the original fork context for the `switch` statement + for (let i = 0; i < context.forkCount; ++i) { this.forkContext = this.forkContext.upper; } /* - * Creates a path from all brokenForkContext paths. - * This is a path after switch statement. + * Creates a path from all `brokenForkContext` paths. + * This is a path after `switch` statement. */ this.forkContext.replaceHead(brokenForkContext.makeNext(0, -1)); } /** * Makes a code path segment for a `SwitchCase` node. - * @param {boolean} isEmpty `true` if the body is empty. - * @param {boolean} isDefault `true` if the body is the default case. + * @param {boolean} isCaseBodyEmpty `true` if the body is empty. + * @param {boolean} isDefaultCase `true` if the body is the default case. * @returns {void} */ - makeSwitchCaseBody(isEmpty, isDefault) { + makeSwitchCaseBody(isCaseBodyEmpty, isDefaultCase) { const context = this.switchContext; if (!context.hasCase) { @@ -734,7 +1516,7 @@ class CodePathState { /* * Merge forks. * The parent fork context has two segments. - * Those are from the current case and the body of the previous case. + * Those are from the current `case` and the body of the previous case. */ const parentForkContext = this.forkContext; const forkContext = this.pushForkContext(); @@ -742,26 +1524,53 @@ class CodePathState { forkContext.add(parentForkContext.makeNext(0, -1)); /* - * Save `default` chunk info. - * If the `default` label is not at the last, we must make a path from - * the last `case` to the `default` chunk. + * Add information about the default case. + * + * The purpose of this is to identify the starting segments for the + * default case to make sure there is a path there. */ - if (isDefault) { + if (isDefaultCase) { + + /* + * This is the default case in the `switch`. + * + * We first save the current pointer as `defaultSegments` to point + * to the `default` keyword. + */ context.defaultSegments = parentForkContext.head; - if (isEmpty) { - context.foundDefault = true; + + /* + * If the body of the case is empty then we just set + * `foundEmptyDefault` to true; otherwise, we save a reference + * to the current pointer as `defaultBodySegments`. + */ + if (isCaseBodyEmpty) { + context.foundEmptyDefault = true; } else { context.defaultBodySegments = forkContext.head; } + } else { - if (!isEmpty && context.foundDefault) { - context.foundDefault = false; + + /* + * This is not the default case in the `switch`. + * + * If it's not empty and there is already an empty default case found, + * that means the default case actually comes before this case, + * and that it will fall through to this case. So, we can now + * ignore the previous default case (reset `foundEmptyDefault` to false) + * and set `defaultBodySegments` to the current segments because this is + * effectively the new default case. + */ + if (!isCaseBodyEmpty && context.foundEmptyDefault) { + context.foundEmptyDefault = false; context.defaultBodySegments = forkContext.head; } } - context.lastIsDefault = isDefault; - context.countForks += 1; + // keep track if the default case ends up last + context.lastIsDefault = isDefaultCase; + context.forkCount += 1; } //-------------------------------------------------------------------------- @@ -775,19 +1584,7 @@ class CodePathState { * @returns {void} */ pushTryContext(hasFinalizer) { - this.tryContext = { - upper: this.tryContext, - position: "try", - hasFinalizer, - - returnedForkContext: hasFinalizer - ? ForkContext.newEmpty(this.forkContext) - : null, - - thrownForkContext: ForkContext.newEmpty(this.forkContext), - lastOfTryIsReachable: false, - lastOfCatchIsReachable: false - }; + this.tryContext = new TryContext(this.tryContext, hasFinalizer, this.forkContext); } /** @@ -799,25 +1596,35 @@ class CodePathState { this.tryContext = context.upper; + /* + * If we're inside the `catch` block, that means there is no `finally`, + * so we can process the `try` and `catch` blocks the simple way and + * merge their two paths. + */ if (context.position === "catch") { - - // Merges two paths from the `try` block and `catch` block merely. this.popForkContext(); return; } /* - * The following process is executed only when there is the `finally` + * The following process is executed only when there is a `finally` * block. */ - const returned = context.returnedForkContext; - const thrown = context.thrownForkContext; + const originalReturnedForkContext = context.returnedForkContext; + const originalThrownForkContext = context.thrownForkContext; - if (returned.empty && thrown.empty) { + // no `return` or `throw` in `try` or `catch` so there's nothing left to do + if (originalReturnedForkContext.empty && originalThrownForkContext.empty) { return; } + /* + * The following process is executed only when there is a `finally` + * block and there was a `return` or `throw` in the `try` or `catch` + * blocks. + */ + // Separate head to normal paths and leaving paths. const headSegments = this.forkContext.head; @@ -826,10 +1633,10 @@ class CodePathState { const leavingSegments = headSegments.slice(headSegments.length / 2 | 0); // Forwards the leaving path to upper contexts. - if (!returned.empty) { + if (!originalReturnedForkContext.empty) { getReturnContext(this).returnedForkContext.add(leavingSegments); } - if (!thrown.empty) { + if (!originalThrownForkContext.empty) { getThrowContext(this).thrownForkContext.add(leavingSegments); } @@ -852,16 +1659,20 @@ class CodePathState { makeCatchBlock() { const context = this.tryContext; const forkContext = this.forkContext; - const thrown = context.thrownForkContext; + const originalThrownForkContext = context.thrownForkContext; - // Update state. + /* + * We are now in a catch block so we need to update the context + * with that information. This includes creating a new fork + * context in case we encounter any `throw` statements here. + */ context.position = "catch"; context.thrownForkContext = ForkContext.newEmpty(forkContext); context.lastOfTryIsReachable = forkContext.reachable; - // Merge thrown paths. - thrown.add(forkContext.head); - const thrownSegments = thrown.makeNext(0, -1); + // Merge the thrown paths from the `try` and `catch` blocks + originalThrownForkContext.add(forkContext.head); + const thrownSegments = originalThrownForkContext.makeNext(0, -1); // Fork to a bypass and the merged thrown path. this.pushForkContext(); @@ -880,8 +1691,8 @@ class CodePathState { makeFinallyBlock() { const context = this.tryContext; let forkContext = this.forkContext; - const returned = context.returnedForkContext; - const thrown = context.thrownForkContext; + const originalReturnedForkContext = context.returnedForkContext; + const originalThrownForContext = context.thrownForkContext; const headOfLeavingSegments = forkContext.head; // Update state. @@ -895,9 +1706,15 @@ class CodePathState { } else { context.lastOfTryIsReachable = forkContext.reachable; } + + context.position = "finally"; - if (returned.empty && thrown.empty) { + /* + * If there was no `return` or `throw` in either the `try` or `catch` + * blocks, then there's no further code paths to create for `finally`. + */ + if (originalReturnedForkContext.empty && originalThrownForContext.empty) { // This path does not leave. return; @@ -905,18 +1722,18 @@ class CodePathState { /* * Create a parallel segment from merging returned and thrown. - * This segment will leave at the end of this finally block. + * This segment will leave at the end of this `finally` block. */ const segments = forkContext.makeNext(-1, -1); for (let i = 0; i < forkContext.count; ++i) { const prevSegsOfLeavingSegment = [headOfLeavingSegments[i]]; - for (let j = 0; j < returned.segmentsList.length; ++j) { - prevSegsOfLeavingSegment.push(returned.segmentsList[j][i]); + for (let j = 0; j < originalReturnedForkContext.segmentsList.length; ++j) { + prevSegsOfLeavingSegment.push(originalReturnedForkContext.segmentsList[j][i]); } - for (let j = 0; j < thrown.segmentsList.length; ++j) { - prevSegsOfLeavingSegment.push(thrown.segmentsList[j][i]); + for (let j = 0; j < originalThrownForContext.segmentsList.length; ++j) { + prevSegsOfLeavingSegment.push(originalThrownForContext.segmentsList[j][i]); } segments.push( @@ -971,63 +1788,32 @@ class CodePathState { */ pushLoopContext(type, label) { const forkContext = this.forkContext; + + // All loops need a path to account for `break` statements const breakContext = this.pushBreakContext(true, label); switch (type) { case "WhileStatement": this.pushChoiceContext("loop", false); - this.loopContext = { - upper: this.loopContext, - type, - label, - test: void 0, - continueDestSegments: null, - brokenForkContext: breakContext.brokenForkContext - }; + this.loopContext = new WhileLoopContext(this.loopContext, label, breakContext); break; case "DoWhileStatement": this.pushChoiceContext("loop", false); - this.loopContext = { - upper: this.loopContext, - type, - label, - test: void 0, - entrySegments: null, - continueForkContext: ForkContext.newEmpty(forkContext), - brokenForkContext: breakContext.brokenForkContext - }; + this.loopContext = new DoWhileLoopContext(this.loopContext, label, breakContext, forkContext); break; case "ForStatement": this.pushChoiceContext("loop", false); - this.loopContext = { - upper: this.loopContext, - type, - label, - test: void 0, - endOfInitSegments: null, - testSegments: null, - endOfTestSegments: null, - updateSegments: null, - endOfUpdateSegments: null, - continueDestSegments: null, - brokenForkContext: breakContext.brokenForkContext - }; + this.loopContext = new ForLoopContext(this.loopContext, label, breakContext); break; case "ForInStatement": + this.loopContext = new ForInLoopContext(this.loopContext, label, breakContext); + break; + case "ForOfStatement": - this.loopContext = { - upper: this.loopContext, - type, - label, - prevSegments: null, - leftSegments: null, - endOfLeftSegments: null, - continueDestSegments: null, - brokenForkContext: breakContext.brokenForkContext - }; + this.loopContext = new ForOfLoopContext(this.loopContext, label, breakContext); break; /* c8 ignore next */ @@ -1054,6 +1840,11 @@ class CodePathState { case "WhileStatement": case "ForStatement": this.popChoiceContext(); + + /* + * Creates the path from the end of the loop body up to the + * location where `continue` would jump to. + */ makeLooped( this, forkContext.head, @@ -1068,11 +1859,21 @@ class CodePathState { choiceContext.trueForkContext.add(forkContext.head); choiceContext.falseForkContext.add(forkContext.head); } + + /* + * If this isn't a hardcoded `true` condition, then `break` + * should continue down the path as if the condition evaluated + * to false. + */ if (context.test !== true) { brokenForkContext.addAll(choiceContext.falseForkContext); } - // `true` paths go to looping. + /* + * When the condition is true, the loop continues back to the top, + * so create a path from each possible true condition back to the + * top of the loop. + */ const segmentsList = choiceContext.trueForkContext.segmentsList; for (let i = 0; i < segmentsList.length; ++i) { @@ -1088,6 +1889,11 @@ class CodePathState { case "ForInStatement": case "ForOfStatement": brokenForkContext.add(forkContext.head); + + /* + * Creates the path from the end of the loop body up to the + * left expression (left of `in` or `of`) of the loop. + */ makeLooped( this, forkContext.head, @@ -1100,7 +1906,14 @@ class CodePathState { throw new Error("unreachable"); } - // Go next. + /* + * If there wasn't a `break` statement in the loop, then we're at + * the end of the loop's path, so we make an unreachable segment + * to mark that. + * + * If there was a `break` statement, then we continue on into the + * `brokenForkContext`. + */ if (brokenForkContext.empty) { forkContext.replaceHead(forkContext.makeUnreachable(-1, -1)); } else { @@ -1138,7 +1951,11 @@ class CodePathState { choiceContext.falseForkContext.add(forkContext.head); } - // Update state. + /* + * If this isn't a hardcoded `true` condition, then `break` + * should continue down the path as if the condition evaluated + * to false. + */ if (context.test !== true) { context.brokenForkContext.addAll(choiceContext.falseForkContext); } @@ -1170,7 +1987,11 @@ class CodePathState { context.test = test; - // Creates paths of `continue` statements. + /* + * If there is a `continue` statement in the loop then `continueForkContext` + * won't be empty. We wire up the path from `continue` to the loop + * test condition and then continue the traversal in the root fork context. + */ if (!context.continueForkContext.empty) { context.continueForkContext.add(forkContext.head); const testSegments = context.continueForkContext.makeNext(0, -1); @@ -1190,7 +2011,14 @@ class CodePathState { const endOfInitSegments = forkContext.head; const testSegments = forkContext.makeNext(-1, -1); - // Update state. + /* + * Update the state. + * + * The `continueDestSegments` are set to `testSegments` because we + * don't yet know if there is an update expression in this loop. So, + * from what we already know at this point, a `continue` statement + * will jump back to the test expression. + */ context.test = test; context.endOfInitSegments = endOfInitSegments; context.continueDestSegments = context.testSegments = testSegments; @@ -1217,7 +2045,14 @@ class CodePathState { context.endOfInitSegments = forkContext.head; } - // Update state. + /* + * Update the state. + * + * The `continueDestSegments` are now set to `updateSegments` because we + * know there is an update expression in this loop. So, a `continue` statement + * in the loop will jump to the update expression first, and then to any + * test expression the loop might have. + */ const updateSegments = forkContext.makeDisconnected(-1, -1); context.continueDestSegments = context.updateSegments = updateSegments; @@ -1233,11 +2068,30 @@ class CodePathState { const choiceContext = this.choiceContext; const forkContext = this.forkContext; - // Update state. + /* + * Determine what to do based on which part of the `for` loop are present. + * 1. If there is an update expression, then `updateSegments` is not null and + * we need to assign `endOfUpdateSegments`, and if there is a test + * expression, we then need to create the looped path to get back to + * the test condition. + * 2. If there is no update expression but there is a test expression, + * then we only need to update the test segment information. + * 3. If there is no update expression and no test expression, then we + * just save `endOfInitSegments`. + */ if (context.updateSegments) { context.endOfUpdateSegments = forkContext.head; - // `update` -> `test` + /* + * In a `for` loop that has both an update expression and a test + * condition, execution flows from the test expression into the + * loop body, to the update expression, and then back to the test + * expression to determine if the loop should continue. + * + * To account for that, we need to make a path from the end of the + * update expression to the start of the test expression. This is + * effectively what creates the loop in the code path. + */ if (context.testSegments) { makeLooped( this, @@ -1257,12 +2111,18 @@ class CodePathState { let bodySegments = context.endOfTestSegments; + /* + * If there is a test condition, then there `endOfTestSegments` is also + * the start of the loop body. If there isn't a test condition then + * `bodySegments` will be null and we need to look elsewhere to find + * the start of the body. + * + * The body starts at the end of the init expression and ends at the end + * of the update expression, so we use those locations to determine the + * body segments. + */ if (!bodySegments) { - /* - * If there is not the `test` part, the `body` path comes from the - * `init` part and the `update` part. - */ const prevForkContext = ForkContext.newEmpty(forkContext); prevForkContext.add(context.endOfInitSegments); @@ -1272,7 +2132,16 @@ class CodePathState { bodySegments = prevForkContext.makeNext(0, -1); } + + /* + * If there was no test condition and no update expression, then + * `continueDestSegments` will be null. In that case, a + * `continue` should skip directly to the body of the loop. + * Otherwise, we want to keep the current `continueDestSegments`. + */ context.continueDestSegments = context.continueDestSegments || bodySegments; + + // move pointer to the body forkContext.replaceHead(bodySegments); } @@ -1336,19 +2205,15 @@ class CodePathState { //-------------------------------------------------------------------------- /** - * Creates new context for BreakStatement. - * @param {boolean} breakable The flag to indicate it can break by - * an unlabeled BreakStatement. - * @param {string|null} label The label of this context. - * @returns {Object} The new context. + * Creates new context in which a `break` statement can be used. This occurs inside of a loop, + * labeled statement, or switch statement. + * @param {boolean} breakable Indicates if we are inside a statement where + * `break` without a label will exit the statement. + * @param {string|null} label The label associated with the statement. + * @returns {BreakContext} The new context. */ pushBreakContext(breakable, label) { - this.breakContext = { - upper: this.breakContext, - breakable, - label, - brokenForkContext: ForkContext.newEmpty(this.forkContext) - }; + this.breakContext = new BreakContext(this.breakContext, breakable, label, this.forkContext); return this.breakContext; } @@ -1380,7 +2245,7 @@ class CodePathState { * * It registers the head segment to a context of `break`. * It makes new unreachable segment, then it set the head with the segment. - * @param {string} label A label of the break statement. + * @param {string|null} label A label of the break statement. * @returns {void} */ makeBreak(label) { @@ -1406,7 +2271,7 @@ class CodePathState { * * It makes a looping path. * It makes new unreachable segment, then it set the head with the segment. - * @param {string} label A label of the continue statement. + * @param {string|null} label A label of the continue statement. * @returns {void} */ makeContinue(label) { @@ -1422,7 +2287,7 @@ class CodePathState { if (context.continueDestSegments) { makeLooped(this, forkContext.head, context.continueDestSegments); - // If the context is a for-in/of loop, this effects a break also. + // If the context is a for-in/of loop, this affects a break also. if (context.type === "ForInStatement" || context.type === "ForOfStatement" ) { diff --git a/node_modules/eslint/lib/linter/code-path-analysis/code-path.js b/node_modules/eslint/lib/linter/code-path-analysis/code-path.js index f6a88a00af..3bf570d754 100644 --- a/node_modules/eslint/lib/linter/code-path-analysis/code-path.js +++ b/node_modules/eslint/lib/linter/code-path-analysis/code-path.js @@ -80,7 +80,9 @@ class CodePath { } /** - * The initial code path segment. + * The initial code path segment. This is the segment that is at the head + * of the code path. + * This is a passthrough to the underlying `CodePathState`. * @type {CodePathSegment} */ get initialSegment() { @@ -88,8 +90,10 @@ class CodePath { } /** - * Final code path segments. - * This array is a mix of `returnedSegments` and `thrownSegments`. + * Final code path segments. These are the terminal (tail) segments in the + * code path, which is the combination of `returnedSegments` and `thrownSegments`. + * All segments in this array are reachable. + * This is a passthrough to the underlying `CodePathState`. * @type {CodePathSegment[]} */ get finalSegments() { @@ -97,9 +101,14 @@ class CodePath { } /** - * Final code path segments which is with `return` statements. - * This array contains the last path segment if it's reachable. - * Since the reachable last path returns `undefined`. + * Final code path segments that represent normal completion of the code path. + * For functions, this means both explicit `return` statements and implicit returns, + * such as the last reachable segment in a function that does not have an + * explicit `return` as this implicitly returns `undefined`. For scripts, + * modules, class field initializers, and class static blocks, this means + * all lines of code have been executed. + * These segments are also present in `finalSegments`. + * This is a passthrough to the underlying `CodePathState`. * @type {CodePathSegment[]} */ get returnedSegments() { @@ -107,7 +116,9 @@ class CodePath { } /** - * Final code path segments which is with `throw` statements. + * Final code path segments that represent `throw` statements. + * This is a passthrough to the underlying `CodePathState`. + * These segments are also present in `finalSegments`. * @type {CodePathSegment[]} */ get thrownSegments() { @@ -115,7 +126,12 @@ class CodePath { } /** - * Current code path segments. + * Tracks the traversal of the code path through each segment. This array + * starts empty and segments are added or removed as the code path is + * traversed. This array always ends up empty at the end of a code path + * traversal. The `CodePathState` uses this to track its progress through + * the code path. + * This is a passthrough to the underlying `CodePathState`. * @type {CodePathSegment[]} * @deprecated */ @@ -126,46 +142,70 @@ class CodePath { /** * Traverses all segments in this code path. * - * codePath.traverseSegments(function(segment, controller) { + * codePath.traverseSegments((segment, controller) => { * // do something. * }); * * This method enumerates segments in order from the head. * - * The `controller` object has two methods. + * The `controller` argument has two methods: * - * - `controller.skip()` - Skip the following segments in this branch. - * - `controller.break()` - Skip all following segments. - * @param {Object} [options] Omittable. - * @param {CodePathSegment} [options.first] The first segment to traverse. - * @param {CodePathSegment} [options.last] The last segment to traverse. + * - `skip()` - skips the following segments in this branch + * - `break()` - skips all following segments in the traversal + * + * A note on the parameters: the `options` argument is optional. This means + * the first argument might be an options object or the callback function. + * @param {Object} [optionsOrCallback] Optional first and last segments to traverse. + * @param {CodePathSegment} [optionsOrCallback.first] The first segment to traverse. + * @param {CodePathSegment} [optionsOrCallback.last] The last segment to traverse. * @param {Function} callback A callback function. * @returns {void} */ - traverseSegments(options, callback) { + traverseSegments(optionsOrCallback, callback) { + + // normalize the arguments into a callback and options let resolvedOptions; let resolvedCallback; - if (typeof options === "function") { - resolvedCallback = options; + if (typeof optionsOrCallback === "function") { + resolvedCallback = optionsOrCallback; resolvedOptions = {}; } else { - resolvedOptions = options || {}; + resolvedOptions = optionsOrCallback || {}; resolvedCallback = callback; } + // determine where to start traversing from based on the options const startSegment = resolvedOptions.first || this.internal.initialSegment; const lastSegment = resolvedOptions.last; - let item = null; + // set up initial location information + let record = null; let index = 0; let end = 0; let segment = null; - const visited = Object.create(null); + + // segments that have already been visited during traversal + const visited = new Set(); + + // tracks the traversal steps const stack = [[startSegment, 0]]; + + // tracks the last skipped segment during traversal let skippedSegment = null; + + // indicates if we exited early from the traversal let broken = false; + + /** + * Maintains traversal state. + */ const controller = { + + /** + * Skip the following segments in this branch. + * @returns {void} + */ skip() { if (stack.length <= 1) { broken = true; @@ -173,32 +213,52 @@ class CodePath { skippedSegment = stack[stack.length - 2][0]; } }, + + /** + * Stop traversal completely - do not traverse to any + * other segments. + * @returns {void} + */ break() { broken = true; } }; /** - * Checks a given previous segment has been visited. + * Checks if a given previous segment has been visited. * @param {CodePathSegment} prevSegment A previous segment to check. * @returns {boolean} `true` if the segment has been visited. */ function isVisited(prevSegment) { return ( - visited[prevSegment.id] || + visited.has(prevSegment) || segment.isLoopedPrevSegment(prevSegment) ); } + // the traversal while (stack.length > 0) { - item = stack[stack.length - 1]; - segment = item[0]; - index = item[1]; + + /* + * This isn't a pure stack. We use the top record all the time + * but don't always pop it off. The record is popped only if + * one of the following is true: + * + * 1) We have already visited the segment. + * 2) We have not visited *all* of the previous segments. + * 3) We have traversed past the available next segments. + * + * Otherwise, we just read the value and sometimes modify the + * record as we traverse. + */ + record = stack[stack.length - 1]; + segment = record[0]; + index = record[1]; if (index === 0) { // Skip if this segment has been visited already. - if (visited[segment.id]) { + if (visited.has(segment)) { stack.pop(); continue; } @@ -212,18 +272,29 @@ class CodePath { continue; } - // Reset the flag of skipping if all branches have been skipped. + // Reset the skipping flag if all branches have been skipped. if (skippedSegment && segment.prevSegments.includes(skippedSegment)) { skippedSegment = null; } - visited[segment.id] = true; + visited.add(segment); - // Call the callback when the first time. + /* + * If the most recent segment hasn't been skipped, then we call + * the callback, passing in the segment and the controller. + */ if (!skippedSegment) { resolvedCallback.call(this, segment, controller); + + // exit if we're at the last segment if (segment === lastSegment) { controller.skip(); } + + /* + * If the previous statement was executed, or if the callback + * called a method on the controller, we might need to exit the + * loop, so check for that and break accordingly. + */ if (broken) { break; } @@ -233,12 +304,35 @@ class CodePath { // Update the stack. end = segment.nextSegments.length - 1; if (index < end) { - item[1] += 1; + + /* + * If we haven't yet visited all of the next segments, update + * the current top record on the stack to the next index to visit + * and then push a record for the current segment on top. + * + * Setting the current top record's index lets us know how many + * times we've been here and ensures that the segment won't be + * reprocessed (because we only process segments with an index + * of 0). + */ + record[1] += 1; stack.push([segment.nextSegments[index], 0]); } else if (index === end) { - item[0] = segment.nextSegments[index]; - item[1] = 0; + + /* + * If we are at the last next segment, then reset the top record + * in the stack to next segment and set its index to 0 so it will + * be processed next. + */ + record[0] = segment.nextSegments[index]; + record[1] = 0; } else { + + /* + * If index > end, that means we have no more segments that need + * processing. So, we pop that record off of the stack in order to + * continue traversing at the next level up. + */ stack.pop(); } } diff --git a/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js b/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js index 04c59b5e41..33140272f5 100644 --- a/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js +++ b/node_modules/eslint/lib/linter/code-path-analysis/fork-context.js @@ -21,8 +21,8 @@ const assert = require("assert"), //------------------------------------------------------------------------------ /** - * Gets whether or not a given segment is reachable. - * @param {CodePathSegment} segment A segment to get. + * Determines whether or not a given segment is reachable. + * @param {CodePathSegment} segment The segment to check. * @returns {boolean} `true` if the segment is reachable. */ function isReachable(segment) { @@ -30,32 +30,64 @@ function isReachable(segment) { } /** - * Creates new segments from the specific range of `context.segmentsList`. + * Creates a new segment for each fork in the given context and appends it + * to the end of the specified range of segments. Ultimately, this ends up calling + * `new CodePathSegment()` for each of the forks using the `create` argument + * as a wrapper around special behavior. + * + * The `startIndex` and `endIndex` arguments specify a range of segments in + * `context` that should become `allPrevSegments` for the newly created + * `CodePathSegment` objects. * * When `context.segmentsList` is `[[a, b], [c, d], [e, f]]`, `begin` is `0`, and - * `end` is `-1`, this creates `[g, h]`. This `g` is from `a`, `c`, and `e`. - * This `h` is from `b`, `d`, and `f`. - * @param {ForkContext} context An instance. - * @param {number} begin The first index of the previous segments. - * @param {number} end The last index of the previous segments. - * @param {Function} create A factory function of new segments. - * @returns {CodePathSegment[]} New segments. + * `end` is `-1`, this creates two new segments, `[g, h]`. This `g` is appended to + * the end of the path from `a`, `c`, and `e`. This `h` is appended to the end of + * `b`, `d`, and `f`. + * @param {ForkContext} context An instance from which the previous segments + * will be obtained. + * @param {number} startIndex The index of the first segment in the context + * that should be specified as previous segments for the newly created segments. + * @param {number} endIndex The index of the last segment in the context + * that should be specified as previous segments for the newly created segments. + * @param {Function} create A function that creates new `CodePathSegment` + * instances in a particular way. See the `CodePathSegment.new*` methods. + * @returns {Array} An array of the newly-created segments. */ -function makeSegments(context, begin, end, create) { +function createSegments(context, startIndex, endIndex, create) { + + /** @type {Array>} */ const list = context.segmentsList; - const normalizedBegin = begin >= 0 ? begin : list.length + begin; - const normalizedEnd = end >= 0 ? end : list.length + end; + /* + * Both `startIndex` and `endIndex` work the same way: if the number is zero + * or more, then the number is used as-is. If the number is negative, + * then that number is added to the length of the segments list to + * determine the index to use. That means -1 for either argument + * is the last element, -2 is the second to last, and so on. + * + * So if `startIndex` is 0, `endIndex` is -1, and `list.length` is 3, the + * effective `startIndex` is 0 and the effective `endIndex` is 2, so this function + * will include items at indices 0, 1, and 2. + * + * Therefore, if `startIndex` is -1 and `endIndex` is -1, that means we'll only + * be using the last segment in `list`. + */ + const normalizedBegin = startIndex >= 0 ? startIndex : list.length + startIndex; + const normalizedEnd = endIndex >= 0 ? endIndex : list.length + endIndex; + /** @type {Array} */ const segments = []; for (let i = 0; i < context.count; ++i) { + + // this is passed into `new CodePathSegment` to add to code path. const allPrevSegments = []; for (let j = normalizedBegin; j <= normalizedEnd; ++j) { allPrevSegments.push(list[j][i]); } + // note: `create` is just a wrapper that augments `new CodePathSegment`. segments.push(create(context.idGenerator.next(), allPrevSegments)); } @@ -63,28 +95,57 @@ function makeSegments(context, begin, end, create) { } /** - * `segments` becomes doubly in a `finally` block. Then if a code path exits by a - * control statement (such as `break`, `continue`) from the `finally` block, the - * destination's segments may be half of the source segments. In that case, this - * merges segments. - * @param {ForkContext} context An instance. - * @param {CodePathSegment[]} segments Segments to merge. - * @returns {CodePathSegment[]} The merged segments. + * Inside of a `finally` block we end up with two parallel paths. If the code path + * exits by a control statement (such as `break` or `continue`) from the `finally` + * block, then we need to merge the remaining parallel paths back into one. + * @param {ForkContext} context The fork context to work on. + * @param {Array} segments Segments to merge. + * @returns {Array} The merged segments. */ function mergeExtraSegments(context, segments) { let currentSegments = segments; + /* + * We need to ensure that the array returned from this function contains no more + * than the number of segments that the context allows. `context.count` indicates + * how many items should be in the returned array to ensure that the new segment + * entries will line up with the already existing segment entries. + */ while (currentSegments.length > context.count) { const merged = []; - for (let i = 0, length = currentSegments.length / 2 | 0; i < length; ++i) { + /* + * Because `context.count` is a factor of 2 inside of a `finally` block, + * we can divide the segment count by 2 to merge the paths together. + * This loops through each segment in the list and creates a new `CodePathSegment` + * that has the segment and the segment two slots away as previous segments. + * + * If `currentSegments` is [a,b,c,d], this will create new segments e and f, such + * that: + * + * When `i` is 0: + * a->e + * c->e + * + * When `i` is 1: + * b->f + * d->f + */ + for (let i = 0, length = Math.floor(currentSegments.length / 2); i < length; ++i) { merged.push(CodePathSegment.newNext( context.idGenerator.next(), [currentSegments[i], currentSegments[i + length]] )); } + + /* + * Go through the loop condition one more time to see if we have the + * number of segments for the context. If not, we'll keep merging paths + * of the merged segments until we get there. + */ currentSegments = merged; } + return currentSegments; } @@ -93,25 +154,55 @@ function mergeExtraSegments(context, segments) { //------------------------------------------------------------------------------ /** - * A class to manage forking. + * Manages the forking of code paths. */ class ForkContext { /** + * Creates a new instance. * @param {IdGenerator} idGenerator An identifier generator for segments. - * @param {ForkContext|null} upper An upper fork context. - * @param {number} count A number of parallel segments. + * @param {ForkContext|null} upper The preceding fork context. + * @param {number} count The number of parallel segments in each element + * of `segmentsList`. */ constructor(idGenerator, upper, count) { + + /** + * The ID generator that will generate segment IDs for any new + * segments that are created. + * @type {IdGenerator} + */ this.idGenerator = idGenerator; + + /** + * The preceding fork context. + * @type {ForkContext|null} + */ this.upper = upper; + + /** + * The number of elements in each element of `segmentsList`. In most + * cases, this is 1 but can be 2 when there is a `finally` present, + * which forks the code path outside of normal flow. In the case of nested + * `finally` blocks, this can be a multiple of 2. + * @type {number} + */ this.count = count; + + /** + * The segments within this context. Each element in this array has + * `count` elements that represent one step in each fork. For example, + * when `segmentsList` is `[[a, b], [c, d], [e, f]]`, there is one path + * a->c->e and one path b->d->f, and `count` is 2 because each element + * is an array with two elements. + * @type {Array>} + */ this.segmentsList = []; } /** - * The head segments. - * @type {CodePathSegment[]} + * The segments that begin this fork context. + * @type {Array} */ get head() { const list = this.segmentsList; @@ -120,7 +211,7 @@ class ForkContext { } /** - * A flag which shows empty. + * Indicates if the context contains no segments. * @type {boolean} */ get empty() { @@ -128,7 +219,7 @@ class ForkContext { } /** - * A flag which shows reachable. + * Indicates if there are any segments that are reachable. * @type {boolean} */ get reachable() { @@ -138,75 +229,82 @@ class ForkContext { } /** - * Creates new segments from this context. - * @param {number} begin The first index of previous segments. - * @param {number} end The last index of previous segments. - * @returns {CodePathSegment[]} New segments. + * Creates new segments in this context and appends them to the end of the + * already existing `CodePathSegment`s specified by `startIndex` and + * `endIndex`. + * @param {number} startIndex The index of the first segment in the context + * that should be specified as previous segments for the newly created segments. + * @param {number} endIndex The index of the last segment in the context + * that should be specified as previous segments for the newly created segments. + * @returns {Array} An array of the newly created segments. */ - makeNext(begin, end) { - return makeSegments(this, begin, end, CodePathSegment.newNext); + makeNext(startIndex, endIndex) { + return createSegments(this, startIndex, endIndex, CodePathSegment.newNext); } /** - * Creates new segments from this context. - * The new segments is always unreachable. - * @param {number} begin The first index of previous segments. - * @param {number} end The last index of previous segments. - * @returns {CodePathSegment[]} New segments. + * Creates new unreachable segments in this context and appends them to the end of the + * already existing `CodePathSegment`s specified by `startIndex` and + * `endIndex`. + * @param {number} startIndex The index of the first segment in the context + * that should be specified as previous segments for the newly created segments. + * @param {number} endIndex The index of the last segment in the context + * that should be specified as previous segments for the newly created segments. + * @returns {Array} An array of the newly created segments. */ - makeUnreachable(begin, end) { - return makeSegments(this, begin, end, CodePathSegment.newUnreachable); + makeUnreachable(startIndex, endIndex) { + return createSegments(this, startIndex, endIndex, CodePathSegment.newUnreachable); } /** - * Creates new segments from this context. - * The new segments don't have connections for previous segments. - * But these inherit the reachable flag from this context. - * @param {number} begin The first index of previous segments. - * @param {number} end The last index of previous segments. - * @returns {CodePathSegment[]} New segments. + * Creates new segments in this context and does not append them to the end + * of the already existing `CodePathSegment`s specified by `startIndex` and + * `endIndex`. The `startIndex` and `endIndex` are only used to determine if + * the new segments should be reachable. If any of the segments in this range + * are reachable then the new segments are also reachable; otherwise, the new + * segments are unreachable. + * @param {number} startIndex The index of the first segment in the context + * that should be considered for reachability. + * @param {number} endIndex The index of the last segment in the context + * that should be considered for reachability. + * @returns {Array} An array of the newly created segments. */ - makeDisconnected(begin, end) { - return makeSegments(this, begin, end, CodePathSegment.newDisconnected); + makeDisconnected(startIndex, endIndex) { + return createSegments(this, startIndex, endIndex, CodePathSegment.newDisconnected); } /** - * Adds segments into this context. - * The added segments become the head. - * @param {CodePathSegment[]} segments Segments to add. + * Adds segments to the head of this context. + * @param {Array} segments The segments to add. * @returns {void} */ add(segments) { assert(segments.length >= this.count, `${segments.length} >= ${this.count}`); - this.segmentsList.push(mergeExtraSegments(this, segments)); } /** - * Replaces the head segments with given segments. + * Replaces the head segments with the given segments. * The current head segments are removed. - * @param {CodePathSegment[]} segments Segments to add. + * @param {Array} replacementHeadSegments The new head segments. * @returns {void} */ - replaceHead(segments) { - assert(segments.length >= this.count, `${segments.length} >= ${this.count}`); - - this.segmentsList.splice(-1, 1, mergeExtraSegments(this, segments)); + replaceHead(replacementHeadSegments) { + assert( + replacementHeadSegments.length >= this.count, + `${replacementHeadSegments.length} >= ${this.count}` + ); + this.segmentsList.splice(-1, 1, mergeExtraSegments(this, replacementHeadSegments)); } /** * Adds all segments of a given fork context into this context. - * @param {ForkContext} context A fork context to add. + * @param {ForkContext} otherForkContext The fork context to add from. * @returns {void} */ - addAll(context) { - assert(context.count === this.count); - - const source = context.segmentsList; - - for (let i = 0; i < source.length; ++i) { - this.segmentsList.push(source[i]); - } + addAll(otherForkContext) { + assert(otherForkContext.count === this.count); + this.segmentsList.push(...otherForkContext.segmentsList); } /** @@ -218,7 +316,8 @@ class ForkContext { } /** - * Creates the root fork context. + * Creates a new root context, meaning that there are no parent + * fork contexts. * @param {IdGenerator} idGenerator An identifier generator for segments. * @returns {ForkContext} New fork context. */ @@ -233,14 +332,16 @@ class ForkContext { /** * Creates an empty fork context preceded by a given context. * @param {ForkContext} parentContext The parent fork context. - * @param {boolean} forkLeavingPath A flag which shows inside of `finally` block. + * @param {boolean} shouldForkLeavingPath Indicates that we are inside of + * a `finally` block and should therefore fork the path that leaves + * `finally`. * @returns {ForkContext} New fork context. */ - static newEmpty(parentContext, forkLeavingPath) { + static newEmpty(parentContext, shouldForkLeavingPath) { return new ForkContext( parentContext.idGenerator, parentContext, - (forkLeavingPath ? 2 : 1) * parentContext.count + (shouldForkLeavingPath ? 2 : 1) * parentContext.count ); } } diff --git a/node_modules/eslint/lib/linter/config-comment-parser.js b/node_modules/eslint/lib/linter/config-comment-parser.js index 9aab3c4445..cde261204f 100644 --- a/node_modules/eslint/lib/linter/config-comment-parser.js +++ b/node_modules/eslint/lib/linter/config-comment-parser.js @@ -139,7 +139,7 @@ module.exports = class ConfigCommentParser { const items = {}; string.split(",").forEach(name => { - const trimmedName = name.trim(); + const trimmedName = name.trim().replace(/^(?['"]?)(?.*)\k$/us, "$"); if (trimmedName) { items[trimmedName] = true; diff --git a/node_modules/eslint/lib/options.js b/node_modules/eslint/lib/options.js index 2bc4018afb..ae9a5d5552 100644 --- a/node_modules/eslint/lib/options.js +++ b/node_modules/eslint/lib/options.js @@ -55,6 +55,7 @@ const optionator = require("optionator"); * @property {string} [stdinFilename] Specify filename to process STDIN as * @property {boolean} quiet Report errors only * @property {boolean} [version] Output the version number + * @property {boolean} warnIgnored Show warnings when the file list includes ignored files * @property {string[]} _ Positional filenames or patterns */ @@ -139,6 +140,17 @@ module.exports = function(usingFlatConfig) { }; } + let warnIgnoredFlag; + + if (usingFlatConfig) { + warnIgnoredFlag = { + option: "warn-ignored", + type: "Boolean", + default: "true", + description: "Suppress warnings when the file list includes ignored files" + }; + } + return optionator({ prepend: "eslint [options] file.js [file.js] [dir]", defaults: { @@ -349,6 +361,7 @@ module.exports = function(usingFlatConfig) { default: "false", description: "Exit with exit code 2 in case of fatal error" }, + warnIgnoredFlag, { option: "debug", type: "Boolean", diff --git a/node_modules/eslint/lib/rules/logical-assignment-operators.js b/node_modules/eslint/lib/rules/logical-assignment-operators.js index 27ca585e99..c084c04c8e 100644 --- a/node_modules/eslint/lib/rules/logical-assignment-operators.js +++ b/node_modules/eslint/lib/rules/logical-assignment-operators.js @@ -150,6 +150,31 @@ function isInsideWithBlock(node) { return node.parent.type === "WithStatement" && node.parent.body === node ? true : isInsideWithBlock(node.parent); } +/** + * Gets the leftmost operand of a consecutive logical expression. + * @param {SourceCode} sourceCode The ESLint source code object + * @param {LogicalExpression} node LogicalExpression + * @returns {Expression} Leftmost operand + */ +function getLeftmostOperand(sourceCode, node) { + let left = node.left; + + while (left.type === "LogicalExpression" && left.operator === node.operator) { + + if (astUtils.isParenthesised(sourceCode, left)) { + + /* + * It should have associativity, + * but ignore it if use parentheses to make the evaluation order clear. + */ + return left; + } + left = left.left; + } + return left; + +} + //------------------------------------------------------------------------------ // Rule Definition //------------------------------------------------------------------------------ @@ -318,7 +343,10 @@ module.exports = { // foo = foo || bar "AssignmentExpression[operator='='][right.type='LogicalExpression']"(assignment) { - if (!astUtils.isSameReference(assignment.left, assignment.right.left)) { + const leftOperand = getLeftmostOperand(sourceCode, assignment.right); + + if (!astUtils.isSameReference(assignment.left, leftOperand) + ) { return; } @@ -342,10 +370,10 @@ module.exports = { yield ruleFixer.insertTextBefore(assignmentOperatorToken, assignment.right.operator); // -> foo ||= bar - const logicalOperatorToken = getOperatorToken(assignment.right); + const logicalOperatorToken = getOperatorToken(leftOperand.parent); const firstRightOperandToken = sourceCode.getTokenAfter(logicalOperatorToken); - yield ruleFixer.removeRange([assignment.right.range[0], firstRightOperandToken.range[0]]); + yield ruleFixer.removeRange([leftOperand.parent.range[0], firstRightOperandToken.range[0]]); } }; diff --git a/node_modules/eslint/package.json b/node_modules/eslint/package.json index 989e3528a4..ece3957419 100644 --- a/node_modules/eslint/package.json +++ b/node_modules/eslint/package.json @@ -1,6 +1,6 @@ { "name": "eslint", - "version": "8.50.0", + "version": "8.51.0", "author": "Nicholas C. Zakas ", "description": "An AST-based pattern checker for JavaScript.", "bin": { @@ -63,7 +63,7 @@ "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.50.0", + "@eslint/js": "8.51.0", "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", diff --git a/node_modules/sinon/CONTRIBUTING.md b/node_modules/sinon/CONTRIBUTING.md index 859bcb4f5d..9a71d508f8 100644 --- a/node_modules/sinon/CONTRIBUTING.md +++ b/node_modules/sinon/CONTRIBUTING.md @@ -104,6 +104,22 @@ $ npm run prettier:write To ensure consistent reporting of lint warnings, you should use the same versions of ESLint and Prettier as defined in `package.json` (which is what the CI servers use). +### Tooling + +To transparently handle all issues with different tool versions we recommend using [_ASDF: The Multiple Runtime Manager_][asdf]. You would then need the Ruby and Node plugins. + +
+ +``` +asdf plugin add ruby +asdf plugin add nodejs +asdf install +``` + +
+ +[asdf]: https://asdf-vm.com + ### Run the tests Following command runs unit tests in PhantomJS, Node and WebWorker @@ -133,4 +149,4 @@ Build requires Node. Under the hood [Browserify](http://browserify.org/) is used To build run - $ node build.js + $ node build.cjs diff --git a/node_modules/sinon/lib/sinon/sandbox.js b/node_modules/sinon/lib/sinon/sandbox.js index 0a4c9a1ba4..9f62e97f8c 100644 --- a/node_modules/sinon/lib/sinon/sandbox.js +++ b/node_modules/sinon/lib/sinon/sandbox.js @@ -35,6 +35,40 @@ function applyOnEach(fakes, method) { }); } +function throwOnAccessors(descriptor) { + if (typeof descriptor.get === "function") { + throw new Error("Use sandbox.replaceGetter for replacing getters"); + } + + if (typeof descriptor.set === "function") { + throw new Error("Use sandbox.replaceSetter for replacing setters"); + } +} + +function verifySameType(object, property, replacement) { + if (typeof object[property] !== typeof replacement) { + throw new TypeError( + `Cannot replace ${typeof object[ + property + ]} with ${typeof replacement}` + ); + } +} + +function checkForValidArguments(descriptor, property, replacement) { + if (typeof descriptor === "undefined") { + throw new TypeError( + `Cannot replace non-existent property ${valueToString( + property + )}. Perhaps you meant sandbox.define()?` + ); + } + + if (typeof replacement === "undefined") { + throw new TypeError("Expected replacement argument to be defined"); + } +} + function Sandbox() { const sandbox = this; let fakeRestorers = []; @@ -66,11 +100,6 @@ function Sandbox() { return collection; }; - // this is for testing only - sandbox.getRestorers = function () { - return fakeRestorers; - }; - sandbox.createStubInstance = function createStubInstance() { const stubbed = sinonCreateStubInstance.apply(null, arguments); @@ -196,11 +225,22 @@ function Sandbox() { sandbox.injectedKeys.length = 0; }; - function getFakeRestorer(object, property) { + /** + * Creates a restorer function for the property + * + * @param {object|Function} object + * @param {string} property + * @param {boolean} forceAssignment + * @returns {Function} restorer function + */ + function getFakeRestorer(object, property, forceAssignment = false) { const descriptor = getPropertyDescriptor(object, property); + const value = object[property]; function restorer() { - if (descriptor?.isOwn) { + if (forceAssignment) { + object[property] = value; + } else if (descriptor?.isOwn) { Object.defineProperty(object, property, descriptor); } else { delete object[property]; @@ -225,41 +265,43 @@ function Sandbox() { }); } + /** + * Replace an existing property + * + * @param {object|Function} object + * @param {string} property + * @param {*} replacement a fake, stub, spy or any other value + * @returns {*} + */ sandbox.replace = function replace(object, property, replacement) { const descriptor = getPropertyDescriptor(object, property); + checkForValidArguments(descriptor, property, replacement); + throwOnAccessors(descriptor); + verifySameType(object, property, replacement); - if (typeof descriptor === "undefined") { - throw new TypeError( - `Cannot replace non-existent property ${valueToString( - property - )}. Perhaps you meant sandbox.define()?` - ); - } + verifyNotReplaced(object, property); - if (typeof replacement === "undefined") { - throw new TypeError("Expected replacement argument to be defined"); - } + // store a function for restoring the replaced property + push(fakeRestorers, getFakeRestorer(object, property)); - if (typeof descriptor.get === "function") { - throw new Error("Use sandbox.replaceGetter for replacing getters"); - } + object[property] = replacement; - if (typeof descriptor.set === "function") { - throw new Error("Use sandbox.replaceSetter for replacing setters"); - } + return replacement; + }; - if (typeof object[property] !== typeof replacement) { - throw new TypeError( - `Cannot replace ${typeof object[ - property - ]} with ${typeof replacement}` - ); - } + sandbox.replace.usingAccessor = function replaceUsingAccessor( + object, + property, + replacement + ) { + const descriptor = getPropertyDescriptor(object, property); + checkForValidArguments(descriptor, property, replacement); + verifySameType(object, property, replacement); verifyNotReplaced(object, property); // store a function for restoring the replaced property - push(fakeRestorers, getFakeRestorer(object, property)); + push(fakeRestorers, getFakeRestorer(object, property, true)); object[property] = replacement; diff --git a/node_modules/sinon/package.json b/node_modules/sinon/package.json index b58a0dcb8f..f97c4b0733 100644 --- a/node_modules/sinon/package.json +++ b/node_modules/sinon/package.json @@ -15,7 +15,7 @@ "xhr", "assert" ], - "version": "16.0.0", + "version": "16.1.0", "homepage": "https://sinonjs.org/", "author": "Christian Johansen", "repository": { @@ -44,9 +44,10 @@ "test": "npm run test-node && npm run test-headless && npm run test-webworker", "check-dependencies": "dependency-check package.json --no-dev --ignore-module esm", "build": "node ./build.cjs", + "dev-docs": "cd docs; cp -rl release-source releases/dev; npm run serve-docs", "build-docs": "cd docs; bundle exec jekyll build", - "serve-docs": "cd docs; bundle exec jekyll serve --incremental --verbose", - "lint": "eslint --max-warnings 99 '**/*.{js,cjs,mjs}'", + "serve-docs": "cd docs; bundle exec jekyll serve --incremental --verbose --livereload", + "lint": "eslint --max-warnings 101 '**/*.{js,cjs,mjs}'", "unimported": "unimported .", "pretest-webworker": "npm run build", "prebuild": "rimraf pkg && npm run check-dependencies", diff --git a/node_modules/sinon/pkg/sinon-esm.js b/node_modules/sinon/pkg/sinon-esm.js index d0a439103a..59523e970e 100644 --- a/node_modules/sinon/pkg/sinon-esm.js +++ b/node_modules/sinon/pkg/sinon-esm.js @@ -1,4 +1,4 @@ -/* Sinon.JS 16.0.0, 2023-09-13, @license BSD-3 */let sinon;(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i