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.
Files changed (137) hide show
  1. package/README.md +3 -3
  2. package/dist/cloudflare/DocumentRoom.d.ts +77 -2
  3. package/dist/cloudflare/DocumentRoom.js +37 -1
  4. package/dist/cloudflare/index.d.ts +1 -1
  5. package/dist/cloudflare/index.js +1 -1
  6. package/dist/cloudflare/room/access.d.ts +6 -1
  7. package/dist/cloudflare/room/access.js +30 -4
  8. package/dist/cloudflare/room/admission.d.ts +11 -0
  9. package/dist/cloudflare/room/admission.js +43 -10
  10. package/dist/cloudflare/room/context.d.ts +73 -76
  11. package/dist/cloudflare/room/context.js +17 -6
  12. package/dist/cloudflare/room/forged.d.ts +1 -1
  13. package/dist/cloudflare/room/forged.js +11 -9
  14. package/dist/cloudflare/room/frames.d.ts +2 -0
  15. package/dist/cloudflare/room/frames.js +2 -0
  16. package/dist/cloudflare/room/presence.js +1 -4
  17. package/dist/cloudflare/room/reseed.d.ts +93 -0
  18. package/dist/cloudflare/room/reseed.js +500 -0
  19. package/dist/cloudflare/room/scheduler.d.ts +1 -1
  20. package/dist/cloudflare/room/scheduler.js +9 -1
  21. package/dist/cloudflare/room/shared.d.ts +10 -0
  22. package/dist/cloudflare/room/shared.js +10 -0
  23. package/dist/cloudflare/room/storage.d.ts +7 -0
  24. package/dist/cloudflare/room/storage.js +33 -1
  25. package/dist/components/Edytor.svelte +18 -3
  26. package/dist/components/Edytor.svelte.d.ts +10 -1
  27. package/dist/components/EdytorRoot.svelte +17 -0
  28. package/dist/components/EdytorRoot.svelte.d.ts +4 -0
  29. package/dist/components/Suggestion.svelte +1 -1
  30. package/dist/crdt/attribution/block.d.ts +3 -0
  31. package/dist/crdt/attribution/block.js +3 -2
  32. package/dist/crdt/doc/history.js +2 -3
  33. package/dist/crdt/doc/ops.d.ts +81 -0
  34. package/dist/crdt/doc/ops.js +1898 -0
  35. package/dist/crdt/doc/suggest.d.ts +6 -2
  36. package/dist/crdt/doc/suggest.js +6 -5
  37. package/dist/crdt/edytor-doc.d.ts +157 -157
  38. package/dist/crdt/edytor-doc.js +15 -43
  39. package/dist/crdt/engine-room.d.ts +4 -0
  40. package/dist/crdt/engine-room.js +6 -0
  41. package/dist/crdt/flow.d.ts +4 -46
  42. package/dist/crdt/flow.js +2 -262
  43. package/dist/crdt/index.d.ts +64 -75
  44. package/dist/crdt/operations.d.ts +1 -1
  45. package/dist/crdt/placement/resolve.d.ts +1 -1
  46. package/dist/crdt/protocol.d.ts +2 -2
  47. package/dist/crdt/protocol.js +2 -2
  48. package/dist/crdt/protocols/auth.d.ts +8 -1
  49. package/dist/crdt/protocols/auth.js +14 -1
  50. package/dist/crdt/protocols/awareness.js +46 -81
  51. package/dist/crdt/providers/index.d.ts +11 -22
  52. package/dist/crdt/providers/index.js +22 -3
  53. package/dist/crdt/providers/indexeddb.d.ts +6 -10
  54. package/dist/crdt/providers/indexeddb.js +10 -16
  55. package/dist/crdt/providers/room.d.ts +26 -0
  56. package/dist/crdt/providers/room.js +41 -12
  57. package/dist/crdt/providers/websocket.d.ts +10 -14
  58. package/dist/crdt/providers/websocket.js +43 -23
  59. package/dist/crdt/rangeDelete.d.ts +2 -47
  60. package/dist/crdt/rangeDelete.js +1 -169
  61. package/dist/crdt/reseed.d.ts +127 -0
  62. package/dist/crdt/reseed.js +533 -0
  63. package/dist/crdt/restore.d.ts +13 -1
  64. package/dist/crdt/restore.js +8 -3
  65. package/dist/crdt/schema.d.ts +6 -0
  66. package/dist/crdt/schema.js +6 -0
  67. package/dist/crdt/structs.d.ts +8 -11
  68. package/dist/crdt/structs.js +25 -44
  69. package/dist/crdt/text/index/build.d.ts +119 -0
  70. package/dist/crdt/text/index/build.js +2801 -0
  71. package/dist/crdt/text/index/shared.d.ts +2 -6
  72. package/dist/crdt/text/index/shared.js +2 -5
  73. package/dist/crdt/text/model.js +2 -3
  74. package/dist/crdt/text/runs.d.ts +9 -12
  75. package/dist/crdt/text/runs.js +2 -165
  76. package/dist/crdt/vendor/yjs/UPSTREAM.md +101 -5
  77. package/dist/crdt/vendor/yjs/dts/index.d.ts +1 -1
  78. package/dist/crdt/vendor/yjs/dts/utils/Transaction.d.ts +10 -10
  79. package/dist/crdt/vendor/yjs/dts/utils/encoding.d.ts +1 -0
  80. package/dist/crdt/vendor/yjs/src/index.js +1 -1
  81. package/dist/crdt/vendor/yjs/src/structs/Item.js +24 -13
  82. package/dist/crdt/vendor/yjs/src/utils/Transaction.js +12 -10
  83. package/dist/crdt/vendor/yjs/src/utils/encoding.js +42 -1
  84. package/dist/events/domTextOffset.d.ts +2 -0
  85. package/dist/events/domTextOffset.js +8 -0
  86. package/dist/export/forms.d.ts +50 -50
  87. package/dist/index.d.ts +1 -1
  88. package/dist/index.js +1 -1
  89. package/dist/plugins/richtext/RichTextPlugin.svelte +63 -61
  90. package/dist/plugins/richtext/richTextOperations.js +26 -32
  91. package/dist/selection/selection.svelte.d.ts +1 -1
  92. package/dist/selection/selection.svelte.js +87 -106
  93. package/dist/selection/selection.utils.js +5 -8
  94. package/dist/session/commands.js +49 -51
  95. package/dist/session/handles.js +3 -7
  96. package/dist/surface/attributes.d.ts +3 -3
  97. package/dist/surface/attributes.js +2 -2
  98. package/dist/surface/observer.svelte.d.ts +7 -7
  99. package/dist/surface/observer.svelte.js +225 -336
  100. package/dist/surface/projector.svelte.js +2 -2
  101. package/dist/utils.d.ts +5 -0
  102. package/dist/utils.js +7 -0
  103. package/package.json +1 -1
  104. package/dist/crdt/doc/capability.d.ts +0 -56
  105. package/dist/crdt/doc/capability.js +0 -207
  106. package/dist/crdt/doc/content.d.ts +0 -16
  107. package/dist/crdt/doc/content.js +0 -77
  108. package/dist/crdt/doc/delete.d.ts +0 -15
  109. package/dist/crdt/doc/delete.js +0 -84
  110. package/dist/crdt/doc/layout.d.ts +0 -9
  111. package/dist/crdt/doc/layout.js +0 -178
  112. package/dist/crdt/doc/meta.d.ts +0 -19
  113. package/dist/crdt/doc/meta.js +0 -198
  114. package/dist/crdt/doc/moves.d.ts +0 -21
  115. package/dist/crdt/doc/moves.js +0 -274
  116. package/dist/crdt/doc/split-merge.d.ts +0 -10
  117. package/dist/crdt/doc/split-merge.js +0 -179
  118. package/dist/crdt/doc/steps.d.ts +0 -65
  119. package/dist/crdt/doc/steps.js +0 -311
  120. package/dist/crdt/text/index/cache.d.ts +0 -16
  121. package/dist/crdt/text/index/cache.js +0 -175
  122. package/dist/crdt/text/index/claims.d.ts +0 -18
  123. package/dist/crdt/text/index/claims.js +0 -203
  124. package/dist/crdt/text/index/fold.d.ts +0 -21
  125. package/dist/crdt/text/index/fold.js +0 -656
  126. package/dist/crdt/text/index/layout.d.ts +0 -22
  127. package/dist/crdt/text/index/layout.js +0 -258
  128. package/dist/crdt/text/index/placement.d.ts +0 -47
  129. package/dist/crdt/text/index/placement.js +0 -738
  130. package/dist/crdt/text/index/records.d.ts +0 -13
  131. package/dist/crdt/text/index/records.js +0 -139
  132. package/dist/crdt/text/index/report.d.ts +0 -18
  133. package/dist/crdt/text/index/report.js +0 -337
  134. package/dist/crdt/text/index/state.d.ts +0 -197
  135. package/dist/crdt/text/index/state.js +0 -116
  136. package/dist/crdt/text/index/streams.d.ts +0 -25
  137. package/dist/crdt/text/index/streams.js +0 -248
