Convert the entire codebase to TypeScript#5549
Convert the entire codebase to TypeScript#5549mstange merged 41 commits intofirefox-devtools:mainfrom
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #5549 +/- ##
==========================================
- Coverage 86.13% 85.84% -0.30%
==========================================
Files 309 309
Lines 29883 30319 +436
Branches 8038 8345 +307
==========================================
+ Hits 25740 26026 +286
- Misses 3552 3872 +320
+ Partials 591 421 -170 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
60d093b to
454f419
Compare
package.json
Outdated
| "flow-stop": "flow stop", | ||
| "flow-coverage": "npx flow-coverage-report -i 'src/**/*.js' -t html -t text", | ||
| "flow-generate-libdefs": "npx flow-typed install --libdefDir src/types/libdef", | ||
| "typecheck": "tsc --noEmit", |
There was a problem hiding this comment.
nit: can we maybe name this ts? yarn ts is shorter and easier to type for me. And we already have the same command in profiler-server.
There was a problem hiding this comment.
I've added a commit to do the rename.
9b9eeee to
16260f2
Compare
canova
left a comment
There was a problem hiding this comment.
Oh wow, this PR is huge, amazing work! I couldn't finish the review yet, I'm at ecff67d (Convert window-console.js and index.js.) at the moment. At least all the shipping code is done! Tomorrow I will continue with the rest. I'm submitting the comments that I wrote so far, so you can look at my them sooner than later. I expect to finish the review tomorrow.
I see a few of places where I see flow being mentioned. But I think they can be removed as a follow-ups.
For example:
- We still have
utils/flow.ts. It's funny that it's flow.ts now, maybe we can change it to utils/typescript.ts or utils/type.ts - I see some flow mentions inside src/reducers/README.md
- Some more flow mentions in the comments.
But they all could be done as follow-ups.
Some files for some reason don't appear they are git mved even though they are in the same commit, but that's fine I think.
Also as a follow-up, it might be good to add the commit hashes of these inside .git-blame-ignore-revs so they would be ignored from the blame? (don't know if adding the merge commit hash is enough or we need to add every one of them individually)
Ah lastly, can you run npx yarn-deduplicate to deduplicate some of the packages that we added?
package.json
Outdated
| "flow-coverage": "npx flow-coverage-report -i 'src/**/*.js' -t html -t text", | ||
| "flow-generate-libdefs": "npx flow-typed install --libdefDir src/types/libdef", | ||
| "protoc": "npx -p protobufjs-cli pbjs -t static-module -w commonjs -o ./src/profile-logic/import/proto/simpleperf_report.js ./src/profile-logic/import/proto/simpleperf_report.proto", | ||
| "ts": "tsc --noEmit", |
There was a problem hiding this comment.
We already have noEmit: true inside tsconfig.json, we can remove this one.
tsconfig.json
Outdated
|
|
||
| // Exceptions to strictness, consider enabling in the future | ||
| "useUnknownInCatchVariables": false, // Sounds fine, enforces `} catch (e) { if (e instanceof Error) {` etc | ||
| "alwaysStrict": false, // Affects runtime behavior, I think - need to check what we had with Flow |
There was a problem hiding this comment.
Doc says: Ensures that your files are parsed in the ECMAScript strict mode, and emit “use strict” for each source file.
Since we have "noEmit": true, we are not actually using tsc itself for transpiling the source into JS, and rely on babel. So I think this option shouldn't have any effect.
I actually removed this line and compiled the source code again and main js bundle file has the same hash.
There was a problem hiding this comment.
Ah of course, makes sense. I'll remove it.
| // Exceptions to strictness, consider enabling in the future | ||
| "useUnknownInCatchVariables": false, // Sounds fine, enforces `} catch (e) { if (e instanceof Error) {` etc | ||
| "alwaysStrict": false, // Affects runtime behavior, I think - need to check what we had with Flow | ||
| "exactOptionalPropertyTypes": false, // Benefit unclear |
There was a problem hiding this comment.
Hm, I'm not so sure about this, removing it doesn't throw any error, but also don't know if it makes much difference.
There was a problem hiding this comment.
Oh, it seems to default to false even in "strict": true mode, so removing this line doesn't enable the flag.
tsconfig.json
Outdated
|
|
||
| // Module Resolution | ||
| "resolveJsonModule": true, | ||
| "baseUrl": ".", |
There was a problem hiding this comment.
seems not, I'll remove it.
| low?: number, | ||
| high?: number | ||
| low: number = 0, | ||
| high: number = array.length |
There was a problem hiding this comment.
Whattt, I don't know why I didn't know this, but I've never tried referencing another parameter inside the following parameters in JS before (like = array.length). I just assumed it wouldn't work. I guess? TIL!
There was a problem hiding this comment.
Haha yes, this is one of the few times where this is quite handy!
src/selectors/app.tsx
Outdated
| getApp(state).trackThreadHeights as unknown as { | ||
| [key: ThreadsKey]: CssPixels; | ||
| }; |
There was a problem hiding this comment.
nit: Removing the casting still passed the ts check for me:
export const getTrackThreadHeights: Selector<{
[key: ThreadsKey]: CssPixels;
}> = (state) => getApp(state).trackThreadHeights;There was a problem hiding this comment.
oh thanks for catching that
src/actions/app.ts
Outdated
| }); | ||
| dispatch({ | ||
| type: 'CHANGE_SELECTED_TAB', | ||
| type: 'CHANGE_SELECTED_TAB' as const, |
There was a problem hiding this comment.
oh curious, why do we need to pass them as const?
There was a problem hiding this comment.
hmm, it seems I don't need to! Maybe I converted this file before I had the Action type properly set up.
There was a problem hiding this comment.
I've removed the as consts.
| |}; | ||
|
|
||
| type Props = {| | ||
| ...RestProps, |
There was a problem hiding this comment.
Is it not possible to use ...RestProps, in ts? Hm, I see & SizeProps in some other places.
There was a problem hiding this comment.
The trouble here was the sampleIndex prop, which is | null for Props but required in RestProps.
If I do type Props = { <nonrestprops> } & RestProps thensampleIndex also becomes required in Props.
| 'TrackPower--tooltip-power-watt', | ||
| 'TrackPower--tooltip-power-milliwatt' | ||
| 'TrackPower--tooltip-power-milliwatt', | ||
| 'TrackPower--tooltip-power-microwatt' |
There was a problem hiding this comment.
Ah, I guess we didn't have this TrackPower--tooltip-power-microwatt l10n id before. It would be good file a bug for that.
There was a problem hiding this comment.
oops, well, we still don't have it. Filed #5554 and removed the change. I changed the type of the last argument to _formatPower to be optional.
canova
left a comment
There was a problem hiding this comment.
I'm done going through the commits! It was easier to look at the second half.
Wow, thanks a lot for the migration! Looks great. Let's land this and we can follow-up with the improvements.
FWIW, I was using this branch locally to test stuff too and I can really feel the difference between flow and this! It was taking a long time to get LSP errors on my editor with flow, now I'm getting near instant feedback on errors! The experience difference is night and day. And after this, I can finally remove every config/plugin related to Flow from my editor.
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
|
||
| // @flow | ||
| // @ts-nocheck Complex window/history mock with extensive DOM API manipulation that requires intricate typing |
There was a problem hiding this comment.
Not really worth a look now, but it could be interesting to see if we can do it somehow (not for this PR, some other time)
| export function fireFullKeyPress( | ||
| element: HTMLElement, | ||
| options: { key: string, ... } | ||
| options: { key: string } |
There was a problem hiding this comment.
Heh non exact typing comes in handy here.
| /** | ||
| * These type tests create various values that should all type check correctly to show | ||
| * that the react-redux system is working correctly. | ||
| * | ||
| * We are catching the following mistakes at the type level: | ||
| * | ||
| * explicitConnect plain connect | ||
| * mapStateToProps: | ||
| * - missing prop yes yes | ||
| * - prop with wrong type yes yes | ||
| * - extra prop no (was yes with Flow) no | ||
| * | ||
| * mapDispatchToProps: | ||
| * - missing prop yes yes | ||
| * - action wrong type yes yes | ||
| * - thunk action wrong type yes yes | ||
| * - extra prop no (was yes with Flow) no | ||
| * | ||
| * OwnProps: | ||
| * - missing prop yes yes | ||
| * - prop with wrong type yes yes | ||
| * - extra prop yes yes | ||
| * | ||
| * In summary, we lost the ability to detect unused state props and unused | ||
| * dispatch props when we migrated to TypeScript. On the other hand, | ||
| * explicitConnect now catches the same mistakes as plain connect, so we | ||
| * can migrate to plain connect at any time without losing type coverage. | ||
| */ |
There was a problem hiding this comment.
Thanks for the comment! I guess that was the reason you mentioned #3063?
| expect(Array.from(set)).toEqual(sampleValues); | ||
| expect(Array.from(set.values())).toEqual(sampleValues); | ||
| // @ts-expect-error The TypeScript definition of Array.from only accepts Iterable, not Iterator - not sure what's correct here | ||
| expect(Array.from<CallNodePath>(set.values())).toEqual(sampleValues); |
There was a problem hiding this comment.
Huh, that's weird, but I have no idea either.
| const matchUrlResult = fetchUrlRe.exec(url); | ||
| if (matchUrlResult) { | ||
| // $FlowExpectError Our Flow doesn't know about named groups. |
There was a problem hiding this comment.
Heh, I agree that this doesn't look like a correct location for this test (not for this PR again ofc).
I had to add two "resolutions" to the package.json: - "@types/react-splitter-layout/@types/react": "^18.3.1" so that we don't end up with two different typings for React. - "@types/trusted-types": "^2.0.7" because workbox depends on "^2.0.2" which has conflicts with the "official" TypeScript DOM types, and this conflict was fixed in v2.0.3. v2.0.7 is just the most recent version, so I picked that.
This test looks like it wanted to be in some directory but couldn't find the right door. It seems a bit lost.
16260f2 to
8ba9ac4
Compare
…ing babel to emit the JS.
8ba9ac4 to
fe67997
Compare
|
Thanks for the thorough review of this huge PR!
I ended up fixing them all.
Renamed to
Fixed, and I went through the other .md files as well.
Oh actually this one I haven't fixed.
Yeah I'm not sure why. Maybe because those didn't hit the percentage threshold of preserved lines.
Ah yes, good idea.
Done.
🎉 |
Changes: [Nazım Can Altınova] Display the marker description at the top inside the marker tooltips (#5534) [Florian Quèze] Change the 'JavaScript' radio button label to 'Script' (#5530) [Markus Stange] Implement profile logic and some selectors for the function list (#5525) [Markus Stange] Some small type fixes (#5538) [Markus Stange] Simplify return type of the callback we pass to setState. (#5540) [Markus Stange] Pass the correct value to the reducer's action argument (#5543) [Markus Stange] Change withSize to accept PropsWithoutSize as its type parameter (#5541) [Nazım Can Altınova] Make sure that the test-debug command runs the tests properly (#5545) [Markus Stange] Improve type coverage involving network phases (#5539) [Markus Stange] Change implementation of withChartViewport (#5542) [Florian Quèze] A new permalink should be generated and shown after using the re-upload feature. (#5547) [Florian Quèze] Show the vertical ruler in the timeline when hovering the network chart (#5548) [Markus Stange] Convert the entire codebase to TypeScript (#5549) [Nazım Can Altınova] Update the yarn.lock file after recent changes (#5557) [Markus Stange] Add proper TypeScript coverage for window-navigation.ts (#5559) [Markus Stange] Remove leftover $FlowExpectError comments (#5560) [Markus Stange] Fix Iterator / Iterable confusion (#5561) [Nazım Can Altınova] Remove the unneeded test-all:ci script (#5566) [Nazım Can Altınova] Fix a type case inconsistency (#5569) [Florian Quèze] Make 'yarn lint --fix' work as an alias to 'yarn lint-fix'. (#5563) [Ryan Hunt] Don't stringify JSON again in fetchUrlResponse (#5570) [Nazım Can Altınova] Upgrade ESLint to version 9 (#5567) [Markus Stange] Simplify Worker setup, and support .json.gz inputs in symbolicator-cli (#5556) [Nazım Can Altınova] Add TypeScript coverage to the intersection observer mock (#5574) [Markus Stange] Set the preview selection to null when there is no selection (#5568) [Markus Stange] Add tests for query-api.ts (#5571) [Markus Stange] Enable noUnusedParameters and @typescript-eslint/no-unused-vars and clean up a few more things (#5576) [Ryan Hunt] Embed iongraph-web and use for iongraph.json source files (#5577) [Markus Stange] Remove recursion in filterThreadToSearchString (#5572) And thanks to our localizers: be: Mikalai Udodau de: Michael Köhler el: Jim Spentzos en-CA: chutten en-GB: Paul es-CL: ravmn fr: Théo Chevalier fur: Fabio Tomat fy-NL: Fjoerfoks ia: Melo46 it: Francesco Lodolo [:flod] nl: Mark Heijl pt-BR: Marcelo Ghelman ru: Valery Ledovskoy sv-SE: Luna Jernberg tr: Rua tr: Selim Şumlu uk: Іhor Hordiichuk zh-CN: Olvcpr423 zh-TW: Pin-guang Chen
Example with Focus function transform: [Production](https://share.firefox.dev/4mW78M3) | [Deploy preview](https://deploy-preview-5613--perf-html.netlify.app/public/ggqb1y28h0nmwyxaqjdhvrnmfpn58hyeg25cza8/calltree/?globalTrackOrder=q0phkm7in1c9f5g862boela34dj&hiddenGlobalTracks=1wo&hiddenLocalTracksByPid=2465-1w4~92294-0~36702-0~2523-0~36259-0w2~71663-01~71664-0&search=oae&thread=x6&transforms=ff-280&v=11) Example with JS-only view: [Production](https://share.firefox.dev/4poRI4M) | [Deploy preview](https://deploy-preview-5613--perf-html.netlify.app/public/rpnres9s7rdrsfb240wtskvrq5sv7xzn3f4m2p0/calltree/?globalTrackOrder=30w2&hiddenGlobalTracks=01&hiddenLocalTracksByPid=2588-1w3~2591-01&implementation=js&range=9133m2135~9517m70&search=aoeu&tabID=25&thread=f&v=11) Fixes #5612. The more stringent array bounds checks from #5599 revealed a bug that I introduced in #5549: Marker stacks were not being substituted if the `convertStack` lambda returned null. This PR fixes the type and restores the working code from before the TypeScript migration.
FIxes #2931.
I squashed and re-split the changes from #5531.
yarn test-allpasses after every commit.702 files changed, 13512 insertions(+), 64132 deletions(-)