Skip to content

Commit 77670eb

Browse files
authored
Add lint rule to protect against this access on unbound methods (#32578)
* Add Actions to ViewModel utility types and specify `this: void` signature Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add https://typescript-eslint.io/rules/unbound-method/ linter to shared-components also fix stray lint config which doesn't apply to SC Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add https://typescript-eslint.io/rules/unbound-method/ linter to element-web Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix genuine issues identified by the linter Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Specify this:void on i18napi Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update Module API Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add comment for MapToVoidThis Added utility type to map VM actions to unbound functions. --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
1 parent 87b28b7 commit 77670eb

File tree

135 files changed

+285
-263
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+285
-263
lines changed

.eslintrc.cjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ module.exports = {
199199
files: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}", "playwright/**/*.ts", "*.ts"],
200200
extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"],
201201
rules: {
202+
"@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
202203
"@typescript-eslint/explicit-function-return-type": [
203204
"error",
204205
{
@@ -238,6 +239,7 @@ module.exports = {
238239
"@typescript-eslint/explicit-function-return-type": "off",
239240
"@typescript-eslint/explicit-member-accessibility": "off",
240241
"@typescript-eslint/no-empty-object-type": "off",
242+
"@typescript-eslint/unbound-method": "off",
241243

242244
// Jest/Playwright specific
243245

docs/MVVM.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ interface FooViewActions {
4747

4848
// ViewModel is an object (usually a class) that implements both the interfaces listed above.
4949
// https://github.com/element-hq/element-web/blob/develop/packages/shared-components/src/ViewModel.ts
50-
export type FooViewModel = ViewModel<FooViewSnapshot> & FooViewActions;
50+
export type FooViewModel = ViewModel<FooViewSnapshot, FooViewActions>;
5151

5252
interface FooViewProps {
5353
// Ideally the view only depends on the view model i.e you don't expect any other props here.

packages/shared-components/.eslintrc.cjs

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ module.exports = {
99
root: true,
1010
plugins: ["matrix-org", "eslint-plugin-react-compiler"],
1111
extends: [
12-
"plugin:matrix-org/babel",
1312
"plugin:matrix-org/react",
1413
"plugin:matrix-org/a11y",
14+
"plugin:matrix-org/typescript",
15+
"plugin:matrix-org/react",
1516
"plugin:storybook/recommended",
1617
],
1718
parserOptions: {
@@ -42,37 +43,35 @@ module.exports = {
4243
],
4344
},
4445
],
46+
47+
"@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }],
48+
"@typescript-eslint/explicit-function-return-type": [
49+
"error",
50+
{
51+
allowExpressions: true,
52+
},
53+
],
54+
55+
// We're okay being explicit at the moment
56+
// "@typescript-eslint/no-empty-interface": "off",
57+
// We'd rather not do this but we do
58+
// "@typescript-eslint/ban-ts-comment": "off",
59+
// We're okay with assertion errors when we ask for them
60+
"@typescript-eslint/no-non-null-assertion": "off",
61+
"@typescript-eslint/no-empty-object-type": [
62+
"error",
63+
{
64+
// We do this sometimes to brand interfaces
65+
allowInterfaces: "with-single-extends",
66+
},
67+
],
4568
},
4669
overrides: [
4770
{
48-
files: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}"],
49-
extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"],
71+
files: ["src/**/*.test.{ts,tsx}"],
5072
rules: {
51-
"@typescript-eslint/explicit-function-return-type": [
52-
"error",
53-
{
54-
allowExpressions: true,
55-
},
56-
],
57-
58-
// Remove Babel things manually due to override limitations
59-
"@babel/no-invalid-this": ["off"],
60-
61-
// We're okay being explicit at the moment
62-
"@typescript-eslint/no-empty-interface": "off",
63-
// We disable this while we're transitioning
73+
"@typescript-eslint/unbound-method": "off",
6474
"@typescript-eslint/no-explicit-any": "off",
65-
// We'd rather not do this but we do
66-
"@typescript-eslint/ban-ts-comment": "off",
67-
// We're okay with assertion errors when we ask for them
68-
"@typescript-eslint/no-non-null-assertion": "off",
69-
"@typescript-eslint/no-empty-object-type": [
70-
"error",
71-
{
72-
// We do this sometimes to brand interfaces
73-
allowInterfaces: "with-single-extends",
74-
},
75-
],
7675
},
7776
},
7877
],

packages/shared-components/src/audio/AudioPlayerView/AudioPlayerView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export interface AudioPlayerViewActions {
7070
/**
7171
* The view model for the audio player.
7272
*/
73-
export type AudioPlayerViewModel = ViewModel<AudioPlayerViewSnapshot> & AudioPlayerViewActions;
73+
export type AudioPlayerViewModel = ViewModel<AudioPlayerViewSnapshot, AudioPlayerViewActions>;
7474

7575
interface AudioPlayerViewProps {
7676
/**

packages/shared-components/src/message-body/DecryptionFailureBodyView/DecryptionFailureBodyView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ interface DecryptionFailureBodyViewProps {
8484
/**
8585
* React ref to attach to any React components returned
8686
*/
87-
ref?: React.RefObject<any>;
87+
ref?: React.RefObject<HTMLDivElement>;
8888
}
8989

9090
/**

packages/shared-components/src/profile/DisambiguatedProfile/DisambiguatedProfileView.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ export interface DisambiguatedProfileViewActions {
5757
/**
5858
* The view model for DisambiguatedProfileView.
5959
*/
60-
export type DisambiguatedProfileViewModel = ViewModel<DisambiguatedProfileViewSnapshot> &
61-
DisambiguatedProfileViewActions;
60+
export type DisambiguatedProfileViewModel = ViewModel<
61+
DisambiguatedProfileViewSnapshot,
62+
DisambiguatedProfileViewActions
63+
>;
6264

6365
interface DisambiguatedProfileViewProps {
6466
/**

packages/shared-components/src/right-panel/WidgetContextMenu/WidgetContextMenuView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export interface WidgetContextMenuAction {
8989
onMoveButton: (direction: number) => void;
9090
}
9191

92-
export type WidgetContextMenuViewModel = ViewModel<WidgetContextMenuSnapshot> & WidgetContextMenuAction;
92+
export type WidgetContextMenuViewModel = ViewModel<WidgetContextMenuSnapshot, WidgetContextMenuAction>;
9393

9494
interface WidgetContextMenuViewProps {
9595
vm: WidgetContextMenuViewModel;

packages/shared-components/src/room-list/RoomListHeaderView/RoomListHeaderView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export interface RoomListHeaderViewActions {
103103
/**
104104
* The view model for the room list header component.
105105
*/
106-
export type RoomListHeaderViewModel = ViewModel<RoomListHeaderViewSnapshot> & RoomListHeaderViewActions;
106+
export type RoomListHeaderViewModel = ViewModel<RoomListHeaderViewSnapshot, RoomListHeaderViewActions>;
107107

108108
interface RoomListHeaderViewProps {
109109
/**

packages/shared-components/src/room-list/RoomListItemView/RoomListItemMoreOptionsMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import type { RoomListItemSnapshot, RoomListItemActions } from "./RoomListItemVi
2525
/**
2626
* View model type for room list item
2727
*/
28-
export type RoomItemViewModel = ViewModel<RoomListItemSnapshot> & RoomListItemActions;
28+
export type RoomItemViewModel = ViewModel<RoomListItemSnapshot, RoomListItemActions>;
2929

3030
/**
3131
* Props for RoomListItemMoreOptionsMenu component

packages/shared-components/src/room-list/RoomListItemView/RoomListItemNotificationMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import type { RoomListItemSnapshot, RoomListItemActions } from "./RoomListItemVi
2121
/**
2222
* View model type for room list item
2323
*/
24-
export type RoomItemViewModel = ViewModel<RoomListItemSnapshot> & RoomListItemActions;
24+
export type RoomItemViewModel = ViewModel<RoomListItemSnapshot, RoomListItemActions>;
2525

2626
/**
2727
* Props for RoomListItemNotificationMenu component

0 commit comments

Comments
 (0)