From 803062bccd412a9202022a541aa08de1e2cfc949 Mon Sep 17 00:00:00 2001 From: AustinMroz Date: Tue, 27 Jan 2026 18:45:48 -0800 Subject: [PATCH] Prevent partial copy of custom widgets when performing linked promotion on subgraphs (#6079) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `toConcrete` call creates a restricted view of a widget that extends from `BaseWidget`. A copy of the widget created by `createCopyForNode` will also inherit this restricted view. This creates two problems - Some widget properties (like `displayValue`) have been judged unsafe and are explicitly blacklisted from being copied - The widget now extends from `BaseWidget`. This results in the widget being processed differently in some logic, such as `#processWidgetClick` - Because `LegacyWidget` provides an implementation for `onClick`, the presence of click handlers can not be used to determine which should be used. As a proposed, minimal workaround. Widgets which do not already extend from BaseWidget are no longer cloned through `createCopyForNode`. Because this PR involves side-stepping properties which have been explicitly blacklisted. I'd recommend waiting to merge/backport until after the release of 1.28.7 Resolves Kosinkadink/ComfyUI-VideoHelperSuite#569 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6079-Prevent-partial-copy-of-custom-widgets-when-performing-linked-promotion-on-subgraphs-28d6d73d36508198950efd401186ddef) by [Unito](https://www.unito.io) --------- Co-authored-by: Alexander Brown Co-authored-by: GitHub Action --- src/lib/litegraph/src/subgraph/SubgraphNode.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lib/litegraph/src/subgraph/SubgraphNode.ts b/src/lib/litegraph/src/subgraph/SubgraphNode.ts index e26e1cd48..a1fc265d8 100644 --- a/src/lib/litegraph/src/subgraph/SubgraphNode.ts +++ b/src/lib/litegraph/src/subgraph/SubgraphNode.ts @@ -28,8 +28,8 @@ import type { } from '@/lib/litegraph/src/types/serialisation' import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets' import type { UUID } from '@/lib/litegraph/src/utils/uuid' +import { BaseWidget } from '@/lib/litegraph/src/widgets/BaseWidget' import { AssetWidget } from '@/lib/litegraph/src/widgets/AssetWidget' -import { toConcreteWidget } from '@/lib/litegraph/src/widgets/widgetMap' import { ExecutableNodeDTO } from './ExecutableNodeDTO' import type { ExecutableLGraphNode, ExecutionId } from './ExecutableNodeDTO' @@ -331,9 +331,10 @@ export class SubgraphNode extends LGraphNode implements BaseLGraph { inputWidget: IWidgetLocator | undefined ) { // Use the first matching widget - const promotedWidget = toConcreteWidget(widget, this).createCopyForNode( - this - ) + const promotedWidget = + widget instanceof BaseWidget + ? widget.createCopyForNode(this) + : { ...widget, node: this } if (widget instanceof AssetWidget) promotedWidget.options.nodeType ??= widget.node.type