braid-text 0.1.2 → 0.1.3

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.
Files changed (3) hide show
  1. package/index.js +87 -41
  2. package/package.json +1 -1
  3. package/test.js +88 -122
package/index.js CHANGED
@@ -220,10 +220,14 @@ braid_text.get = async (key, options) => {
220
220
  let doc = resource.doc
221
221
  if (options.version || options.parents) doc = dt_get(doc, options.version || options.parents)
222
222
 
223
- return {
223
+ let ret = {
224
224
  version: doc.getRemoteVersion().map((x) => x.join("-")).sort(),
225
225
  body: doc.get()
226
226
  }
227
+
228
+ if (options.version || options.parents) doc.free()
229
+
230
+ return ret
227
231
  } else {
228
232
  if (options.merge_type != "dt") {
229
233
  let version = resource.doc.getRemoteVersion().map((x) => x.join("-")).sort()
@@ -269,17 +273,12 @@ braid_text.get = async (key, options) => {
269
273
  updates = dt_get_patches(resource.doc, options.parents || options.version)
270
274
  }
271
275
 
272
- for (let u of updates) {
273
- u.version = decode_version(u.version)
274
- u.version[1] += u.end - u.start - 1
275
- u.version = u.version.join("-")
276
-
276
+ for (let u of updates)
277
277
  options.subscribe({
278
278
  version: [u.version],
279
279
  parents: u.parents,
280
280
  patches: [{ unit: u.unit, range: u.range, content: u.content }],
281
281
  })
282
- }
283
282
 
284
283
  // Output at least *some* data, or else chrome gets confused and
285
284
  // thinks the connection failed. This isn't strictly necessary,
@@ -292,6 +291,16 @@ braid_text.get = async (key, options) => {
292
291
  }
293
292
  }
294
293
 
294
+ braid_text.forget = async (key, options) => {
295
+ if (!options) throw new Error('options is required')
296
+
297
+ let resource = (typeof key == 'string') ? await get_resource(key) : key
298
+
299
+ if (options.merge_type != "dt")
300
+ resource.simpleton_clients.delete(options)
301
+ else resource.clients.delete(options)
302
+ }
303
+
295
304
  braid_text.put = async (key, options) => {
296
305
  let { version, patches, body, peer } = options
297
306
 
@@ -320,9 +329,15 @@ braid_text.put = async (key, options) => {
320
329
  let parents = resource.doc.getRemoteVersion().map((x) => x.join("-")).sort()
321
330
  let og_parents = options_parents || parents
322
331
 
332
+ function get_len() {
333
+ let d = dt_get(resource.doc, og_parents)
334
+ let len = d.len()
335
+ d.free()
336
+ return len
337
+ }
338
+
323
339
  let max_pos = resource.length_cache.get('' + og_parents) ??
324
- (v_eq(parents, og_parents) ? resource.doc.len() :
325
- dt_get(resource.doc, og_parents).len())
340
+ (v_eq(parents, og_parents) ? resource.doc.len() : get_len())
326
341
 
327
342
  if (body != null) {
328
343
  patches = [{
@@ -336,7 +351,7 @@ braid_text.put = async (key, options) => {
336
351
  patches = patches.map((p) => ({
337
352
  ...p,
338
353
  range: p.range.match(/\d+/g).map((x) => parseInt(x)),
339
- content: [...p.content],
354
+ content_codepoints: [...p.content],
340
355
  })).sort((a, b) => a.range[0] - b.range[0])
341
356
 
342
357
  // validate patch positions
@@ -347,7 +362,7 @@ braid_text.put = async (key, options) => {
347
362
  must_be_at_least = p.range[1]
348
363
  }
349
364
 
350
- let change_count = patches.reduce((a, b) => a + b.content.length + (b.range[1] - b.range[0]), 0)
365
+ let change_count = patches.reduce((a, b) => a + b.content_codepoints.length + (b.range[1] - b.range[0]), 0)
351
366
 
352
367
  let og_v = version?.[0] || `${(is_valid_actor(peer) && peer) || Math.random().toString(36).slice(2, 7)}-${change_count - 1}`
353
368
 
@@ -365,7 +380,6 @@ braid_text.put = async (key, options) => {
365
380
  let seen = {}
366
381
  for (let u of updates) {
367
382
  u.version = decode_version(u.version)
368
- u.version[1] += u.end - u.start - 1
369
383
 
370
384
  if (!u.content) {
371
385
  // delete
@@ -401,9 +415,9 @@ braid_text.put = async (key, options) => {
401
415
  v = `${v[0]}-${v[1] + 1}`
402
416
  }
403
417
  // insert
404
- for (let i = 0; i < p.content?.length ?? 0; i++) {
418
+ for (let i = 0; i < p.content_codepoints?.length ?? 0; i++) {
405
419
  let vv = decode_version(v)
406
- let c = p.content[i]
420
+ let c = p.content_codepoints[i]
407
421
 
408
422
  if (!seen[JSON.stringify([vv[0], vv[1], ps, p.range[1] + offset, c])]) throw new Error('invalid update: different from previous update with same version')
409
423
 
@@ -420,7 +434,7 @@ braid_text.put = async (key, options) => {
420
434
  resource.actor_seqs[v[0]] = v[1]
421
435
 
422
436
  resource.length_cache.put(`${v[0]}-${v[1]}`, patches.reduce((a, b) =>
423
- a + (b.content.length ? b.content.length : -(b.range[1] - b.range[0])),
437
+ a + (b.content_codepoints.length ? b.content_codepoints.length : -(b.range[1] - b.range[0])),
424
438
  max_pos))
425
439
 
426
440
  v = `${v[0]}-${v[1] + 1 - change_count}`
@@ -434,21 +448,21 @@ braid_text.put = async (key, options) => {
434
448
  let offset = 0
435
449
  for (let p of patches) {
436
450
  // delete
437
- for (let i = p.range[0]; i < p.range[1]; i++) {
438
- bytes.push(dt_create_bytes(v, ps, p.range[1] - 1 + offset, null))
439
- offset--
440
- ps = [v]
451
+ let del = p.range[1] - p.range[0]
452
+ if (del) {
453
+ bytes.push(dt_create_bytes(v, ps, p.range[0] + offset, del, null))
454
+ offset -= del
441
455
  v = decode_version(v)
442
- v = `${v[0]}-${v[1] + 1}`
456
+ ps = [`${v[0]}-${v[1] + (del - 1)}`]
457
+ v = `${v[0]}-${v[1] + del}`
443
458
  }
444
459
  // insert
445
- for (let i = 0; i < p.content?.length ?? 0; i++) {
446
- let c = p.content[i]
447
- bytes.push(dt_create_bytes(v, ps, p.range[1] + offset, c))
448
- offset++
449
- ps = [v]
460
+ if (p.content?.length) {
461
+ bytes.push(dt_create_bytes(v, ps, p.range[1] + offset, 0, p.content))
462
+ offset += p.content_codepoints.length
450
463
  v = decode_version(v)
451
- v = `${v[0]}-${v[1] + 1}`
464
+ ps = [`${v[0]}-${v[1] + (p.content_codepoints.length - 1)}`]
465
+ v = `${v[0]}-${v[1] + p.content_codepoints.length}`
452
466
  }
453
467
  }
454
468
 
@@ -787,6 +801,8 @@ async function file_sync(key, process_delta, get_init) {
787
801
  //////////////////////////////////////////////////////////////////
788
802
 
789
803
  function dt_get(doc, version, agent = null) {
804
+ if (dt_get.last_doc) dt_get.last_doc.free()
805
+
790
806
  let bytes = doc.toBytes()
791
807
  dt_get.last_doc = doc = Doc.fromBytes(bytes, agent)
792
808
 
@@ -834,6 +850,7 @@ function dt_get(doc, version, agent = null) {
834
850
  op_run.start + (i - base_i) :
835
851
  op_run.start) :
836
852
  op_run.end - 1 - (i - base_i),
853
+ op_run.content?.[i - base_i] != null ? 0 : 1,
837
854
  op_run.content?.[i - base_i]
838
855
  )
839
856
  )
@@ -866,12 +883,16 @@ function dt_get_patches(doc, version = null) {
866
883
 
867
884
  before_doc.mergeBytes(after_bytes)
868
885
  op_runs = before_doc.getOpsSince(before_doc_frontier)
886
+
887
+ before_doc.free()
869
888
  } else op_runs = doc.getOpsSince([])
870
889
 
890
+ doc.free()
891
+
871
892
  let i = 0
872
893
  let patches = []
873
894
  op_runs.forEach((op_run) => {
874
- let version = versions[i].join("-")
895
+ let version = versions[i]
875
896
  let parents = parentss[i].map((x) => x.join("-")).sort()
876
897
  let start = op_run.start
877
898
  let end = start + 1
@@ -899,7 +920,7 @@ function dt_get_patches(doc, version = null) {
899
920
  op_run.start + (end - start)) :
900
921
  (op_run.end - (start - op_run.start))
901
922
  patches.push({
902
- version,
923
+ version: `${version[0]}-${version[1] + e - s - 1}`,
903
924
  parents,
904
925
  unit: "text",
905
926
  range: op_run.content ? `[${s}:${s}]` : `[${s}:${e}]`,
@@ -908,7 +929,7 @@ function dt_get_patches(doc, version = null) {
908
929
  end: e,
909
930
  })
910
931
  if (j == len) break
911
- version = versions[I].join("-")
932
+ version = versions[I]
912
933
  parents = parentss[I].map((x) => x.join("-")).sort()
913
934
  start = op_run.start + j
914
935
  }
@@ -1014,7 +1035,8 @@ function dt_parse(byte_array) {
1014
1035
  return [agents, versions, parentss]
1015
1036
  }
1016
1037
 
1017
- function dt_create_bytes(version, parents, pos, ins) {
1038
+ function dt_create_bytes(version, parents, pos, del, ins) {
1039
+ if (del) pos += del - 1
1018
1040
 
1019
1041
  function write_varint(bytes, value) {
1020
1042
  while (value >= 0x80) {
@@ -1085,6 +1107,8 @@ function dt_create_bytes(version, parents, pos, ins) {
1085
1107
 
1086
1108
  let patches = []
1087
1109
 
1110
+ let unicode_chars = ins ? [...ins] : []
1111
+
1088
1112
  if (ins) {
1089
1113
  let inserted_content_bytes = []
1090
1114
 
@@ -1095,18 +1119,21 @@ function dt_create_bytes(version, parents, pos, ins) {
1095
1119
  let encoder = new TextEncoder()
1096
1120
  let utf8Bytes = encoder.encode(ins)
1097
1121
 
1098
- inserted_content_bytes.push(1 + utf8Bytes.length) // length of content chunk
1122
+ write_varint(inserted_content_bytes, 1 + utf8Bytes.length)
1123
+ // inserted_content_bytes.push(1 + utf8Bytes.length) // length of content chunk
1099
1124
  inserted_content_bytes.push(4) // "plain text" enum
1100
1125
 
1101
1126
  for (let b of utf8Bytes) inserted_content_bytes.push(b) // actual text
1102
1127
 
1103
1128
  inserted_content_bytes.push(25) // "known" enum
1104
- inserted_content_bytes.push(1) // length of "known" chunk
1105
- inserted_content_bytes.push(3) // content of length 1, and we "know" it
1129
+ let known_chunk = []
1130
+ write_varint(known_chunk, unicode_chars.length * 2 + 1)
1131
+ write_varint(inserted_content_bytes, known_chunk.length)
1132
+ inserted_content_bytes.push(...known_chunk)
1106
1133
 
1107
1134
  patches.push(24)
1108
1135
  write_varint(patches, inserted_content_bytes.length)
1109
- patches.push(...inserted_content_bytes)
1136
+ for (let b of inserted_content_bytes) patches.push(b)
1110
1137
  }
1111
1138
 
1112
1139
  // write in the version
@@ -1117,26 +1144,43 @@ function dt_create_bytes(version, parents, pos, ins) {
1117
1144
  let jump = seq
1118
1145
 
1119
1146
  write_varint(version_bytes, ((agent_i + 1) << 1) | (jump != 0 ? 1 : 0))
1120
- write_varint(version_bytes, 1)
1147
+ write_varint(version_bytes, ins ? unicode_chars.length : del)
1121
1148
  if (jump) write_varint(version_bytes, jump << 1)
1122
1149
 
1123
1150
  patches.push(21)
1124
1151
  write_varint(patches, version_bytes.length)
1125
- patches.push(...version_bytes)
1152
+ for (let b of version_bytes) patches.push(b)
1126
1153
 
1127
1154
  // write in "op" bytes (some encoding of position)
1128
1155
  let op_bytes = []
1129
1156
 
1130
- write_varint(op_bytes, (pos << 4) | (pos ? 2 : 0) | (ins ? 0 : 4))
1157
+ if (del) {
1158
+ if (pos == 0) {
1159
+ write_varint(op_bytes, 4)
1160
+ } else if (del == 1) {
1161
+ write_varint(op_bytes, pos * 16 + 6)
1162
+ } else {
1163
+ write_varint(op_bytes, del * 16 + 7)
1164
+ write_varint(op_bytes, pos * 2 + 2)
1165
+ }
1166
+ } else if (unicode_chars.length == 1) {
1167
+ if (pos == 0) write_varint(op_bytes, 0)
1168
+ else write_varint(op_bytes, pos * 16 + 2)
1169
+ } else if (pos == 0) {
1170
+ write_varint(op_bytes, unicode_chars.length * 8 + 1)
1171
+ } else {
1172
+ write_varint(op_bytes, unicode_chars.length * 8 + 3)
1173
+ write_varint(op_bytes, pos * 2)
1174
+ }
1131
1175
 
1132
1176
  patches.push(22)
1133
1177
  write_varint(patches, op_bytes.length)
1134
- patches.push(...op_bytes)
1178
+ for (let b of op_bytes) patches.push(b)
1135
1179
 
1136
1180
  // write in parents
1137
1181
  let parents_bytes = []
1138
1182
 
1139
- write_varint(parents_bytes, 1)
1183
+ write_varint(parents_bytes, ins ? unicode_chars.length : del)
1140
1184
 
1141
1185
  if (parents.length) {
1142
1186
  for (let [i, [agent, seq]] of parents.entries()) {
@@ -1154,14 +1198,16 @@ function dt_create_bytes(version, parents, pos, ins) {
1154
1198
  // write in patches
1155
1199
  bytes.push(20)
1156
1200
  write_varint(bytes, patches.length)
1157
- bytes.push(...patches)
1201
+ for (let b of patches) bytes.push(b)
1158
1202
 
1159
1203
  // console.log(bytes);
1160
1204
  return bytes
1161
1205
  }
1162
1206
 
1163
1207
  function defrag_dt(doc) {
1164
- return Doc.fromBytes(doc.toBytes(), 'server')
1208
+ let bytes = doc.toBytes()
1209
+ doc.free()
1210
+ return Doc.fromBytes(bytes, 'server')
1165
1211
  }
1166
1212
 
1167
1213
  function OpLog_remote_to_local(doc, frontier) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-text",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Library for collaborative text over http using braid.",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braidjs",
package/test.js CHANGED
@@ -1,9 +1,19 @@
1
1
 
2
2
  let { Doc } = require("diamond-types-node")
3
- let {dt_get, dt_get_patches, dt_parse, dt_create_bytes} = require('./index.js')
3
+ let braid_text = require('./index.js')
4
+ let {dt_get, dt_get_patches, dt_parse, dt_create_bytes} = braid_text
5
+
6
+ process.on("unhandledRejection", (x) =>
7
+ console.log(`unhandledRejection: ${x.stack}`)
8
+ )
9
+ process.on("uncaughtException", (x) =>
10
+ console.log(`uncaughtException: ${x.stack}`)
11
+ )
12
+
13
+ braid_text.db_folder = null
4
14
 
5
15
  async function main() {
6
- let best_seed = 0
16
+ let best_seed = NaN
7
17
  let best_n = Infinity
8
18
  let base = Math.floor(Math.random() * 10000000)
9
19
 
@@ -11,89 +21,89 @@ async function main() {
11
21
  console.log = () => {}
12
22
  for (let t = 0; t < 10000; t++) {
13
23
  let seed = base + t
14
- // for (let t = 0; t < 10; t++) {
15
- // let seed = 1188661 + t
24
+ // for (let t = 0; t < 1; t++) {
25
+ // let seed = 7572861
16
26
 
17
27
  og_log(`t = ${t}, seed = ${seed}, best_n = ${best_n} @ ${best_seed}`)
18
28
  Math.randomSeed(seed)
19
29
 
20
- let n = Math.floor(Math.random() * 15)
30
+ let n = Math.floor(Math.random() * 15) + 5
21
31
  console.log(`n = ${n}`)
22
32
 
23
33
  try {
24
- // 1. create a bunch of edits to a dt
34
+ // create a bunch of edits called doc,
35
+ // and remember a point along the way of adding all these edits,
36
+ // called middle_doc
25
37
  let doc = new Doc('server')
26
-
27
38
  let middle_doc = null
28
39
 
29
- if (!middle_doc && (Math.random() < 1/n || n == 0)) {
40
+ if (!middle_doc && (Math.random() < 1/n || n == 0))
30
41
  middle_doc = Doc.fromBytes(doc.toBytes())
31
- }
32
42
  for (let i = 0; i < n; i++) {
33
- make_random_edit(doc)
43
+ console.log(`edit ${i}`)
34
44
 
35
- if (!middle_doc && (Math.random() < 1/n || i == n - 1)) {
45
+ make_random_edit(doc)
46
+ if (!middle_doc && (Math.random() < 1/n || i == n - 1))
36
47
  middle_doc = Doc.fromBytes(doc.toBytes())
37
- }
38
- }
39
- if (!middle_doc) throw 'bad'
40
-
41
- // 2. let x = the resulting string
42
- let x = doc.get()
43
- console.log('x = ' + x)
44
-
45
- // // 3. use the code for sending these edits over the wire to create a new dt
46
- let updates = dt_get_patches(doc)
47
- console.log(updates)
48
-
49
- let new_doc = new Doc('server')
50
- apply_updates(new_doc, updates)
51
- let y = new_doc.get()
52
- console.log('y = ' + y)
53
-
54
- // 4. is the resulting string == x?
55
- console.log(x == y)
56
- if (x != y && n < best_n) {
57
- best_n = n
58
- best_seed = seed
59
- }
60
-
61
- // 5. test dt_get
62
- let middle_v = middle_doc.getRemoteVersion().map(x => x.join('-'))
63
- let new_middle_doc = dt_get(doc, middle_v)
64
- console.log('new_middle_doc = ' + new_middle_doc.get())
65
- if (middle_doc.get() != new_middle_doc.get() && n < best_n) {
66
- best_n = n
67
- best_seed = seed
68
48
  }
69
-
70
- // 6. test dt_get_patches(doc, version)
71
- if (true) {
72
- let updates = dt_get_patches(doc, middle_v)
73
- console.log(`updates:`, updates)
74
-
75
- apply_updates(middle_doc, updates)
76
- console.log(`middle_doc2:${middle_doc.get()}`)
77
- if (middle_doc.get() != doc.get() && n < best_n) {
78
- best_n = n
79
- best_seed = seed
49
+ if (!middle_doc) throw new Error('bad')
50
+
51
+ // put them into braid-text
52
+ let dt_to_braid = async (doc, key) => {
53
+ await braid_text.get(key, {})
54
+ for (let x of dt_get_patches(doc)) {
55
+ console.log(`x = `, x)
56
+ let y = {
57
+ merge_type: 'dt',
58
+ version: [x.version],
59
+ parents: x.parents,
60
+ patches: [{
61
+ unit: x.unit,
62
+ range: x.range,
63
+ content: x.content
64
+ }]
65
+ }
66
+ await braid_text.put(key, y)
67
+ y.validate_already_seen_versions = true
68
+ await braid_text.put(key, y)
80
69
  }
81
70
  }
82
-
83
- // 7. try applying a patch that's out of range..
84
- // if (true) {
85
- // let agent = Math.random().toString(36).slice(2)
86
- // let parents = doc.getRemoteVersion().map(x => x.join('-'))
87
- // let len = doc.len()
88
- // let args = [`${agent}-0`, parents, len + 1, 'c']
89
- // console.log('ARGS:', args)
90
- // try {
91
- // doc.mergeBytes(dt_create_bytes(...args))
92
- // } catch (e) {
93
- // console.log(`EEEE = ${e}`)
94
- // }
95
- // console.log('did that..')
96
- // }
71
+ await dt_to_braid(doc, 'doc')
72
+ await dt_to_braid(middle_doc, 'middle_doc')
73
+ console.log(`doc dt = ${doc.get()}`)
74
+ console.log(`middle_doc dt = ${middle_doc.get()}`)
75
+ console.log(`doc = ${await braid_text.get('doc')}`)
76
+ console.log(`middle_doc = ${await braid_text.get('middle_doc')}`)
77
+
78
+ // ensure they look right
79
+ if (doc.get() != await braid_text.get('doc')) throw new Error('bad')
80
+ if (middle_doc.get() != await braid_text.get('middle_doc')) throw new Error('bad')
81
+
82
+ // test getting old version
83
+ let middle_v = middle_doc.getRemoteVersion().map(x => x.join('-'))
84
+ console.log(`middle_doc = ${await braid_text.get('middle_doc')}`)
85
+ console.log(`middle_v = `, middle_v)
86
+
87
+ let doc_v = doc.getRemoteVersion().map(x => x.join('-'))
88
+ console.log(`doc_v = `, doc_v)
89
+
90
+ console.log(`doc = `, await braid_text.get('doc', {version: middle_v}))
91
+ if (await braid_text.get('middle_doc') != (await braid_text.get('doc', {version: middle_v})).body) throw new Error('bad')
92
+
93
+ // try getting updates from middle_doc to doc
94
+ let o = {merge_type: 'dt', parents: middle_v, subscribe: update => {
95
+ braid_text.put('middle_doc', update)
96
+ }}
97
+ await braid_text.get('doc', o)
98
+ await braid_text.forget('doc', o)
99
+
100
+ if (await braid_text.get('middle_doc') != await braid_text.get('doc')) throw new Error('bad')
101
+
102
+ doc.free()
103
+ middle_doc.free()
104
+ for (let p of Object.values(braid_text.cache))
105
+ (await p).doc.free()
106
+ braid_text.cache = {}
97
107
  } catch (e) {
98
108
  if (console.log == og_log) throw e
99
109
  if (n < best_n) {
@@ -132,74 +142,30 @@ function make_random_edit(doc) {
132
142
  let len = parent_doc.len()
133
143
  console.log(`len = ${len}`)
134
144
 
145
+ parent_doc.free()
146
+
135
147
  if (len && Math.random() > 0.5) {
136
148
  // delete
137
149
  let start = Math.floor(Math.random() * len)
138
150
  let del_len = Math.floor(Math.random() * (len - start - 1)) + 1
139
151
 
140
- for (let i = 0; i < del_len; i++) {
141
- let v = `${agent}-${base_seq++}`
142
- let args = [v, parents, start + del_len - 1 - i, null]
143
- console.log(args)
144
- doc.mergeBytes(dt_create_bytes(...args))
145
- parents = [v]
146
- }
152
+ let args = [`${agent}-${base_seq}`, parents, start, del_len, null]
153
+ console.log(args)
154
+ doc.mergeBytes(dt_create_bytes(...args))
147
155
  } else {
148
156
  // insert
149
157
  let start = Math.floor(Math.random() * (len + 1))
150
- let ins_len = Math.floor(Math.random() * 10) + 1
151
-
152
- for (let i = 0; i < ins_len; i++) {
153
- let v = `${agent}-${base_seq++}`
154
- let args = [v, parents, start++, getRandomCharacter()]
155
- console.log(args)
156
- doc.mergeBytes(dt_create_bytes(...args))
157
- parents = [v]
158
- }
158
+ let ins = Array(Math.floor(Math.random() * 10) + 1).fill(0).map(() => getRandomCharacter()).join('')
159
+
160
+ let args = [`${agent}-${base_seq}`, parents, start, 0, ins]
161
+ console.log(args)
162
+ doc.mergeBytes(dt_create_bytes(...args))
159
163
  }
160
164
 
161
165
  // work here
162
166
  console.log(`doc => ${doc.get()}`)
163
167
  }
164
168
 
165
- function apply_updates(doc, updates) {
166
- for (let u of updates) {
167
- u.range = u.range.match(/\d+/g).map((x) => parseInt(x))
168
- u.content = [...u.content]
169
-
170
- let v = u.version
171
- let ps = u.parents
172
-
173
- console.log('UPDATE:', u)
174
-
175
- // delete
176
- for (let i = u.range[1] - 1; i >= u.range[0]; i--) {
177
-
178
- // work here
179
- let args = [v, ps, i, null]
180
- console.log(`args`, args)
181
-
182
- doc.mergeBytes(dt_create_bytes(...args))
183
- ps = [v]
184
- v = decode_version(v)
185
- v = `${v[0]}-${v[1] + 1}`
186
- }
187
- // insert
188
- for (let i = 0; i < u.content?.length ?? 0; i++) {
189
- let c = u.content[i]
190
-
191
- // work here
192
- let args = [v, ps, u.range[0] + i, c]
193
- console.log(`args`, args)
194
-
195
- doc.mergeBytes(dt_create_bytes(...args))
196
- ps = [v]
197
- v = decode_version(v)
198
- v = `${v[0]}-${v[1] + 1}`
199
- }
200
- }
201
- }
202
-
203
169
  //////////////////////////////////////////////////////////////////
204
170
  //////////////////////////////////////////////////////////////////
205
171
  //////////////////////////////////////////////////////////////////