edytor 5.0.0 → 7.0.0
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/README.md +3 -3
- package/dist/cloudflare/DocumentRoom.d.ts +77 -2
- package/dist/cloudflare/DocumentRoom.js +37 -1
- package/dist/cloudflare/index.d.ts +1 -1
- package/dist/cloudflare/index.js +1 -1
- package/dist/cloudflare/room/access.d.ts +6 -1
- package/dist/cloudflare/room/access.js +30 -4
- package/dist/cloudflare/room/admission.d.ts +11 -0
- package/dist/cloudflare/room/admission.js +43 -10
- package/dist/cloudflare/room/context.d.ts +73 -76
- package/dist/cloudflare/room/context.js +17 -6
- package/dist/cloudflare/room/forged.d.ts +1 -1
- package/dist/cloudflare/room/forged.js +11 -9
- package/dist/cloudflare/room/frames.d.ts +2 -0
- package/dist/cloudflare/room/frames.js +2 -0
- package/dist/cloudflare/room/presence.js +1 -4
- package/dist/cloudflare/room/reseed.d.ts +93 -0
- package/dist/cloudflare/room/reseed.js +500 -0
- package/dist/cloudflare/room/scheduler.d.ts +1 -1
- package/dist/cloudflare/room/scheduler.js +9 -1
- package/dist/cloudflare/room/shared.d.ts +10 -0
- package/dist/cloudflare/room/shared.js +10 -0
- package/dist/cloudflare/room/storage.d.ts +7 -0
- package/dist/cloudflare/room/storage.js +33 -1
- package/dist/components/Edytor.svelte +18 -3
- package/dist/components/Edytor.svelte.d.ts +10 -1
- package/dist/components/EdytorRoot.svelte +17 -0
- package/dist/components/EdytorRoot.svelte.d.ts +4 -0
- package/dist/components/Suggestion.svelte +1 -1
- package/dist/crdt/attribution/block.d.ts +3 -0
- package/dist/crdt/attribution/block.js +3 -2
- package/dist/crdt/doc/history.js +2 -3
- package/dist/crdt/doc/ops.d.ts +81 -0
- package/dist/crdt/doc/ops.js +1898 -0
- package/dist/crdt/doc/suggest.d.ts +6 -2
- package/dist/crdt/doc/suggest.js +6 -5
- package/dist/crdt/edytor-doc.d.ts +157 -157
- package/dist/crdt/edytor-doc.js +15 -43
- package/dist/crdt/engine-room.d.ts +4 -0
- package/dist/crdt/engine-room.js +6 -0
- package/dist/crdt/flow.d.ts +4 -46
- package/dist/crdt/flow.js +2 -262
- package/dist/crdt/index.d.ts +64 -75
- package/dist/crdt/operations.d.ts +1 -1
- package/dist/crdt/placement/resolve.d.ts +1 -1
- package/dist/crdt/protocol.d.ts +2 -2
- package/dist/crdt/protocol.js +2 -2
- package/dist/crdt/protocols/auth.d.ts +8 -1
- package/dist/crdt/protocols/auth.js +14 -1
- package/dist/crdt/protocols/awareness.js +46 -81
- package/dist/crdt/providers/index.d.ts +11 -22
- package/dist/crdt/providers/index.js +22 -3
- package/dist/crdt/providers/indexeddb.d.ts +6 -10
- package/dist/crdt/providers/indexeddb.js +10 -16
- package/dist/crdt/providers/room.d.ts +26 -0
- package/dist/crdt/providers/room.js +41 -12
- package/dist/crdt/providers/websocket.d.ts +10 -14
- package/dist/crdt/providers/websocket.js +43 -23
- package/dist/crdt/rangeDelete.d.ts +2 -47
- package/dist/crdt/rangeDelete.js +1 -169
- package/dist/crdt/reseed.d.ts +127 -0
- package/dist/crdt/reseed.js +533 -0
- package/dist/crdt/restore.d.ts +13 -1
- package/dist/crdt/restore.js +8 -3
- package/dist/crdt/schema.d.ts +6 -0
- package/dist/crdt/schema.js +6 -0
- package/dist/crdt/structs.d.ts +8 -11
- package/dist/crdt/structs.js +25 -44
- package/dist/crdt/text/index/build.d.ts +119 -0
- package/dist/crdt/text/index/build.js +2801 -0
- package/dist/crdt/text/index/shared.d.ts +2 -6
- package/dist/crdt/text/index/shared.js +2 -5
- package/dist/crdt/text/model.js +2 -3
- package/dist/crdt/text/runs.d.ts +9 -12
- package/dist/crdt/text/runs.js +2 -165
- package/dist/crdt/vendor/yjs/UPSTREAM.md +101 -5
- package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
- package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +10 -10
- package/dist/crdt/vendor/yjs/dts/utils/encoding.d.ts +1 -0
- package/dist/crdt/vendor/yjs/src/index.js +1 -1
- package/dist/crdt/vendor/yjs/src/structs/Item.js +24 -13
- package/dist/crdt/vendor/yjs/src/utils/Transaction.js +12 -10
- package/dist/crdt/vendor/yjs/src/utils/encoding.js +42 -1
- package/dist/events/domTextOffset.d.ts +2 -0
- package/dist/events/domTextOffset.js +8 -0
- package/dist/export/forms.d.ts +50 -50
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/plugins/richtext/RichTextPlugin.svelte +63 -61
- package/dist/plugins/richtext/richTextOperations.js +26 -32
- package/dist/selection/selection.svelte.d.ts +1 -1
- package/dist/selection/selection.svelte.js +87 -106
- package/dist/selection/selection.utils.js +5 -8
- package/dist/session/commands.js +49 -51
- package/dist/session/handles.js +3 -7
- package/dist/surface/attributes.d.ts +3 -3
- package/dist/surface/attributes.js +2 -2
- package/dist/surface/observer.svelte.d.ts +7 -7
- package/dist/surface/observer.svelte.js +225 -336
- package/dist/surface/projector.svelte.js +2 -2
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +7 -0
- package/package.json +1 -1
- package/dist/crdt/doc/capability.d.ts +0 -56
- package/dist/crdt/doc/capability.js +0 -207
- package/dist/crdt/doc/content.d.ts +0 -16
- package/dist/crdt/doc/content.js +0 -77
- package/dist/crdt/doc/delete.d.ts +0 -15
- package/dist/crdt/doc/delete.js +0 -84
- package/dist/crdt/doc/layout.d.ts +0 -9
- package/dist/crdt/doc/layout.js +0 -178
- package/dist/crdt/doc/meta.d.ts +0 -19
- package/dist/crdt/doc/meta.js +0 -198
- package/dist/crdt/doc/moves.d.ts +0 -21
- package/dist/crdt/doc/moves.js +0 -274
- package/dist/crdt/doc/split-merge.d.ts +0 -10
- package/dist/crdt/doc/split-merge.js +0 -179
- package/dist/crdt/doc/steps.d.ts +0 -65
- package/dist/crdt/doc/steps.js +0 -311
- package/dist/crdt/text/index/cache.d.ts +0 -16
- package/dist/crdt/text/index/cache.js +0 -175
- package/dist/crdt/text/index/claims.d.ts +0 -18
- package/dist/crdt/text/index/claims.js +0 -203
- package/dist/crdt/text/index/fold.d.ts +0 -21
- package/dist/crdt/text/index/fold.js +0 -656
- package/dist/crdt/text/index/layout.d.ts +0 -22
- package/dist/crdt/text/index/layout.js +0 -258
- package/dist/crdt/text/index/placement.d.ts +0 -47
- package/dist/crdt/text/index/placement.js +0 -738
- package/dist/crdt/text/index/records.d.ts +0 -13
- package/dist/crdt/text/index/records.js +0 -139
- package/dist/crdt/text/index/report.d.ts +0 -18
- package/dist/crdt/text/index/report.js +0 -337
- package/dist/crdt/text/index/state.d.ts +0 -197
- package/dist/crdt/text/index/state.js +0 -116
- package/dist/crdt/text/index/streams.d.ts +0 -25
- package/dist/crdt/text/index/streams.js +0 -248
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { EngineNode } from '../../engine-api.js';
|
|
2
2
|
import type { BlockId, BlockRec } from '../../placement/model.js';
|
|
3
3
|
import type { ContentRun, DisplayRoles } from '../runs.js';
|
|
4
|
-
import type { SelfChecks } from './
|
|
4
|
+
import type { IndexFacts, SelfChecks } from './build.js';
|
|
5
5
|
/**
|
|
6
6
|
* The facet name of a block's registry entry itself (inserted or removed) —
|
|
7
7
|
* every other facet is named by the block attr it entered through.
|
|
@@ -65,12 +65,8 @@ export declare const sameShape: (roles: DisplayRoles, a: string, b: string) => b
|
|
|
65
65
|
*/
|
|
66
66
|
export declare const indexChecks: {
|
|
67
67
|
on: boolean;
|
|
68
|
-
of?: (
|
|
68
|
+
of?: (facts: IndexFacts) => SelfChecks;
|
|
69
69
|
};
|
|
70
|
-
/** `ix`'s checker ({@link indexChecks}), built on its first check. */
|
|
71
|
-
export declare const checksOf: (ix: {
|
|
72
|
-
checks: SelfChecks | null;
|
|
73
|
-
}) => SelfChecks;
|
|
74
70
|
/** Add `value` to `key`'s set in `index`. */
|
|
75
71
|
export declare const addTo: <K, V>(index: Map<K, Set<V>>, key: K, value: V) => void;
|
|
76
72
|
/** Remove `value` from `key`'s set in `index` (the set goes once empty). */
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { cloneJsonSafe } from '../../../utils/json.js';
|
|
7
7
|
import { CONTENT, DATA, DATA_LEAF_PREFIX, ID, LAST_CHANGED_ATTR, TYPE } from '../../schema.js';
|
|
8
|
+
import { getOr } from '../../../utils.js';
|
|
8
9
|
/**
|
|
9
10
|
* The facet name of a block's registry entry itself (inserted or removed) —
|
|
10
11
|
* every other facet is named by the block attr it entered through.
|
|
@@ -93,13 +94,9 @@ export const sameShape = (roles, a, b) => {
|
|
|
93
94
|
* difference; after every report, the published tree.
|
|
94
95
|
*/
|
|
95
96
|
export const indexChecks = { on: false };
|
|
96
|
-
/** `ix`'s checker ({@link indexChecks}), built on its first check. */
|
|
97
|
-
export const checksOf = (ix) => (ix.checks ??= indexChecks.of(ix));
|
|
98
97
|
/** Add `value` to `key`'s set in `index`. */
|
|
99
98
|
export const addTo = (index, key, value) => {
|
|
100
|
-
|
|
101
|
-
if (set === undefined)
|
|
102
|
-
index.set(key, (set = new Set()));
|
|
99
|
+
const set = getOr(index, key, () => new Set());
|
|
103
100
|
set.add(value);
|
|
104
101
|
};
|
|
105
102
|
/** Remove `value` from `key`'s set in `index` (the set goes once empty). */
|
package/dist/crdt/text/model.js
CHANGED
|
@@ -7,6 +7,7 @@ import { fitMarks, writeMarks } from './marks.js';
|
|
|
7
7
|
import { nodeStart } from './items.js';
|
|
8
8
|
import { readRange } from './ranges.js';
|
|
9
9
|
import { claimsIn, delimiters, displayOf, locate, ownedLength, pieces, placeText, rangesOf, removedKeys, scanText } from './streams.js';
|
|
10
|
+
import { getOr } from '../../utils.js';
|
|
10
11
|
export { isBoundary, isClaimItem, isRowMark, nodeStart } from './items.js';
|
|
11
12
|
export { canonKey, deepFreeze, inlineItemOf, protectItems, readRange } from './ranges.js';
|
|
12
13
|
export { byId, claimsIn, delimiters, displayOf, locate, ownedLength, pieces, placeText, removedKeys, scanText } from './streams.js';
|
|
@@ -107,9 +108,7 @@ export const readSegs = (segs, stats) => {
|
|
|
107
108
|
const out = [];
|
|
108
109
|
const cursors = new Map();
|
|
109
110
|
for (const seg of segs) {
|
|
110
|
-
|
|
111
|
-
if (cur === undefined)
|
|
112
|
-
cursors.set(seg.text, (cur = openRangeCursor(seg.text)));
|
|
111
|
+
const cur = getOr(cursors, seg.text, () => openRangeCursor(seg.text));
|
|
113
112
|
readRange(cur, seg.i0, seg.i1, stats, out);
|
|
114
113
|
}
|
|
115
114
|
return out;
|
package/dist/crdt/text/runs.d.ts
CHANGED
|
@@ -53,17 +53,16 @@
|
|
|
53
53
|
* advancing the published tree in place (after a whole rebuild, the
|
|
54
54
|
* reachable tree is compared).
|
|
55
55
|
*
|
|
56
|
-
* The index is
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* the
|
|
60
|
-
*
|
|
61
|
-
* cache (`cache.ts`), the fold (`fold.ts`), the change report
|
|
62
|
-
* (`report.ts`); the self-checks a test lane installs are `indexChecks`. This module declares the
|
|
63
|
-
* index's types and wires the parts into the doc's one index.
|
|
56
|
+
* The index is one closure (`index/build.ts`) over its state: the claim
|
|
57
|
+
* graph, the stream table and each block's claims, the layout rules,
|
|
58
|
+
* placements and the children index, block records, the run cache, the fold
|
|
59
|
+
* and the change report; the self-checks a test lane installs are
|
|
60
|
+
* `indexChecks`. This module declares the index's types.
|
|
64
61
|
*/
|
|
65
|
-
import type { EngineApi
|
|
62
|
+
import type { EngineApi } from '../engine-api.js';
|
|
66
63
|
import type { BlockId, ContentItem, ModelView, ProjectedBlock } from '../placement/model.js';
|
|
64
|
+
import { indexOf } from './index/build.js';
|
|
65
|
+
export { indexOf };
|
|
67
66
|
export { CONTENT_ATTR, ENTRY_FACET, SEQ_FACET, indexChecks } from './index/shared.js';
|
|
68
67
|
/**
|
|
69
68
|
* One visible run of a block — the maintained form of `ContentItem`.
|
|
@@ -257,9 +256,7 @@ export type DisplayRoles = {
|
|
|
257
256
|
of: (type: string | null) => KindRole;
|
|
258
257
|
declared: () => DeclaredKinds;
|
|
259
258
|
};
|
|
260
|
-
/** The doc's index — built on first use, torn down when the doc is destroyed. */
|
|
261
|
-
export declare const indexOf: (doc: EngineDoc) => RunView;
|
|
262
259
|
/** The index binding (the public binding's `runs`): {@link indexOf}. */
|
|
263
260
|
export declare const bindRuns: (_Y: EngineApi) => {
|
|
264
|
-
attach: (doc: EngineDoc) => RunView;
|
|
261
|
+
attach: (doc: import("../engine-api.js").EngineDoc) => RunView;
|
|
265
262
|
};
|
package/dist/crdt/text/runs.js
CHANGED
|
@@ -1,168 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { indexState } from './index/state.js';
|
|
4
|
-
import { indexClaims } from './index/claims.js';
|
|
5
|
-
import { indexStreams } from './index/streams.js';
|
|
6
|
-
import { indexLayout } from './index/layout.js';
|
|
7
|
-
import { indexPlacement } from './index/placement.js';
|
|
8
|
-
import { indexRecords } from './index/records.js';
|
|
9
|
-
import { indexCache } from './index/cache.js';
|
|
10
|
-
import { indexFold } from './index/fold.js';
|
|
11
|
-
import { indexReporter } from './index/report.js';
|
|
1
|
+
import { indexOf } from './index/build.js';
|
|
2
|
+
export { indexOf };
|
|
12
3
|
export { CONTENT_ATTR, ENTRY_FACET, SEQ_FACET, indexChecks } from './index/shared.js';
|
|
13
|
-
/** One index per engine doc, shared by every binding (the doc's lifetime). */
|
|
14
|
-
const indexes = new WeakMap();
|
|
15
|
-
/** The doc's index — built on first use, torn down when the doc is destroyed. */
|
|
16
|
-
export const indexOf = (doc) => {
|
|
17
|
-
let index = indexes.get(doc);
|
|
18
|
-
if (index === undefined)
|
|
19
|
-
indexes.set(doc, (index = buildView(doc)));
|
|
20
|
-
return index;
|
|
21
|
-
};
|
|
22
4
|
/** The index binding (the public binding's `runs`): {@link indexOf}. */
|
|
23
5
|
export const bindRuns = (_Y) => ({ attach: indexOf });
|
|
24
|
-
const buildView = (doc) => {
|
|
25
|
-
// The index's parts, each over the state and the parts before it (`index/*`).
|
|
26
|
-
const ix0 = indexState(doc);
|
|
27
|
-
const ix1 = Object.assign(ix0, indexClaims(ix0));
|
|
28
|
-
const ix2 = Object.assign(ix1, indexStreams(ix1));
|
|
29
|
-
const ix4 = Object.assign(ix2, indexLayout(ix2));
|
|
30
|
-
const ix5 = Object.assign(ix4, indexPlacement(ix4));
|
|
31
|
-
const ix6 = Object.assign(ix5, indexRecords(ix5));
|
|
32
|
-
const ix7 = Object.assign(ix6, indexCache(ix6));
|
|
33
|
-
const ix8 = Object.assign(ix7, indexFold(ix7));
|
|
34
|
-
const ix = Object.assign(ix8, indexReporter(ix8));
|
|
35
|
-
const { registry, blocks, rows, homeOfText, shells, placementsMap, frames, displays, ownShim, ensurePlacements, typeOf, order, rebuildTable, scanRow, applyReclaims, updateBlockRec, syncIncarnations, intern, debug, runs, settle, syncPending, syncAll, openTx, onCommit, committed, itemsOf, projectBlock, publish, onUpdate, onReport, hasSubscribers } = ix;
|
|
36
|
-
const ctx = {
|
|
37
|
-
blocks,
|
|
38
|
-
own: ownShim,
|
|
39
|
-
get placements() {
|
|
40
|
-
ensurePlacements();
|
|
41
|
-
return placementsMap;
|
|
42
|
-
},
|
|
43
|
-
get kids() {
|
|
44
|
-
ensurePlacements();
|
|
45
|
-
return ix.kidsMap;
|
|
46
|
-
},
|
|
47
|
-
get order() {
|
|
48
|
-
ensurePlacements();
|
|
49
|
-
return order();
|
|
50
|
-
},
|
|
51
|
-
// The publication boundary shares THIS interner, so a payload
|
|
52
|
-
// emitted by `project()`/`contentItems()` is `===` the runs' one.
|
|
53
|
-
intern,
|
|
54
|
-
displays,
|
|
55
|
-
accepted: (id) => {
|
|
56
|
-
ensurePlacements();
|
|
57
|
-
return ix.rejected.has(id) ? null : (ix.edges.get(id) ?? null);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
// ── initial scan: index every existing block ────────────────────
|
|
61
|
-
registry.forEachAttr((v, id) => {
|
|
62
|
-
if (!isNodeLike(v))
|
|
63
|
-
return;
|
|
64
|
-
updateBlockRec(id);
|
|
65
|
-
for (const b of [id, ...syncIncarnations(id)]) {
|
|
66
|
-
const row = scanRow(b);
|
|
67
|
-
if (row !== undefined) {
|
|
68
|
-
rows.set(b, row);
|
|
69
|
-
homeOfText.set(row.text, b);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
rebuildTable(new Set());
|
|
74
|
-
applyReclaims(null);
|
|
75
|
-
settle(shells, null);
|
|
76
|
-
// Every commit folds once, before the document's `afterTransaction` listeners.
|
|
77
|
-
doc.on('commit', onCommit);
|
|
78
|
-
/** Derived state lives exactly as long as the doc. */
|
|
79
|
-
const teardown = () => {
|
|
80
|
-
doc.off('commit', onCommit);
|
|
81
|
-
doc.off('destroy', teardown);
|
|
82
|
-
doc.off('update', onUpdate);
|
|
83
|
-
indexes.delete(doc);
|
|
84
|
-
};
|
|
85
|
-
doc.on('destroy', teardown);
|
|
86
|
-
// ── public surface ───────────────────────────────────────────────
|
|
87
|
-
const view = {
|
|
88
|
-
version: () => {
|
|
89
|
-
syncAll();
|
|
90
|
-
return ix.version;
|
|
91
|
-
},
|
|
92
|
-
runs,
|
|
93
|
-
contentItems: (b) => {
|
|
94
|
-
syncAll();
|
|
95
|
-
return blocks.get(b)?.deleted === false ? itemsOf(b) : [];
|
|
96
|
-
},
|
|
97
|
-
// Inline atoms always carry `data` (`{}` when absent) — the public
|
|
98
|
-
// `JSONInlineBlock` shape of `edytor.value`.
|
|
99
|
-
contentJSON: (b) => runs(b).map((r) => r.kind === 'text'
|
|
100
|
-
? { text: r.text, ...(r.marks !== undefined && { marks: cloneJsonSafe(r.marks) }) }
|
|
101
|
-
: { id: r.id, type: r.type, data: r.data === undefined ? {} : cloneJsonSafe(r.data) }),
|
|
102
|
-
view: (tr) => {
|
|
103
|
-
syncAll();
|
|
104
|
-
if (tr !== undefined && !committed.has(tr))
|
|
105
|
-
syncPending(tr);
|
|
106
|
-
return ctx;
|
|
107
|
-
},
|
|
108
|
-
displayType: (id) => {
|
|
109
|
-
if (ix.roles === null)
|
|
110
|
-
return undefined;
|
|
111
|
-
syncAll();
|
|
112
|
-
ensurePlacements();
|
|
113
|
-
const shown = blocks.has(id) ? typeOf(id) : undefined;
|
|
114
|
-
return shown === blocks.get(id)?.type ? undefined : shown;
|
|
115
|
-
},
|
|
116
|
-
dissolved: (id) => {
|
|
117
|
-
syncAll();
|
|
118
|
-
ensurePlacements();
|
|
119
|
-
return ix.dissolved.has(id);
|
|
120
|
-
},
|
|
121
|
-
project: (root) => {
|
|
122
|
-
syncAll();
|
|
123
|
-
ensurePlacements();
|
|
124
|
-
return root === undefined
|
|
125
|
-
? (ix.kidsMap.get(null) ?? []).map((k) => projectBlock(k.id))
|
|
126
|
-
: [projectBlock(root)];
|
|
127
|
-
},
|
|
128
|
-
roles: (next) => {
|
|
129
|
-
ix.roles = next;
|
|
130
|
-
ix.placementFull = true;
|
|
131
|
-
ix.version++;
|
|
132
|
-
// No commit carries a role change: report it now (not inside a
|
|
133
|
-
// transaction, whose commit reports it), so every view follows.
|
|
134
|
-
if (hasSubscribers() && !openTx())
|
|
135
|
-
publish(null, false);
|
|
136
|
-
},
|
|
137
|
-
track: () => {
|
|
138
|
-
syncAll();
|
|
139
|
-
const f = { touched: new Map(), wrote: false };
|
|
140
|
-
frames.add(f);
|
|
141
|
-
return {
|
|
142
|
-
end: () => {
|
|
143
|
-
syncAll();
|
|
144
|
-
frames.delete(f);
|
|
145
|
-
return f;
|
|
146
|
-
},
|
|
147
|
-
quiet: (write) => {
|
|
148
|
-
syncAll();
|
|
149
|
-
const g = { touched: new Map(), wrote: false };
|
|
150
|
-
frames.delete(f);
|
|
151
|
-
frames.add(g);
|
|
152
|
-
try {
|
|
153
|
-
write();
|
|
154
|
-
syncAll();
|
|
155
|
-
}
|
|
156
|
-
finally {
|
|
157
|
-
frames.delete(g);
|
|
158
|
-
frames.add(f);
|
|
159
|
-
f.wrote ||= g.wrote;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
},
|
|
164
|
-
onReport,
|
|
165
|
-
debug
|
|
166
|
-
};
|
|
167
|
-
return view;
|
|
168
|
-
};
|
|
@@ -33,7 +33,7 @@ is no longer a dependency of any kind: `tests/packed-consumer/smoke.js` and
|
|
|
33
33
|
## Layout
|
|
34
34
|
|
|
35
35
|
```text
|
|
36
|
-
src/ upstream src/, plus patches YP1 (import specifiers), YP4, YP5, YP7, YP8 (pruning), YP9–YP15, YP16 (no delta layer), YP17 (one update encoding), YP18 (no undo manager), YP19 (only what edytor calls), YP20 (hold records), YP21 (claim items), YP22 (move records), YP23 (a block set's trim), YP24 (a string table per update), YP25 (paired marks written in parts), YP26 (a client table per update), YP27 (the parent kind in the info byte), YP28 (large integers in content values), YP29 (a collected mark or claim keeps its class)
|
|
36
|
+
src/ upstream src/, plus patches YP1 (import specifiers), YP4, YP5, YP7, YP8 (pruning), YP9–YP15, YP16 (no delta layer), YP17 (one update encoding), YP18 (no undo manager), YP19 (only what edytor calls), YP20 (hold records), YP21 (claim items), YP22 (move records), YP23 (a block set's trim), YP24 (a string table per update), YP25 (paired marks written in parts), YP26 (a client table per update), YP27 (the parent kind in the info byte), YP28 (large integers in content values), YP29 (a collected mark or claim keeps its class), YP30 (a transaction's `beforeCommit`), YP31 (a hold inside a nested node holds nothing), YP32 (a delete that proposes), YP33 (one transaction log) and YP34 (an update read at an earlier state)
|
|
37
37
|
global.d.ts upstream global.d.ts, plus patches YP1, YP8 and YP19
|
|
38
38
|
dts/ generated TypeScript declarations (not upstream source — see below)
|
|
39
39
|
LICENSE upstream MIT license, verbatim
|
|
@@ -1022,7 +1022,8 @@ Patch (new code delimited by `// YP20 begin` / `// YP20 end`, edits marked `// Y
|
|
|
1022
1022
|
text a room lost is stored and acknowledged at once. A GC struct takes
|
|
1023
1023
|
nothing. An item that starts or stops being held (and is not removed)
|
|
1024
1024
|
moves its parent's length, drops its search markers, joins
|
|
1025
|
-
`transaction.changed` and is logged in `transaction.holds`
|
|
1025
|
+
`transaction.changed` and is logged in `transaction.holds` (since YP33:
|
|
1026
|
+
`transaction.log`, kind 1)
|
|
1026
1027
|
(`client, clock, ±len`, in order: the index's edits).
|
|
1027
1028
|
- **`YNode#delete(index, length, into, fresh)`**: with `into` (the records
|
|
1028
1029
|
list) the live units are held by one record appended there instead of
|
|
@@ -1038,7 +1039,8 @@ Edytor side: a text delete passes the records list (`crdt/text/model.ts`
|
|
|
1038
1039
|
copies the record (never the text), an undo of typing holds the typed text,
|
|
1039
1040
|
a dropped step removes what this writer's records of it hold
|
|
1040
1041
|
(`hist.delete-marks.release`); the purge removes what a record older than
|
|
1041
|
-
the horizon holds; the index folds `transaction.holds
|
|
1042
|
+
the horizon holds; the index folds `transaction.holds` (since YP33, the one
|
|
1043
|
+
`transaction.log`). Removed:
|
|
1042
1044
|
`bindCrdt(Y).doc.keepCopies`, `PurgeReport.records`, the restoration
|
|
1043
1045
|
records root, the engine object's `ContentAny`.
|
|
1044
1046
|
|
|
@@ -1172,7 +1174,8 @@ Patch (new code delimited by `// YP22 begin` / `// YP22 end`, edits marked `// Y
|
|
|
1172
1174
|
pending holds only. A
|
|
1173
1175
|
unit that starts or stops being moved (and is not gone) moves
|
|
1174
1176
|
its home sequence's length and drops its search markers; one whose mover
|
|
1175
|
-
changed is logged in `transaction.moves` (
|
|
1177
|
+
changed is logged in `transaction.moves` (since YP33: `transaction.log`,
|
|
1178
|
+
kind 2; `client, clock, len`, in
|
|
1176
1179
|
order), and its home and its new mover's sequences are marked changed.
|
|
1177
1180
|
- **`doc._clock`** (was YP13's `_markClock`): the greatest Lamport
|
|
1178
1181
|
timestamp of a mark or a move this document integrated; a local mark or
|
|
@@ -1537,7 +1540,7 @@ Patch (new code delimited by `// YP31 begin` / `// YP31 end`, edits marked `// Y
|
|
|
1537
1540
|
records list, `textdel`). `ContentHold#integrate` and `ContentHold#delete`
|
|
1538
1541
|
hold and release only then; inside a nested node's sequence the record is
|
|
1539
1542
|
a list of ids: it moves no length, waits in no `pendingHolds`, logs
|
|
1540
|
-
nothing in `transaction.holds
|
|
1543
|
+
nothing in `transaction.holds` (YP33: `transaction.log`), and its delete (an undo, a reviewer's
|
|
1541
1544
|
withdrawal, its node's delete) releases nothing. `YNode#hold(ids)` on a
|
|
1542
1545
|
nested node appends one such list entry.
|
|
1543
1546
|
|
|
@@ -1598,6 +1601,99 @@ schedules with the index's self-checks on), `suggesting-input.test.tsx`
|
|
|
1598
1601
|
(typing over a selection, a paste, Backspace and Delete over struck text),
|
|
1599
1602
|
the YP20 rows, the upstream suite unchanged.
|
|
1600
1603
|
|
|
1604
|
+
### YP33 — one log of what a transaction did to items (`src/utils/Transaction.js`, `src/structs/Item.js`)
|
|
1605
|
+
|
|
1606
|
+
Reason: edytor's index folds each transaction into its derived facts (rows,
|
|
1607
|
+
streams, slots, placements) once at commit and, for read-your-writes, over
|
|
1608
|
+
the part of an open transaction a read has not folded. The engine logged
|
|
1609
|
+
the holds (YP20, `transaction.holds`) and the mover changes (YP22,
|
|
1610
|
+
`transaction.moves`) in order, but the inserts and removals only as id sets,
|
|
1611
|
+
so the fold reconstructed them: it kept, per open transaction, copies of the
|
|
1612
|
+
insert and delete sets and diffed them at every read, walked both sets'
|
|
1613
|
+
structs again for the texts and again for the sequences, and decided by set
|
|
1614
|
+
membership which edits cancelled within a fold (about 1.6 KB minified in
|
|
1615
|
+
every app, `makeEditIndex` and `syncPending` in `crdt/text/index/build.ts`).
|
|
1616
|
+
The engine now logs the edits in the same log as the holds and the moves,
|
|
1617
|
+
and the fold reads one log from a cursor. In memory only: nothing encoded,
|
|
1618
|
+
no schema change.
|
|
1619
|
+
|
|
1620
|
+
Patch (new code delimited by `// YP33 begin` / `// YP33 end`, edits marked `// YP33`):
|
|
1621
|
+
|
|
1622
|
+
- **`transaction.log`** (replaces YP20's `holds` and YP22's `moves`): per
|
|
1623
|
+
run of one writer's items `kind, client, clock, len`, in the order the
|
|
1624
|
+
transaction did them; an item that continues the last entry (its kind,
|
|
1625
|
+
its client, the next clock, its sign) extends it, so a bulk insert or
|
|
1626
|
+
delete is a few entries, as the id sets' ranges were. Kind 0, an edit:
|
|
1627
|
+
`Item#integrate` logs `+length` before its content integrates (a node's
|
|
1628
|
+
children follow it; nothing for an item integrated removed, a
|
|
1629
|
+
`ContentDeleted`), `Item#delete` `-length`; kind 1,
|
|
1630
|
+
a hold record's change of visibility (YP20's entries, unchanged: a held
|
|
1631
|
+
item removed logs its give-back, so an item's kinds 0 and 1 sum to its
|
|
1632
|
+
visibility change); kind 2, a mover change (YP22's entries, unchanged).
|
|
1633
|
+
- **`logItem(tr, kind, item, len, mark)`** (`Item.js`): the one writer (it
|
|
1634
|
+
extends a run's entry), which also marks the parent changed (it replaces
|
|
1635
|
+
`logHold` and `Item#delete`'s `addChangedTypeToTransaction`; `logMove`
|
|
1636
|
+
calls it). `Item#integrate` logs with `mark` false and keeps its own
|
|
1637
|
+
mark, after its content, so `transaction.changed` keeps its order.
|
|
1638
|
+
|
|
1639
|
+
The insert and delete sets, `transaction.changed` and every upstream path
|
|
1640
|
+
are untouched: the log is a list the engine appends to and never reads.
|
|
1641
|
+
|
|
1642
|
+
Edytor side: the fold keeps one number per open transaction (the length of
|
|
1643
|
+
its log a read folded and that entry's last length then, so the units the
|
|
1644
|
+
engine added to it since are folded too), reads each entry's structs once
|
|
1645
|
+
(`walkRange`, the walk `walkIdSet` now runs per range) and replays the units each item showed
|
|
1646
|
+
or hid in order, so an edit made and undone within one fold moves the row
|
|
1647
|
+
by nothing; the sequences read kind 0 as their slots and records written and
|
|
1648
|
+
removed, kind 2 as their units whose mover changed. Removed: the copied and
|
|
1649
|
+
diffed id sets, the watermark, the second and third walks, the membership
|
|
1650
|
+
tests, the incomplete-walk fallback.
|
|
1651
|
+
|
|
1652
|
+
Measured (`scripts/bundle-size.mjs`, own minified): minimal 425,374 →
|
|
1653
|
+
424,034 (−1,340 B; gzip −290), every plugin 675,230 → 673,890 (−1,340),
|
|
1654
|
+
`edytor/export` unchanged; the engine's share +106 B (one log writer, which
|
|
1655
|
+
extends a run's entry). A first version logged one entry per item: the
|
|
1656
|
+
fold walked them one by one where the id sets gave it ranges, and a 5,000
|
|
1657
|
+
block construction and a 40-block range delete got slower (`bench/scale.js`);
|
|
1658
|
+
the runs bring both back.
|
|
1659
|
+
|
|
1660
|
+
Oracle: `src/tests/crdt/yp33-log.test.ts` (edits, holds and a removed held
|
|
1661
|
+
item's give-back, a move, a remote update with an item integrated removed),
|
|
1662
|
+
the YP20, YP22 and YP31 rows reading their entries of the log, the index's
|
|
1663
|
+
self-checks after every fold (they rebuild from the replicated state and
|
|
1664
|
+
never read the log), the fold's counters (`foldedStructs`, the scale rows),
|
|
1665
|
+
the random corpus, the upstream suite unchanged.
|
|
1666
|
+
|
|
1667
|
+
### YP34 — an update read at an earlier state (`src/utils/encoding.js`, `src/index.js`)
|
|
1668
|
+
|
|
1669
|
+
Reason: a re-seed's rebase (`room.reseed.rebase`, `crdt/reseed.ts`) gets an
|
|
1670
|
+
offline client's whole old document and must split it into the part the
|
|
1671
|
+
room held at the cut (the client's base) and the rest (its unsaved edits).
|
|
1672
|
+
`diffUpdate(update, sv)` gives the rest; nothing gave the base, and edytor
|
|
1673
|
+
has no access to the lazy struct reader and writer it would need (they are
|
|
1674
|
+
not exported). The engine now gives the counterpart. Encoding unchanged, no
|
|
1675
|
+
schema change.
|
|
1676
|
+
|
|
1677
|
+
Patch (new code delimited by `// YP34 begin` / `// YP34 end`, edits marked `// YP34`):
|
|
1678
|
+
|
|
1679
|
+
- **`clipUpdate(update, sv, ds)`**: the structs of `update` under the state
|
|
1680
|
+
vector `sv` (a struct that crosses it is cut there, through the content's
|
|
1681
|
+
`offsetEnd`; a skip is written only where a later struct of its client
|
|
1682
|
+
follows it), and the deletes of `update` that the id set `ds` also holds
|
|
1683
|
+
(`intersectSets`). Exported from `src/index.js`, not from edytor's engine
|
|
1684
|
+
object (`crdt/engine.js`): only the room calls it, so apps keep none of it.
|
|
1685
|
+
|
|
1686
|
+
Deleted content a document collected cannot come back (a collecting
|
|
1687
|
+
document writes it as deleted); edytor's text deletes are hold records
|
|
1688
|
+
(YP20), which keep it.
|
|
1689
|
+
|
|
1690
|
+
Measured: vendored execution lines +30; the app bundle unchanged (the
|
|
1691
|
+
engine object does not hold it).
|
|
1692
|
+
|
|
1693
|
+
Oracle: `src/tests/crdt/yp34-clip.test.ts` (an update read at an earlier
|
|
1694
|
+
state, its later deletes left out; a run cut at the state vector), the
|
|
1695
|
+
re-seed rows (`src/tests/crdt/reseed/`), the upstream suite unchanged.
|
|
1696
|
+
|
|
1601
1697
|
## Generated declarations (`dts/`)
|
|
1602
1698
|
|
|
1603
1699
|
`svelte-package` copies JS verbatim but emits no `.d.ts` for JS inputs, so
|
|
@@ -11,7 +11,7 @@ export { GC } from "./structs/GC.js";
|
|
|
11
11
|
export { Skip } from "./structs/Skip.js";
|
|
12
12
|
export type ContentIds = import("./utils/ids.js").ContentIds;
|
|
13
13
|
export { IdSet, createDeleteSetFromStructStore, diffIdSet, createIdSet, mergeIdSets, insertIntoIdSet, iterateStructsByIdSet, readIdSet, writeIdSet, intersectSets } from "./utils/ids.js";
|
|
14
|
-
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, mergeUpdates } from "./utils/encoding.js";
|
|
14
|
+
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, clipUpdate, mergeUpdates } from "./utils/encoding.js";
|
|
15
15
|
export { ID, createID, compareIDs, findRootTypeKey } from "./utils/ID.js";
|
|
16
16
|
export { idAtIndex, indexOfId } from "./utils/positions.js";
|
|
17
17
|
export { findIndexSS, getItemCleanStart, getItemCleanEnd, isKeptReplaced } from "./utils/transaction-helpers.js";
|
|
@@ -31,18 +31,18 @@ export class Transaction {
|
|
|
31
31
|
*/
|
|
32
32
|
insertSet: import("./ids.js").IdSet;
|
|
33
33
|
/**
|
|
34
|
-
*
|
|
35
|
-
* `client, clock, len` (
|
|
36
|
-
*
|
|
34
|
+
* What the transaction did to items, in order: per run of one writer's
|
|
35
|
+
* items `kind, client, clock, len` (an item that continues the last entry
|
|
36
|
+
* extends it). Kind 0, an edit: integrated (`len > 0`, before its content
|
|
37
|
+
* integrates; an item integrated removed logs none) or removed (`len < 0`);
|
|
38
|
+
* kind 1, a hold record's
|
|
39
|
+
* (YP20): shown (`len > 0`) or hidden (`< 0`; an item removed while held
|
|
40
|
+
* is logged shown, so an item's kinds 0 and 1 sum to its visibility
|
|
41
|
+
* change); kind 2, its mover changed (YP22: a move record integrated or
|
|
42
|
+
* deleted, a moved unit removed).
|
|
37
43
|
* @type {Array<number>}
|
|
38
44
|
*/
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* YP22: the units whose mover changed (a move record integrated or
|
|
42
|
-
* deleted, a moved unit removed), in order: per item `client, clock, len`.
|
|
43
|
-
* @type {Array<number>}
|
|
44
|
-
*/
|
|
45
|
-
moves: Array<number>;
|
|
45
|
+
log: Array<number>;
|
|
46
46
|
/**
|
|
47
47
|
* All types that were directly modified (property added or child
|
|
48
48
|
* inserted/deleted). New types are not included in this Set.
|
|
@@ -5,6 +5,7 @@ export function writeStateAsUpdate(encoder: UpdateEncoder, doc: Doc, targetState
|
|
|
5
5
|
export function encodeStateAsUpdate(doc: Doc, encodedTargetStateVector?: Uint8Array): Uint8Array<ArrayBuffer>;
|
|
6
6
|
export function mergeUpdates(updates: Array<Uint8Array<ArrayBuffer>>): Uint8Array<ArrayBuffer>;
|
|
7
7
|
export function diffUpdate(update: Uint8Array, sv: Uint8Array): Uint8Array<ArrayBuffer>;
|
|
8
|
+
export function clipUpdate(update: Uint8Array, sv: Uint8Array, ds: import("./ids.js").IdSet): Uint8Array<ArrayBuffer>;
|
|
8
9
|
export function decodeStateVector(decodedState: Uint8Array): Map<number, number>;
|
|
9
10
|
export function encodeStateVector(doc: Doc | Map<number, number>): Uint8Array<ArrayBuffer>;
|
|
10
11
|
import { UpdateEncoder } from './UpdateEncoder.js';
|
|
@@ -7,7 +7,7 @@ export { IdSet, createDeleteSetFromStructStore, diffIdSet, createIdSet, mergeIdS
|
|
|
7
7
|
export { Doc } from './utils/Doc.js'
|
|
8
8
|
export { UpdateDecoder } from './utils/UpdateDecoder.js'
|
|
9
9
|
export { UpdateEncoder } from './utils/UpdateEncoder.js'
|
|
10
|
-
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, mergeUpdates } from './utils/encoding.js'
|
|
10
|
+
export { applyUpdate, encodeStateAsUpdate, encodeStateVector, decodeStateVector, diffUpdate, clipUpdate, mergeUpdates } from './utils/encoding.js' // YP34: clipUpdate
|
|
11
11
|
export { ID, createID, compareIDs, findRootTypeKey } from './utils/ID.js'
|
|
12
12
|
export { isParentOf } from './utils/isParentOf.js'
|
|
13
13
|
export { idAtIndex, indexOfId } from './utils/positions.js' // YP19
|
|
@@ -308,6 +308,8 @@ export class Item extends AbstractStruct {
|
|
|
308
308
|
}
|
|
309
309
|
addStructToIdSet(transaction.insertSet, this)
|
|
310
310
|
transaction.doc.store.add(this)
|
|
311
|
+
// YP33: log the units it shows before its content integrates (a node's children follow it)
|
|
312
|
+
logItem(transaction, 0, this, this.content.constructor === ContentDeleted ? 0 : this.length, false)
|
|
311
313
|
this.content.integrate(transaction, this)
|
|
312
314
|
// add parent to transaction.changed
|
|
313
315
|
addChangedTypeToTransaction(transaction, /** @type {YNode} */ (this.parent), this.parentSub)
|
|
@@ -393,7 +395,7 @@ export class Item extends AbstractStruct {
|
|
|
393
395
|
// adjust the length of parent
|
|
394
396
|
if (this.holds > 0) {
|
|
395
397
|
// YP20: already hidden — the delete set counts it again, the log gives it back
|
|
396
|
-
|
|
398
|
+
logItem(transaction, 1, this, this.length) // YP33
|
|
397
399
|
} else if (this.movers !== null) {
|
|
398
400
|
// YP22: hidden at home already; its mover shows it no more (`gone`)
|
|
399
401
|
logMove(transaction, this, this.mover)
|
|
@@ -411,7 +413,7 @@ export class Item extends AbstractStruct {
|
|
|
411
413
|
}
|
|
412
414
|
this.markDeleted()
|
|
413
415
|
transaction.deleteSet.add(this.id.client, this.id.clock, this.length)
|
|
414
|
-
|
|
416
|
+
logItem(transaction, 0, this, -this.length) // YP33
|
|
415
417
|
// YP14: a node a concurrent value replaced keeps its subtree (the document asked)
|
|
416
418
|
if (!isKeptReplaced(this)) this.content.delete(transaction, this) // YP22: a move record drops itself from its units' movers
|
|
417
419
|
}
|
|
@@ -929,26 +931,36 @@ export class ContentDeleted {
|
|
|
929
931
|
}
|
|
930
932
|
|
|
931
933
|
// YP20 begin (edytor fork: hold records — see UPSTREAM.md YP20)
|
|
934
|
+
// YP33 begin (edytor fork: one log of what a transaction did to items — see UPSTREAM.md YP33)
|
|
932
935
|
/**
|
|
933
|
-
* Log
|
|
934
|
-
*
|
|
936
|
+
* Log `len` units of `item` as `kind` (0 an edit, 1 a hold, 2 a move) in
|
|
937
|
+
* `tr.log`, in order, and (unless `mark` is false) its parent as changed.
|
|
938
|
+
* An entry the last one continues (its kind, its client, the next clock, its
|
|
939
|
+
* sign) extends it, so a run of one writer's items is one entry; `len` 0
|
|
940
|
+
* logs none.
|
|
935
941
|
*
|
|
936
942
|
* @param {Transaction} tr
|
|
943
|
+
* @param {number} kind
|
|
937
944
|
* @param {Item} item
|
|
938
945
|
* @param {number} len
|
|
946
|
+
* @param {boolean} [mark]
|
|
939
947
|
*/
|
|
940
|
-
const
|
|
941
|
-
tr.
|
|
942
|
-
|
|
948
|
+
const logItem = (tr, kind, item, len, mark = true) => {
|
|
949
|
+
const log = tr.log
|
|
950
|
+
const n = log.length
|
|
951
|
+
const { client, clock } = item.id
|
|
952
|
+
if (log[n - 4] === kind && log[n - 3] === client && log[n - 2] + math.abs(log[n - 1]) === clock && log[n - 1] * len > 0) log[n - 1] += len
|
|
953
|
+
else if (len !== 0) log.push(kind, client, clock, len)
|
|
954
|
+
if (mark) addChangedTypeToTransaction(tr, /** @type {YNode} */ (item.parent), item.parentSub)
|
|
943
955
|
}
|
|
956
|
+
// YP33 end
|
|
944
957
|
|
|
945
958
|
/**
|
|
946
959
|
* Add `delta` (1, or -1: release) of a hold record (`record` null: `holds`)
|
|
947
960
|
* or of the move record `record` (its `movers`, YP22; a record never moves a
|
|
948
961
|
* record) to `item`. An item that is not removed and starts or stops being
|
|
949
962
|
* hidden moves its parent's length and drops its search markers; a hold that
|
|
950
|
-
* does is logged (`tr.
|
|
951
|
-
* (`tr.moves`).
|
|
963
|
+
* does is logged (`tr.log`, YP33), and so is a unit whose mover changed.
|
|
952
964
|
*
|
|
953
965
|
* @param {Transaction} tr
|
|
954
966
|
* @param {Item} item
|
|
@@ -976,7 +988,7 @@ const holdItem = (tr, item, delta, record) => {
|
|
|
976
988
|
if (item.countable && item.parentSub === null) parent._length += len
|
|
977
989
|
// the indices the search markers counted moved (a held delete moves them itself)
|
|
978
990
|
if (parent._searchMarker) parent._searchMarker.length = 0
|
|
979
|
-
if (record === null)
|
|
991
|
+
if (record === null) logItem(tr, 1, item, len) // YP33
|
|
980
992
|
}
|
|
981
993
|
const after = item.mover
|
|
982
994
|
if (before !== after) {
|
|
@@ -1223,15 +1235,14 @@ const stronger = (a, b) =>
|
|
|
1223
1235
|
|
|
1224
1236
|
/**
|
|
1225
1237
|
* Log that `item`'s mover changed (or it left its mover: removed) in
|
|
1226
|
-
* `tr.
|
|
1238
|
+
* `tr.log` (YP33), and its home and its new mover's sequences as changed.
|
|
1227
1239
|
*
|
|
1228
1240
|
* @param {Transaction} tr
|
|
1229
1241
|
* @param {Item} item
|
|
1230
1242
|
* @param {Item|null} mover
|
|
1231
1243
|
*/
|
|
1232
1244
|
const logMove = (tr, item, mover) => {
|
|
1233
|
-
tr
|
|
1234
|
-
addChangedTypeToTransaction(tr, /** @type {YNode} */ (item.parent), item.parentSub)
|
|
1245
|
+
logItem(tr, 2, item, item.length) // YP33
|
|
1235
1246
|
if (mover !== null) addChangedTypeToTransaction(tr, /** @type {YNode} */ (mover.parent), null)
|
|
1236
1247
|
}
|
|
1237
1248
|
|
|
@@ -40,19 +40,21 @@ export class Transaction {
|
|
|
40
40
|
* Describes the set of inserted items by ids
|
|
41
41
|
*/
|
|
42
42
|
this.insertSet = createIdSet()
|
|
43
|
+
// YP33 begin (edytor fork: one log of what the transaction did to items — see UPSTREAM.md YP33)
|
|
43
44
|
/**
|
|
44
|
-
*
|
|
45
|
-
* `client, clock, len` (
|
|
46
|
-
*
|
|
45
|
+
* What the transaction did to items, in order: per run of one writer's
|
|
46
|
+
* items `kind, client, clock, len` (an item that continues the last entry
|
|
47
|
+
* extends it). Kind 0, an edit: integrated (`len > 0`, before its content
|
|
48
|
+
* integrates; an item integrated removed logs none) or removed (`len < 0`);
|
|
49
|
+
* kind 1, a hold record's
|
|
50
|
+
* (YP20): shown (`len > 0`) or hidden (`< 0`; an item removed while held
|
|
51
|
+
* is logged shown, so an item's kinds 0 and 1 sum to its visibility
|
|
52
|
+
* change); kind 2, its mover changed (YP22: a move record integrated or
|
|
53
|
+
* deleted, a moved unit removed).
|
|
47
54
|
* @type {Array<number>}
|
|
48
55
|
*/
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
* YP22: the units whose mover changed (a move record integrated or
|
|
52
|
-
* deleted, a moved unit removed), in order: per item `client, clock, len`.
|
|
53
|
-
* @type {Array<number>}
|
|
54
|
-
*/
|
|
55
|
-
this.moves = []
|
|
56
|
+
this.log = []
|
|
57
|
+
// YP33 end
|
|
56
58
|
/**
|
|
57
59
|
* All types that were directly modified (property added or child
|
|
58
60
|
* inserted/deleted). New types are not included in this Set.
|