From d391adf1a73baf73d658dacfcaa415bf7ffccd3f Mon Sep 17 00:00:00 2001 From: EralChen Date: Tue, 3 Mar 2026 17:37:42 +0800 Subject: [PATCH 1/2] feat(vue-node-registry): scope vueNodesMap per LogicFlow instance to support nested scenarios --- packages/vue-node-registry/src/registry.ts | 50 +++++++++++++++++----- packages/vue-node-registry/src/view.ts | 6 ++- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/packages/vue-node-registry/src/registry.ts b/packages/vue-node-registry/src/registry.ts index d261c06e0..d1bcb6145 100644 --- a/packages/vue-node-registry/src/registry.ts +++ b/packages/vue-node-registry/src/registry.ts @@ -1,4 +1,4 @@ -import LogicFlow from '@logicflow/core' +import LogicFlow, { GraphModel } from '@logicflow/core' import { VueNodeView } from './view' import { VueNodeModel } from './model' @@ -10,13 +10,32 @@ export type VueNodeConfig = { effect?: (keyof LogicFlow.PropertiesType)[] } & Partial -export const vueNodesMap: Record< - string, - { - component: any - effect?: (keyof LogicFlow.PropertiesType)[] - } -> = {} +type VueNodeEntry = { + component: any + effect?: (keyof LogicFlow.PropertiesType)[] +} + +// Per-instance map: automatically garbage-collected when the GraphModel is destroyed +const vueNodesMaps = new WeakMap>() + +/** + * @deprecated Use {@link getVueNodeConfig} instead for multi-instance support. + * This global map is still populated for backward compatibility but does NOT + * isolate registrations across different LogicFlow instances. + */ +export const vueNodesMap: Record = Object.create( + null, +) as Record + +/** + * Retrieve the Vue node configuration scoped to a specific LogicFlow instance. + */ +export function getVueNodeConfig( + type: string, + graphModel: GraphModel, +): VueNodeEntry | undefined { + return vueNodesMaps.get(graphModel)?.get(type) +} export function register(config: VueNodeConfig, lf: LogicFlow) { const { @@ -30,10 +49,19 @@ export function register(config: VueNodeConfig, lf: LogicFlow) { if (!type) { throw new Error('You should specify type in config') } - vueNodesMap[type] = { - component, - effect, + + const entry: VueNodeEntry = { component, effect } + + // Scope to this LogicFlow instance + let map = vueNodesMaps.get(lf.graphModel) + if (!map) { + map = new Map() + vueNodesMaps.set(lf.graphModel, map) } + map.set(type, entry) + + // Also populate global map for backward compatibility + vueNodesMap[type] = entry lf.register({ type, diff --git a/packages/vue-node-registry/src/view.ts b/packages/vue-node-registry/src/view.ts index 305da35b4..82540538f 100644 --- a/packages/vue-node-registry/src/view.ts +++ b/packages/vue-node-registry/src/view.ts @@ -10,7 +10,7 @@ import { isNumber, } from 'lodash-es' import { HtmlNode } from '@logicflow/core' -import { vueNodesMap } from './registry' +import { getVueNodeConfig } from './registry' import { isActive, connect, disconnect } from './teleport' import { Container } from './components/container' @@ -87,7 +87,9 @@ export class VueNodeView extends HtmlNode { }) if (root) { - const { component } = vueNodesMap[model.type] + const nodeConfig = getVueNodeConfig(model.type, graphModel) + if (!nodeConfig) return + const { component } = nodeConfig if (component) { if (isVue2) { const Vue = Vue2 as any From 8ecf9ca823d6b88e653e3e1c5a7554aae3368357 Mon Sep 17 00:00:00 2001 From: EralChen <82485978+EralChen@users.noreply.github.com> Date: Tue, 3 Mar 2026 17:52:28 +0800 Subject: [PATCH 2/2] Update packages/vue-node-registry/src/registry.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/vue-node-registry/src/registry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vue-node-registry/src/registry.ts b/packages/vue-node-registry/src/registry.ts index d1bcb6145..1e66214aa 100644 --- a/packages/vue-node-registry/src/registry.ts +++ b/packages/vue-node-registry/src/registry.ts @@ -15,7 +15,7 @@ type VueNodeEntry = { effect?: (keyof LogicFlow.PropertiesType)[] } -// Per-instance map: automatically garbage-collected when the GraphModel is destroyed +// Per-instance map: entries are eligible for garbage collection once the associated GraphModel instance is no longer referenced const vueNodesMaps = new WeakMap>() /**