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.
- package/index.js +87 -41
- package/package.json +1 -1
- 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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
418
|
+
for (let i = 0; i < p.content_codepoints?.length ?? 0; i++) {
|
|
405
419
|
let vv = decode_version(v)
|
|
406
|
-
let c = p.
|
|
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.
|
|
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
|
-
|
|
438
|
-
|
|
439
|
-
offset
|
|
440
|
-
|
|
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
|
-
|
|
456
|
+
ps = [`${v[0]}-${v[1] + (del - 1)}`]
|
|
457
|
+
v = `${v[0]}-${v[1] + del}`
|
|
443
458
|
}
|
|
444
459
|
// insert
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
-
|
|
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]
|
|
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]
|
|
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
|
|
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
|
-
|
|
1105
|
-
|
|
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(
|
|
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,
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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,
|
|
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(
|
|
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
|
-
|
|
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
package/test.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
|
|
2
2
|
let { Doc } = require("diamond-types-node")
|
|
3
|
-
let
|
|
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 =
|
|
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 <
|
|
15
|
-
// let seed =
|
|
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
|
-
//
|
|
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
|
-
|
|
43
|
+
console.log(`edit ${i}`)
|
|
34
44
|
|
|
35
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
//
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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
|
//////////////////////////////////////////////////////////////////
|