diff --git a/packages/core/shortcuts/definitions.test.ts b/packages/core/shortcuts/definitions.test.ts index 7fb7e5d9d..d01f2c5de 100644 --- a/packages/core/shortcuts/definitions.test.ts +++ b/packages/core/shortcuts/definitions.test.ts @@ -98,6 +98,14 @@ describe("keyboard shortcut definitions", () => { expect(shortcutMatchesEvent(null, keyEvent(key, modifiers), "macos")).toBe(false); }); + it("ignores synthetic events without a key, such as Chrome autofill", () => { + const event = keyEvent(undefined as unknown as string, { metaKey: true }); + expect(shortcutFromEvent(event, "macos")).toBeNull(); + expect( + shortcutMatchesEvent(createShortcutChord("K", { primary: true }), event, "macos"), + ).toBe(false); + }); + it("formats the same semantic binding for each platform", () => { const shortcut = createShortcutChord("Enter", { primary: true }); expect(formatShortcut(shortcut, "macos")).toBe("⌘↵"); diff --git a/packages/core/shortcuts/definitions.ts b/packages/core/shortcuts/definitions.ts index 10bdb69ed..2598808f2 100644 --- a/packages/core/shortcuts/definitions.ts +++ b/packages/core/shortcuts/definitions.ts @@ -114,6 +114,8 @@ const KEY_LABELS: Record = { }; function eventKey(event: KeyboardEvent): string | null { + // Synthetic events (e.g. Chrome autofill) may omit `key` entirely. + if (typeof event.key !== "string") return null; if (MODIFIER_KEYS.has(event.key) || NON_ACTIONABLE_KEYS.has(event.key)) return null; const key = KEY_LABELS[event.key] ?? event.key; if (key.length === 1 && /[a-z]/i.test(key)) return key.toUpperCase();