braid-text 0.2.43 → 0.2.45

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 +54 -25
  2. package/package.json +1 -1
  3. package/test/test.html +80 -0
package/index.js CHANGED
@@ -122,6 +122,7 @@ braid_text.serve = async (req, res, options = {}) => {
122
122
  } else {
123
123
  if (!res.hasHeader("editable")) res.setHeader("Editable", "true")
124
124
  res.setHeader("Merge-Type", merge_type)
125
+ res.setHeader("Current-Version", get_current_version())
125
126
  if (req.method == "HEAD") return my_end(200)
126
127
 
127
128
  let options = {
@@ -290,11 +291,6 @@ braid_text.get = async (key, options) => {
290
291
  options.my_last_sent_version = x.version
291
292
  resource.simpleton_clients.add(options)
292
293
  } else {
293
- if (resource.need_defrag) {
294
- if (braid_text.verbose) console.log(`doing defrag..`)
295
- resource.need_defrag = false
296
- resource.doc = defrag_dt(resource.doc)
297
- }
298
294
 
299
295
  if (options.accept_encoding?.match(/updates\s*\((.*)\)/)?.[1].split(',').map(x=>x.trim()).includes('dt')) {
300
296
  var bytes = resource.doc.toBytes()
@@ -525,8 +521,6 @@ braid_text.put = async (key, options) => {
525
521
  for (let b of bytes) resource.doc.mergeBytes(b)
526
522
  resource.val = resource.doc.get()
527
523
 
528
- resource.need_defrag = true
529
-
530
524
  var post_commit_updates = []
531
525
 
532
526
  if (options.merge_type != "dt") {
@@ -673,17 +667,12 @@ async function get_resource(key) {
673
667
 
674
668
  resource.db_delta = change
675
669
 
676
- resource.doc = defrag_dt(resource.doc)
677
- resource.need_defrag = false
678
-
679
670
  resource.actor_seqs = {}
680
671
 
681
- let max_version = resource.doc.getLocalVersion().reduce((a, b) => Math.max(a, b), -1)
682
- for (let i = 0; i <= max_version; i++) {
683
- let v = resource.doc.localToRemoteVersion([i])[0]
684
- if (!resource.actor_seqs[v[0]]) resource.actor_seqs[v[0]] = new RangeSet()
685
- resource.actor_seqs[v[0]].add_range(v[1], v[1])
686
- }
672
+ dt_get_actor_seq_runs([...resource.doc.toBytes()], (actor, base, len) => {
673
+ if (!resource.actor_seqs[actor]) resource.actor_seqs[actor] = new RangeSet()
674
+ resource.actor_seqs[actor].add_range(base, base + len - 1)
675
+ })
687
676
 
688
677
  resource.val = resource.doc.get()
689
678
 
@@ -1068,16 +1057,19 @@ function dt_get(doc, version, agent = null, anti_version = null) {
1068
1057
  }
1069
1058
 
1070
1059
  function dt_get_patches(doc, version = null) {
1060
+ if (version && v_eq(version,
1061
+ doc.getRemoteVersion().map((x) => x.join("-")).sort())) {
1062
+ // they want everything past the end, which is nothing
1063
+ return []
1064
+ }
1065
+
1071
1066
  let bytes = doc.toBytes()
1072
1067
  doc = Doc.fromBytes(bytes)
1073
1068
 
1074
1069
  let [_agents, versions, parentss] = dt_parse([...bytes])
1075
1070
 
1076
1071
  let op_runs = []
1077
- if (version && v_eq(version,
1078
- doc.getRemoteVersion().map((x) => x.join("-")).sort())) {
1079
- // they want everything past the end, which is nothing
1080
- } else if (version?.length) {
1072
+ if (version?.length) {
1081
1073
  let frontier = {}
1082
1074
  version.forEach((x) => frontier[x] = true)
1083
1075
  let local_version = []
@@ -1222,6 +1214,48 @@ function dt_parse(byte_array) {
1222
1214
  return [agents, versions, parentss]
1223
1215
  }
1224
1216
 
1217
+ function dt_get_actor_seq_runs(byte_array, cb) {
1218
+ if (new TextDecoder().decode(new Uint8Array(byte_array.splice(0, 8))) !== "DMNDTYPS") throw new Error("dt parse error, expected DMNDTYPS")
1219
+
1220
+ if (byte_array.shift() != 0) throw new Error("dt parse error, expected version 0")
1221
+
1222
+ let agents = []
1223
+
1224
+ while (byte_array.length) {
1225
+ let id = byte_array.shift()
1226
+ let len = dt_read_varint(byte_array)
1227
+ if (id == 1) {
1228
+ } else if (id == 3) {
1229
+ let goal = byte_array.length - len
1230
+ while (byte_array.length > goal) {
1231
+ agents.push(dt_read_string(byte_array))
1232
+ }
1233
+ } else if (id == 20) {
1234
+ } else if (id == 21) {
1235
+ let seqs = {}
1236
+ let goal = byte_array.length - len
1237
+ while (byte_array.length > goal) {
1238
+ let part0 = dt_read_varint(byte_array)
1239
+ let has_jump = part0 & 1
1240
+ let agent_i = (part0 >> 1) - 1
1241
+ let run_length = dt_read_varint(byte_array)
1242
+ let jump = 0
1243
+ if (has_jump) {
1244
+ let part2 = dt_read_varint(byte_array)
1245
+ jump = part2 >> 1
1246
+ if (part2 & 1) jump *= -1
1247
+ }
1248
+ let base = (seqs[agent_i] || 0) + jump
1249
+
1250
+ cb(agents[agent_i], base, run_length)
1251
+ seqs[agent_i] = base + run_length
1252
+ }
1253
+ } else {
1254
+ byte_array.splice(0, len)
1255
+ }
1256
+ }
1257
+ }
1258
+
1225
1259
  function dt_get_local_version(bytes, version) {
1226
1260
  var looking_for = new Map()
1227
1261
  for (var event of version) {
@@ -1491,11 +1525,6 @@ function dt_create_bytes(version, parents, pos, del, ins) {
1491
1525
  return bytes
1492
1526
  }
1493
1527
 
1494
- function defrag_dt(doc) {
1495
- let bytes = doc.toBytes()
1496
- doc.free()
1497
- return Doc.fromBytes(bytes, 'server')
1498
- }
1499
1528
 
1500
1529
  function OpLog_remote_to_local(doc, frontier) {
1501
1530
  let map = Object.fromEntries(frontier.map((x) => [x, true]))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-text",
3
- "version": "0.2.43",
3
+ "version": "0.2.45",
4
4
  "description": "Library for collaborative text over http using braid.",
5
5
  "author": "Braid Working Group",
6
6
  "repository": "braid-org/braid-text",
package/test/test.html CHANGED
@@ -96,6 +96,65 @@ async function runTest(testName, testFunction, expectedResult) {
96
96
  }
97
97
  }
98
98
 
99
+ runTest(
100
+ "test loading a previously saved resource",
101
+ async () => {
102
+ var key = 'test-' + Math.random().toString(36).slice(2)
103
+
104
+ var f1 = await braid_fetch(`/${key}`, {
105
+ method: 'PUT',
106
+ version: ['hi-2'],
107
+ parents: [],
108
+ body: 'abc'
109
+ })
110
+
111
+ var f1 = await braid_fetch(`/eval`, {
112
+ method: 'PUT',
113
+ body: `
114
+ delete braid_text.cache['/${key}']
115
+ res.end()
116
+ `
117
+ })
118
+
119
+ var r = await braid_fetch(`/${key}`)
120
+ return await r.text()
121
+ },
122
+ 'abc'
123
+ )
124
+
125
+ runTest(
126
+ "test non-contigous ids",
127
+ async () => {
128
+ var key = 'test-' + Math.random().toString(36).slice(2)
129
+
130
+ var r = await braid_fetch(`/${key}`, {
131
+ method: 'PUT',
132
+ version: ['hi-10'],
133
+ parents: [],
134
+ body: 'abc'
135
+ })
136
+
137
+ var r = await braid_fetch(`/${key}`, {
138
+ method: 'PUT',
139
+ version: ['hi-20'],
140
+ parents: ['hi-10'],
141
+ body: 'ABC'
142
+ })
143
+
144
+ var f1 = await braid_fetch(`/eval`, {
145
+ method: 'PUT',
146
+ body: `
147
+ delete braid_text.cache['/${key}']
148
+ res.end()
149
+ `
150
+ })
151
+
152
+ var r = await braid_fetch(`/${key}`)
153
+ return await r.text()
154
+ },
155
+ 'ABC'
156
+ )
157
+
99
158
  runTest(
100
159
  "test when PUT cache/buffer size fails",
101
160
  async () => {
@@ -1024,4 +1083,25 @@ runTest(
1024
1083
  '"yo-1", "hi-5", "hi-8"'
1025
1084
  )
1026
1085
 
1086
+ runTest(
1087
+ "test that subscribe returns current-version header",
1088
+ async () => {
1089
+ var key = 'test-' + Math.random().toString(36).slice(2)
1090
+
1091
+ var r = await braid_fetch(`/${key}`, {
1092
+ method: 'PUT',
1093
+ version: ['hi-11'],
1094
+ parents: [],
1095
+ body: 'xyz'
1096
+ })
1097
+ if (!r.ok) throw 'got: ' + r.statusCode
1098
+
1099
+ var r = await braid_fetch(`/${key}`, {
1100
+ subscribe: true
1101
+ })
1102
+ return r.headers.get('current-version')
1103
+ },
1104
+ '"hi-11"'
1105
+ )
1106
+
1027
1107
  </script>