Skip to content

Conversation

@ermshiperete
Copy link
Contributor

@ermshiperete ermshiperete commented Jan 19, 2026

This addresses code review comments in #15437 and removes some unnecessary definitions related to variable stores. It keeps the VariableStoreSerializer interface although currently VariableStoreCookieSerializer is the only implementation. Conceptually IMO it makes sense to use a more abstract interface so that in the future for example we could easily use a different store for a node implementation.

Details of this change:

  • remove VariableStoreDictionary interface and replace with VariableStore type
  • remove VarStoreSerializer class and replace with CookieSerializer<VariableStore>

Follow-up-of: #15437
Test-bot: skip

@keymanapp-test-bot
Copy link

keymanapp-test-bot bot commented Jan 19, 2026

User Test Results

Test specification and instructions

User tests are not required

Test Artifacts

  • Android
    • Keyman for Android apk - build : all tests passed (no artifacts on BuildLevel "build")
    • FirstVoices Keyboards for Android apk - build : all tests passed (no artifacts on BuildLevel "build")
    • FirstVoices Keyboards for Android apk (old PRs) - build : all tests passed (no artifacts on BuildLevel "build")
    • KeyboardHarness apk - build : all tests passed (no artifacts on BuildLevel "build")
    • Keyman for Android apk (old PRs) - build : all tests passed (no artifacts on BuildLevel "build")
    • KMSample1 apk - build : all tests passed (no artifacts on BuildLevel "build")
    • KMSample2 apk - build : all tests passed (no artifacts on BuildLevel "build")
  • Developer
    • Keyman Developer - build : all tests passed (no artifacts on BuildLevel "build")
    • Compiler Regression Tests - build : all tests passed (no artifacts on BuildLevel "build")
    • Keyman Developer (old PRs) - build : all tests passed (no artifacts on BuildLevel "build")
    • kmcomp.zip - build : all tests passed (no artifacts on BuildLevel "build")
    • kmcomp.zip (old PRs) - build : all tests passed (no artifacts on BuildLevel "build")
  • iOS
    • Keyman for iOS (simulator image) - build : all tests passed (no artifacts on BuildLevel "build")
    • FirstVoices Keyboards for iOS (simulator image) - build : all tests passed (no artifacts on BuildLevel "build")
    • FirstVoices Keyboards for iOS (simulator image) (old PRs) - build : all tests passed (no artifacts on BuildLevel "build")
    • Keyman for iOS (simulator image) (old PRs) - build : all tests passed (no artifacts on BuildLevel "build")
  • Keyboards
    • Test Keyboards - build : all tests passed (no artifacts on BuildLevel "build")
  • Web
    • KeymanWeb Test Home - build : all tests passed (no artifacts on BuildLevel "build")

@keymanapp-test-bot keymanapp-test-bot bot changed the title feat(web): cleanup of variable stores feat(web): cleanup of variable stores 🎼 Jan 19, 2026
@keymanapp-test-bot keymanapp-test-bot bot added this to the A19S21 milestone Jan 19, 2026
This addresses code review comments in #15437 and removes some
unnecessary definitions related to variable stores. It keeps the
`VariableStoreSerializer` interface although currently
`VariableStoreCookieSerializer` is the only implementation. Conceptually
IMO it makes sense to use a more abstract interface so that in the future
for example we could easily use a different store for a node
implementation.

Details of this change:
- remove `VariableStoreDictionary` interface and replace with
  `VariableStore` type
- remove `VarStoreSerializer` class and replace with
  ` CookieSerializer<VariableStore>`

