Skip to content

[feat]: Scope vueNodesMap per LogicFlow instance to support nested scenarios#2378

Open
EralChen wants to merge 1 commit intodidi:masterfrom
EralChen:feat/vue_nodes_scoped
Open

[feat]: Scope vueNodesMap per LogicFlow instance to support nested scenarios#2378
EralChen wants to merge 1 commit intodidi:masterfrom
EralChen:feat/vue_nodes_scoped

Conversation

@EralChen
Copy link
Contributor

Store Vue node registrations in a WeakMap<GraphModel, ...> and add getVueNodeConfig(type, graphModel) so node configs are resolved per LogicFlow instance instead of from a shared global map.

Updated VueNodeView to read configs through the new scoped getter, which prevents cross-instance registration collisions in multi-instance usage. Kept populating the legacy vueNodesMap (marked deprecated) for backward compatibility.fix(vue-node-registry): isolate node config per LF instance

Store Vue node registrations in a WeakMap<GraphModel, ...> and add getVueNodeConfig(type, graphModel) so node configs are resolved per LogicFlow instance instead of from a shared global map.

Updated VueNodeView to read configs through the new scoped getter, which prevents cross-instance registration collisions in multi-instance usage. Kept populating the legacy vueNodesMap (marked deprecated) for backward compatibility.

Store Vue node registrations in a `WeakMap<GraphModel, ...>` and add
`getVueNodeConfig(type, graphModel)` so node configs are resolved per
LogicFlow instance instead of from a shared global map.

Updated `VueNodeView` to read configs through the new scoped getter, which
prevents cross-instance registration collisions in multi-instance usage.
Kept populating the legacy `vueNodesMap` (marked deprecated) for backward
compatibility.fix(vue-node-registry): isolate node config per LF instance

Store Vue node registrations in a `WeakMap<GraphModel, ...>` and add
`getVueNodeConfig(type, graphModel)` so node configs are resolved per
LogicFlow instance instead of from a shared global map.

Updated `VueNodeView` to read configs through the new scoped getter, which
prevents cross-instance registration collisions in multi-instance usage.
Kept populating the legacy `vueNodesMap` (marked deprecated) for backward
compatibility.
@changeset-bot
Copy link

changeset-bot bot commented Feb 28, 2026

⚠️ No Changeset found

Latest commit: 0b49833

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@EralChen
Copy link
Contributor Author

About #2377

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR scopes Vue node registrations to a specific LogicFlow instance to avoid cross-instance collisions (notably in nested / multi-instance scenarios), by introducing a WeakMap<GraphModel, ...> registry and updating VueNodeView to resolve configs through a scoped getter.

Changes:

  • Added per-GraphModel Vue node registry stored in a module-level WeakMap plus getVueNodeConfig(type, graphModel).
  • Deprecated (but still populated) the legacy global vueNodesMap for backward compatibility.
  • Updated VueNodeView to load the node component via getVueNodeConfig(...) instead of the global map.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
packages/vue-node-registry/src/view.ts Switches runtime config lookup to the new per-instance getter.
packages/vue-node-registry/src/registry.ts Introduces WeakMap-scoped registry, adds getter, keeps legacy global map populated.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (root) {
const { component } = vueNodesMap[model.type]
const nodeConfig = getVueNodeConfig(model.type, graphModel)
const { component } = nodeConfig!
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.

getVueNodeConfig() can return undefined, but the code uses nodeConfig! and immediately destructures component, which will throw at runtime if the type wasn’t registered for this graphModel (or if callers previously populated the deprecated vueNodesMap directly). Handle the undefined case (early return / warning) and consider falling back to the legacy global map to preserve backward compatibility.

Suggested change
const { component } = nodeConfig!
if (!nodeConfig) {
// 未找到对应的 Vue 节点配置,避免运行时异常
if (process.env && process.env.NODE_ENV !== 'production') {
console.warn(
'[VueNodeView] No vue node config registered for type:',
model.type,
)
}
return
}
const { component } = nodeConfig

Copilot uses AI. Check for mistakes.
type: string,
graphModel: GraphModel,
): VueNodeEntry | undefined {
return vueNodesMaps.get(graphModel)?.[type]
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.

getVueNodeConfig() only checks the per-instance WeakMap. Given vueNodesMap is still exported for backward compatibility, consider falling back to vueNodesMap[type] when no scoped entry exists. This avoids breaking consumers that previously relied on the legacy map and also prevents downstream callers from needing non-null assertions.

Suggested change
return vueNodesMaps.get(graphModel)?.[type]
const scopedMap = vueNodesMaps.get(graphModel)
if (scopedMap && scopedMap[type]) {
return scopedMap[type]
}
// Fallback to the legacy global map for backward compatibility
return vueNodesMap[type]

Copilot uses AI. Check for mistakes.
Comment on lines +54 to +59
let map = vueNodesMaps.get(lf.graphModel)
if (!map) {
map = {}
vueNodesMaps.set(lf.graphModel, map)
}
map[type] = entry
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants