From d5b2250a167b8c018b624c0c230774cd2c5bfe5a Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 19 Sep 2025 15:22:20 -0400 Subject: [PATCH 1/5] Enable TypeScript ESLint type-aware linting with defineConfig --- eslint.config.mjs | 59 +++++++++++++-- package.json | 1 + src/app-logic/web-channel.ts | 1 + tsconfig.json | 2 +- yarn.lock | 140 ++++++++++++++++++++++++++++++++++- 5 files changed, 191 insertions(+), 12 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 11ca6d0516..34cb9022ef 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,6 +1,7 @@ +import { defineConfig } from 'eslint/config'; import js from '@eslint/js'; +import tseslint from 'typescript-eslint'; import tsParser from '@typescript-eslint/parser'; -import tsPlugin from '@typescript-eslint/eslint-plugin'; import babelPlugin from '@babel/eslint-plugin'; import reactPlugin from 'eslint-plugin-react'; import importPlugin from 'eslint-plugin-import'; @@ -11,7 +12,7 @@ import jestDomPlugin from 'eslint-plugin-jest-dom'; import prettierConfig from 'eslint-config-prettier'; import globals from 'globals'; -export default [ +export default defineConfig( // Global ignores { ignores: [ @@ -27,8 +28,8 @@ export default [ // Base JavaScript config js.configs.recommended, - // TypeScript config - ...tsPlugin.configs['flat/recommended'], + // TypeScript config with type checking + ...tseslint.configs.recommendedTypeChecked, // React config reactPlugin.configs.flat.recommended, @@ -50,6 +51,7 @@ export default [ ecmaFeatures: { jsx: true, }, + // Note: projectService is configured per file type below }, }, plugins: { @@ -178,6 +180,32 @@ export default [ }, ], '@typescript-eslint/no-require-imports': 'off', + + // Disable "no-unsafe" checks which complain about using "any" freely. + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + '@typescript-eslint/no-unsafe-return': 'off', + + // Disable this one due to false positives when narrowing return types, + // see https://github.com/typescript-eslint/typescript-eslint/issues/6951 + // (it can make `yarn ts` fail after `yarn lint-fix`) + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + + // Consider enabling these in the future + '@typescript-eslint/unbound-method': 'off', + '@typescript-eslint/only-throw-error': 'off', + '@typescript-eslint/no-floating-promises': 'off', + '@typescript-eslint/require-await': 'off', + '@typescript-eslint/no-redundant-type-constituents': 'off', + '@typescript-eslint/no-misused-promises': 'off', + '@typescript-eslint/await-thenable': 'off', + '@typescript-eslint/restrict-plus-operands': 'off', + '@typescript-eslint/no-base-to-string': 'off', + '@typescript-eslint/restrict-template-expressions': 'off', + '@typescript-eslint/prefer-promise-reject-errors': 'off', + '@typescript-eslint/no-array-delete': 'off', }, linterOptions: { // This property is specified both here in addition to the command line in @@ -189,6 +217,23 @@ export default [ }, }, + // TypeScript files - enable type checking + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + projectService: true, + tsconfigRootDir: import.meta.dirname, + }, + }, + }, + + // JavaScript files - disable type-aware rules (they can't run on JS anyway) + { + files: ['**/*.js', '**/*.mjs', '**/*.cjs'], + ...tseslint.configs.disableTypeChecked, + }, + // Source files - enable stricter TypeScript rules { files: ['src/**/*.ts', 'src/**/*.tsx'], @@ -255,7 +300,7 @@ export default [ }, }, - // __mocks__ directory configuration + // __mocks__ directory configuration - globals { files: ['__mocks__/**/*'], languageOptions: { @@ -266,5 +311,5 @@ export default [ }, // Prettier config (must be last to override other formatting rules) - prettierConfig, -]; + prettierConfig +); diff --git a/package.json b/package.json index d39d446051..ccbf847dfb 100644 --- a/package.json +++ b/package.json @@ -184,6 +184,7 @@ "stylelint-config-idiomatic-order": "^10.0.0", "stylelint-config-standard": "^39.0.0", "typescript": "^5.8.3", + "typescript-eslint": "^8.44.0", "webpack": "^5.101.3", "webpack-cli": "^6.0.1", "webpack-dev-server": "^5.2.2", diff --git a/src/app-logic/web-channel.ts b/src/app-logic/web-channel.ts index 2dbe25fbf0..539ad6be73 100644 --- a/src/app-logic/web-channel.ts +++ b/src/app-logic/web-channel.ts @@ -96,6 +96,7 @@ export type ResponseFromBrowser = | GetSymbolTableResponse | QuerySymbolicationApiResponse | GetPageFaviconsResponse + // eslint-disable-next-line @typescript-eslint/no-duplicate-type-constituents | OpenScriptInTabDebuggerResponse; type StatusQueryResponse = { diff --git a/tsconfig.json b/tsconfig.json index b8dab0ca32..28b14b261a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -38,6 +38,6 @@ // React & JSX "jsx": "react-jsx" }, - "include": ["src/**/*.ts", "src/**/*.tsx"], + "include": ["src/**/*.ts", "src/**/*.tsx", "__mocks__/**/*.ts"], "exclude": ["node_modules", "dist"] } diff --git a/yarn.lock b/yarn.lock index 6d38cbff50..4ec13446dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2492,6 +2492,21 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/eslint-plugin@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.0.tgz#d72bf8b2d3052afee919ba38f38c57138eee0396" + integrity sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.44.0" + "@typescript-eslint/type-utils" "8.44.0" + "@typescript-eslint/utils" "8.44.0" + "@typescript-eslint/visitor-keys" "8.44.0" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + "@typescript-eslint/eslint-plugin@^8.41.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.41.0.tgz#42209e2ce3e2274de0f5f9b75c777deedacaa558" @@ -2507,6 +2522,17 @@ natural-compare "^1.4.0" ts-api-utils "^2.1.0" +"@typescript-eslint/parser@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.44.0.tgz#0436fbe0a72f86d3366d2d157d480524b0ab3f26" + integrity sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw== + dependencies: + "@typescript-eslint/scope-manager" "8.44.0" + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/typescript-estree" "8.44.0" + "@typescript-eslint/visitor-keys" "8.44.0" + debug "^4.3.4" + "@typescript-eslint/parser@^8.41.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.41.0.tgz#677f5b2b3fa947ee1eac4129220c051b1990d898" @@ -2527,6 +2553,15 @@ "@typescript-eslint/types" "^8.41.0" debug "^4.3.4" +"@typescript-eslint/project-service@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.44.0.tgz#89060651dcecde946e758441fe94dceb6f769a29" + integrity sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.44.0" + "@typescript-eslint/types" "^8.44.0" + debug "^4.3.4" + "@typescript-eslint/scope-manager@8.41.0", "@typescript-eslint/scope-manager@^8.15.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.41.0.tgz#c8aba12129cb9cead1f1727f58e6a0fcebeecdb5" @@ -2535,11 +2570,24 @@ "@typescript-eslint/types" "8.41.0" "@typescript-eslint/visitor-keys" "8.41.0" +"@typescript-eslint/scope-manager@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.44.0.tgz#c37f1e786fd0e5b40607985c769a61c24c761c26" + integrity sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA== + dependencies: + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/visitor-keys" "8.44.0" + "@typescript-eslint/tsconfig-utils@8.41.0", "@typescript-eslint/tsconfig-utils@^8.41.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.41.0.tgz#134dee36eb16cdd78095a20bca0516d10b5dda75" integrity sha512-TDhxYFPUYRFxFhuU5hTIJk+auzM/wKvWgoNYOPcOf6i4ReYlOoYN8q1dV5kOTjNQNJgzWN3TUUQMtlLOcUgdUw== +"@typescript-eslint/tsconfig-utils@8.44.0", "@typescript-eslint/tsconfig-utils@^8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.0.tgz#8c0601372bf889f0663a08df001ad666442aa3a8" + integrity sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ== + "@typescript-eslint/type-utils@8.41.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.41.0.tgz#68d401e38fccf239925447e97bdbd048a9891ae5" @@ -2551,11 +2599,27 @@ debug "^4.3.4" ts-api-utils "^2.1.0" +"@typescript-eslint/type-utils@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.44.0.tgz#5b875f8a961d15bb47df787cbfde50baea312613" + integrity sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg== + dependencies: + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/typescript-estree" "8.44.0" + "@typescript-eslint/utils" "8.44.0" + debug "^4.3.4" + ts-api-utils "^2.1.0" + "@typescript-eslint/types@8.41.0", "@typescript-eslint/types@^8.41.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.41.0.tgz#9935afeaae65e535abcbcee95383fa649c64d16d" integrity sha512-9EwxsWdVqh42afLbHP90n2VdHaWU/oWgbH2P0CfcNfdKL7CuKpwMQGjwev56vWu9cSKU7FWSu6r9zck6CVfnag== +"@typescript-eslint/types@8.44.0", "@typescript-eslint/types@^8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.44.0.tgz#4b9154ab164a0beff22d3217ff0fdc8d10bce924" + integrity sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA== + "@typescript-eslint/typescript-estree@8.41.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.41.0.tgz#7c9cff8b4334ce96f14e9689692e8cf426ce4d59" @@ -2572,6 +2636,22 @@ semver "^7.6.0" ts-api-utils "^2.1.0" +"@typescript-eslint/typescript-estree@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.0.tgz#e23e9946c466cf5f53b7e46ecdd9789fd8192daa" + integrity sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw== + dependencies: + "@typescript-eslint/project-service" "8.44.0" + "@typescript-eslint/tsconfig-utils" "8.44.0" + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/visitor-keys" "8.44.0" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.1.0" + "@typescript-eslint/utils@8.41.0", "@typescript-eslint/utils@^8.0.0", "@typescript-eslint/utils@^8.15.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.41.0.tgz#17cb3b766c1626311004ea41ffd8c27eb226b953" @@ -2582,6 +2662,16 @@ "@typescript-eslint/types" "8.41.0" "@typescript-eslint/typescript-estree" "8.41.0" +"@typescript-eslint/utils@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.44.0.tgz#2c0650a1e8a832ed15658e7ca3c7bd2818d92c7c" + integrity sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.44.0" + "@typescript-eslint/types" "8.44.0" + "@typescript-eslint/typescript-estree" "8.44.0" + "@typescript-eslint/visitor-keys@8.41.0": version "8.41.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.41.0.tgz#16eb99b55d207f6688002a2cf425e039579aa9a9" @@ -2590,6 +2680,14 @@ "@typescript-eslint/types" "8.41.0" eslint-visitor-keys "^4.2.1" +"@typescript-eslint/visitor-keys@8.44.0": + version "8.44.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.0.tgz#0d9d5647e005c2ff8acc391d1208ab37d08850aa" + integrity sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw== + dependencies: + "@typescript-eslint/types" "8.44.0" + eslint-visitor-keys "^4.2.1" + "@ungap/structured-clone@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" @@ -11304,7 +11402,16 @@ string-length@^4.0.2: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -11426,7 +11533,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -11440,6 +11547,13 @@ strip-ansi@^0.3.0: dependencies: ansi-regex "^0.2.1" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1, strip-ansi@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -12011,6 +12125,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== +typescript-eslint@^8.44.0: + version "8.44.0" + resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-8.44.0.tgz#5f052fa52af2420fdc488ab4cabd823f4f8594c8" + integrity sha512-ib7mCkYuIzYonCq9XWF5XNw+fkj2zg629PSa9KNIQ47RXFF763S5BIX4wqz1+FLPogTZoiw8KmCiRPRa8bL3qw== + dependencies: + "@typescript-eslint/eslint-plugin" "8.44.0" + "@typescript-eslint/parser" "8.44.0" + "@typescript-eslint/typescript-estree" "8.44.0" + "@typescript-eslint/utils" "8.44.0" + typescript@^5.8.3: version "5.9.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" @@ -12955,8 +13079,16 @@ workbox-window@7.3.0, workbox-window@^7.3.0: "@types/trusted-types" "^2.0.2" workbox-core "7.3.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== From 22a3742f625725c89f241cf043aa3a25e8276037 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 19 Sep 2025 17:37:37 -0400 Subject: [PATCH 2/5] Turn on '@typescript-eslint/no-unnecessary-condition'. --- eslint.config.mjs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/eslint.config.mjs b/eslint.config.mjs index 34cb9022ef..698d1b9c07 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -193,6 +193,14 @@ export default defineConfig( // (it can make `yarn ts` fail after `yarn lint-fix`) '@typescript-eslint/no-unnecessary-type-assertion': 'off', + '@typescript-eslint/no-unnecessary-condition': [ + 'error', + { + allowConstantLoopConditions: 'only-allowed-literals', + checkTypePredicates: true, + }, + ], + // Consider enabling these in the future '@typescript-eslint/unbound-method': 'off', '@typescript-eslint/only-throw-error': 'off', From 03dd8ce667e892799272b0c3513edde53c320b81 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 19 Sep 2025 17:50:30 -0400 Subject: [PATCH 3/5] Add type annotations to all React component state members. I'm not really sure why, but without this, TypeScript thinks that the state can only have the values that it sees in the initialization value. It also doesn't complain if setState is called with values that don't match the type it inferred for the state member. It needs to know that this.state can have other values than the initial value if we want to avoid false positives from '@typescript-eslint/no-unnecessary-condition'. --- src/components/app/CompareHome.tsx | 2 +- src/components/app/FooterLinks.tsx | 2 +- src/components/app/Home.tsx | 4 ++-- src/components/app/KeyboardShortcut.tsx | 2 +- src/components/app/ListOfPublishedProfiles.tsx | 4 ++-- src/components/app/MenuButtons/MetaInfo.tsx | 2 +- src/components/app/MenuButtons/Permalink.tsx | 2 +- src/components/app/ProfileName.tsx | 2 +- src/components/js-tracer/Canvas.tsx | 2 +- src/components/js-tracer/Chart.tsx | 2 +- src/components/network-chart/NetworkChartRow.tsx | 2 +- src/components/shared/ButtonWithPanel/ArrowPanel.tsx | 2 +- src/components/shared/Draggable.tsx | 2 +- src/components/shared/MarkerSettings.tsx | 2 +- src/components/shared/PanelSearch.tsx | 2 +- src/components/shared/Reorderable.tsx | 2 +- src/components/shared/TreeView.tsx | 2 +- src/components/shared/VirtualList.tsx | 2 +- src/components/shared/Warning.tsx | 2 +- src/components/shared/WithSize.tsx | 2 +- src/components/shared/thread/SampleGraph.tsx | 2 +- src/components/timeline/FullTimeline.tsx | 2 +- src/components/timeline/Markers.tsx | 2 +- src/components/timeline/OverflowEdgeIndicator.tsx | 2 +- src/components/timeline/TrackBandwidthGraph.tsx | 2 +- src/components/timeline/TrackContextMenu.tsx | 2 +- src/components/timeline/TrackCustomMarkerGraph.tsx | 2 +- src/components/timeline/TrackEventDelayGraph.tsx | 2 +- src/components/timeline/TrackMemoryGraph.tsx | 2 +- src/components/timeline/TrackNetwork.tsx | 2 +- src/components/timeline/TrackPowerGraph.tsx | 2 +- src/components/timeline/TrackProcessCPUGraph.tsx | 2 +- src/components/timeline/TrackScreenshots.tsx | 2 +- src/components/timeline/TrackVisualProgressGraph.tsx | 2 +- src/components/tooltip/DivWithTooltip.tsx | 2 +- 35 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/components/app/CompareHome.tsx b/src/components/app/CompareHome.tsx index 71a1923459..2eac84424c 100644 --- a/src/components/app/CompareHome.tsx +++ b/src/components/app/CompareHome.tsx @@ -23,7 +23,7 @@ type State = { }; class CompareHomeImpl extends PureComponent { - override state = { profile1: '', profile2: '' }; + override state: State = { profile1: '', profile2: '' }; handleInputChange = (event: React.ChangeEvent) => { const { name, value } = event.target; diff --git a/src/components/app/FooterLinks.tsx b/src/components/app/FooterLinks.tsx index d1fb2745c8..a570915cda 100644 --- a/src/components/app/FooterLinks.tsx +++ b/src/components/app/FooterLinks.tsx @@ -15,7 +15,7 @@ export class FooterLinks extends PureComponent<{}, State> { this.setState({ hide: true }); }; - override state = { + override state: State = { hide: false, }; diff --git a/src/components/app/Home.tsx b/src/components/app/Home.tsx index 99e4d67898..15045dfd18 100644 --- a/src/components/app/Home.tsx +++ b/src/components/app/Home.tsx @@ -54,7 +54,7 @@ class ActionButtons extends React.PureComponent< > { _fileInput: HTMLInputElement | null = null; - override state = { + override state: ActionButtonsState = { isLoadFromUrlPressed: false, }; @@ -129,7 +129,7 @@ class LoadFromUrl extends React.PureComponent< LoadFromUrlProps, LoadFromUrlState > { - override state = { + override state: LoadFromUrlState = { value: '', }; diff --git a/src/components/app/KeyboardShortcut.tsx b/src/components/app/KeyboardShortcut.tsx index 58ee157ca1..b0c648f658 100644 --- a/src/components/app/KeyboardShortcut.tsx +++ b/src/components/app/KeyboardShortcut.tsx @@ -23,7 +23,7 @@ type State = { * Display a list of shortcuts that overlays the screen. */ export class KeyboardShortcut extends React.PureComponent { - override state = { + override state: State = { isOpen: false, // The eslint error is a false positive due to how it's used, see the line: // `focusAfterClosed.focus()` diff --git a/src/components/app/ListOfPublishedProfiles.tsx b/src/components/app/ListOfPublishedProfiles.tsx index 650c87f432..574b89b709 100644 --- a/src/components/app/ListOfPublishedProfiles.tsx +++ b/src/components/app/ListOfPublishedProfiles.tsx @@ -49,7 +49,7 @@ class PublishedProfile extends React.PureComponent< PublishedProfileProps, PublishedProfileState > { - override state = { + override state: PublishedProfileState = { confirmDialogIsOpen: false, }; @@ -162,7 +162,7 @@ type State = { export class ListOfPublishedProfiles extends PureComponent { _isMounted = false; - override state = { + override state: State = { uploadedProfileInformationList: null, }; diff --git a/src/components/app/MenuButtons/MetaInfo.tsx b/src/components/app/MenuButtons/MetaInfo.tsx index f9b319342a..87fd9e7058 100644 --- a/src/components/app/MenuButtons/MetaInfo.tsx +++ b/src/components/app/MenuButtons/MetaInfo.tsx @@ -55,7 +55,7 @@ type Props = ConnectedProps<{}, StateProps, DispatchProps>; * This component formats the profile's meta information into a dropdown panel. */ class MetaInfoPanelImpl extends React.PureComponent { - override state = { showsMoreInfo: false }; + override state: State = { showsMoreInfo: false }; /** * This method provides information about the symbolication status, and a button diff --git a/src/components/app/MenuButtons/Permalink.tsx b/src/components/app/MenuButtons/Permalink.tsx index 42f165e726..f0748f66e2 100644 --- a/src/components/app/MenuButtons/Permalink.tsx +++ b/src/components/app/MenuButtons/Permalink.tsx @@ -30,7 +30,7 @@ export class MenuButtonsPermalink extends React.PureComponent { this._permalinkTextField = elem; }; - override state = { + override state: State = { fullUrl: '', shortUrl: '', }; diff --git a/src/components/app/ProfileName.tsx b/src/components/app/ProfileName.tsx index 12e78e7df9..ced242dd2e 100644 --- a/src/components/app/ProfileName.tsx +++ b/src/components/app/ProfileName.tsx @@ -37,7 +37,7 @@ type State = { * state), and then when active, it switches to an input, which is only fixed in size. */ class ProfileNameImpl extends React.PureComponent { - override state = { + override state: State = { focusedWithKey: null, focusGeneration: 0, }; diff --git a/src/components/js-tracer/Canvas.tsx b/src/components/js-tracer/Canvas.tsx index abed86ac95..a40c9928f3 100644 --- a/src/components/js-tracer/Canvas.tsx +++ b/src/components/js-tracer/Canvas.tsx @@ -90,7 +90,7 @@ const ROW_LABEL_OFFSET_LEFT: CssPixels = 5; const FONT_SIZE: CssPixels = 10; class JsTracerCanvasImpl extends React.PureComponent { - override state = { + override state: State = { hasFirstDraw: false, }; _textMeasurement: TextMeasurement | null = null; diff --git a/src/components/js-tracer/Chart.tsx b/src/components/js-tracer/Chart.tsx index c980c96d93..bbabf09c80 100644 --- a/src/components/js-tracer/Chart.tsx +++ b/src/components/js-tracer/Chart.tsx @@ -175,7 +175,7 @@ class JsTracerChartLoader extends React.PureComponent< ChartLoaderProps, ChartLoaderState > { - override state = { + override state: ChartLoaderState = { // The loader needs to be mounted before rendering the chart, as it has expensive // selectors. readyToRenderExpensiveChart: false, diff --git a/src/components/network-chart/NetworkChartRow.tsx b/src/components/network-chart/NetworkChartRow.tsx index e1bb62e180..2090b46c09 100644 --- a/src/components/network-chart/NetworkChartRow.tsx +++ b/src/components/network-chart/NetworkChartRow.tsx @@ -314,7 +314,7 @@ export class NetworkChartRow extends React.PureComponent< NetworkChartRowProps, State > { - override state = { + override state: State = { pageX: 0, pageY: 0, hovered: false, diff --git a/src/components/shared/ButtonWithPanel/ArrowPanel.tsx b/src/components/shared/ButtonWithPanel/ArrowPanel.tsx index 109ac54b84..7bc64f9a31 100644 --- a/src/components/shared/ButtonWithPanel/ArrowPanel.tsx +++ b/src/components/shared/ButtonWithPanel/ArrowPanel.tsx @@ -27,7 +27,7 @@ type State = { export class ArrowPanel extends React.PureComponent { closeTimeout: NodeJS.Timeout | null = null; - override state = { + override state: State = { open: false, isClosing: false, openGeneration: 0, diff --git a/src/components/shared/Draggable.tsx b/src/components/shared/Draggable.tsx index c463d035e6..c4648a2ed4 100644 --- a/src/components/shared/Draggable.tsx +++ b/src/components/shared/Draggable.tsx @@ -36,7 +36,7 @@ export class Draggable extends React.PureComponent, State> { mouseMoveHandler: (param: MouseEvent) => void; mouseUpHandler: (param: MouseEvent) => void; } | null = null; - override state = { + override state: State = { dragging: false, }; diff --git a/src/components/shared/MarkerSettings.tsx b/src/components/shared/MarkerSettings.tsx index d7f8383e2e..06dd707fd7 100644 --- a/src/components/shared/MarkerSettings.tsx +++ b/src/components/shared/MarkerSettings.tsx @@ -42,7 +42,7 @@ type State = { }; class MarkerSettingsImpl extends PureComponent { - override state = { + override state: State = { isMarkerFiltersMenuVisible: false, isFilterMenuVisibleOnMouseDown: false, }; diff --git a/src/components/shared/PanelSearch.tsx b/src/components/shared/PanelSearch.tsx index be4be2aef7..c1a93c8121 100644 --- a/src/components/shared/PanelSearch.tsx +++ b/src/components/shared/PanelSearch.tsx @@ -19,7 +19,7 @@ type Props = { type State = { searchFieldFocused: boolean }; export class PanelSearch extends React.PureComponent { - override state = { searchFieldFocused: false }; + override state: State = { searchFieldFocused: false }; _onSearchFieldIdleAfterChange = (value: string) => { this.props.onSearch(value); }; diff --git a/src/components/shared/Reorderable.tsx b/src/components/shared/Reorderable.tsx index ad287fca42..7165b11fde 100644 --- a/src/components/shared/Reorderable.tsx +++ b/src/components/shared/Reorderable.tsx @@ -65,7 +65,7 @@ export class Reorderable extends React.PureComponent { }, }; - override state = { + override state: State = { phase: 'RESTING' as const, manipulatingIndex: -1, destinationIndex: -1, diff --git a/src/components/shared/TreeView.tsx b/src/components/shared/TreeView.tsx index a6eb6e374d..8f3df2e829 100644 --- a/src/components/shared/TreeView.tsx +++ b/src/components/shared/TreeView.tsx @@ -485,7 +485,7 @@ export class TreeView< initialWidth: CssPixels; } | null = null; - override state = { + override state: TreeViewState = { // This contains the current widths, while or after the user resizes them. fixedColumnWidths: null, diff --git a/src/components/shared/VirtualList.tsx b/src/components/shared/VirtualList.tsx index bd01924cf2..bc634c9fc3 100644 --- a/src/components/shared/VirtualList.tsx +++ b/src/components/shared/VirtualList.tsx @@ -260,7 +260,7 @@ export class VirtualList extends React.PureComponent< VirtualListState > { _container: { current: HTMLDivElement | null } = React.createRef(); - override state = { scrollTop: 0, containerHeight: 0 }; + override state: VirtualListState = { scrollTop: 0, containerHeight: 0 }; override componentDidMount() { document.addEventListener('copy', this._onCopy, false); diff --git a/src/components/shared/Warning.tsx b/src/components/shared/Warning.tsx index de54bf4c76..9fc0827979 100644 --- a/src/components/shared/Warning.tsx +++ b/src/components/shared/Warning.tsx @@ -18,7 +18,7 @@ type State = { }; export class Warning extends PureComponent { - override state = { isNoticeDisplayed: true }; + override state: State = { isNoticeDisplayed: true }; _onHideClick = () => { this.setState({ diff --git a/src/components/shared/WithSize.tsx b/src/components/shared/WithSize.tsx index 596ddabba7..5c51da89c5 100644 --- a/src/components/shared/WithSize.tsx +++ b/src/components/shared/WithSize.tsx @@ -29,7 +29,7 @@ export function withSize( Wrapped: React.ComponentType> ): React.ComponentType { return class WithSizeWrapper extends React.PureComponent { - override state = { width: 0, height: 0 }; + override state: State = { width: 0, height: 0 }; _container: HTMLElement | null = null; override componentDidMount() { diff --git a/src/components/shared/thread/SampleGraph.tsx b/src/components/shared/thread/SampleGraph.tsx index 032e0bb35f..76f84afe23 100644 --- a/src/components/shared/thread/SampleGraph.tsx +++ b/src/components/shared/thread/SampleGraph.tsx @@ -243,7 +243,7 @@ class ThreadSampleGraphCanvas extends React.PureComponent { } export class ThreadSampleGraphImpl extends PureComponent { - override state = { + override state: State = { hoveredPixelState: null, mouseX: 0, mouseY: 0, diff --git a/src/components/timeline/FullTimeline.tsx b/src/components/timeline/FullTimeline.tsx index 32fa0629b2..b6c9921f5a 100644 --- a/src/components/timeline/FullTimeline.tsx +++ b/src/components/timeline/FullTimeline.tsx @@ -123,7 +123,7 @@ class TimelineSettingsHiddenTracks extends React.PureComponent<{ } class FullTimelineImpl extends React.PureComponent { - override state = { + override state: State = { initialSelected: null, }; diff --git a/src/components/timeline/Markers.tsx b/src/components/timeline/Markers.tsx index f75f72db74..6132a9770a 100644 --- a/src/components/timeline/Markers.tsx +++ b/src/components/timeline/Markers.tsx @@ -312,7 +312,7 @@ type State = { }; class TimelineMarkers extends React.PureComponent { - override state = { + override state: State = { hoveredMarkerIndex: null, mouseDownMarker: null, mouseX: 0, diff --git a/src/components/timeline/OverflowEdgeIndicator.tsx b/src/components/timeline/OverflowEdgeIndicator.tsx index b9c5bc0072..14f0c612df 100644 --- a/src/components/timeline/OverflowEdgeIndicator.tsx +++ b/src/components/timeline/OverflowEdgeIndicator.tsx @@ -28,7 +28,7 @@ class OverflowEdgeIndicator extends React.PureComponent { _contentsWrapper: HTMLDivElement | null = null; _scrolledToInitialSelected: boolean = false; - override state = { + override state: State = { overflowsOnTop: false, overflowsOnRight: false, overflowsOnBottom: false, diff --git a/src/components/timeline/TrackBandwidthGraph.tsx b/src/components/timeline/TrackBandwidthGraph.tsx index 6f05c80bd2..ab69a052a1 100644 --- a/src/components/timeline/TrackBandwidthGraph.tsx +++ b/src/components/timeline/TrackBandwidthGraph.tsx @@ -334,7 +334,7 @@ type State = { * graph in the timeline. */ class TrackBandwidthGraphImpl extends React.PureComponent { - override state = { + override state: State = { hoveredCounter: null, mouseX: 0, mouseY: 0, diff --git a/src/components/timeline/TrackContextMenu.tsx b/src/components/timeline/TrackContextMenu.tsx index d4939d3526..f90af33130 100644 --- a/src/components/timeline/TrackContextMenu.tsx +++ b/src/components/timeline/TrackContextMenu.tsx @@ -107,7 +107,7 @@ class TimelineTrackContextMenuImpl extends PureComponent< TimelineTrackContextMenuProps, TimelineTrackContextMenuState > { - override state = { searchFilter: '' }; + override state: TimelineTrackContextMenuState = { searchFilter: '' }; _globalTrackClickTimeout: NodeJS.Timeout | null = null; _trackSearchFieldElem: { current: TrackSearchField | null } = React.createRef(); diff --git a/src/components/timeline/TrackCustomMarkerGraph.tsx b/src/components/timeline/TrackCustomMarkerGraph.tsx index db5d254e00..67c4a8d3d7 100644 --- a/src/components/timeline/TrackCustomMarkerGraph.tsx +++ b/src/components/timeline/TrackCustomMarkerGraph.tsx @@ -358,7 +358,7 @@ type State = { * graph in the timeline. */ class TrackCustomMarkerGraphImpl extends React.PureComponent { - override state = { + override state: State = { hoveredCounter: null, mouseX: 0, mouseY: 0, diff --git a/src/components/timeline/TrackEventDelayGraph.tsx b/src/components/timeline/TrackEventDelayGraph.tsx index 85461b52c2..5dba93539f 100644 --- a/src/components/timeline/TrackEventDelayGraph.tsx +++ b/src/components/timeline/TrackEventDelayGraph.tsx @@ -197,7 +197,7 @@ type State = { * */ class TrackEventDelayGraphImpl extends React.PureComponent { - override state = { + override state: State = { hoveredDelay: null, mouseX: 0, mouseY: 0, diff --git a/src/components/timeline/TrackMemoryGraph.tsx b/src/components/timeline/TrackMemoryGraph.tsx index 8e1a0f74a6..e16edfe802 100644 --- a/src/components/timeline/TrackMemoryGraph.tsx +++ b/src/components/timeline/TrackMemoryGraph.tsx @@ -273,7 +273,7 @@ type State = { * graph in the timeline. */ class TrackMemoryGraphImpl extends React.PureComponent { - override state = { + override state: State = { hoveredCounter: null, mouseX: 0, mouseY: 0, diff --git a/src/components/timeline/TrackNetwork.tsx b/src/components/timeline/TrackNetwork.tsx index 04f6ffb664..339a4bc6ab 100644 --- a/src/components/timeline/TrackNetwork.tsx +++ b/src/components/timeline/TrackNetwork.tsx @@ -277,7 +277,7 @@ type State = { }; class Network extends PureComponent { - override state = { hoveredMarkerIndex: null, mouseX: 0, mouseY: 0 }; + override state: State = { hoveredMarkerIndex: null, mouseX: 0, mouseY: 0 }; _onHoveredMarkerChange = ( hoveredMarkerIndex: MarkerIndex | null, diff --git a/src/components/timeline/TrackPowerGraph.tsx b/src/components/timeline/TrackPowerGraph.tsx index c8613636f5..446eef23dc 100644 --- a/src/components/timeline/TrackPowerGraph.tsx +++ b/src/components/timeline/TrackPowerGraph.tsx @@ -304,7 +304,7 @@ type State = { * graph in the timeline. */ class TrackPowerGraphImpl extends React.PureComponent { - override state = { + override state: State = { hoveredCounter: null, mouseX: 0, mouseY: 0, diff --git a/src/components/timeline/TrackProcessCPUGraph.tsx b/src/components/timeline/TrackProcessCPUGraph.tsx index 0f6c7d7fe3..dbe9bfce8c 100644 --- a/src/components/timeline/TrackProcessCPUGraph.tsx +++ b/src/components/timeline/TrackProcessCPUGraph.tsx @@ -228,7 +228,7 @@ type State = { * graph in the timeline. */ class TrackProcessCPUGraphImpl extends React.PureComponent { - override state = { + override state: State = { hoveredCounter: null, mouseX: 0, mouseY: 0, diff --git a/src/components/timeline/TrackScreenshots.tsx b/src/components/timeline/TrackScreenshots.tsx index 4ec906de4e..93a227301c 100644 --- a/src/components/timeline/TrackScreenshots.tsx +++ b/src/components/timeline/TrackScreenshots.tsx @@ -54,7 +54,7 @@ type State = { }; class Screenshots extends PureComponent { - override state = { + override state: State = { offsetX: null, pageX: null, containerTop: null, diff --git a/src/components/timeline/TrackVisualProgressGraph.tsx b/src/components/timeline/TrackVisualProgressGraph.tsx index bdf7f1d715..5aefdc4dd4 100644 --- a/src/components/timeline/TrackVisualProgressGraph.tsx +++ b/src/components/timeline/TrackVisualProgressGraph.tsx @@ -197,7 +197,7 @@ type State = { * graph in the timeline. */ class TrackVisualProgressGraphImpl extends React.PureComponent { - override state = { + override state: State = { hoveredVisualProgress: null, mouseX: 0, mouseY: 0, diff --git a/src/components/tooltip/DivWithTooltip.tsx b/src/components/tooltip/DivWithTooltip.tsx index bb430e9c79..aa1e0cef02 100644 --- a/src/components/tooltip/DivWithTooltip.tsx +++ b/src/components/tooltip/DivWithTooltip.tsx @@ -22,7 +22,7 @@ type State = { * a div. */ export class DivWithTooltip extends React.PureComponent { - override state = { + override state: State = { isMouseOver: false, mouseX: 0, mouseY: 0, From e6e45a67bad26218795f034a0139a1d6eca090db Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 19 Sep 2025 17:50:30 -0400 Subject: [PATCH 4/5] Add some Partial<> annotations. Without these, it thinks that all of the possible keys are present. Fixing this is needed if we want to avoid '@typescript-eslint/no-unnecessary-condition' complaining about our 'prop in obj' tests. --- src/reducers/app.ts | 2 +- src/selectors/app.tsx | 6 +++--- src/types/state.ts | 2 +- src/types/transforms.ts | 4 +++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/reducers/app.ts b/src/reducers/app.ts index d3cff8785e..661071a1ae 100644 --- a/src/reducers/app.ts +++ b/src/reducers/app.ts @@ -176,7 +176,7 @@ const lastVisibleThreadTabSlug: Reducer = ( } }; -const trackThreadHeights: Reducer<{ [key: ThreadsKey]: CssPixels }> = ( +const trackThreadHeights: Reducer>> = ( state = {}, action ) => { diff --git a/src/selectors/app.tsx b/src/selectors/app.tsx index 65cb1d043e..496d2f4b4c 100644 --- a/src/selectors/app.tsx +++ b/src/selectors/app.tsx @@ -58,9 +58,9 @@ export const getPanelLayoutGeneration: Selector = (state) => getApp(state).panelLayoutGeneration; export const getLastVisibleThreadTabSlug: Selector = (state) => getApp(state).lastVisibleThreadTabSlug; -export const getTrackThreadHeights: Selector<{ - [key: ThreadsKey]: CssPixels; -}> = (state) => getApp(state).trackThreadHeights; +export const getTrackThreadHeights: Selector< + Partial> +> = (state) => getApp(state).trackThreadHeights; export const getIsNewlyPublished: Selector = (state) => getApp(state).isNewlyPublished; export const getExperimental: Selector = (state) => diff --git a/src/types/state.ts b/src/types/state.ts index 59a388782a..f939e0cc2b 100644 --- a/src/types/state.ts +++ b/src/types/state.ts @@ -180,7 +180,7 @@ export type AppState = { readonly sidebarOpenCategories: Map>; readonly panelLayoutGeneration: number; readonly lastVisibleThreadTabSlug: TabSlug; - readonly trackThreadHeights: Record; + readonly trackThreadHeights: Partial>; readonly isNewlyPublished: boolean; readonly isDragAndDropDragging: boolean; readonly isDragAndDropOverlayRegistered: boolean; diff --git a/src/types/transforms.ts b/src/types/transforms.ts index 4487a0c4ab..5017bfe5ab 100644 --- a/src/types/transforms.ts +++ b/src/types/transforms.ts @@ -350,4 +350,6 @@ export type Transform = TransformDefinitions[keyof TransformDefinitions]; export type TransformType = Transform['type']; export type TransformStack = Transform[]; -export type TransformStacksPerThread = { [key: ThreadsKey]: TransformStack }; +export type TransformStacksPerThread = Partial< + Record +>; From e1439dac93a5e4e827f8150e413a9ee4c5076641 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Fri, 19 Sep 2025 17:50:30 -0400 Subject: [PATCH 5/5] WIP address no-unnecessary-condition --- src/actions/profile-view.ts | 1 - src/actions/receive-profile.ts | 6 +----- src/app-logic/url-handling.ts | 2 +- src/profile-logic/profile-data.ts | 8 ++------ src/profile-logic/tracks.ts | 5 +---- src/selectors/profile.ts | 11 +---------- src/selectors/zipped-profiles.tsx | 9 +++++---- src/symbolicator-cli/index.ts | 3 --- src/types/state.ts | 2 +- 9 files changed, 12 insertions(+), 35 deletions(-) diff --git a/src/actions/profile-view.ts b/src/actions/profile-view.ts index 43af88bb8b..675e2eb48d 100644 --- a/src/actions/profile-view.ts +++ b/src/actions/profile-view.ts @@ -1080,7 +1080,6 @@ export function isolateProcess( for (const localTrack of localTracks) { if ( localTrack.type === 'thread' && - localTrack.threadIndex !== undefined && oldSelectedThreadIndexes.has(localTrack.threadIndex) ) { newSelectedThreadIndexes.add(localTrack.threadIndex); diff --git a/src/actions/receive-profile.ts b/src/actions/receive-profile.ts index 0bd60fb0ec..0d2e704f2d 100644 --- a/src/actions/receive-profile.ts +++ b/src/actions/receive-profile.ts @@ -1096,7 +1096,7 @@ async function _extractJsonFromResponse( message = 'The network request to load the profile was aborted.'; } else if (fileType === 'application/json') { message = 'The profile’s JSON could not be decoded.'; - } else if (fileType === null && arrayBuffer !== null) { + } else if (arrayBuffer !== null) { // If the content type is not specified, use a raw array buffer // to fallback to other supported profile formats. return arrayBuffer; @@ -1163,10 +1163,6 @@ export function retrieveProfileOrZipFromUrl( serializedProfile, profileUrl ); - if (profile === undefined) { - throw new Error('Unable to parse the profile.'); - } - await dispatch(loadProfile(profile, {}, initialLoad)); break; } diff --git a/src/app-logic/url-handling.ts b/src/app-logic/url-handling.ts index df7b8adbae..571313bb48 100644 --- a/src/app-logic/url-handling.ts +++ b/src/app-logic/url-handling.ts @@ -892,7 +892,7 @@ const _upgraders: { // will not be preserved. const transforms = parseTransforms(query.transforms); - if (!transforms || transforms.length === 0) { + if (transforms.length === 0) { // We don't have any transforms to upgrade. return; } diff --git a/src/profile-logic/profile-data.ts b/src/profile-logic/profile-data.ts index 76bff5aecf..fe16ff38dc 100644 --- a/src/profile-logic/profile-data.ts +++ b/src/profile-logic/profile-data.ts @@ -2773,15 +2773,11 @@ export function getThreadProcessDetails( ): string { let label = `${friendlyThreadName}\n`; label += `Thread: "${thread.name}"`; - if (thread.tid !== undefined) { - label += ` (${thread.tid})`; - } + label += ` (${thread.tid})`; if (thread.processType) { label += `\nProcess: "${thread.processType}"`; - if (thread.pid !== undefined) { - label += ` (${thread.pid})`; - } + label += ` (${thread.pid})`; } if (thread.isPrivateBrowsing) { diff --git a/src/profile-logic/tracks.ts b/src/profile-logic/tracks.ts index 44277e17b5..a4cf472a3c 100644 --- a/src/profile-logic/tracks.ts +++ b/src/profile-logic/tracks.ts @@ -144,10 +144,7 @@ function _getDefaultLocalTrackOrder( if (tracks[a].type === 'thread' && tracks[b].type === 'thread' && profile) { const idxA = tracks[a].threadIndex; const idxB = tracks[b].threadIndex; - if (idxA === undefined || idxB === undefined) { - return -1; - } - if (profile && profile.meta.keepProfileThreadOrder) { + if (profile.meta.keepProfileThreadOrder) { return idxA - idxB; } const nameA = profile.threads[idxA].name; diff --git a/src/selectors/profile.ts b/src/selectors/profile.ts index 13ed4a647b..a596fb8ee2 100644 --- a/src/selectors/profile.ts +++ b/src/selectors/profile.ts @@ -274,7 +274,7 @@ export const getMarkerSchemaByName: Selector = type CounterSelectors = ReturnType; -const _counterSelectors: { [key: number]: CounterSelectors } = {}; +const _counterSelectors: Partial> = {}; export const getCounterSelectors = (index: CounterIndex): CounterSelectors => { let selectors = _counterSelectors[index]; if (!selectors) { @@ -629,11 +629,6 @@ export const getHiddenTrackCount: Selector = createSelector( if (globalTrackIndex === -1) { throw new Error('Unable to find a global track from the given pid.'); } - if (!hiddenLocalTracks) { - throw new Error( - 'Unable to find the hidden local tracks from the given pid' - ); - } if (hiddenGlobalTracks.has(globalTrackIndex)) { // The entire process group is hidden, count all of the tracks. @@ -805,10 +800,6 @@ export const getProfileFilterSortedPageData: Selector = } for (const threadIndex of threadIndexes.values()) { const threadScore = threadActivityScores[threadIndex]; - if (!threadScore) { - throw new Error('Failed to find the thread score!'); - } - tabScore += threadScore.boostedSampleScore; } pageDataWithScore.push({ diff --git a/src/selectors/zipped-profiles.tsx b/src/selectors/zipped-profiles.tsx index 3ed8cf16fb..c2c5f55005 100644 --- a/src/selectors/zipped-profiles.tsx +++ b/src/selectors/zipped-profiles.tsx @@ -74,10 +74,11 @@ export const getZipFileMaxDepth: Selector = createSelector( * render a file picker to load profiles from the zip file. */ export const getZipFileTreeOrNull: Selector = - createSelector(getZipFileTable, getProfileUrl, (zipFileTable, zipFileUrl) => - zipFileTable === null - ? null - : new ZipFiles.ZipFileTree(zipFileTable, zipFileUrl) + createSelector( + getZipFileTable, + getProfileUrl, + (zipFileTable, zipFileUrl) => + new ZipFiles.ZipFileTree(zipFileTable, zipFileUrl) ); /** diff --git a/src/symbolicator-cli/index.ts b/src/symbolicator-cli/index.ts index cf0ff1bb21..901b40098c 100644 --- a/src/symbolicator-cli/index.ts +++ b/src/symbolicator-cli/index.ts @@ -94,9 +94,6 @@ export async function run(options: CliOptions) { // Load the profile. const profile = await unserializeProfileOfArbitraryFormat(byteBufferCopy); - if (profile === undefined) { - throw new Error('Unable to parse the profile.'); - } const symbolStoreDB = new InMemorySymbolDB(); diff --git a/src/types/state.ts b/src/types/state.ts index f939e0cc2b..dcc9d193b2 100644 --- a/src/types/state.ts +++ b/src/types/state.ts @@ -67,7 +67,7 @@ export type TableViewOptions = { readonly fixedColumnWidths: Array | null; }; -export type TableViewOptionsPerTab = { [K in TabSlug]: TableViewOptions }; +export type TableViewOptionsPerTab = Partial>; export type RightClickedCallNode = { readonly threadsKey: ThreadsKey;