From 9c5c461ecebb29ff8f34f4a87ac5fa2b37da3de1 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Wed, 26 Jun 2024 21:52:04 -0230 Subject: [PATCH] fix: Fix BaseControllerV1 state rehydration We were failing to properly restore persisted state for some BaseControllerV1 controllers. This resulted in state being lost when the application was restarted. The only confirmed affected controller so far is the `NftController`. The context here is that for some older controllers, rather than passing the initial state into the controller directly when it is constructed, we call the `update` function directly. This has always been a bad practice (controllers should update their own state), and we're forced to fix this for controllers that we update to `BaseControllerV2` (because directly updating state like this is no longer possible. But this method of rehydrating controller state was still relied upon in some cases. This was broken recently in #9570 when a condition was added to fix a type error. The condition was meant to check that the controller had a `subscribe` function. Unfortunately this `hasProperty` check only looks at owned properties, not inherited properties, and the `subscribe` function was inherited from the base class. It has been updated to use the `in` operator instead, which does look up the entire prototype chain. Fixes #10057 --- app/core/Engine.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/core/Engine.ts b/app/core/Engine.ts index 8f666a0333e..b7fb1a10a9c 100644 --- a/app/core/Engine.ts +++ b/app/core/Engine.ts @@ -1340,7 +1340,8 @@ class Engine { for (const controller of controllers) { if ( hasProperty(initialState, controller.name) && - hasProperty(controller, 'subscribe') && + // Use `in` operator here because the `subscribe` function is one level up the prototype chain + 'subscribe' in controller && controller.subscribe !== undefined ) { // The following type error can be addressed by passing initial state into controller constructors instead