loro-crdt 1.3.5 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 9090c4d: fix: memory leak issue
8
+
9
+ ## 1.4.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 2f3364a: refactor!: use better data type for doc.diff #646
14
+
15
+ ### Patch Changes
16
+
17
+ - 72699ae: fix: getting values by path in LoroTree (#643)
18
+
3
19
  ## 1.3.5
4
20
 
5
21
  ### Patch Changes
package/base64/index.js CHANGED
@@ -2610,8 +2610,32 @@ class LoroDoc {
2610
2610
  }
2611
2611
  }
2612
2612
  /**
2613
- * Apply a diff batch to the document
2614
- * @param {Record<ContainerID, Diff>} diff
2613
+ * Apply a batch of diff to the document
2614
+ *
2615
+ * A diff batch represents a set of changes between two versions of the document.
2616
+ * You can calculate a diff batch using `doc.diff()`.
2617
+ *
2618
+ * Changes are associated with container IDs. During diff application, if new containers were created in the source
2619
+ * document, they will be assigned fresh IDs in the target document. Loro automatically handles remapping these
2620
+ * container IDs from their original IDs to the new IDs as the diff is applied.
2621
+ *
2622
+ * @example
2623
+ * ```ts
2624
+ * const doc1 = new LoroDoc();
2625
+ * const doc2 = new LoroDoc();
2626
+ *
2627
+ * // Make some changes to doc1
2628
+ * const text = doc1.getText("text");
2629
+ * text.insert(0, "Hello");
2630
+ *
2631
+ * // Calculate diff between empty and current state
2632
+ * const diff = doc1.diff([], doc1.frontiers());
2633
+ *
2634
+ * // Apply changes to doc2
2635
+ * doc2.applyDiff(diff);
2636
+ * console.log(doc2.getText("text").toString()); // "Hello"
2637
+ * ```
2638
+ * @param {[ContainerID, Diff|JsonDiff][]} diff
2615
2639
  */
