From ae5aacb8f0b276fbd92f828c1906dc2b582ccd8c Mon Sep 17 00:00:00 2001 From: Glary-Bot Date: Sat, 2 May 2026 02:10:37 +0000 Subject: [PATCH] fix: address review feedback for refreshComboInNode - Distinguish 'no result' (undefined) from 'empty options' ([]) so a legitimate empty combo list propagates to the widget instead of being treated as a no-op. - Fall back to input.name when the connected target's input has no widget locator, mirroring _onFirstConnection. - Add regression tests for V2 combo specs, empty option propagation, and the widgetless-input fallback path. --- src/extensions/core/widgetInputs.test.ts | 55 ++++++++++++++++++++++++ src/extensions/core/widgetInputs.ts | 16 +++---- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/extensions/core/widgetInputs.test.ts b/src/extensions/core/widgetInputs.test.ts index 13eb723fca..d8c0727184 100644 --- a/src/extensions/core/widgetInputs.test.ts +++ b/src/extensions/core/widgetInputs.test.ts @@ -122,6 +122,18 @@ function defsWithCombo( } } +function defsWithV2Combo( + values: (string | number)[] +): Record { + return { + [TARGET_NODE_TYPE]: fromPartial({ + input: { + required: { [TARGET_INPUT_NAME]: ['COMBO', { options: values }] } + } + }) + } +} + describe('PrimitiveNode.refreshComboInNode', () => { it('updates combo options from the freshly passed defs', () => { const widget = createComboWidget('euler', ORIGINAL_OPTIONS) @@ -196,6 +208,49 @@ describe('PrimitiveNode.refreshComboInNode', () => { expect(widget.callback).not.toHaveBeenCalled() }) + it('updates combo options from V2 combo specs in defs', () => { + const widget = createComboWidget('euler', ORIGINAL_OPTIONS) + const stub = createPrimitiveStub({ + widget, + slotWidget: createSlotWidget([ORIGINAL_OPTIONS, {}]) + }) + + refreshOnStub(stub, defsWithV2Combo(FRESH_OPTIONS)) + + expect(widget.options.values).toEqual(FRESH_OPTIONS) + }) + + it('propagates an empty option list when defs return one', () => { + const widget = createComboWidget('euler', ORIGINAL_OPTIONS) + const stub = createPrimitiveStub({ + widget, + slotWidget: createSlotWidget([ORIGINAL_OPTIONS, {}]) + }) + + refreshOnStub(stub, defsWithCombo([])) + + expect(widget.options.values).toEqual([]) + expect(widget.value).toBeUndefined() + }) + + it('falls back to input.name when the target input has no widget locator', () => { + const widget = createComboWidget('euler', []) + const targetNode = fromPartial({ + id: 9, + type: TARGET_NODE_TYPE, + inputs: [ + fromPartial({ + name: TARGET_INPUT_NAME + }) + ] + }) + const stub = createPrimitiveStub({ widget, targetNode }) + + refreshOnStub(stub, defsWithCombo(FRESH_OPTIONS)) + + expect(widget.options.values).toEqual(FRESH_OPTIONS) + }) + it('skips non-combo widgets', () => { const widget = fromPartial({ type: 'string', diff --git a/src/extensions/core/widgetInputs.ts b/src/extensions/core/widgetInputs.ts index 62d8c609eb..2965e4aef0 100644 --- a/src/extensions/core/widgetInputs.ts +++ b/src/extensions/core/widgetInputs.ts @@ -64,7 +64,7 @@ export class PrimitiveNode extends LGraphNode { if (widget?.type !== 'combo') return const newValues = this._resolveComboValues(defs) - if (!newValues?.length) return + if (newValues === undefined) return widget.options.values = newValues @@ -78,17 +78,15 @@ export class PrimitiveNode extends LGraphNode { defs?: Record ): (string | number)[] | undefined { const fromDefs = defs ? this._comboValuesFromDefs(defs) : undefined - if (fromDefs?.length) return fromDefs + if (fromDefs !== undefined) return fromDefs const slotWidget = this.outputs?.[0]?.widget const config = ( slotWidget?.[GET_CONFIG] as (() => InputSpec) | undefined )?.() - if (!config) return undefined + if (!config || !isComboInputSpec(config)) return undefined - return isComboInputSpec(config) - ? getComboSpecComboOptions(config) - : undefined + return getComboSpecComboOptions(config) } private _comboValuesFromDefs( @@ -102,12 +100,12 @@ export class PrimitiveNode extends LGraphNode { if (!targetType) return undefined const targetInput = targetNode?.inputs?.[link.target_slot] - const widgetName = targetInput?.widget?.name - if (!widgetName) return undefined + const inputName = targetInput?.widget?.name ?? targetInput?.name + if (!inputName) return undefined const def = defs[targetType] const inputSpec = - def?.input?.required?.[widgetName] ?? def?.input?.optional?.[widgetName] + def?.input?.required?.[inputName] ?? def?.input?.optional?.[inputName] if (!inputSpec || !isComboInputSpec(inputSpec)) return undefined return getComboSpecComboOptions(inputSpec)