-
-
Notifications
You must be signed in to change notification settings - Fork 404
fix: add seen weakset during mergeDeep #1588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix: add seen weakset during mergeDeep #1588
Conversation
WalkthroughAdded cycle-guarding to mergeDeep by introducing an optional Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
fc68e41 to
1819ba3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/utils.ts (1)
105-110: Call-stack tracking pattern may still exhibit quadratic behavior for shared references.The pattern of adding source to
seenbefore recursion and deleting it after (line 110) creates a "call-stack tracker" rather than a "global seen set." This prevents infinite recursion but allows the same object to be merged multiple times when it appears in different branches of the object graph.Consider this scenario:
const shared = { nested: { deep: { value: 1 } } } const source = { a: shared, b: shared, c: shared }With the current implementation,
shared(and its nested objects) will be processed once for each branch (a, b, c), potentially leading to O(n²) behavior for wide graphs with many shared references.This is still a significant improvement over the exponential/infinite recursion reported in issue #1587, and the approach is valid for preventing stack overflow. However, if performance issues persist with complex object graphs, consider using a WeakMap to cache merged results per source object.
test/units/merge-deep.test.ts (1)
90-110: Consider verifying circular structure is preserved.The test validates that nested values are accessible but doesn't verify that the circular reference itself is preserved (i.e., that
result.prop.toB.toA === result.prop).Given the implementation's behavior of direct assignment when keys don't exist in the target, circular structures should be preserved in this scenario. Adding an assertion would make this explicit:
expect(result.prop.x).toBe(1) expect(result.prop.toB?.y).toBe(2) +expect(result.prop.toB?.toA).toBe(result.prop)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/utils.ts(2 hunks)test/units/merge-deep.test.ts(1 hunks)
🔇 Additional comments (2)
src/utils.ts (1)
61-67: Cycle detection approach effectively prevents infinite recursion.The use of
WeakSet<object>to track seen sources is appropriate and prevents infinite recursion when encountering circular references. WeakSet allows automatic garbage collection and provides O(1) lookup/insertion.The early return on line 71 when
seen.has(source)is true correctly short-circuits recursive processing for objects already on the call stack.Also applies to: 71-72
test/units/merge-deep.test.ts (1)
123-162: Excellent real-world test coverage for the circular decorator scenario.This test comprehensively validates the fix for issue #1587 by reproducing the plugin-with-circular-decorators scenario across multiple modules and routes. The assertions confirm that values remain consistent and accessible across all endpoints, demonstrating that the cycle detection prevents the exponential call count reported in the issue.
Attempt to resolve: #1587
This doesn't handle the plugin deduplication for plugins of plugins which the above issue also points out, but this tries to fix the recursion in
mergeDeepby maintaining a seen set.Summary by CodeRabbit
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.