fix(editor): array proxy splice will cause too large yjs update (#12201)

Splice will produce large yjs updates for splice because it will call insert and delete operation for every item in yarray.
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Added support for `splice`, `shift`, and `unshift` methods on reactive arrays, enabling enhanced dynamic array operations with synchronization.
- **Tests**
  - Expanded test coverage for array operations including `push`, `splice`, `shift`, and `unshift`, verifying complete array state after each change.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Saul-Mirone
2025-05-09 06:19:57 +00:00
parent 2e3b721603
commit 97aa3fc672
2 changed files with 112 additions and 8 deletions

View File

@@ -7,23 +7,64 @@ import type { Text } from '../reactive/index.js';
import { Boxed, createYProxy, popProp, stashProp } from '../reactive/index.js';
describe('array', () => {
test('proxy', () => {
test('push and splice', () => {
const ydoc = new Y.Doc();
const arr = ydoc.getArray('arr');
arr.push([0]);
arr.push([0, 1, 2, 3, 4, 5]);
const proxy = createYProxy(arr) as unknown[];
expect(arr.get(0)).toBe(0);
expect(arr.toJSON()).toEqual([0, 1, 2, 3, 4, 5]);
expect(proxy).toEqual([0, 1, 2, 3, 4, 5]);
proxy.push(1);
expect(arr.get(1)).toBe(1);
expect(arr.length).toBe(2);
proxy.push(6);
expect(arr.toJSON()).toEqual([0, 1, 2, 3, 4, 5, 6]);
expect(proxy).toEqual([0, 1, 2, 3, 4, 5, 6]);
proxy.splice(1, 1);
expect(arr.length).toBe(1);
expect(arr.toJSON()).toEqual([0, 2, 3, 4, 5, 6]);
expect(proxy).toEqual([0, 2, 3, 4, 5, 6]);
proxy[0] = 2;
expect(arr.length).toBe(1);
expect(arr.toJSON()).toEqual([2, 2, 3, 4, 5, 6]);
expect(proxy).toEqual([2, 2, 3, 4, 5, 6]);
});
test('shift and unshift', () => {
const ydoc = new Y.Doc();
const arr = ydoc.getArray('arr');
arr.push([0, 1, 2, 3, 4, 5]);
const proxy = createYProxy(arr) as unknown[];
expect(arr.toJSON()).toEqual([0, 1, 2, 3, 4, 5]);
// Test shift
const shifted = proxy.shift();
expect(shifted).toBe(0);
expect(arr.toJSON()).toEqual([1, 2, 3, 4, 5]);
expect(proxy).toEqual([1, 2, 3, 4, 5]);
const shifted2 = proxy.shift();
expect(shifted2).toBe(1);
expect(arr.toJSON()).toEqual([2, 3, 4, 5]);
expect(proxy).toEqual([2, 3, 4, 5]);
// Test shift on empty array
const emptyArr = ydoc.getArray('empty');
const emptyProxy = createYProxy(emptyArr) as unknown[];
const emptyShifted = emptyProxy.shift();
expect(emptyShifted).toBeUndefined();
expect(emptyArr.toJSON()).toEqual([]);
expect(emptyProxy).toEqual([]);
// Test unshift
proxy.unshift(-1, 0, 1);
expect(arr.toJSON()).toEqual([-1, 0, 1, 2, 3, 4, 5]);
expect(proxy).toEqual([-1, 0, 1, 2, 3, 4, 5]);
// Test unshift with multiple items
proxy.unshift(-3, -2);
expect(arr.toJSON()).toEqual([-3, -2, -1, 0, 1, 2, 3, 4, 5]);
expect(proxy).toEqual([-3, -2, -1, 0, 1, 2, 3, 4, 5]);
});
});