Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 37 additions & 11 deletions packages/vue-node-registry/src/registry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import LogicFlow from '@logicflow/core'
import LogicFlow, { GraphModel } from '@logicflow/core'
import { VueNodeView } from './view'
import { VueNodeModel } from './model'

Expand All @@ -10,13 +10,30 @@ export type VueNodeConfig = {
effect?: (keyof LogicFlow.PropertiesType)[]
} & Partial<RegisterConfig>

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<GraphModel, Record<string, VueNodeEntry>>()

/**
* @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<string, VueNodeEntry> = {}

/**
* Retrieve the Vue node configuration scoped to a specific LogicFlow instance.
*/
export function getVueNodeConfig(
type: string,
graphModel: GraphModel,
): VueNodeEntry | undefined {
return vueNodesMaps.get(graphModel)?.[type]
}

export function register(config: VueNodeConfig, lf: LogicFlow) {
const {
Expand All @@ -30,10 +47,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 = {}
vueNodesMaps.set(lf.graphModel, map)
}
map[type] = entry
Comment on lines +54 to +59
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both the per-instance registry (map) and the deprecated global vueNodesMap use plain objects indexed by type. If type is not strictly controlled, keys like __proto__/constructor can lead to prototype pollution. Prefer Map<string, VueNodeEntry> (and store it in the WeakMap), or initialize with Object.create(null) and reject dangerous keys.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s strange
it doesn’t seem to be running. Could you please manually add a commit?


// Also populate global map for backward compatibility
vueNodesMap[type] = entry

lf.register({
type,
Expand Down
5 changes: 3 additions & 2 deletions packages/vue-node-registry/src/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -87,7 +87,8 @@ export class VueNodeView extends HtmlNode {
})

if (root) {
const { component } = vueNodesMap[model.type]
const nodeConfig = getVueNodeConfig(model.type, graphModel)
const { component } = nodeConfig!
if (component) {
if (isVue2) {
const Vue = Vue2 as any
Expand Down