Prevent calling messenger actions in controller/service constructors#8353
Prevent calling messenger actions in controller/service constructors#8353
Conversation
Some controllers or services call actions from other controllers or services in the constructor (e.g. to populate local or persisted state). But this practice is not recommended, as it forces clients to use a specific order when instantiating controllers and services. This commit updates the controller guidelines to advise against this practice and adds a lint rule to prevent it from appearing again.
| "count": 6 | ||
| } | ||
| }, | ||
| "packages/assets-controller/src/AssetsController.ts": { |
There was a problem hiding this comment.
I believe that the no-restricted-syntax rule in @metamask/eslint-config-typescript overrides the rule in @metamask/eslint-config. We are effectively adding back the rule from @metamask/eslint-config in this commit. So a lot of these changes don't have anything to do with the new lint rule but are merely a side effect of using this collectExistingRuleOptions function I added in a previous PR.
Most of the violations of no-restricted-syntax are The "in" operator is not allowed. Here are all of the violations of the new lint rule:
core/packages/assets-controller/src/AssetsController.ts
743:44 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/assets-controller/src/data-sources/RpcDataSource.ts
262:23 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
274:16 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/assets-controllers/src/AccountTrackerController.ts
344:28 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/assets-controllers/src/MultichainAssetsRatesController/MultichainAssetsRatesController.ts
244:51 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/assets-controllers/src/NftController.ts
415:31 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/assets-controllers/src/TokenBalancesController.ts
405:7 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
410:28 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/assets-controllers/src/TokenDetectionController.ts
282:35 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
288:61 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
297:28 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/core-backend/src/AccountActivityService.ts
246:5 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/gas-fee-controller/src/GasFeeController.ts
417:43 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
420:29 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/perps-controller/src/PerpsController.ts
909:45 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.ts
307:13 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
312:26 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/selected-network-controller/src/SelectedNetworkController.ts
156:5 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
162:11 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
178:17 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
core/packages/transaction-controller/src/TransactionController.ts
982:14 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
991:16 error Do not call messenger actions in the constructor, as this forces clients to instantiate controllers or services in a specific order. Move this call to an init() method instead. Read the controller guidelines for more: .. no-restricted-syntax
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| const NO_MESSENGER_ACTIONS_IN_CONSTRUCTORS_RULES = [ | ||
| { | ||
| selector: | ||
| 'MethodDefinition[kind="constructor"] CallExpression[callee.type="MemberExpression"][callee.property.name="call"][callee.object.type="MemberExpression"][callee.object.object.type="ThisExpression"][callee.object.property.name="messenger"]', |
There was a problem hiding this comment.
Constructor rule misses direct messenger calls
Medium Severity
The no-restricted-syntax selector only matches this.messenger.call(...) in constructors. A constructor can still call messenger.call(...) via its parameter or a local alias, so the new rule does not fully enforce the “no messenger actions in constructors” policy.


Explanation
Some controllers or services call actions from other controllers or services in the constructor (e.g. to populate local or persisted state). But this practice is not recommended, as it forces clients to use a specific order when instantiating controllers and services.
This commit updates the controller guidelines to advise against this practice and adds a lint rule to prevent it from appearing again.
References
No ticket, but I discovered while going through PerpsController that
RemoteFeatureFlagController:getStateis being called in the constructor.Checklist
Note
Medium Risk
Medium risk because it changes repo-wide ESLint behavior and introduces a new
no-restricted-syntaxselector that may surface new lint failures or require additional suppressions across many packages.Overview
Updates controller guidelines to explicitly ban calling messenger actions in constructors and recommends deferring such work to an
init()method.Enforces the guideline via a new repo-wide
no-restricted-syntaxrule ineslint.config.mjs(including inpackages/*/src/index.tsalongside the existing export restrictions), and expandseslint-suppressions.jsonwith the initial set of suppressions for affected packages/files.Written by Cursor Bugbot for commit 640126c. This will update automatically on new commits. Configure here.