From 9ff985a792d5efe18ab12b64c5662b6055dffa4a Mon Sep 17 00:00:00 2001 From: Hunter Date: Thu, 26 Feb 2026 00:35:59 -0500 Subject: [PATCH] fix: sync DOM widget default values to widgetValueStore on registration (#9164) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description DOM widgets (textarea/customtext) override the `value` getter via `Object.defineProperty` to use `getValue()/setValue()` with a fallback to `inputEl.value`. But `BaseWidget.setNodeId()` registered `_state.value` (undefined from constructor) instead of `this.value` (the actual getter). This caused Vue nodes (Nodes 2.0) to read `undefined` from the store and display empty textareas, while execution correctly fell back to `inputEl.value`. **Fix:** Use `this.value` in `setNodeId()` so the store is initialized with the actual widget value. **Impact:** Fixes Nano Banana / Nano Banana Pro `system_prompt` showing empty in Nodes 2.0 while still sending the correct value during execution. ## Thread https://ampcode.com/threads/T-019c8e99-49ce-77f5-bf2a-a32320fac477 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9164-fix-sync-DOM-widget-default-values-to-widgetValueStore-on-registration-3116d73d36508169a2fbd8308d9eec91) by [Unito](https://www.unito.io) --- .../litegraph/src/widgets/BaseWidget.test.ts | 32 +++++++++++++++++++ src/lib/litegraph/src/widgets/BaseWidget.ts | 1 + 2 files changed, 33 insertions(+) diff --git a/src/lib/litegraph/src/widgets/BaseWidget.test.ts b/src/lib/litegraph/src/widgets/BaseWidget.test.ts index 6d1075896d..0f72dc5e26 100644 --- a/src/lib/litegraph/src/widgets/BaseWidget.test.ts +++ b/src/lib/litegraph/src/widgets/BaseWidget.test.ts @@ -162,6 +162,38 @@ describe('BaseWidget store integration', () => { }) }) + describe('DOM widget value registration', () => { + it('registers value from getter when value property is overridden', () => { + const defaultValue = 'You are an expert image-generation engine.' + const widget = createTestWidget(node, { + name: 'system_prompt', + value: undefined as unknown as number + }) + + // Simulate what addDOMWidget does: override value with getter/setter + // that falls back to a default (like inputEl.value for textarea widgets) + Object.defineProperty(widget, 'value', { + get() { + const graphId = widget.node.graph?.rootGraph.id + if (!graphId) return defaultValue + const state = store.getWidget(graphId, node.id, 'system_prompt') + return (state?.value as string) ?? defaultValue + }, + set(v: string) { + const graphId = widget.node.graph?.rootGraph.id + if (!graphId) return + const state = store.getWidget(graphId, node.id, 'system_prompt') + if (state) state.value = v + } + }) + + widget.setNodeId(node.id) + + const state = store.getWidget(graph.id, node.id, 'system_prompt') + expect(state?.value).toBe(defaultValue) + }) + }) + describe('fallback behavior', () => { it('uses internal value before registration', () => { const widget = createTestWidget(node, { diff --git a/src/lib/litegraph/src/widgets/BaseWidget.ts b/src/lib/litegraph/src/widgets/BaseWidget.ts index f633092dbe..1406e0bb79 100644 --- a/src/lib/litegraph/src/widgets/BaseWidget.ts +++ b/src/lib/litegraph/src/widgets/BaseWidget.ts @@ -140,6 +140,7 @@ export abstract class BaseWidget this._state = useWidgetValueStore().registerWidget(graphId, { ...this._state, + value: this.value, nodeId }) }