2616
2640
  applyDiff(diff) {
2617
2641
  try {
@@ -2633,16 +2657,17 @@ class LoroDoc {
2633
2657
  * presented before its use.
2634
2658
  * @param {({ peer: PeerID, counter: number })[]} from
2635
2659
  * @param {({ peer: PeerID, counter: number })[]} to
2636
- * @returns {Record<ContainerID, Diff>}
2660
+ * @param {boolean | undefined} [for_json]
2661
+ * @returns {[ContainerID, Diff|JsonDiff][]}
2637
2662
  */
2638
- diff(from, to) {
2663
+ diff(from, to, for_json) {
2639
2664
  try {
2640
2665
  const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
2641
2666
  const ptr0 = passArrayJsValueToWasm0(from, wasm.__wbindgen_export_0);
2642
2667
  const len0 = WASM_VECTOR_LEN;
2643
2668
  const ptr1 = passArrayJsValueToWasm0(to, wasm.__wbindgen_export_0);
2644
2669
  const len1 = WASM_VECTOR_LEN;
2645
- wasm.lorodoc_diff(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1);
2670
+ wasm.lorodoc_diff(retptr, this.__wbg_ptr, ptr0, len0, ptr1, len1, isLikeNone(for_json) ? 0xFFFFFF : for_json ? 1 : 0);
2646
2671
  var r0 = getInt32Memory0()[retptr / 4 + 0];
2647
2672
  var r1 = getInt32Memory0()[retptr / 4 + 1];
2648
2673
  var r2 = getInt32Memory0()[retptr / 4 + 2];
@@ -5991,32 +6016,32 @@ function __wbg_lorotreenode_new(arg0) {
5991
6016
  const ret = LoroTreeNode.__wrap(arg0);
5992
6017
  return addHeapObject(ret);
5993
6018
  }
5994
- function __wbg_lorocounter_new(arg0) {
5995
- const ret = LoroCounter.__wrap(arg0);
5996
- return addHeapObject(ret);
5997
- }
5998
- function __wbg_lorotext_new(arg0) {
5999
- const ret = LoroText.__wrap(arg0);
6019
+ function __wbg_lorotree_new(arg0) {
6020
+ const ret = LoroTree.__wrap(arg0);
6000
6021
  return addHeapObject(ret);
6001
6022
  }
6002
6023
  function __wbg_lorolist_new(arg0) {
6003
6024
  const ret = LoroList.__wrap(arg0);
6004
6025
  return addHeapObject(ret);
6005
6026
  }
6006
- function __wbg_loromap_new(arg0) {
6007
- const ret = LoroMap.__wrap(arg0);
6027
+ function __wbg_lorocounter_new(arg0) {
6028
+ const ret = LoroCounter.__wrap(arg0);
6008
6029
  return addHeapObject(ret);
6009
6030
  }
6010
- function __wbg_cursor_new(arg0) {
6011
- const ret = Cursor.__wrap(arg0);
6031
+ function __wbg_loromap_new(arg0) {
6032
+ const ret = LoroMap.__wrap(arg0);
6012
6033
  return addHeapObject(ret);
6013
6034
  }
6014
6035
  function __wbg_loromovablelist_new(arg0) {
6015
6036
  const ret = LoroMovableList.__wrap(arg0);
6016
6037
  return addHeapObject(ret);
6017
6038
  }
6018
- function __wbg_lorotree_new(arg0) {
6019
- const ret = LoroTree.__wrap(arg0);
6039
+ function __wbg_lorotext_new(arg0) {
6040
+ const ret = LoroText.__wrap(arg0);
6041
+ return addHeapObject(ret);
6042
+ }
6043
+ function __wbg_cursor_new(arg0) {
6044
+ const ret = Cursor.__wrap(arg0);
6020
6045
  return addHeapObject(ret);
6021
6046
  }
6022
6047
  function __wbg_versionvector_new(arg0) {
@@ -6211,7 +6236,7 @@ function __wbg_error_f851667af71bcfc6(arg0, arg1) {
6211
6236
  wasm.__wbindgen_export_5(deferred0_0, deferred0_1, 1);
6212
6237
  }
6213
6238
  }
6214
- const __wbg_now_6dd635953150ee31 = typeof Date.now == 'function' ? Date.now : notDefined('Date.now');
6239
+ const __wbg_now_bc6f749123583eb9 = typeof Date.now == 'function' ? Date.now : notDefined('Date.now');
6215
6240
 
6216
6241
  function __wbg_crypto_1d1f22824a6a080c(arg0) {
6217
6242
  const ret = getObject(arg0).crypto;
@@ -6476,11 +6501,11 @@ function __wbindgen_memory() {
6476
6501
  return addHeapObject(ret);
6477
6502
  }
6478
6503
  function __wbindgen_closure_wrapper482(arg0, arg1, arg2) {
6479
- const ret = makeMutClosure(arg0, arg1, 8, __wbg_adapter_60);
6504
+ const ret = makeMutClosure(arg0, arg1, 10, __wbg_adapter_60);
6480
6505
  return addHeapObject(ret);
6481
6506
  }
6482
- function __wbindgen_closure_wrapper484(arg0, arg1, arg2) {
6483
- const ret = makeMutClosure(arg0, arg1, 10, __wbg_adapter_63);
6507
+ function __wbindgen_closure_wrapper485(arg0, arg1, arg2) {
6508
+ const ret = makeMutClosure(arg0, arg1, 8, __wbg_adapter_63);
6484
6509
  return addHeapObject(ret);
6485
6510
  }
6486
6511
 
@@ -6554,7 +6579,7 @@ var imports = /*#__PURE__*/Object.freeze({
6554
6579
  __wbg_next_196c84450b364254: __wbg_next_196c84450b364254,
6555
6580
  __wbg_next_40fc327bfc8770e6: __wbg_next_40fc327bfc8770e6,
6556
6581
  __wbg_node_104a2ff8d6ea03a2: __wbg_node_104a2ff8d6ea03a2,
6557
- __wbg_now_6dd635953150ee31: __wbg_now_6dd635953150ee31,
6582
+ __wbg_now_bc6f749123583eb9: __wbg_now_bc6f749123583eb9,
6558
6583
  __wbg_ownKeys_658942b7f28d1fe9: __wbg_ownKeys_658942b7f28d1fe9,
6559
6584
  __wbg_process_4a72847cc503995b: __wbg_process_4a72847cc503995b,
6560
6585
  __wbg_push_a5b05aedc7234f9f: __wbg_push_a5b05aedc7234f9f,
@@ -6583,7 +6608,7 @@ var imports = /*#__PURE__*/Object.freeze({
6583
6608
  __wbindgen_boolean_get: __wbindgen_boolean_get,
6584
6609
  __wbindgen_cb_drop: __wbindgen_cb_drop,
6585
6610
  __wbindgen_closure_wrapper482: __wbindgen_closure_wrapper482,
6586
- __wbindgen_closure_wrapper484: __wbindgen_closure_wrapper484,
6611
+ __wbindgen_closure_wrapper485: __wbindgen_closure_wrapper485,
6587
6612
  __wbindgen_debug_string: __wbindgen_debug_string,
6588
6613
  __wbindgen_error_new: __wbindgen_error_new,
6589
6614
  __wbindgen_in: __wbindgen_in,
@@ -6618,7 +6643,7 @@ var imports = /*#__PURE__*/Object.freeze({
6618
6643
  // Without this patch, Cloudflare Worker would raise issue like: "Uncaught TypeError: wasm2.__wbindgen_start is not a function"
6619
6644
 
6620
6645
 
6621
- import loro_wasm_bg_js from './loro_wasm_bg-75063aaa.js';
6646
+ import loro_wasm_bg_js from './loro_wasm_bg-4116d6d8.js';
6622
6647
  const instance = new WebAssembly.Instance(loro_wasm_bg_js(), {
6623
6648
  "./loro_wasm_bg.js": imports,
6624
6649
  });
@@ -6823,4 +6848,4 @@ LoroDoc.prototype.toJsonWithReplacer = function (replacer) {
6823
6848
  return run(layer);
6824
6849
  };
6825
6850
 
6826
- export { Awareness, AwarenessWasm, Cursor, Loro, LoroCounter, LoroDoc, LoroList, LoroMap, LoroMovableList, LoroText, LoroTree, LoroTreeNode, UndoManager, VersionVector, __wbg_String_b9412f8799faab3e, __wbg_apply_0a5aa603881e6d79, __wbg_buffer_12d079cc21e14bdb, __wbg_call_27c0f87801dedf93, __wbg_call_8e7cb608789c2528, __wbg_call_938992c832f74314, __wbg_call_b3ca7c6051f9bec1, __wbg_crypto_1d1f22824a6a080c, __wbg_cursor_new, __wbg_done_298b57d23c0fc80c, __wbg_entries_95cc2c823b285a09, __wbg_entries_ce844941d0c51880, __wbg_error_9384d761bf46409d, __wbg_error_f851667af71bcfc6, __wbg_from_89e3fc3ba5e6fb48, __wbg_getRandomValues_3aa56aa6edec874c, __wbg_get_bd8e338fbd5f5cc8, __wbg_get_e3c254076557e348, __wbg_getindex_03d06b4e7ea3475e, __wbg_getwithrefkey_edc2c8960f0f1191, __wbg_globalThis_d1e6af4856ba331b, __wbg_global_207b558942527489, __wbg_instanceof_ArrayBuffer_836825be07d4c9d2, __wbg_instanceof_Map_87917e0a7aaf4012, __wbg_instanceof_Object_71ca3c0a59266746, __wbg_instanceof_Uint8Array_2b3bbecd033d19f6, __wbg_isArray_2ab64d95e09ea0ae, __wbg_isSafeInteger_f7b04ef02296c4d2, __wbg_iterator_2cee6dadfd956dfa, __wbg_length_c20a40f15020d68a, __wbg_length_cd7af8117672b8b8, __wbg_log_aba5996d9bde071f, __wbg_log_c86c3e1bf097ba35, __wbg_log_c9486ca5d8e2cbe8, __wbg_lorocounter_new, __wbg_lorolist_new, __wbg_loromap_new, __wbg_loromovablelist_new, __wbg_lorotext_new, __wbg_lorotree_new, __wbg_lorotreenode_new, __wbg_mark_40e050a77cc39fea, __wbg_measure_aa7a73f17813f708, __wbg_msCrypto_eb05e62b530a1508, __wbg_new_16b304a2cfa7ff4a, __wbg_new_63b92bc8671ed464, __wbg_new_72fb9a18b5ae2624, __wbg_new_abda76e883ba8a5f, __wbg_new_d9bc3a0147634640, __wbg_newnoargs_e258087cd0daa0ea, __wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb, __wbg_newwithlength_66ae46612e7f0234, __wbg_newwithlength_e9b4878cebadb3d3, __wbg_next_196c84450b364254, __wbg_next_40fc327bfc8770e6, __wbg_node_104a2ff8d6ea03a2, __wbg_now_6dd635953150ee31, __wbg_ownKeys_658942b7f28d1fe9, __wbg_process_4a72847cc503995b, __wbg_push_a5b05aedc7234f9f, __wbg_randomFillSync_5c9c955aa56b6049, __wbg_require_cca90b1a94a0255b, __wbg_resolve_b0083a7967828ec8, __wbg_self_ce0dbfc45cf2f5be, __wbg_set_1f9b04f170055d33, __wbg_set_8417257aaedc936b, __wbg_set_a47bac70306a19a7, __wbg_set_d4638f722068f043, __wbg_set_f975102236d3c502, __wbg_set_wasm, __wbg_setindex_0b7ede192dc5eca8, __wbg_stack_658279fe44541cf6, __wbg_subarray_a1f73cd4b5b42fe1, __wbg_then_0c86a60e8fcfe9f6, __wbg_value_d93c65011f51a456, __wbg_versions_f686565e586dd935, __wbg_versionvector_new, __wbg_window_c6fb939a7f436783, __wbindgen_as_number, __wbindgen_bigint_from_i64, __wbindgen_bigint_from_u64, __wbindgen_bigint_get_as_i64, __wbindgen_boolean_get, __wbindgen_cb_drop, __wbindgen_closure_wrapper482, __wbindgen_closure_wrapper484, __wbindgen_debug_string, __wbindgen_error_new, __wbindgen_in, __wbindgen_is_array, __wbindgen_is_bigint, __wbindgen_is_falsy, __wbindgen_is_function, __wbindgen_is_null, __wbindgen_is_object, __wbindgen_is_string, __wbindgen_is_undefined, __wbindgen_jsval_eq, __wbindgen_jsval_loose_eq, __wbindgen_memory, __wbindgen_number_get, __wbindgen_number_new, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_rethrow, __wbindgen_string_get, __wbindgen_string_new, __wbindgen_throw, __wbindgen_typeof, decodeFrontiers, decodeImportBlobMeta, encodeFrontiers, getType, isContainer, isContainerId, newContainerID, newRootContainerID, run, setDebug };
6851
+ export { Awareness, AwarenessWasm, Cursor, Loro, LoroCounter, LoroDoc, LoroList, LoroMap, LoroMovableList, LoroText, LoroTree, LoroTreeNode, UndoManager, VersionVector, __wbg_String_b9412f8799faab3e, __wbg_apply_0a5aa603881e6d79, __wbg_buffer_12d079cc21e14bdb, __wbg_call_27c0f87801dedf93, __wbg_call_8e7cb608789c2528, __wbg_call_938992c832f74314, __wbg_call_b3ca7c6051f9bec1, __wbg_crypto_1d1f22824a6a080c, __wbg_cursor_new, __wbg_done_298b57d23c0fc80c, __wbg_entries_95cc2c823b285a09, __wbg_entries_ce844941d0c51880, __wbg_error_9384d761bf46409d, __wbg_error_f851667af71bcfc6, __wbg_from_89e3fc3ba5e6fb48, __wbg_getRandomValues_3aa56aa6edec874c, __wbg_get_bd8e338fbd5f5cc8, __wbg_get_e3c254076557e348, __wbg_getindex_03d06b4e7ea3475e, __wbg_getwithrefkey_edc2c8960f0f1191, __wbg_globalThis_d1e6af4856ba331b, __wbg_global_207b558942527489, __wbg_instanceof_ArrayBuffer_836825be07d4c9d2, __wbg_instanceof_Map_87917e0a7aaf4012, __wbg_instanceof_Object_71ca3c0a59266746, __wbg_instanceof_Uint8Array_2b3bbecd033d19f6, __wbg_isArray_2ab64d95e09ea0ae, __wbg_isSafeInteger_f7b04ef02296c4d2, __wbg_iterator_2cee6dadfd956dfa, __wbg_length_c20a40f15020d68a, __wbg_length_cd7af8117672b8b8, __wbg_log_aba5996d9bde071f, __wbg_log_c86c3e1bf097ba35, __wbg_log_c9486ca5d8e2cbe8, __wbg_lorocounter_new, __wbg_lorolist_new, __wbg_loromap_new, __wbg_loromovablelist_new, __wbg_lorotext_new, __wbg_lorotree_new, __wbg_lorotreenode_new, __wbg_mark_40e050a77cc39fea, __wbg_measure_aa7a73f17813f708, __wbg_msCrypto_eb05e62b530a1508, __wbg_new_16b304a2cfa7ff4a, __wbg_new_63b92bc8671ed464, __wbg_new_72fb9a18b5ae2624, __wbg_new_abda76e883ba8a5f, __wbg_new_d9bc3a0147634640, __wbg_newnoargs_e258087cd0daa0ea, __wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb, __wbg_newwithlength_66ae46612e7f0234, __wbg_newwithlength_e9b4878cebadb3d3, __wbg_next_196c84450b364254, __wbg_next_40fc327bfc8770e6, __wbg_node_104a2ff8d6ea03a2, __wbg_now_bc6f749123583eb9, __wbg_ownKeys_658942b7f28d1fe9, __wbg_process_4a72847cc503995b, __wbg_push_a5b05aedc7234f9f, __wbg_randomFillSync_5c9c955aa56b6049, __wbg_require_cca90b1a94a0255b, __wbg_resolve_b0083a7967828ec8, __wbg_self_ce0dbfc45cf2f5be, __wbg_set_1f9b04f170055d33, __wbg_set_8417257aaedc936b, __wbg_set_a47bac70306a19a7, __wbg_set_d4638f722068f043, __wbg_set_f975102236d3c502, __wbg_set_wasm, __wbg_setindex_0b7ede192dc5eca8, __wbg_stack_658279fe44541cf6, __wbg_subarray_a1f73cd4b5b42fe1, __wbg_then_0c86a60e8fcfe9f6, __wbg_value_d93c65011f51a456, __wbg_versions_f686565e586dd935, __wbg_versionvector_new, __wbg_window_c6fb939a7f436783, __wbindgen_as_number, __wbindgen_bigint_from_i64, __wbindgen_bigint_from_u64, __wbindgen_bigint_get_as_i64, __wbindgen_boolean_get, __wbindgen_cb_drop, __wbindgen_closure_wrapper482, __wbindgen_closure_wrapper485, __wbindgen_debug_string, __wbindgen_error_new, __wbindgen_in, __wbindgen_is_array, __wbindgen_is_bigint, __wbindgen_is_falsy, __wbindgen_is_function, __wbindgen_is_null, __wbindgen_is_object, __wbindgen_is_string, __wbindgen_is_undefined, __wbindgen_jsval_eq, __wbindgen_jsval_loose_eq, __wbindgen_memory, __wbindgen_number_get, __wbindgen_number_new, __wbindgen_object_clone_ref, __wbindgen_object_drop_ref, __wbindgen_rethrow, __wbindgen_string_get, __wbindgen_string_new, __wbindgen_throw, __wbindgen_typeof, decodeFrontiers, decodeImportBlobMeta, encodeFrontiers, getType, isContainer, isContainerId, newContainerID, newRootContainerID, run, setDebug };
@@ -155,36 +155,55 @@ interface LoroDoc {
155
155
  * ```
156
156
  */
157
157
  subscribeLocalUpdates(f: (bytes: Uint8Array) => void): () => void
158
+
158
159
  /**
159
160
  * Convert the document to a JSON value with a custom replacer function.
160
- *
161
+ *
161
162
  * This method works similarly to `JSON.stringify`'s replacer parameter.
162
163
  * The replacer function is called for each value in the document and can transform
163
164
  * how values are serialized to JSON.
164
- *
165
+ *
165
166
  * @param replacer - A function that takes a key and value, and returns how that value
166
- * should be serialized. Similar to JSON.stringify's replacer.
167
+ * should be serialized. Similar to JSON.stringify's replacer.
167
168
  * If return undefined, the value will be skipped.
168
169
  * @returns The JSON representation of the document after applying the replacer function.
169
- *
170
+ *
170
171
  * @example
171
172
  * ```ts
172
173
  * const doc = new LoroDoc();
173
174
  * const text = doc.getText("text");
174
175
  * text.insert(0, "Hello");
175
176
  * text.mark({ start: 0, end: 2 }, "bold", true);
176
- *
177
+ *
177
178
  * // Use delta to represent text
178
179
  * const json = doc.toJsonWithReplacer((key, value) => {
179
180
  * if (value instanceof LoroText) {
180
181
  * return value.toDelta();
181
- * }
182
- *
182
+ * }
183
+ *
183
184
  * return value;
184
185
  * });
185
186
  * ```
186
187
  */
187
188
  toJsonWithReplacer(replacer: (key: string | index, value: Value | Container) => Value | Container | undefined): Value;
189
+
190
+ /**
191
+ * Calculate the differences between two frontiers
192
+ *
193
+ * The entries in the returned object are sorted by causal order: the creation of a child container will be
194
+ * presented before its use.
195
+ *
196
+ * @param from - The source frontier to diff from. A frontier represents a consistent version of the document.
197
+ * @param to - The target frontier to diff to. A frontier represents a consistent version of the document.
198
+ * @param for_json - Controls the diff format:
199
+ * - If true, returns JsonDiff format suitable for JSON serialization
200
+ * - If false, returns Diff format that shares the same type as LoroEvent
201
+ * - The default value is `true`
202
+ */
203
+ diff(from: OpId[], to: OpId[], for_json: false): [ContainerID, Diff][];
204
+ diff(from: OpId[], to: OpId[], for_json: true): [ContainerID, JsonDiff][];
205
+ diff(from: OpId[], to: OpId[], for_json: undefined): [ContainerID, JsonDiff][];
206
+ diff(from: OpId[], to: OpId[], for_json?: boolean): [ContainerID, JsonDiff|Diff][];
188
207
  }
189
208
 
190
209
  /**
@@ -672,6 +691,11 @@ export type ListDiff = {
672
691
  diff: Delta<(Value | Container)[]>[];
673
692
  };
674
693
 
694
+ export type ListJsonDiff = {
695
+ type: "list";
696
+ diff: Delta<(Value | JsonContainerID )[]>[];
697
+ };
698
+
675
699
  export type TextDiff = {
676
700
  type: "text";
677
701
  diff: Delta<string>[];
@@ -682,6 +706,11 @@ export type MapDiff = {
682
706
  updated: Record<string, Value | Container | undefined>;
683
707
  };
684
708
 
709
+ export type MapJsonDiff = {
710
+ type: "map";
711
+ updated: Record<string, Value | JsonContainerID | undefined>;
712
+ };
713
+
685
714
  export type TreeDiffItem =
686
715
  | {
687
716
  target: TreeID;
@@ -717,6 +746,7 @@ export type CounterDiff = {
717
746
  };
718
747
 
719
748
  export type Diff = ListDiff | TextDiff | MapDiff | TreeDiff | CounterDiff;
749
+ export type JsonDiff = ListJsonDiff | TextDiff | MapJsonDiff | CounterDiff | TreeDiff;
720
750
  export type Subscription = () => void;
721
751
  type NonNullableType<T> = Exclude<T, null | undefined>;
722
752
  export type AwarenessListener = (
@@ -1082,7 +1112,7 @@ interface LoroMap<T extends Record<string, unknown> = Record<string, unknown>> {
1082
1112
  * If the key already exists, its value will be updated. If the key doesn't exist,
1083
1113
  * a new key-value pair will be created.
1084
1114
  *
1085
- * > **Note**: When calling `map.set(key, value)` on a LoroMap, if `map.get(key)` already returns `value`,
1115
+ * > **Note**: When calling `map.set(key, value)` on a LoroMap, if `map.get(key)` already returns `value`,
1086
1116
  * > the operation will be a no-op (no operation recorded) to avoid unnecessary updates.
1087
1117
  *
1088
1118
  * @example
@@ -2318,20 +2348,34 @@ export class LoroDoc {
2318
2348
  */
2319
2349
  revertTo(frontiers: ({ peer: PeerID, counter: number })[]): void;
2320
2350
  /**
2321
- * Apply a diff batch to the document
2322
- * @param {Record<ContainerID, Diff>} diff
2323
- */
2324
- applyDiff(diff: Record<ContainerID, Diff>): void;
2325
- /**
2326
- * Calculate the differences between two frontiers
2351
+ * Apply a batch of diff to the document
2327
2352
  *
2328
- * The entries in the returned object are sorted by causal order: the creation of a child container will be
2329
- * presented before its use.
2330
- * @param {({ peer: PeerID, counter: number })[]} from
2331
- * @param {({ peer: PeerID, counter: number })[]} to
2332
- * @returns {Record<ContainerID, Diff>}
2353
+ * A diff batch represents a set of changes between two versions of the document.
2354
+ * You can calculate a diff batch using `doc.diff()`.
2355
+ *
2356
+ * Changes are associated with container IDs. During diff application, if new containers were created in the source
2357
+ * document, they will be assigned fresh IDs in the target document. Loro automatically handles remapping these
2358
+ * container IDs from their original IDs to the new IDs as the diff is applied.
2359
+ *
2360
+ * @example
2361
+ * ```ts
2362
+ * const doc1 = new LoroDoc();
2363
+ * const doc2 = new LoroDoc();
2364
+ *
2365
+ * // Make some changes to doc1
2366
+ * const text = doc1.getText("text");
2367
+ * text.insert(0, "Hello");
2368
+ *
2369
+ * // Calculate diff between empty and current state
2370
+ * const diff = doc1.diff([], doc1.frontiers());
2371
+ *
2372
+ * // Apply changes to doc2
2373
+ * doc2.applyDiff(diff);
2374
+ * console.log(doc2.getText("text").toString()); // "Hello"
2375
+ * ```
2376
+ * @param {[ContainerID, Diff|JsonDiff][]} diff
2333
2377
  */
2334
- diff(from: ({ peer: PeerID, counter: number })[], to: ({ peer: PeerID, counter: number })[]): Record<ContainerID, Diff>;
2378
+ applyDiff(diff: [ContainerID, Diff|JsonDiff][]): void;
2335
2379
  /**
2336
2380
  * Peer ID of the current writer.
2337
2381
  */