Skip to content
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

Event.path mismatch within observeDeep() when dealing with nested structure change of an array #481

Open
stellit opened this issue Oct 31, 2022 — with Huly GitHub · 1 comment
Assignees
Labels

Comments

Copy link

stellit commented Oct 31, 2022

Describe the bug

To Reproduce Steps to reproduce the behavior:

import { test, expect, jest } from '@jest/globals';
import * as encoding from 'lib0/encoding';
import * as Y from 'yjs';

test('nested-observer', () => {
    const doc = init(false);
    const updateSeq = doc.getArray('sync-mark');

    updateSeq.observeDeep((events, txn) => {
        events.forEach(event => {
            if (event.path.length > 0) {
                // !!!ERROR!!!
                const firstPathPart = event.path[0] as number;
                const currentTarget = event.currentTarget as Y.Array<any>;
                console.info(`curr Target length: ${currentTarget.length}`);
                console.info(`Target index from path: ${firstPathPart}, PATH IS GREATOR THAN LAST INDEX`);
                console.error(`THIS LINE WILL THROW AN ERROR: ${currentTarget.get(firstPathPart)}`);
             }
        });
    });
    const server = new SyncPeer(new Uint8Array(), doc);
    server.append([
        ['a', '1.1'],
        ['b', '2.2'],
        ['c', '3.1'],
        ['d', '4.1'],
        ['e', '5.1']
    ]);
    const peer$1 = new SyncPeer(Y.encodeStateAsUpdateV2(doc));
    const move41$1 = peer$1.move(4, 1);

    server.applyUpdate(move41$1);
});

// utility class to simulate peer behaviour
class SyncPeer {
    private doc: Y.Doc;

    public constructor(bin: Uint8Array, doc?: Y.Doc) {
        if (doc !== undefined) {
            this.doc = doc;
        } else {
            this.doc = init(true, bin);
        }
    }

    public move(from: number, to: number): Uint8Array {
        const encoder = encoding.createEncoder();
        const sub = (update: Uint8Array) => {
            encoding.writeUint8Array(encoder, update);
        };
        this.doc.once('updateV2', sub);
        this.doc.transact(txn => {
            const innerArray = txn.doc.getArray('sync-mark').get(from) as Y.Array<string>;
            innerArray.delete(1);
            innerArray.insert(1, [`${Math.random()}`]);
            txn.doc.getArray('sync-mark').move(from, to);
        }, encoder);
        return encoding.toUint8Array(encoder);
    }

    public append(nodes: [string, string][]) {
        const encoder = encoding.createEncoder();
        const sub = (update: Uint8Array) => {
            encoding.writeUint8Array(encoder, update);
        };
        this.doc.once('updateV2', sub);
        this.doc.transact(txn => {
            nodes.forEach(node => {
                const innerArray = new Y.Array<string>();
                innerArray.push([node[0], node[1]]);
                txn.doc.getArray('sync-mark').push([innerArray]);
            });
        });
        return encoding.toUint8Array(encoder);
    }

    public applyUpdate(bin: Uint8Array) {
        if (bin.length > 0) {
            Y.applyUpdateV2(this.doc, bin);
        }
    }
}

const init = (gc: boolean, bin?: Uint8Array): Y.Doc => {
    const tree = new Y.Doc({
        gc,
        gcFilter: () => {
            return gc;
        }
    });
    if (bin && bin.length > 0) {
        Y.applyUpdateV2(tree, bin);
    }
    return tree;
};

This issue is related to array move operation, since move operation introduces ContentMove amoung other types.

Expected behavior The path of event should not exceeded the length of currentTarget

Screenshots

Environment Information

  • "yjs": "14.0.0-0"

Huly®: YJS-368

@dmonad
Copy link
Member

dmonad commented Jun 28, 2023

Hi @stellit,
I fixed #481 & #485 and made another release ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants