From 2a87768a89b71a41539d71cf005fcfd0d6469279 Mon Sep 17 00:00:00 2001 From: "posthog-eu[bot]" <226701856+posthog-eu[bot]@users.noreply.github.com> Date: Sat, 25 Jul 2026 15:19:19 +0000 Subject: [PATCH] fix(search): guard against key-less keydown events in search bar The swizzled SearchBar uses `useDocSearchKeyboardEvents` from typesense-docsearch-react, which registers a global keydown listener that calls `event.key.toLowerCase()` with no guard. Synthetic keydown events dispatched by password managers, autofill, or browser extensions (seen on Safari) can arrive without a `key`, so `event.key` is undefined and the handler throws `undefined is not an object (evaluating 'e.key.toLowerCase')`. Install a capture-phase keydown listener that runs before the upstream handler and swallows malformed, key-less events via `stopImmediatePropagation()`. A real user keystroke always carries a `key`, so nothing legitimate is affected. Generated-By: PostHog Code Task-Id: e789835e-7941-4ae9-b98e-056e87ff47b1 --- src/theme/SearchBar/index.tsx | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/theme/SearchBar/index.tsx b/src/theme/SearchBar/index.tsx index 7afd708239..a90e8cb037 100644 --- a/src/theme/SearchBar/index.tsx +++ b/src/theme/SearchBar/index.tsx @@ -10,7 +10,7 @@ * themeConfig.typesense.productRoutes. */ -import React, {useState, useRef, useCallback, useMemo} from 'react'; +import React, {useState, useRef, useCallback, useEffect, useMemo} from 'react'; // @ts-ignore import {createPortal} from 'react-dom'; // @ts-ignore @@ -312,6 +312,28 @@ function DocSearch({ [onClose], ); + // `useDocSearchKeyboardEvents` (from typesense-docsearch-react) registers a + // global keydown listener that calls `event.key.toLowerCase()` with no guard. + // Synthetic keydown events dispatched by password managers, autofill, or + // browser extensions (notably on Safari) can arrive without a `key`, making + // `event.key` undefined and throwing `undefined is not an object`. We install + // our own capture-phase listener first so it runs before the upstream handler + // and swallows these malformed, key-less events. A real user keystroke always + // carries a `key`, so nothing legitimate is affected. + useEffect(() => { + function guardKeylessKeydown(event: KeyboardEvent) { + if (!event.key) { + event.stopImmediatePropagation(); + } + } + window.addEventListener('keydown', guardKeylessKeydown, {capture: true}); + return () => { + window.removeEventListener('keydown', guardKeylessKeydown, { + capture: true, + }); + }; + }, []); + useDocSearchKeyboardEvents({ isOpen, onOpen,