Skip to content

Commit 059e817

Browse files
fix: stop on cycles
1 parent 3179609 commit 059e817

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

packages/core/injector/topology-tree/topology-tree.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ export class TopologyTree {
2929
}
3030
if (this.links.has(child)) {
3131
const existingSubtree = this.links.get(child)!;
32-
const existingDepth = existingSubtree.getDepth({ stopOn: node.value });
32+
33+
if (node.hasCycleWith(child)) {
34+
return;
35+
}
36+
const existingDepth = existingSubtree.getDepth();
3337
if (existingDepth < depth) {
3438
existingSubtree.relink(node);
3539
}

packages/core/injector/topology-tree/tree-node.ts

+40
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,47 @@ export class TreeNode<T> {
1717
}
1818

1919
relink(parent: TreeNode<T>) {
20+
this.parent?.removeChild(this);
21+
2022
this.parent = parent;
2123
this.parent.addChild(this);
2224
}
25+
26+
getDepth() {
27+
const visited = new Set<TreeNode<T>>();
28+
29+
let depth = 0;
30+
let current: TreeNode<T> | null = this;
31+
32+
while (current) {
33+
depth++;
34+
current = current.parent;
35+
36+
// Stop on cycle
37+
if (visited.has(current!)) {
38+
return -1;
39+
}
40+
visited.add(current!);
41+
}
42+
return depth;
43+
}
44+
45+
hasCycleWith(target: T) {
46+
const visited = new Set<TreeNode<T>>();
47+
48+
let current: TreeNode<T> | null = this;
49+
50+
while (current) {
51+
if (current.value === target) {
52+
return true;
53+
}
54+
current = current.parent;
55+
56+
if (visited.has(current!)) {
57+
return false;
58+
}
59+
visited.add(current!);
60+
}
61+
return false;
62+
}
2363
}

0 commit comments

Comments
 (0)