Skip to content

Commit 8ac4951

Browse files
authored
fix the diffing (tldraw#7108)
doing fine grained diffs on the tip tap documents was no bueno ### Change type - [x] `other` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Treat `props` and `meta` as nested patches, while defaulting non-string/non-array object fields to full `put` when changed; update diffing internals accordingly. > > - **Diffing behavior**: > - Treat `props` and `meta` as nested keys for patching via `diffObject`. > - For other object fields, emit `put` when changed unless values are arrays or strings (which still diff/append). > - Maintain fine-grained handling for arrays (`diffArray`) and strings (append optimization). > - **API/Internal changes**: > - `diffRecord` now calls `diffObject(prev, next, new Set(['props','meta']), legacyAppendMode)`. > - `diffObject` signature includes `nestedKeys` and uses shallow equality to choose between nested `diffValue` vs `put`. > - Recursive calls to `diffObject` pass `undefined` for `nestedKeys` to limit deep nesting. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 8329710. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 7bf7adf commit 8ac4951

1 file changed

Lines changed: 23 additions & 7 deletions

File tree

packages/sync-core/src/lib/diff.ts

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,15 @@ export function diffRecord(
187187
next: object,
188188
legacyAppendMode = false
189189
): ObjectDiff | null {
190-
return diffObject(prev, next, legacyAppendMode)
190+
return diffObject(prev, next, new Set(['props', 'meta']), legacyAppendMode)
191191
}
192192

193-
function diffObject(prev: object, next: object, legacyAppendMode: boolean): ObjectDiff | null {
193+
function diffObject(
194+
prev: object,
195+
next: object,
196+
nestedKeys: Set<string> | undefined,
197+
legacyAppendMode: boolean
198+
): ObjectDiff | null {
194199
if (prev === next) {
195200
return null
196201
}
@@ -202,11 +207,22 @@ function diffObject(prev: object, next: object, legacyAppendMode: boolean): Obje
202207
result[key] = [ValueOpType.Delete]
203208
continue
204209
}
205-
// if key is in both places, then compare values
206-
const diff = diffValue((prev as any)[key], (next as any)[key], legacyAppendMode)
207-
if (diff) {
210+
const prevValue = (prev as any)[key]
211+
const nextValue = (next as any)[key]
212+
if (
213+
nestedKeys?.has(key) ||
214+
(Array.isArray(prevValue) && Array.isArray(nextValue)) ||
215+
(typeof prevValue === 'string' && typeof nextValue === 'string')
216+
) {
217+
// if key is in both places, then compare values
218+
const diff = diffValue(prevValue, nextValue, legacyAppendMode)
219+
if (diff) {
220+
if (!result) result = {}
221+
result[key] = diff
222+
}
223+
} else if (!isEqual(prevValue, nextValue)) {
208224
if (!result) result = {}
209-
result[key] = diff
225+
result[key] = [ValueOpType.Put, nextValue]
210226
}
211227
}
212228
for (const key of Object.keys(next)) {
@@ -232,7 +248,7 @@ function diffValue(valueA: unknown, valueB: unknown, legacyAppendMode: boolean):
232248
} else if (!valueA || !valueB || typeof valueA !== 'object' || typeof valueB !== 'object') {
233249
return isEqual(valueA, valueB) ? null : [ValueOpType.Put, valueB]
234250
} else {
235-
const diff = diffObject(valueA, valueB, legacyAppendMode)
251+
const diff = diffObject(valueA, valueB, undefined, legacyAppendMode)
236252
return diff ? [ValueOpType.Patch, diff] : null
237253
}
238254
}

0 commit comments

Comments
 (0)