Skip to content

Commit aad35a3

Browse files
trotzigclaude
andauthored
fix: infinite loop when object has an empty string key (#58)
The key-advance logic in `diffObject` used falsy checks (!keyLeft, !keyRight) to detect when one side had run out of keys. Because an empty string is falsy in JavaScript, any JSON object containing "" as a key would cause the left pointer to never advance, producing an infinite while-loop that exhausted all available memory. Fix: replace the falsy checks with strict undefined comparisons (=== undefined) so that empty-string keys are handled correctly. A regression test is added to differ.spec.ts covering objects with an empty-string key on both sides. Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent ab5529e commit aad35a3

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

src/differ.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
import Differ from './differ';
22

33
describe('object diff', () => {
4+
it('should not infinite loop when an object has an empty string key', () => {
5+
const l = { '': 'before', a: 1 };
6+
const r = { '': 'after', b: 2 };
7+
const d = new Differ();
8+
// Should complete without hanging or throwing
9+
expect(() => d.diff(l, r)).not.toThrow();
10+
const result = d.diff(l, r);
11+
// Both sides must have the same number of lines
12+
expect(result[0].length).toBe(result[1].length);
13+
// The empty-string key's value change should appear as a modification
14+
const leftTypes = result[0].map(line => line.type);
15+
const rightTypes = result[1].map(line => line.type);
16+
expect(leftTypes).toContain('modify');
17+
expect(rightTypes).toContain('modify');
18+
});
19+
420
it('preserve key order', () => {
521
const l = { a: 1, b: 2, c: 3 };
622
const r = { c: 3, b: 2, d: 4, a: 1 };

src/utils/diff-object.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ const diffObject = (
181181
}
182182
}
183183

184-
if (!keyLeft) {
184+
if (keyLeft === undefined) {
185185
keysRight.shift();
186-
} else if (!keyRight) {
186+
} else if (keyRight === undefined) {
187187
keysLeft.shift();
188188
} else if (keyCmpResult === 0) {
189189
keysLeft.shift();

0 commit comments

Comments
 (0)