From ac981879efc4c7103b8bd74973fded2b7de8a4bd Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 11 Jul 2025 07:38:08 +1000 Subject: [PATCH] fix(ui): runtime errors related to calling reduce on array iterator Fix an issue in certain browsers/builds causing a runtime error. A zod enum has a .options property, which is an array of all the options for the enum. This is handy for when you need to derive something from a zod schema. In this case, we represented the possible focus regions in the zod enum, then derived a mapping of region names to set of target HTML elements. Why isn't important, but suffice to say, we were using the .options property for this. But actually, we were using .options.values(), then calling .reduce() on that. An array's .values() method returns an _array iterator_. Array iterators do not have .reduce() methods! Except, apparently in some environments they do - it depends on the JS engine and whether or not polyfills for iterator helpers were included in the build. Turns out my dev environment - and most user browsers - do provide .reduce(), so we didn't catch this error. It took a large deployment and error monitoring to catch it. I've refactored the code to totally avoid deriving data from zod in this way. --- invokeai/frontend/web/src/common/hooks/focus.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/invokeai/frontend/web/src/common/hooks/focus.ts b/invokeai/frontend/web/src/common/hooks/focus.ts index 2d0510e751..4e093c5c63 100644 --- a/invokeai/frontend/web/src/common/hooks/focus.ts +++ b/invokeai/frontend/web/src/common/hooks/focus.ts @@ -6,7 +6,6 @@ import { atom, computed } from 'nanostores'; import type { RefObject } from 'react'; import { useEffect } from 'react'; import { objectKeys } from 'tsafe'; -import z from 'zod/v4'; /** * We need to manage focus regions to conditionally enable hotkeys: @@ -28,10 +27,7 @@ import z from 'zod/v4'; const log = logger('system'); -/** - * The names of the focus regions. - */ -const zFocusRegionName = z.enum([ +const REGION_NAMES = [ 'launchpad', 'viewer', 'gallery', @@ -41,13 +37,16 @@ const zFocusRegionName = z.enum([ 'workflows', 'progress', 'settings', -]); -export type FocusRegionName = z.infer; +] as const; +/** + * The names of the focus regions. + */ +export type FocusRegionName = (typeof REGION_NAMES)[number]; /** * A map of focus regions to the elements that are part of that region. */ -const REGION_TARGETS: Record> = zFocusRegionName.options.values().reduce( +const REGION_TARGETS: Record> = REGION_NAMES.reduce( (acc, region) => { acc[region] = new Set(); return acc;