@@ -1,197 +0,0 @@
1
- /**
2
- * The index's state: every fact the parts of the index share, kept in one
3
- * object each part reads (`ix`). Containers are created once and mutated in
4
- * place; the fields a part reassigns (`delim`, `roles`, the children
5
- * indexes, the counters and flags) are read through `ix` at every use.
6
- * What one part alone keeps stays in that part.
7
- */
8
- import type { EngineDoc, EngineTransaction } from '../../engine-api.js';
9
- import { type BlockId, type BlockRec, type ChildSlot, type Edge, type ResolvedPlacement, type SlotRef } from '../../placement/model.js';
10
- import type { IdSetLike } from '../../structs.js';
11
- import type { LiveRow, RowItem } from '../rows.js';
12
- import type { ContentRun, DisplayRoles, Folded } from '../runs.js';
13
- import type { Cached } from './shared.js';
14
- export type TextEdit = {
15
- item: RowItem;
16
- len: number;
17
- del: boolean;
18
- };
19
- export type TextEdits = {
20
- edits: TextEdit[];
21
- scan: boolean;
22
- opaque: boolean;
23
- };
24
- /** One fold's effects: invalidated blocks, rescanned texts, rebuilt facets. */
25
- export type FoldCtx = {
26
- invalidated: Set<BlockId>;
27
- /** Per home block: its text's edits, whether it rescans, whether every reader re-reads. */
28
- texts: Map<BlockId, {
29
- edits: TextEdit[];
30
- scan: boolean;
31
- opaque: boolean;
32
- seen: Set<TextEdits>;
33
- }>;
34
- /** The blocks whose entry or nonce changed: their delimiters are re-decided. */
35
- named: Set<BlockId>;
36
- table: boolean;
37
- /** The winning parents, before and after, of the blocks the fold touched. */
38
- parents: Set<BlockId>;
39
- };
40
- /** A slot in a children index: its display parent, rank and the island it displays out of. */
41
- export type Slot = {
42
- parent: BlockId | null;
43
- rank: string;
44
- reset?: BlockId;
45
- };
46
- /** Each row's segments at its last placement: segment 0's block, then each cut's key and block. */
47
- export type Placed = {
48
- head: BlockId | null;
49
- keys: string[];
50
- blocks: (BlockId | null)[];
51
- };
52
- /** The tree the change report last published. */
53
- export type Published = {
54
- nodes: Map<BlockId, {
55
- parent: BlockId | null;
56
- index: number;
57
- type: string;
58
- data: unknown;
59
- runs: readonly ContentRun[];
60
- key?: string;
61
- }>;
62
- order: Map<BlockId | null, readonly BlockId[]>;
63
- /** The children index version it was taken at. */
64
- kids: number;
65
- };
66
- /** A transaction as the fold reads it. */
67
- export type Tx = {
68
- insertSet?: IdSetLike;
69
- deleteSet?: IdSetLike;
70
- changed?: EngineTransaction['changed'];
71
- /** The visibility changes hold records made, in order (fork patch YP20). */
72
- holds?: number[];
73
- /** The units whose mover changed, in order (fork patch YP22). */
74
- moves?: number[];
75
- };
76
- /** The index's self-checks (`indexChecks`), run after each fold and each report. */
77
- export type SelfChecks = {
78
- check: () => void;
79
- checkPublished: (pub: Published) => void;
80
- };
81
- /** Build the empty state of `doc`'s index. */
82
- export declare const indexState: (doc: EngineDoc) => {
83
- doc: EngineDoc;
84
- registry: import("../../engine-api.js").EngineNode;
85
- /** The document's own data (`crdt/data.ts`): outside the registry, reported apart. */
86
- dataRoot: import("../../engine-api.js").EngineNode;
87
- blocks: Map<string, BlockRec>;
88
- /** Withdrawn blocks without a delete mark (`hist.undo.withdraw`), see the fold's `settle`. */
89
- shells: Set<string>;
90
- /** Forward dependencies of cached runs: backing text (by home) / walked block → consumers. */
91
- textConsumers: Map<string, Set<string>>;
92
- listConsumers: Map<string, Set<string>>;
93
- /** Owner → the blocks it displays (itself included while it owns itself). */
94
- displaysMap: Map<string, Set<string>>;
95
- /** Blocks whose claims, delete mark or record changed since the last owner pass. */
96
- ownerSeeds: Set<string>;
97
- /** Blocks whose owner changed since the last placement pass. */
98
- ownerChanged: Set<string>;
99
- rows: Map<string, LiveRow>;
100
- delim: Map<string, string>;
101
- /** Each block's segment: its row and the cut that opens it (`null`: the row's segment 0). */
102
- streamIx: Map<string, {
103
- home: BlockId;
104
- cut: string | null;
105
- }>;
106
- placed: Map<string, Placed>;
107
- /** Each row's text → its home (rows are keyed by home). */
108
- homeOfText: WeakMap<object, string>;
109
- /** Blocks whose claims (implicit, then their stream's claim items) the next pass re-reads. */
110
- reclaim: Set<string>;
111
- /** The role table the display reads; `null` → none. */
112
- roles: DisplayRoles | null;
113
- /** A stored kind changed since the last report: derived kinds may follow it. */
114
- retyped: boolean;
115
- /** The live blocks the layout rules do not display (`layout.*`), per placement build. */
116
- dissolved: Set<string>;
117
- /** Resolved placements. */
118
- placementsMap: Map<string, ResolvedPlacement>;
119
- /** Counts the folds that changed a sequence (a slot or record written or removed): a slot map read before one is stale. */
120
- seqEpoch: number;
121
- /** Every block slot by the id it names (`{ b }`, fork patch YP22), kept from the folds; a block's home is `homeFor`. */
122
- slotsByBlock: Map<string, SlotRef[]>;
123
- /** Each sequence owner's blocks (every block whose display edge it holds), sorted by key. */
124
- rawOrder: Map<string | null, ChildSlot[]>;
125
- /** Each block's display edge as accepted, or its strongest when none is (`null`: no slot). */
126
- edges: Map<string, Edge | null>;
127
- /** The blocks shown below their strongest edge: a cycle dropped a later move, they are back where they stood. */
128
- fallen: Set<string>;
129
- /** The blocks at the root's tail: every edge closes a cycle, or no slot. */
130
- rejected: Set<string>;
131
- /** The children index without the layout rules (what they read), and with them. */
132
- kids0: Map<string | null, ChildSlot[]>;
133
- slots0: Map<string, Slot>;
134
- kidsMap: Map<string | null, ChildSlot[]>;
135
- /** Each visible block's slot (display parent, rank, the island it displays out of). */
136
- slots: Map<string, Slot>;
137
- /**
138
- * The blocks whose shown kind follows their slot — displayed out of
139
- * an island, then in a lined island or of a line kind — which the
140
- * report re-reads after a retype.
141
- */
142
- following: Set<string>;
143
- /** Bumps whenever a child list changes (the report compares it). */
144
- kidsVersion: number;
145
- /** The child lists patched since the last report (`all`: every list was rebuilt). */
146
- dirtyLists: Set<string | null>;
147
- /** The blocks that left every list since the last report. */
148
- leftLists: Set<string>;
149
- allListsDirty: boolean;
150
- /** The next pass rebuilds everything (first build, roles, an irregular state). */
151
- placementFull: boolean;
152
- /** Blocks whose slot, record or mover changed; blocks whose display state changed. */
153
- placementSeeds: Set<string>;
154
- stateSeeds: Set<string>;
155
- /**
156
- * Per block: whether its kind is a layout, an item, a lines island
157
- * (with its line kind), a table, a table's row or a row's cell.
158
- */
159
- kindsOf: Map<string, {
160
- layout: boolean;
161
- item: boolean;
162
- line?: string;
163
- table: boolean;
164
- row: boolean;
165
- cell: boolean;
166
- }>;
167
- /** The item kinds the roles declare, and those the document holds. */
168
- itemKinds: Set<string>;
169
- /** The row kinds of the table kinds the roles declare and the document holds, with their cell kinds. */
170
- rowKinds: Map<string, string>;
171
- /** The cell kinds of {@link rowKinds}. */
172
- cellKinds: Set<string>;
173
- /**
174
- * The losing incarnations each key shows (`id.same.concurrent`):
175
- * blocks of their own under derived ids, claimed by the key's block
176
- * before its own claims (`incarnations.ts`).
177
- */
178
- incarnations: Map<string, string[]>;
179
- cache: Map<string, Cached>;
180
- dirty: Set<string>;
181
- /** The index version (`RunView.version`). */
182
- version: number;
183
- /** The fold counters `debug` exposes read-only. */
184
- foldStats: {
185
- folds: number;
186
- pairs: number;
187
- structs: number;
188
- placed: number;
189
- };
190
- /** Frames tracking the folds (the write funnel's `track()`), and the report's candidates. */
191
- frames: Set<Folded>;
192
- candidates: Set<string>;
193
- reporting: boolean;
194
- /** The self-checks, once built (`checksOf`). */
195
- checks: SelfChecks | null;
196
- };
197
- export type IndexState = ReturnType<typeof indexState>;
@@ -1,116 +0,0 @@
1
- import { REGISTRY_KEY } from '../../placement/model.js';
2
- import { DOC_DATA_ROOT } from '../../schema.js';
3
- /** Build the empty state of `doc`'s index. */
4
- export const indexState = (doc) => {
5
- // The children index starts as the one without the layout rules (no layout yet).
6
- const kids0 = new Map();
7
- const slots0 = new Map();
8
- return {
9
- doc,
10
- registry: doc.get(REGISTRY_KEY),
11
- /** The document's own data (`crdt/data.ts`): outside the registry, reported apart. */
12
- dataRoot: doc.get(DOC_DATA_ROOT),
13
- // ── the replicated-state index
14
- blocks: new Map(),
15
- /** Withdrawn blocks without a delete mark (`hist.undo.withdraw`), see the fold's `settle`. */
16
- shells: new Set(),
17
- /** Forward dependencies of cached runs: backing text (by home) / walked block → consumers. */
18
- textConsumers: new Map(),
19
- listConsumers: new Map(),
20
- // ── the claim graph (`claims.ts`)
21
- /** Owner → the blocks it displays (itself included while it owns itself). */
22
- displaysMap: new Map(),
23
- /** Blocks whose claims, delete mark or record changed since the last owner pass. */
24
- ownerSeeds: new Set(),
25
- /** Blocks whose owner changed since the last placement pass. */
26
- ownerChanged: new Set(),
27
- // ── the stream table (`streams.ts`)
28
- rows: new Map(),
29
- delim: new Map(),
30
- /** Each block's segment: its row and the cut that opens it (`null`: the row's segment 0). */
31
- streamIx: new Map(),
32
- placed: new Map(),
33
- /** Each row's text → its home (rows are keyed by home). */
34
- homeOfText: new WeakMap(),
35
- /** Blocks whose claims (implicit, then their stream's claim items) the next pass re-reads. */
36
- reclaim: new Set(),
37
- // ── roles
38
- /** The role table the display reads; `null` → none. */
39
- roles: null,
40
- /** A stored kind changed since the last report: derived kinds may follow it. */
41
- retyped: false,
42
- // ── placements and the children index (`placement.ts`, `layout.ts`)
43
- /** The live blocks the layout rules do not display (`layout.*`), per placement build. */
44
- dissolved: new Set(),
45
- /** Resolved placements. */
46
- placementsMap: new Map(),
47
- /** Counts the folds that changed a sequence (a slot or record written or removed): a slot map read before one is stale. */
48
- seqEpoch: 0,
49
- /** Every block slot by the id it names (`{ b }`, fork patch YP22), kept from the folds; a block's home is `homeFor`. */
50
- slotsByBlock: new Map(),
51
- /** Each sequence owner's blocks (every block whose display edge it holds), sorted by key. */
52
- rawOrder: new Map(),
53
- /** Each block's display edge as accepted, or its strongest when none is (`null`: no slot). */
54
- edges: new Map(),
55
- /** The blocks shown below their strongest edge: a cycle dropped a later move, they are back where they stood. */
56
- fallen: new Set(),
57
- /** The blocks at the root's tail: every edge closes a cycle, or no slot. */
58
- rejected: new Set(),
59
- /** The children index without the layout rules (what they read), and with them. */
60
- kids0,
61
- slots0,
62
- kidsMap: kids0,
63
- /** Each visible block's slot (display parent, rank, the island it displays out of). */
64
- slots: slots0,
65
- /**
66
- * The blocks whose shown kind follows their slot — displayed out of
67
- * an island, then in a lined island or of a line kind — which the
68
- * report re-reads after a retype.
69
- */
70
- following: new Set(),
71
- /** Bumps whenever a child list changes (the report compares it). */
72
- kidsVersion: 0,
73
- /** The child lists patched since the last report (`all`: every list was rebuilt). */
74
- dirtyLists: new Set(),
75
- /** The blocks that left every list since the last report. */
76
- leftLists: new Set(),
77
- allListsDirty: true,
78
- /** The next pass rebuilds everything (first build, roles, an irregular state). */
79
- placementFull: true,
80
- /** Blocks whose slot, record or mover changed; blocks whose display state changed. */
81
- placementSeeds: new Set(),
82
- stateSeeds: new Set(),
83
- /**
84
- * Per block: whether its kind is a layout, an item, a lines island
85
- * (with its line kind), a table, a table's row or a row's cell.
86
- */
87
- kindsOf: new Map(),
88
- /** The item kinds the roles declare, and those the document holds. */
89
- itemKinds: new Set(),
90
- /** The row kinds of the table kinds the roles declare and the document holds, with their cell kinds. */
91
- rowKinds: new Map(),
92
- /** The cell kinds of {@link rowKinds}. */
93
- cellKinds: new Set(),
94
- // ── records (`records.ts`)
95
- /**
96
- * The losing incarnations each key shows (`id.same.concurrent`):
97
- * blocks of their own under derived ids, claimed by the key's block
98
- * before its own claims (`incarnations.ts`).
99
- */
100
- incarnations: new Map(),
101
- // ── the run cache (`cache.ts`)
102
- cache: new Map(),
103
- dirty: new Set(),
104
- /** The index version (`RunView.version`). */
105
- version: 0,
106
- /** The fold counters `debug` exposes read-only. */
107
- foldStats: { folds: 0, pairs: 0, structs: 0, placed: 0 },
108
- // ── the fold (`fold.ts`) and the report (`report.ts`)
109
- /** Frames tracking the folds (the write funnel's `track()`), and the report's candidates. */
110
- frames: new Set(),
111
- candidates: new Set(),
112
- reporting: false,
113
- /** The self-checks, once built (`checksOf`). */
114
- checks: null
115
- };
116
- };
@@ -1,25 +0,0 @@
1
- /**
2
- * The stream table: one maintained row per backing text, the
3
- * delimiting boundary of each block, each block's segment, and each
4
- * block's claims (the claim items of its segment).
5
- */
6
- import type { BlockId } from '../../placement/model.js';
7
- import { type Claim, type Stream } from '../model.js';
8
- import { type LiveRow } from '../rows.js';
9
- import type { IndexClaims } from './claims.js';
10
- import type { FoldCtx, IndexState } from './state.js';
11
- /** The stream table of one doc's index, over its state and claim graph. */
12
- export declare const indexStreams: (ix: IndexState & IndexClaims) => {
13
- streamOf: (b: BlockId) => Stream | undefined;
14
- streamsIn: (home: BlockId) => Stream[];
15
- streamAt: (home: BlockId, i: number) => Stream | undefined;
16
- setRow: (home: BlockId, row: LiveRow | undefined, named: Set<BlockId>) => void;
17
- scanRow: (home: BlockId) => LiveRow | undefined;
18
- refreshDelims: (named: Iterable<BlockId>, homes: Set<BlockId>) => void;
19
- placeHome: (home: BlockId, invalidated: Set<BlockId>) => void;
20
- rebuildTable: (invalidated: Set<BlockId>) => void;
21
- sameClaims: (x: readonly Claim[], y: readonly Claim[]) => boolean;
22
- claimsOf: (b: BlockId) => Claim[];
23
- applyReclaims: (ctx: FoldCtx | null) => void;
24
- };
25
- export type IndexStreams = ReturnType<typeof indexStreams>;
@@ -1,248 +0,0 @@
1
- import { byId, cmpStamp, scanText } from '../model.js';
2
- import { removedKeys } from '../streams.js';
3
- import { headOf, placeRow, rowOf, segmentAt, segmentClaims, segmentOfCut, streamOfSegment } from '../rows.js';
4
- /** The stream table of one doc's index, over its state and claim graph. */
5
- export const indexStreams = (ix) => {
6
- const { registry, blocks, listConsumers, rows, streamIx, placed, homeOfText, reclaim, noteClaims, invalidateBlock } = ix;
7
- // ── the stream table ────────────────────────────────────
8
- // One maintained row per backing text (keyed by its home block): its
9
- // live boundaries and the units between them (`text/rows.ts`), the
10
- // delimiting boundary of each block, and each block's segment. An edit
11
- // that writes or removes no boundary moves its row by its units
12
- // (`shiftGap`); a row is rescanned only when its boundary set (or its
13
- // text) changed, and only the delimiters of the blocks its boundaries
14
- // name are re-decided, so only the rows those delimiters cut re-place.
15
- /** Every live boundary naming a block, by block: key → its row and nonce. */
16
- const boundsBy = new Map();
17
- const streamOf = (b) => {
18
- const at = streamIx.get(b);
19
- const row = at && rows.get(at.home);
20
- if (row === undefined)
21
- return undefined;
22
- const k = segmentOfCut(row, at.cut);
23
- return k < 0 ? undefined : streamOfSegment(row, k, b);
24
- };
25
- const streamsIn = (home) => {
26
- const row = rows.get(home);
27
- const out = [];
28
- for (let k = 0; row !== undefined && k <= row.cuts.length; k++) {
29
- const b = headOf(row, k);
30
- if (b !== null)
31
- out.push(streamOfSegment(row, k, b));
32
- }
33
- return out;
34
- };
35
- const streamAt = (home, i) => {
36
- const row = rows.get(home);
37
- if (row === undefined)
38
- return undefined;
39
- const k = segmentAt(row, i);
40
- const b = headOf(row, k);
41
- if (b === null)
42
- return undefined;
43
- const st = streamOfSegment(row, k, b);
44
- return st.start <= i && i <= st.end ? st : undefined;
45
- };
46
- /** Record `home`'s new row (or none); the blocks its boundary set change names join `named`. */
47
- const setRow = (home, row, named) => {
48
- const old = rows.get(home);
49
- if (row === undefined)
50
- rows.delete(home);
51
- else {
52
- rows.set(home, row);
53
- homeOfText.set(row.text, home);
54
- }
55
- if (old?.key === row?.key)
56
- return;
57
- for (const b of old?.bounds ?? []) {
58
- if (b.m !== undefined || row?.keyIndex.has(b.key))
59
- continue;
60
- const by = boundsBy.get(b.s);
61
- // A text can change homes (a key's node becomes a losing incarnation,
62
- // `id.same.concurrent`): drop the entry only while it is still this row's.
63
- if (by?.get(b.key)?.home === home)
64
- by.delete(b.key);
65
- if (by?.size === 0)
66
- boundsBy.delete(b.s);
67
- named.add(b.s);
68
- }
69
- for (const b of row?.bounds ?? []) {
70
- if (b.m !== undefined || old?.keyIndex.has(b.key))
71
- continue;
72
- let by = boundsBy.get(b.s);
73
- if (by === undefined)
74
- boundsBy.set(b.s, (by = new Map()));
75
- by.set(b.key, { home, n: b.n });
76
- named.add(b.s);
77
- }
78
- };
79
- /** A fresh row of `home`'s text (none without one). */
80
- const scanRow = (home) => {
81
- const text = blocks.get(home)?.content;
82
- return text === undefined ? undefined : rowOf(scanText(home, text));
83
- };
84
- /** A removed block's key (`room.purge.what`): its boundary delimits nobody's stretch. */
85
- const removed = removedKeys(registry);
86
- /** A cut's stretch is nobody's when it names no block (a removed one). */
87
- const nobody = (s) => !blocks.has(s);
88
- /** Re-decide the delimiting boundary of each block in `named`; the rows a change cuts join `homes`. */
89
- const refreshDelims = (named, homes) => {
90
- for (const s of named) {
91
- const rec = blocks.get(s);
92
- const gone = rec === undefined && removed(s);
93
- let best;
94
- if (rec !== undefined || gone)
95
- for (const [key, b] of boundsBy.get(s) ?? [])
96
- if ((gone || b.n === rec.n) && (best === undefined || byId(key, best) < 0))
97
- best = key;
98
- const old = ix.delim.get(s);
99
- if (old === best) {
100
- // The cut stays, and the block it opens may have come or gone (removed).
101
- if (best !== undefined)
102
- homes.add(boundsBy.get(s).get(best).home);
103
- continue;
104
- }
105
- if (best === undefined)
106
- ix.delim.delete(s);
107
- else
108
- ix.delim.set(s, best);
109
- const was = old === undefined ? undefined : boundsBy.get(s)?.get(old)?.home;
110
- if (was !== undefined)
111
- homes.add(was);
112
- if (best !== undefined)
113
- homes.add(boundsBy.get(s).get(best).home);
114
- if (rows.has(s) || placed.has(s))
115
- homes.add(s);
116
- }
117
- };
118
- /**
119
- * Place `home`'s row; invalidate the blocks whose segment changed (or
120
- * appeared, or went). A segment is its two delimiting cuts, so only the
121
- * segments between the longest common prefix and suffix of the old and
122
- * new cut lists can differ: the others keep their entries untouched.
123
- */
124
- const placeHome = (home, invalidated) => {
125
- const row = rows.get(home);
126
- const before = placed.get(home) ?? { head: null, keys: [], blocks: [] };
127
- const now = { head: null, keys: [], blocks: [] };
128
- if (row !== undefined) {
129
- placeRow(row, ix.delim, nobody);
130
- now.head = row.head;
131
- row.cuts.forEach((j, k) => {
132
- now.keys.push(row.bounds[j].key);
133
- now.blocks.push(row.heads[k]);
134
- });
135
- }
136
- if (row === undefined)
137
- placed.delete(home);
138
- else
139
- placed.set(home, now);
140
- // Its segments' claim items may have changed, or gone to other blocks.
141
- for (const x of [before, now]) {
142
- if (x.head !== null)
143
- reclaim.add(x.head);
144
- for (const b of x.blocks)
145
- if (b !== null)
146
- reclaim.add(b);
147
- }
148
- const [a, b] = [before.keys, now.keys];
149
- // A cut is the same when its boundary and the block it opens are (a
150
- // removed block's cut opens nobody's stretch).
151
- const same = (i, j) => a[i] === b[j] && before.blocks[i] === now.blocks[j];
152
- let p = 0;
153
- while (p < a.length && p < b.length && same(p, p))
154
- p++;
155
- let q = 0;
156
- while (q < a.length - p && q < b.length - p && same(a.length - 1 - q, b.length - 1 - q))
157
- q++;
158
- // Segment k ends at cut k: it changed iff k lies in [p, n - q] (segment 0 also with its block).
159
- const from = before.head === now.head ? p : 0;
160
- const changed = (blk) => {
161
- if (blk === null)
162
- return;
163
- invalidated.add(blk);
164
- for (const c of listConsumers.get(blk) ?? [])
165
- invalidated.add(c);
166
- };
167
- const blockOf = (x, k) => (k === 0 ? x.head : x.blocks[k - 1]);
168
- for (let k = from; k <= a.length - q; k++) {
169
- const blk = blockOf(before, k);
170
- if (blk !== null && streamIx.get(blk)?.home === home)
171
- streamIx.delete(blk);
172
- changed(blk);
173
- }
174
- for (let k = from; k <= b.length - q; k++) {
175
- const blk = blockOf(now, k);
176
- if (blk === null)
177
- continue;
178
- streamIx.set(blk, { home, cut: k === 0 ? null : b[k - 1] });
179
- changed(blk);
180
- }
181
- };
182
- /** Rebuild the delimiters and every row's segments (the first build). */
183
- const rebuildTable = (invalidated) => {
184
- boundsBy.clear();
185
- for (const [home, row] of rows)
186
- for (const b of row.bounds) {
187
- if (b.m !== undefined)
188
- continue;
189
- let by = boundsBy.get(b.s);
190
- if (by === undefined)
191
- boundsBy.set(b.s, (by = new Map()));
192
- by.set(b.key, { home, n: b.n });
193
- }
194
- ix.delim = new Map();
195
- const homes = new Set([...rows.keys(), ...placed.keys()]);
196
- refreshDelims(boundsBy.keys(), homes);
197
- for (const home of homes)
198
- placeHome(home, invalidated);
199
- };
200
- // ── claims ──────────────────────────────────────────────
201
- // A block's claims are its implicit ones (`id.same.concurrent`), then
202
- // the claim items of its segment, in text order (fork patch YP21:
203
- // YATA placed each one, so a split its writer did not see leaves it in
204
- // the piece that ends its holder's region, `merge.claim.anchor`). They
205
- // change with the record (its implicit claims) and with its row's bounds
206
- // or cuts: re-read after each fold's texts for the blocks queued.
207
- const sameClaims = (x, y) => x.length === y.length &&
208
- x.every((c, i) => c.m === y[i].m && cmpStamp(c.stamp, y[i].stamp) === 0);
209
- /** `b`'s claims now: its implicit ones, then its segment's claim items. */
210
- const claimsOf = (b) => {
211
- const at = streamIx.get(b);
212
- const row = at && rows.get(at.home);
213
- const k = row === undefined ? -1 : segmentOfCut(row, at.cut);
214
- const items = k < 0 ? [] : segmentClaims(row, k);
215
- const implicit = blocks.get(b)?.implicit ?? [];
216
- return implicit.length === 0 ? items : [...implicit, ...items];
217
- };
218
- /** Re-read the claims of the blocks queued; a change is a structural change of the block. */
219
- const applyReclaims = (ctx) => {
220
- for (const b of reclaim) {
221
- const rec = blocks.get(b);
222
- if (rec === undefined)
223
- continue;
224
- const before = rec.claims;
225
- const after = claimsOf(b);
226
- if (sameClaims(before, after))
227
- continue;
228
- rec.claims = after;
229
- noteClaims(b, before, after);
230
- if (ctx !== null)
231
- invalidateBlock(b, ctx, before);
232
- }
233
- reclaim.clear();
234
- };
235
- return {
236
- streamOf,
237
- streamsIn,
238
- streamAt,
239
- setRow,
240
- scanRow,
241
- refreshDelims,
242
- placeHome,
243
- rebuildTable,
244
- sameClaims,
245
- claimsOf,
246
- applyReclaims
247
- };
248
- };