Follow-up-of: #15437
Test-bot: skip
@ermshiperete ermshiperete force-pushed the feat/web/varStoresCleanup branch from 8fb8c95 to 01bee77 Compare January 19, 2026 17:18
@ermshiperete ermshiperete changed the base branch from epic/web-core to fix/web/baselinetests January 19, 2026 17:20
* @returns an object with each property referencing a variable store
*/
get variableStores(): VariableStoreDictionary {
get variableStores(): VariableStore {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, the function is plural but the return value is singular. Is that right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to plural.

[name: string]: string;
};

export type VariableStore = { [name: string]: string; };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be VariableStores since it is can contain more than one value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment below (#15470 (comment)).

Base automatically changed from fix/web/baselinetests to epic/web-core January 20, 2026 07:35
@ermshiperete ermshiperete requested a review from mcdurdin January 20, 2026 14:08
Comment on lines 10 to 12
loadStore(keyboardID: string, storeName: string): VariableStores;
saveStore(keyboardID: string, storeName: string, storeMap: VariableStores): void;
findStores(keyboardID: string): VariableStores[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense to me. loadStore should be returning 1 store. findStores shouldn't be finding an array of a set of variable stores!

Copy link
Contributor Author

@ermshiperete ermshiperete Jan 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not as bad as it looks (other than that it looks bad and might be confusing): currently each VariableStores object contains only one key/value pair (except in tests), so loadStore and saveStore function names make sense. findStores returns all cookies/stores for a keyboard.

Thinking about it - maybe the term store is part of a problem. In every day life I think of a store as something where you can get different things. With that in mind, a VariableStore in our code would be able to hold multiple key/value pairs. The plural VariableStores would be several stores, each holding multiple key/value pairs.

But if we think from .kmn, store(x) defines a variable store, i.e. one key/value pair. This calls for naming the type that can hold multiple key/value pairs a VariableStores type.

Since currently we store only one key/value pair in that type although it can hold multiple ones, I think it's probably best to change it back to VariableStore and use it in the sense of a .kmn variable store.

I think if we implement what's discussed in #15436 (comment) things might get a bit cleaner. It doesn't help with the terminology, but at least then it would hold only one key/value pair and the type would match that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we only ever store one key + value in the object then why don't we change it to a more conventional pattern:

export type VariableStore = { name: string; value: string; }

That also then allows us to add extra metadata in the future if we want and eliminates this confusion. IMHO the current model is fragile and liable to trip maintainers up in the future (as we can see in this discussion where we are going around in circles). I can't see that we are deriving any benefits from the current model, either in performance or in clarity.

Either that, or we refactor to store all of the variable stores in a single object... but that seems more complicated from my reading of the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(except in tests)

If tests are doing something different to the real-life use of the code, then the tests are definitely wrong -- tests must match the real-life usage or they are testing the wrong thing. IMVHO it's crazy that the only place this pattern is used is in the unit tests!

Copy link
Contributor Author

@ermshiperete ermshiperete Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not entirely sure that my analysis was correct.

jsKeyboard.ts has this code: values[store] = this.scriptObject[store]; and I'm not sure what scriptObject[store] can return.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is certainly adding more than one value into the VariableStore type. From my current reading, it's buggy -- in one place we add multiple values to one VariableStore but in other places we have multiple VariableStores. I think we need to review again -- it's a very simple data model, but the implementation seems overly complicated right now.

@ermshiperete ermshiperete force-pushed the feat/web/varStoresCleanup branch from b94661a to 01bee77 Compare January 21, 2026 11:38
@ermshiperete
Copy link
Contributor Author

Reverted the rename from VariableStoreVariableStores based on #15470 (comment).

@ermshiperete ermshiperete requested a review from mcdurdin January 21, 2026 11:40
@keyman-server keyman-server modified the milestones: A19S21, A19S22 Jan 31, 2026
@@ -54,6 +32,8 @@ export class VariableStoreCookieSerializer implements VariableStoreSerializer {
* @returns An array of VariableStore objects found for the keyboard.
*/
public findStores(keyboardID: string): VariableStore[] {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the broken function, right? VariableStore is already a map, so it should be returning a map, not an array of maps. And this is a change in epic/web-core, not in the current alpha, so I think it's a change you made based on VariableStore being badly named.

Should we go ahead with naming it VariableStores and eliminate VariableStoreDictionary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants