diff --git a/src/json-crdt/model/Model.ts b/src/json-crdt/model/Model.ts index d07406c178..f7a58af018 100644 --- a/src/json-crdt/model/Model.ts +++ b/src/json-crdt/model/Model.ts @@ -308,7 +308,8 @@ export class Model> implements Printable { /** * Applies a single patch to the document. All mutations to the model must go - * through this method. + * through this method. (With the only exception of local changes through API, + * which have an alternative path.) */ public applyPatch(patch: Patch) { this.onbeforepatch?.(patch); @@ -492,7 +493,11 @@ export class Model> implements Printable { decoder.decode(blob, this); this.clock = to.clock.clone(); this.ext = to.ext.clone(); - this._api?.flush(); + const api = this._api; + if (api) { + api.flush(); + api.builder.clock = this.clock; + } index.forEach(({v: node}) => { const api = node.api as NodeApi | undefined; if (!api) return; diff --git a/src/json-crdt/model/__tests__/Model.cloning.spec.ts b/src/json-crdt/model/__tests__/Model.cloning.spec.ts index 6c84fa698d..40b2b28403 100644 --- a/src/json-crdt/model/__tests__/Model.cloning.spec.ts +++ b/src/json-crdt/model/__tests__/Model.cloning.spec.ts @@ -252,4 +252,19 @@ describe('reset()', () => { doc1.reset(doc2); expect(str.view()).toBe('hello'); }); + + test('uses the same clock in Model and NodeBuilder', async () => { + const doc1 = Model.create().setSchema( + schema.obj({ + text: schema.str('hell'), + }), + ); + const doc2 = doc1.fork(); + doc2.s.text.toApi().ins(4, 'o'); + expect(doc1.clock).toBe(doc1.api.builder.clock); + expect(doc2.clock).toBe(doc2.api.builder.clock); + doc1.reset(doc2); + expect(doc1.clock).toBe(doc1.api.builder.clock); + expect(doc2.clock).toBe(doc2.api.builder.clock); + }); });