@earendil-works/chord 0.87.1 → 0.99.1
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 +80 -27
- package/dist/api.d.ts +6 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +8 -3
- package/dist/api.js.map +1 -1
- package/dist/bundler.d.ts.map +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/delta/apply-immutable-trusted.d.ts +4 -0
- package/dist/delta/apply-immutable-trusted.d.ts.map +1 -0
- package/dist/delta/apply-immutable-trusted.js +127 -0
- package/dist/delta/apply-immutable-trusted.js.map +1 -0
- package/dist/{state → delta}/diff.d.ts +1 -1
- package/dist/delta/diff.d.ts.map +1 -0
- package/dist/delta/diff.js +433 -0
- package/dist/delta/diff.js.map +1 -0
- package/dist/delta/draft.d.ts +5 -0
- package/dist/delta/draft.d.ts.map +1 -0
- package/dist/delta/draft.js +2 -0
- package/dist/delta/draft.js.map +1 -0
- package/dist/delta/index.d.ts +11 -21
- package/dist/delta/index.d.ts.map +1 -1
- package/dist/delta/index.js +43 -1341
- package/dist/delta/index.js.map +1 -1
- package/dist/delta/revision-validator.d.ts +7 -0
- package/dist/delta/revision-validator.d.ts.map +1 -0
- package/dist/delta/revision-validator.js +71 -0
- package/dist/delta/revision-validator.js.map +1 -0
- package/dist/delta/tracker.d.ts +26 -0
- package/dist/delta/tracker.d.ts.map +1 -0
- package/dist/delta/tracker.js +2069 -0
- package/dist/delta/tracker.js.map +1 -0
- package/dist/facets/host.d.ts.map +1 -1
- package/dist/facets/host.js.map +1 -1
- package/dist/facets/loader.d.ts.map +1 -1
- package/dist/facets/loader.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +6 -0
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +73 -6
- package/dist/json.js.map +1 -1
- package/dist/node/bundle-loader.d.ts.map +1 -1
- package/dist/node/bundle-loader.js.map +1 -1
- package/dist/node/bundle.d.ts.map +1 -1
- package/dist/node/bundle.js.map +1 -1
- package/dist/node/manifest.d.ts.map +1 -1
- package/dist/node/package.d.ts.map +1 -1
- package/dist/node/package.js.map +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/services/consumer.d.ts.map +1 -1
- package/dist/services/consumer.js +49 -1
- package/dist/services/consumer.js.map +1 -1
- package/dist/services/errors.d.ts.map +1 -1
- package/dist/services/errors.js.map +1 -1
- package/dist/services/handle.d.ts.map +1 -1
- package/dist/services/handle.js +3 -1
- package/dist/services/handle.js.map +1 -1
- package/dist/services/instances.d.ts +1 -0
- package/dist/services/instances.d.ts.map +1 -1
- package/dist/services/instances.js +3 -0
- package/dist/services/instances.js.map +1 -1
- package/dist/services/loopback.d.ts.map +1 -1
- package/dist/services/loopback.js.map +1 -1
- package/dist/services/provider.d.ts.map +1 -1
- package/dist/services/provider.js +48 -29
- package/dist/services/provider.js.map +1 -1
- package/dist/services/state-codec.d.ts.map +1 -1
- package/dist/services/state-codec.js +18 -0
- package/dist/services/state-codec.js.map +1 -1
- package/dist/services/state-internals.d.ts +5 -2
- package/dist/services/state-internals.d.ts.map +1 -1
- package/dist/services/state-internals.js.map +1 -1
- package/dist/services/state.d.ts +8 -3
- package/dist/services/state.d.ts.map +1 -1
- package/dist/services/state.js +288 -88
- package/dist/services/state.js.map +1 -1
- package/dist/services/wire.d.ts +3 -0
- package/dist/services/wire.d.ts.map +1 -1
- package/dist/services/wire.js +13 -0
- package/dist/services/wire.js.map +1 -1
- package/dist/types.d.ts +74 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -3
- package/src/delta/README.md +143 -360
- package/dist/state/diff.d.ts.map +0 -1
- package/dist/state/diff.js +0 -259
- package/dist/state/diff.js.map +0 -1
- package/dist/state/draft.d.ts +0 -13
- package/dist/state/draft.d.ts.map +0 -1
- package/dist/state/draft.js +0 -540
- package/dist/state/draft.js.map +0 -1
- package/dist/state/value.d.ts +0 -9
- package/dist/state/value.d.ts.map +0 -1
- package/dist/state/value.js +0 -175
- package/dist/state/value.js.map +0 -1
package/dist/state/diff.js
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import { overlap, RESERVED_SEGMENTS } from "../delta/index.js";
|
|
2
|
-
const DEFAULT_OVERLAP_SCAN = 65_536;
|
|
3
|
-
const MAX_DELTA_OPERATIONS = 4_096;
|
|
4
|
-
const isContainer = (value) => value !== null && typeof value === "object";
|
|
5
|
-
const emitSet = (path, value, operations) => {
|
|
6
|
-
if (path.length === 0)
|
|
7
|
-
operations.push(["r", value]);
|
|
8
|
-
else
|
|
9
|
-
operations.push(["s", path, value]);
|
|
10
|
-
};
|
|
11
|
-
const equalJson = (left, right) => {
|
|
12
|
-
if (left === right)
|
|
13
|
-
return true;
|
|
14
|
-
if (!isContainer(left) || !isContainer(right) || Array.isArray(left) !== Array.isArray(right))
|
|
15
|
-
return false;
|
|
16
|
-
if (Array.isArray(left)) {
|
|
17
|
-
const other = right;
|
|
18
|
-
if (left.length !== other.length)
|
|
19
|
-
return false;
|
|
20
|
-
for (let index = 0; index < left.length; index++) {
|
|
21
|
-
if (!equalJson(left[index], other[index]))
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
const other = right;
|
|
27
|
-
const keys = Object.keys(left);
|
|
28
|
-
if (keys.length !== Object.keys(other).length)
|
|
29
|
-
return false;
|
|
30
|
-
for (const key of keys) {
|
|
31
|
-
if (!Object.hasOwn(other, key) || !equalJson(left[key], other[key]))
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
return true;
|
|
35
|
-
};
|
|
36
|
-
const permutation = (before, after) => {
|
|
37
|
-
if (before.length !== after.length)
|
|
38
|
-
return undefined;
|
|
39
|
-
const positions = new Map();
|
|
40
|
-
for (let index = 0; index < before.length; index++) {
|
|
41
|
-
const value = before[index];
|
|
42
|
-
const entry = positions.get(value);
|
|
43
|
-
if (entry === undefined)
|
|
44
|
-
positions.set(value, { indices: [index], used: 0 });
|
|
45
|
-
else
|
|
46
|
-
entry.indices.push(index);
|
|
47
|
-
}
|
|
48
|
-
const result = new Array(after.length);
|
|
49
|
-
for (let index = 0; index < after.length; index++) {
|
|
50
|
-
const entry = positions.get(after[index]);
|
|
51
|
-
if (entry === undefined || entry.used === entry.indices.length)
|
|
52
|
-
return undefined;
|
|
53
|
-
result[index] = entry.indices[entry.used++];
|
|
54
|
-
}
|
|
55
|
-
return result;
|
|
56
|
-
};
|
|
57
|
-
const emitString = (before, after, path, operations) => {
|
|
58
|
-
if (before === after)
|
|
59
|
-
return;
|
|
60
|
-
if (after.length > before.length && after.slice(0, before.length) === before) {
|
|
61
|
-
operations.push(["a", path, after.slice(before.length)]);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const shared = overlap(before, after, DEFAULT_OVERLAP_SCAN);
|
|
65
|
-
if (shared === 0) {
|
|
66
|
-
operations.push(["s", path, after]);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
operations.push(["t", path, before.length - shared]);
|
|
70
|
-
if (after.length > shared)
|
|
71
|
-
operations.push(["a", path, after.slice(shared)]);
|
|
72
|
-
};
|
|
73
|
-
const emitSameLengthShift = (before, after, path, operations) => {
|
|
74
|
-
const length = before.length;
|
|
75
|
-
if (length < 2)
|
|
76
|
-
return false;
|
|
77
|
-
let candidates = 0;
|
|
78
|
-
for (let removed = 1; removed < length && candidates < 16; removed++) {
|
|
79
|
-
if (before[removed] !== after[0])
|
|
80
|
-
continue;
|
|
81
|
-
candidates += 1;
|
|
82
|
-
let matches = true;
|
|
83
|
-
for (let index = removed; index < length; index++) {
|
|
84
|
-
if (before[index] !== after[index - removed]) {
|
|
85
|
-
matches = false;
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (!matches)
|
|
90
|
-
continue;
|
|
91
|
-
operations.push(["p", path, 0, removed, []]);
|
|
92
|
-
operations.push(["p", path, length - removed, 0, after.slice(length - removed)]);
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
candidates = 0;
|
|
96
|
-
for (let inserted = 1; inserted < length && candidates < 16; inserted++) {
|
|
97
|
-
if (after[inserted] !== before[0])
|
|
98
|
-
continue;
|
|
99
|
-
candidates += 1;
|
|
100
|
-
let matches = true;
|
|
101
|
-
for (let index = inserted; index < length; index++) {
|
|
102
|
-
if (after[index] !== before[index - inserted]) {
|
|
103
|
-
matches = false;
|
|
104
|
-
break;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (!matches)
|
|
108
|
-
continue;
|
|
109
|
-
operations.push(["p", path, 0, 0, after.slice(0, inserted)]);
|
|
110
|
-
operations.push(["p", path, length, inserted, []]);
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
return false;
|
|
114
|
-
};
|
|
115
|
-
const diffArray = (before, after, path, operations) => {
|
|
116
|
-
if (before.length === after.length) {
|
|
117
|
-
let mismatches = 0;
|
|
118
|
-
for (let index = 0; index < after.length; index++) {
|
|
119
|
-
if (before[index] !== after[index])
|
|
120
|
-
mismatches += 1;
|
|
121
|
-
}
|
|
122
|
-
if (mismatches === 0)
|
|
123
|
-
return;
|
|
124
|
-
if (mismatches > 1) {
|
|
125
|
-
const order = permutation(before, after);
|
|
126
|
-
if (order !== undefined) {
|
|
127
|
-
operations.push(["m", path, order]);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (emitSameLengthShift(before, after, path, operations))
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
for (let index = 0; index < after.length; index++) {
|
|
134
|
-
if (operations.length > MAX_DELTA_OPERATIONS)
|
|
135
|
-
return;
|
|
136
|
-
diffValue(before[index], after[index], [...path, index], operations);
|
|
137
|
-
}
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
let prefix = 0;
|
|
141
|
-
const shortest = Math.min(before.length, after.length);
|
|
142
|
-
while (prefix < shortest && equalJson(before[prefix], after[prefix]))
|
|
143
|
-
prefix += 1;
|
|
144
|
-
let suffix = 0;
|
|
145
|
-
while (suffix < shortest - prefix &&
|
|
146
|
-
equalJson(before[before.length - 1 - suffix], after[after.length - 1 - suffix])) {
|
|
147
|
-
suffix += 1;
|
|
148
|
-
}
|
|
149
|
-
operations.push(["p", path, prefix, before.length - prefix - suffix, after.slice(prefix, after.length - suffix)]);
|
|
150
|
-
};
|
|
151
|
-
const diffObject = (before, after, path, operations) => {
|
|
152
|
-
const beforeKeys = Object.keys(before);
|
|
153
|
-
const afterKeys = Object.keys(after);
|
|
154
|
-
if ([...beforeKeys, ...afterKeys].some((key) => RESERVED_SEGMENTS.has(key))) {
|
|
155
|
-
if (!equalJson(before, after))
|
|
156
|
-
emitSet(path, after, operations);
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
for (const key of afterKeys) {
|
|
160
|
-
if (operations.length > MAX_DELTA_OPERATIONS)
|
|
161
|
-
return;
|
|
162
|
-
if (Object.hasOwn(before, key))
|
|
163
|
-
diffValue(before[key], after[key], [...path, key], operations);
|
|
164
|
-
else
|
|
165
|
-
emitSet([...path, key], after[key], operations);
|
|
166
|
-
}
|
|
167
|
-
for (const key of beforeKeys) {
|
|
168
|
-
if (operations.length > MAX_DELTA_OPERATIONS)
|
|
169
|
-
return;
|
|
170
|
-
if (!Object.hasOwn(after, key))
|
|
171
|
-
operations.push(["d", [...path, key]]);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
const diffValue = (before, after, path, operations) => {
|
|
175
|
-
if (before === after || operations.length > MAX_DELTA_OPERATIONS)
|
|
176
|
-
return;
|
|
177
|
-
if (typeof before === "string" && typeof after === "string" && path.length > 0) {
|
|
178
|
-
emitString(before, after, path, operations);
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
if (Array.isArray(before) && Array.isArray(after)) {
|
|
182
|
-
diffArray(before, after, path, operations);
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
if (isContainer(before) && isContainer(after) && !Array.isArray(before) && !Array.isArray(after)) {
|
|
186
|
-
diffObject(before, after, path, operations);
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
emitSet(path, after, operations);
|
|
190
|
-
};
|
|
191
|
-
const jsonCost = (value) => {
|
|
192
|
-
if (value === null)
|
|
193
|
-
return 4;
|
|
194
|
-
if (typeof value === "string")
|
|
195
|
-
return value.length + 2;
|
|
196
|
-
if (typeof value === "number")
|
|
197
|
-
return String(value).length;
|
|
198
|
-
if (typeof value === "boolean")
|
|
199
|
-
return value ? 4 : 5;
|
|
200
|
-
if (Array.isArray(value)) {
|
|
201
|
-
let cost = 2;
|
|
202
|
-
for (let index = 0; index < value.length; index++)
|
|
203
|
-
cost += jsonCost(value[index]) + (index === 0 ? 0 : 1);
|
|
204
|
-
return cost;
|
|
205
|
-
}
|
|
206
|
-
let cost = 2;
|
|
207
|
-
let index = 0;
|
|
208
|
-
for (const key of Object.keys(value)) {
|
|
209
|
-
cost += key.length + 3 + jsonCost(value[key]) + (index++ === 0 ? 0 : 1);
|
|
210
|
-
}
|
|
211
|
-
return cost;
|
|
212
|
-
};
|
|
213
|
-
const pathCost = (path) => {
|
|
214
|
-
let cost = 2;
|
|
215
|
-
for (let index = 0; index < path.length; index++) {
|
|
216
|
-
const segment = path[index];
|
|
217
|
-
cost += (typeof segment === "string" ? segment.length + 2 : String(segment).length) + (index === 0 ? 0 : 1);
|
|
218
|
-
}
|
|
219
|
-
return cost;
|
|
220
|
-
};
|
|
221
|
-
const operationCost = (operation) => {
|
|
222
|
-
switch (operation[0]) {
|
|
223
|
-
case "r":
|
|
224
|
-
return 6 + jsonCost(operation[1]);
|
|
225
|
-
case "s":
|
|
226
|
-
return 7 + pathCost(operation[1]) + jsonCost(operation[2]);
|
|
227
|
-
case "d":
|
|
228
|
-
return 6 + pathCost(operation[1]);
|
|
229
|
-
case "a":
|
|
230
|
-
return 7 + pathCost(operation[1]) + operation[2].length + 2;
|
|
231
|
-
case "t":
|
|
232
|
-
return 7 + pathCost(operation[1]) + String(operation[2]).length;
|
|
233
|
-
case "p":
|
|
234
|
-
return (10 +
|
|
235
|
-
pathCost(operation[1]) +
|
|
236
|
-
String(operation[2]).length +
|
|
237
|
-
String(operation[3]).length +
|
|
238
|
-
jsonCost(operation[4]));
|
|
239
|
-
case "m":
|
|
240
|
-
return 7 + pathCost(operation[1]) + jsonCost(operation[2]);
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
/** Compute a compact operation batch from two immutable JSON revisions. */
|
|
244
|
-
export function diffRevisions(before, after) {
|
|
245
|
-
const operations = [];
|
|
246
|
-
diffValue(before, after, [], operations);
|
|
247
|
-
if (operations.length > MAX_DELTA_OPERATIONS)
|
|
248
|
-
return [["r", after]];
|
|
249
|
-
if (operations.length === 0 || operations[0]?.[0] === "r")
|
|
250
|
-
return operations;
|
|
251
|
-
let deltaCost = 2;
|
|
252
|
-
for (const operation of operations)
|
|
253
|
-
deltaCost += operationCost(operation) + 1;
|
|
254
|
-
if (deltaCost < 65_536)
|
|
255
|
-
return operations;
|
|
256
|
-
const snapshotCost = jsonCost(after) + 6;
|
|
257
|
-
return deltaCost >= snapshotCost ? [["r", after]] : operations;
|
|
258
|
-
}
|
|
259
|
-
//# sourceMappingURL=diff.js.map
|
package/dist/state/diff.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/state/diff.ts"],"names":[],"mappings":"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","sourcesContent":["import { type NonEmptyPath, type Op, overlap, type Path, RESERVED_SEGMENTS, type Seg } from \"../delta/index.ts\";\nimport type { JsonValue } from \"../types.ts\";\n\nconst DEFAULT_OVERLAP_SCAN = 65_536;\nconst MAX_DELTA_OPERATIONS = 4_096;\n\nconst isContainer = (value: JsonValue): value is JsonValue[] | Record<string, JsonValue> =>\n\tvalue !== null && typeof value === \"object\";\n\nconst emitSet = (path: Path, value: JsonValue, operations: Op[]): void => {\n\tif (path.length === 0) operations.push([\"r\", value]);\n\telse operations.push([\"s\", path as NonEmptyPath, value]);\n};\n\nconst equalJson = (left: JsonValue, right: JsonValue): boolean => {\n\tif (left === right) return true;\n\tif (!isContainer(left) || !isContainer(right) || Array.isArray(left) !== Array.isArray(right)) return false;\n\tif (Array.isArray(left)) {\n\t\tconst other = right as JsonValue[];\n\t\tif (left.length !== other.length) return false;\n\t\tfor (let index = 0; index < left.length; index++) {\n\t\t\tif (!equalJson(left[index]!, other[index]!)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\tconst other = right as Record<string, JsonValue>;\n\tconst keys = Object.keys(left);\n\tif (keys.length !== Object.keys(other).length) return false;\n\tfor (const key of keys) {\n\t\tif (!Object.hasOwn(other, key) || !equalJson(left[key]!, other[key]!)) return false;\n\t}\n\treturn true;\n};\n\nconst permutation = (before: readonly JsonValue[], after: readonly JsonValue[]): number[] | undefined => {\n\tif (before.length !== after.length) return undefined;\n\tconst positions = new Map<JsonValue, { indices: number[]; used: number }>();\n\tfor (let index = 0; index < before.length; index++) {\n\t\tconst value = before[index]!;\n\t\tconst entry = positions.get(value);\n\t\tif (entry === undefined) positions.set(value, { indices: [index], used: 0 });\n\t\telse entry.indices.push(index);\n\t}\n\tconst result = new Array<number>(after.length);\n\tfor (let index = 0; index < after.length; index++) {\n\t\tconst entry = positions.get(after[index]!);\n\t\tif (entry === undefined || entry.used === entry.indices.length) return undefined;\n\t\tresult[index] = entry.indices[entry.used++]!;\n\t}\n\treturn result;\n};\n\nconst emitString = (before: string, after: string, path: NonEmptyPath, operations: Op[]): void => {\n\tif (before === after) return;\n\tif (after.length > before.length && after.slice(0, before.length) === before) {\n\t\toperations.push([\"a\", path, after.slice(before.length)]);\n\t\treturn;\n\t}\n\tconst shared = overlap(before, after, DEFAULT_OVERLAP_SCAN);\n\tif (shared === 0) {\n\t\toperations.push([\"s\", path, after]);\n\t\treturn;\n\t}\n\toperations.push([\"t\", path, before.length - shared]);\n\tif (after.length > shared) operations.push([\"a\", path, after.slice(shared)]);\n};\n\nconst emitSameLengthShift = (\n\tbefore: readonly JsonValue[],\n\tafter: readonly JsonValue[],\n\tpath: Path,\n\toperations: Op[],\n): boolean => {\n\tconst length = before.length;\n\tif (length < 2) return false;\n\tlet candidates = 0;\n\tfor (let removed = 1; removed < length && candidates < 16; removed++) {\n\t\tif (before[removed] !== after[0]) continue;\n\t\tcandidates += 1;\n\t\tlet matches = true;\n\t\tfor (let index = removed; index < length; index++) {\n\t\t\tif (before[index] !== after[index - removed]) {\n\t\t\t\tmatches = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!matches) continue;\n\t\toperations.push([\"p\", path, 0, removed, []]);\n\t\toperations.push([\"p\", path, length - removed, 0, after.slice(length - removed)]);\n\t\treturn true;\n\t}\n\tcandidates = 0;\n\tfor (let inserted = 1; inserted < length && candidates < 16; inserted++) {\n\t\tif (after[inserted] !== before[0]) continue;\n\t\tcandidates += 1;\n\t\tlet matches = true;\n\t\tfor (let index = inserted; index < length; index++) {\n\t\t\tif (after[index] !== before[index - inserted]) {\n\t\t\t\tmatches = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (!matches) continue;\n\t\toperations.push([\"p\", path, 0, 0, after.slice(0, inserted)]);\n\t\toperations.push([\"p\", path, length, inserted, []]);\n\t\treturn true;\n\t}\n\treturn false;\n};\n\nconst diffArray = (before: JsonValue[], after: JsonValue[], path: Path, operations: Op[]): void => {\n\tif (before.length === after.length) {\n\t\tlet mismatches = 0;\n\t\tfor (let index = 0; index < after.length; index++) {\n\t\t\tif (before[index] !== after[index]) mismatches += 1;\n\t\t}\n\t\tif (mismatches === 0) return;\n\t\tif (mismatches > 1) {\n\t\t\tconst order = permutation(before, after);\n\t\t\tif (order !== undefined) {\n\t\t\t\toperations.push([\"m\", path, order]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (emitSameLengthShift(before, after, path, operations)) return;\n\t\t}\n\t\tfor (let index = 0; index < after.length; index++) {\n\t\t\tif (operations.length > MAX_DELTA_OPERATIONS) return;\n\t\t\tdiffValue(before[index]!, after[index]!, [...path, index], operations);\n\t\t}\n\t\treturn;\n\t}\n\n\tlet prefix = 0;\n\tconst shortest = Math.min(before.length, after.length);\n\twhile (prefix < shortest && equalJson(before[prefix]!, after[prefix]!)) prefix += 1;\n\tlet suffix = 0;\n\twhile (\n\t\tsuffix < shortest - prefix &&\n\t\tequalJson(before[before.length - 1 - suffix]!, after[after.length - 1 - suffix]!)\n\t) {\n\t\tsuffix += 1;\n\t}\n\toperations.push([\"p\", path, prefix, before.length - prefix - suffix, after.slice(prefix, after.length - suffix)]);\n};\n\nconst diffObject = (\n\tbefore: Record<string, JsonValue>,\n\tafter: Record<string, JsonValue>,\n\tpath: Path,\n\toperations: Op[],\n): void => {\n\tconst beforeKeys = Object.keys(before);\n\tconst afterKeys = Object.keys(after);\n\tif ([...beforeKeys, ...afterKeys].some((key) => RESERVED_SEGMENTS.has(key))) {\n\t\tif (!equalJson(before, after)) emitSet(path, after, operations);\n\t\treturn;\n\t}\n\tfor (const key of afterKeys) {\n\t\tif (operations.length > MAX_DELTA_OPERATIONS) return;\n\t\tif (Object.hasOwn(before, key)) diffValue(before[key]!, after[key]!, [...path, key], operations);\n\t\telse emitSet([...path, key], after[key]!, operations);\n\t}\n\tfor (const key of beforeKeys) {\n\t\tif (operations.length > MAX_DELTA_OPERATIONS) return;\n\t\tif (!Object.hasOwn(after, key)) operations.push([\"d\", [...path, key] as unknown as NonEmptyPath]);\n\t}\n};\n\nconst diffValue = (before: JsonValue, after: JsonValue, path: Path, operations: Op[]): void => {\n\tif (before === after || operations.length > MAX_DELTA_OPERATIONS) return;\n\tif (typeof before === \"string\" && typeof after === \"string\" && path.length > 0) {\n\t\temitString(before, after, path as NonEmptyPath, operations);\n\t\treturn;\n\t}\n\tif (Array.isArray(before) && Array.isArray(after)) {\n\t\tdiffArray(before, after, path, operations);\n\t\treturn;\n\t}\n\tif (isContainer(before) && isContainer(after) && !Array.isArray(before) && !Array.isArray(after)) {\n\t\tdiffObject(before, after, path, operations);\n\t\treturn;\n\t}\n\temitSet(path, after, operations);\n};\n\nconst jsonCost = (value: JsonValue): number => {\n\tif (value === null) return 4;\n\tif (typeof value === \"string\") return value.length + 2;\n\tif (typeof value === \"number\") return String(value).length;\n\tif (typeof value === \"boolean\") return value ? 4 : 5;\n\tif (Array.isArray(value)) {\n\t\tlet cost = 2;\n\t\tfor (let index = 0; index < value.length; index++) cost += jsonCost(value[index]!) + (index === 0 ? 0 : 1);\n\t\treturn cost;\n\t}\n\tlet cost = 2;\n\tlet index = 0;\n\tfor (const key of Object.keys(value)) {\n\t\tcost += key.length + 3 + jsonCost(value[key]!) + (index++ === 0 ? 0 : 1);\n\t}\n\treturn cost;\n};\n\nconst pathCost = (path: Path): number => {\n\tlet cost = 2;\n\tfor (let index = 0; index < path.length; index++) {\n\t\tconst segment: Seg = path[index]!;\n\t\tcost += (typeof segment === \"string\" ? segment.length + 2 : String(segment).length) + (index === 0 ? 0 : 1);\n\t}\n\treturn cost;\n};\n\nconst operationCost = (operation: Op): number => {\n\tswitch (operation[0]) {\n\t\tcase \"r\":\n\t\t\treturn 6 + jsonCost(operation[1]);\n\t\tcase \"s\":\n\t\t\treturn 7 + pathCost(operation[1]) + jsonCost(operation[2]);\n\t\tcase \"d\":\n\t\t\treturn 6 + pathCost(operation[1]);\n\t\tcase \"a\":\n\t\t\treturn 7 + pathCost(operation[1]) + operation[2].length + 2;\n\t\tcase \"t\":\n\t\t\treturn 7 + pathCost(operation[1]) + String(operation[2]).length;\n\t\tcase \"p\":\n\t\t\treturn (\n\t\t\t\t10 +\n\t\t\t\tpathCost(operation[1]) +\n\t\t\t\tString(operation[2]).length +\n\t\t\t\tString(operation[3]).length +\n\t\t\t\tjsonCost(operation[4])\n\t\t\t);\n\t\tcase \"m\":\n\t\t\treturn 7 + pathCost(operation[1]) + jsonCost(operation[2]);\n\t}\n};\n\n/** Compute a compact operation batch from two immutable JSON revisions. */\nexport function diffRevisions(before: JsonValue, after: JsonValue): Op[] {\n\tconst operations: Op[] = [];\n\tdiffValue(before, after, [], operations);\n\tif (operations.length > MAX_DELTA_OPERATIONS) return [[\"r\", after]];\n\tif (operations.length === 0 || operations[0]?.[0] === \"r\") return operations;\n\tlet deltaCost = 2;\n\tfor (const operation of operations) deltaCost += operationCost(operation) + 1;\n\tif (deltaCost < 65_536) return operations;\n\tconst snapshotCost = jsonCost(after) + 6;\n\treturn deltaCost >= snapshotCost ? [[\"r\", after]] : operations;\n}\n"]}
|
package/dist/state/draft.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/** A mutable transaction-scoped view of a JSON value, preserving tuple positions. */
|
|
2
|
-
export type Draft<T, Depth extends readonly unknown[] = []> = Depth["length"] extends 8 ? T : T extends null | boolean | number | string ? T : T extends (...args: never[]) => unknown ? T : T extends object ? {
|
|
3
|
-
-readonly [Key in keyof T]: Draft<T[Key], [...Depth, unknown]>;
|
|
4
|
-
} : T;
|
|
5
|
-
export type ProduceMetadata<T> = {
|
|
6
|
-
value: T;
|
|
7
|
-
owned: WeakSet<object>;
|
|
8
|
-
};
|
|
9
|
-
/** Run a mutation recipe and return its value with transaction ownership metadata. */
|
|
10
|
-
export declare function produceWithMetadata<T extends object>(base: T, recipe: (draft: Draft<T>) => void): ProduceMetadata<T>;
|
|
11
|
-
/** Run a mutation recipe against a copy-on-write draft of `base`. */
|
|
12
|
-
export declare function produce<T extends object>(base: T, recipe: (draft: Draft<T>) => void): T;
|
|
13
|
-
//# sourceMappingURL=draft.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/state/draft.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,KAAK,SAAS,SAAS,OAAO,EAAE,GAAG,EAAE,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GACpF,CAAC,GACD,CAAC,SAAS,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GACzC,CAAC,GACD,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GACtC,CAAC,GACD,CAAC,SAAS,MAAM,GACf;IAAE,CAAC,UAAU,GAAG,IAAI,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC;CAAE,GAClE,CAAC,CAAC;AAER,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI;IAChC,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAwBF,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,eAAe,CAAC,CAAC,CAAC,CAgCpH;AAED,qEAAqE;AACrE,wBAAgB,OAAO,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAEvF","sourcesContent":["/** A mutable transaction-scoped view of a JSON value, preserving tuple positions. */\nexport type Draft<T, Depth extends readonly unknown[] = []> = Depth[\"length\"] extends 8\n\t? T\n\t: T extends null | boolean | number | string\n\t\t? T\n\t\t: T extends (...args: never[]) => unknown\n\t\t\t? T\n\t\t\t: T extends object\n\t\t\t\t? { -readonly [Key in keyof T]: Draft<T[Key], [...Depth, unknown]> }\n\t\t\t\t: T;\n\nexport type ProduceMetadata<T> = {\n\tvalue: T;\n\towned: WeakSet<object>;\n};\n\ntype Container = Record<string, unknown> | unknown[];\n\ntype DraftState = {\n\tbase: Container;\n\tcontext: DraftContext;\n\tcopy: Container | undefined;\n\tmethods: Map<string, unknown> | undefined;\n\tproxy: object;\n\ttarget: unknown[] | undefined;\n};\n\ntype DraftContext = {\n\tactive: boolean;\n\tcreated: DraftState[];\n\towned: WeakSet<object>;\n\tproxies: WeakMap<object, DraftState>;\n\tstates: WeakMap<object, DraftState>;\n};\n\nconst RELEASED_BASE: Container = Object.freeze({});\nconst ARRAY_MUTATORS = new Set([\"push\", \"pop\", \"shift\", \"unshift\", \"splice\", \"sort\", \"reverse\", \"fill\", \"copyWithin\"]);\n\n/** Run a mutation recipe and return its value with transaction ownership metadata. */\nexport function produceWithMetadata<T extends object>(base: T, recipe: (draft: Draft<T>) => void): ProduceMetadata<T> {\n\tconst context: DraftContext = {\n\t\tactive: true,\n\t\tcreated: [],\n\t\towned: new WeakSet<object>(),\n\t\tproxies: new WeakMap<object, DraftState>(),\n\t\tstates: new WeakMap<object, DraftState>(),\n\t};\n\tconst root = getState(context, base as Container);\n\ttry {\n\t\tconst outcome = (recipe as (draft: Draft<T>) => unknown)(root.proxy as Draft<T>);\n\t\tif (isPromiseLike(outcome)) {\n\t\t\tvoid Promise.resolve(outcome).catch(() => undefined);\n\t\t\tthrow new TypeError(\"Replicated state change callbacks must be synchronous\");\n\t\t}\n\t\treturn {\n\t\t\tvalue: finalize(root, new Set<DraftState>(), new WeakMap<DraftState, Container>()) as T,\n\t\t\towned: context.owned,\n\t\t};\n\t} finally {\n\t\tcontext.active = false;\n\t\tfor (const state of context.created) {\n\t\t\tstate.base = RELEASED_BASE;\n\t\t\tstate.copy = undefined;\n\t\t\tstate.methods = undefined;\n\t\t\tstate.proxy = RELEASED_BASE;\n\t\t\tstate.target = undefined;\n\t\t}\n\t\tcontext.created.length = 0;\n\t\tcontext.proxies = new WeakMap();\n\t\tcontext.states = new WeakMap();\n\t}\n}\n\n/** Run a mutation recipe against a copy-on-write draft of `base`. */\nexport function produce<T extends object>(base: T, recipe: (draft: Draft<T>) => void): T {\n\treturn produceWithMetadata(base, recipe).value;\n}\n\nfunction getState(context: DraftContext, base: Container): DraftState {\n\tconst existing = context.states.get(base);\n\tif (existing !== undefined) return existing;\n\n\tconst target = Array.isArray(base) ? [] : undefined;\n\tif (target !== undefined) Reflect.set(target, \"length\", base.length);\n\tconst state: DraftState = {\n\t\tbase,\n\t\tcontext,\n\t\tcopy: undefined,\n\t\tmethods: undefined,\n\t\tproxy: target ?? {},\n\t\ttarget,\n\t};\n\tstate.proxy = new Proxy(target ?? state, createHandler(state));\n\tcontext.states.set(base, state);\n\tcontext.proxies.set(state.proxy, state);\n\tcontext.created.push(state);\n\treturn state;\n}\n\ntype DraftHandler = ProxyHandler<object> & { state: DraftState };\n\nconst handlerPrototype: ProxyHandler<object> = {\n\tdeleteProperty(this: DraftHandler, _target, property): boolean {\n\t\tconst state = this.state;\n\t\tassertStringWrite(property);\n\t\tconst current = currentValue(state);\n\t\tif (Array.isArray(current)) throw new TypeError(\"Draft arrays cannot contain holes\");\n\t\tif (!Object.hasOwn(current, property)) return true;\n\t\tconst deleted = Reflect.deleteProperty(ensureCopy(state), property);\n\t\tsyncArrayTarget(state);\n\t\treturn deleted;\n\t},\n\tdefineProperty(this: DraftHandler): never {\n\t\tassertActive(this.state.context);\n\t\tthrow new TypeError(\"Defining draft properties is not supported\");\n\t},\n\tget(this: DraftHandler, _target, property): unknown {\n\t\tconst state = this.state;\n\t\tconst current = currentValue(state);\n\t\tconst value = Reflect.get(current, property, state.proxy);\n\t\tif (Array.isArray(current) && typeof property === \"string\" && ARRAY_MUTATORS.has(property)) {\n\t\t\treturn arrayMutator(state, property, value);\n\t\t}\n\t\treturn draftValue(state.context, value);\n\t},\n\tgetOwnPropertyDescriptor(this: DraftHandler, _target, property): PropertyDescriptor | undefined {\n\t\tconst state = this.state;\n\t\tconst current = currentValue(state);\n\t\tconst descriptor = Reflect.getOwnPropertyDescriptor(current, property);\n\t\tif (descriptor === undefined) return undefined;\n\t\tif (Array.isArray(current) && property === \"length\") {\n\t\t\tsyncArrayTarget(state);\n\t\t\treturn Reflect.getOwnPropertyDescriptor(state.target!, property);\n\t\t}\n\t\treturn {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: descriptor.enumerable,\n\t\t\tvalue: \"value\" in descriptor ? draftValue(state.context, descriptor.value) : undefined,\n\t\t\twritable: true,\n\t\t};\n\t},\n\tgetPrototypeOf(this: DraftHandler): object | null {\n\t\tassertActive(this.state.context);\n\t\treturn Object.getPrototypeOf(this.state.base);\n\t},\n\thas(this: DraftHandler, _target, property): boolean {\n\t\treturn Reflect.has(currentValue(this.state), property);\n\t},\n\tisExtensible(this: DraftHandler): boolean {\n\t\tassertActive(this.state.context);\n\t\treturn true;\n\t},\n\townKeys(this: DraftHandler): ArrayLike<string | symbol> {\n\t\treturn Reflect.ownKeys(currentValue(this.state));\n\t},\n\tpreventExtensions(this: DraftHandler): never {\n\t\tassertActive(this.state.context);\n\t\tthrow new TypeError(\"Drafts cannot be made non-extensible\");\n\t},\n\tset(this: DraftHandler, _target, property, value): boolean {\n\t\tconst state = this.state;\n\t\tassertStringWrite(property);\n\t\tconst current = currentValue(state);\n\t\tlet stored: unknown;\n\t\tif (isContainer(value)) {\n\t\t\tstored = cloneAssigned(value, state.context, new Set<object>());\n\t\t} else {\n\t\t\tassertJsonPrimitive(value);\n\t\t\tstored = value;\n\t\t}\n\t\tif (Object.hasOwn(current, property) && Object.is(Reflect.get(current, property), stored)) return true;\n\t\tconst copy = ensureCopy(state);\n\t\tif (Array.isArray(copy) && property === \"length\") {\n\t\t\tconst written = Reflect.set(copy, property, stored);\n\t\t\tsyncArrayTarget(state);\n\t\t\treturn written;\n\t\t}\n\t\tObject.defineProperty(copy, property, {\n\t\t\tvalue: stored,\n\t\t\twritable: true,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t});\n\t\tsyncArrayTarget(state);\n\t\treturn true;\n\t},\n\tsetPrototypeOf(this: DraftHandler): never {\n\t\tassertActive(this.state.context);\n\t\tthrow new TypeError(\"Changing a draft prototype is not supported\");\n\t},\n};\n\nfunction createHandler(state: DraftState): ProxyHandler<object> {\n\tconst handler = Object.create(handlerPrototype) as DraftHandler;\n\thandler.state = state;\n\treturn handler;\n}\n\nfunction arrayMutator(state: DraftState, property: string, value: unknown): unknown {\n\tassertActive(state.context);\n\tconst cached = state.methods?.get(property);\n\tif (cached !== undefined) return cached;\n\tif (typeof value !== \"function\") return draftValue(state.context, value);\n\tconst wrapped = function (this: unknown, ...args: unknown[]): unknown {\n\t\tassertActive(state.context);\n\t\tconst receiver = isContainer(this) ? state.context.proxies.get(this) : undefined;\n\t\tif (receiver === undefined) return Reflect.apply(value, this, args);\n\t\tconst target = ensureCopy(receiver);\n\t\tif (!Array.isArray(target)) throw new TypeError(\"Array mutator receiver is not an array draft\");\n\t\ttry {\n\t\t\treturn mutateArray(receiver, target, property, args);\n\t\t} finally {\n\t\t\tsyncArrayTarget(receiver);\n\t\t}\n\t};\n\tif (state.methods === undefined) state.methods = new Map();\n\tstate.methods.set(property, wrapped);\n\treturn wrapped;\n}\n\nfunction mutateArray(state: DraftState, target: unknown[], property: string, args: unknown[]): unknown {\n\tconst { context } = state;\n\tswitch (property) {\n\t\tcase \"push\": {\n\t\t\tconst items = cloneArrayItems(args, context);\n\t\t\tfor (const item of items) defineArrayValue(target, target.length, item);\n\t\t\treturn target.length;\n\t\t}\n\t\tcase \"pop\": {\n\t\t\tif (target.length === 0) return undefined;\n\t\t\tconst index = target.length - 1;\n\t\t\tconst removed = target[index];\n\t\t\tReflect.deleteProperty(target, String(index));\n\t\t\ttarget.length = index;\n\t\t\treturn draftValue(context, removed);\n\t\t}\n\t\tcase \"shift\":\n\t\t\treturn draftValue(context, Reflect.apply(Array.prototype.shift, target, []));\n\t\tcase \"unshift\": {\n\t\t\tconst items = cloneArrayItems(args, context);\n\t\t\tif (hasInheritedGrowthIndex(target, target.length + items.length)) {\n\t\t\t\tspliceArray(target, items, 0, 0, context);\n\t\t\t\treturn target.length;\n\t\t\t}\n\t\t\treturn Reflect.apply(Array.prototype.unshift, target, items);\n\t\t}\n\t\tcase \"splice\": {\n\t\t\tconst length = target.length;\n\t\t\tconst start = args.length === 0 ? 0 : clampArrayIndex(toIntegerOrInfinity(args[0]), length);\n\t\t\tconst remove =\n\t\t\t\targs.length === 0\n\t\t\t\t\t? 0\n\t\t\t\t\t: args.length === 1\n\t\t\t\t\t\t? length - start\n\t\t\t\t\t\t: Math.min(Math.max(toIntegerOrInfinity(args[1]), 0), length - start);\n\t\t\tconst items = cloneArrayItems(args.slice(2), context);\n\t\t\tif (\n\t\t\t\t!mayRunCoercionCode(args[0]) &&\n\t\t\t\t!mayRunCoercionCode(args[1]) &&\n\t\t\t\t!hasInheritedGrowthIndex(target, length - remove + items.length)\n\t\t\t) {\n\t\t\t\tconst removed = Reflect.apply(Array.prototype.splice, target, [start, remove, ...items]) as unknown[];\n\t\t\t\treturn removed.map((item) => draftValue(context, item));\n\t\t\t}\n\t\t\treturn spliceArray(target, items, start, remove, context, length);\n\t\t}\n\t\tcase \"sort\": {\n\t\t\tconst comparator = args[0];\n\t\t\tif (comparator !== undefined && typeof comparator !== \"function\") {\n\t\t\t\tReflect.apply(Array.prototype.sort, target, args);\n\t\t\t} else {\n\t\t\t\tReflect.apply(Array.prototype.sort, target, [\n\t\t\t\t\t(left: unknown, right: unknown): number => {\n\t\t\t\t\t\tconst draftedLeft = draftValue(context, left);\n\t\t\t\t\t\tconst draftedRight = draftValue(context, right);\n\t\t\t\t\t\tif (typeof comparator === \"function\") {\n\t\t\t\t\t\t\treturn Reflect.apply(comparator, undefined, [draftedLeft, draftedRight]) as number;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst leftString = String(draftedLeft);\n\t\t\t\t\t\tconst rightString = String(draftedRight);\n\t\t\t\t\t\treturn leftString < rightString ? -1 : leftString > rightString ? 1 : 0;\n\t\t\t\t\t},\n\t\t\t\t]);\n\t\t\t}\n\t\t\treturn state.proxy;\n\t\t}\n\t\tcase \"reverse\":\n\t\t\tReflect.apply(Array.prototype.reverse, target, []);\n\t\t\treturn state.proxy;\n\t\tcase \"fill\": {\n\t\t\tconst length = target.length;\n\t\t\tconst start = args.length > 1 ? clampArrayIndex(toIntegerOrInfinity(args[1]), length) : 0;\n\t\t\tconst end =\n\t\t\t\targs.length > 2 && args[2] !== undefined ? clampArrayIndex(toIntegerOrInfinity(args[2]), length) : length;\n\t\t\tif (end <= start) return state.proxy;\n\t\t\tconst supplied = args[0];\n\t\t\tfor (let index = start; index < end; index++) {\n\t\t\t\tconst item = isContainer(supplied)\n\t\t\t\t\t? cloneAssigned(supplied, context, new Set<object>())\n\t\t\t\t\t: assertJsonPrimitive(supplied);\n\t\t\t\tdefineArrayValue(target, index, item);\n\t\t\t}\n\t\t\treturn state.proxy;\n\t\t}\n\t\tcase \"copyWithin\": {\n\t\t\tconst length = target.length;\n\t\t\tconst to = clampArrayIndex(toIntegerOrInfinity(args[0]), length);\n\t\t\tconst from = clampArrayIndex(toIntegerOrInfinity(args[1]), length);\n\t\t\tconst end =\n\t\t\t\targs.length > 2 && args[2] !== undefined ? clampArrayIndex(toIntegerOrInfinity(args[2]), length) : length;\n\t\t\tconst count = Math.min(Math.max(end - from, 0), length - to);\n\t\t\tconst source = target.slice(from, from + count);\n\t\t\tfor (let offset = 0; offset < count; offset++) {\n\t\t\t\tconst item = source[offset];\n\t\t\t\tconst itemState = isContainer(item) ? context.states.get(item) : undefined;\n\t\t\t\tconst current = (itemState?.proxy as Container | undefined) ?? item;\n\t\t\t\tconst copy = isContainer(current)\n\t\t\t\t\t? cloneAssigned(current, context, new Set<object>())\n\t\t\t\t\t: assertJsonPrimitive(current);\n\t\t\t\tdefineArrayValue(target, to + offset, copy);\n\t\t\t}\n\t\t\treturn state.proxy;\n\t\t}\n\t}\n\tthrow new TypeError(`Unsupported array mutator: ${property}`);\n}\n\nfunction cloneArrayItems(items: readonly unknown[], context: DraftContext): unknown[] {\n\treturn items.map((item) => {\n\t\tif (isContainer(item)) return cloneAssigned(item, context, new Set<object>());\n\t\tassertJsonPrimitive(item);\n\t\treturn item;\n\t});\n}\n\nfunction hasInheritedGrowthIndex(target: unknown[], nextLength: number): boolean {\n\tfor (let index = target.length; index < nextLength; index++) {\n\t\tif (index in target) return true;\n\t}\n\treturn false;\n}\n\nfunction mayRunCoercionCode(value: unknown): boolean {\n\treturn (typeof value === \"object\" && value !== null) || typeof value === \"function\";\n}\n\nfunction spliceArray(\n\ttarget: unknown[],\n\titems: readonly unknown[],\n\tindex: number,\n\tremove: number,\n\tcontext: DraftContext,\n\tlength = target.length,\n): unknown[] {\n\tconst removed = new Array<unknown>(remove);\n\tfor (let offset = 0; offset < remove; offset++) {\n\t\tconst source = index + offset;\n\t\tif (!(source in target)) continue;\n\t\tdefineArrayValue(removed, offset, draftValue(context, target[source]));\n\t}\n\tif (items.length < remove) {\n\t\tfor (let source = index + remove; source < length; source++) {\n\t\t\tdefineArrayValue(target, source - remove + items.length, target[source]);\n\t\t}\n\t} else if (items.length > remove) {\n\t\tfor (let source = length - 1; source >= index + remove; source--) {\n\t\t\tdefineArrayValue(target, source - remove + items.length, target[source]);\n\t\t}\n\t}\n\tfor (let offset = 0; offset < items.length; offset++) defineArrayValue(target, index + offset, items[offset]);\n\ttarget.length = length - remove + items.length;\n\treturn removed;\n}\n\nfunction defineArrayValue(target: unknown[], index: number, value: unknown): void {\n\tObject.defineProperty(target, index, {\n\t\tvalue,\n\t\twritable: true,\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t});\n}\n\nfunction toIntegerOrInfinity(value: unknown): number {\n\tconst number = +(value as unknown as number);\n\tif (Number.isNaN(number) || number === 0) return 0;\n\treturn Number.isFinite(number) ? Math.trunc(number) : number;\n}\n\nfunction clampArrayIndex(value: number, length: number): number {\n\tif (value === Number.NEGATIVE_INFINITY) return 0;\n\tif (value < 0) return Math.max(length + value, 0);\n\treturn Math.min(value, length);\n}\n\nfunction currentValue(state: DraftState): Container {\n\tassertActive(state.context);\n\treturn state.copy ?? state.base;\n}\n\nfunction ensureCopy(state: DraftState): Container {\n\tif (state.copy !== undefined) return state.copy;\n\tif (state.context.owned.has(state.base)) {\n\t\tstate.copy = state.base;\n\t} else {\n\t\tstate.copy = shallowOwnedCopy(state.base, state.context);\n\t}\n\treturn state.copy;\n}\n\nfunction shallowOwnedCopy(value: Container, context: DraftContext): Container {\n\tif (Array.isArray(value)) {\n\t\tconst copy = value.slice();\n\t\tcontext.owned.add(copy);\n\t\treturn copy;\n\t}\n\tconst copy = Object.create(Object.getPrototypeOf(value)) as Record<string, unknown>;\n\tfor (const key of Object.keys(value)) {\n\t\tObject.defineProperty(copy, key, {\n\t\t\tvalue: value[key],\n\t\t\twritable: true,\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t});\n\t}\n\tcontext.owned.add(copy);\n\treturn copy;\n}\n\nfunction cloneAssigned(value: Container, context: DraftContext, ancestors: Set<object>): Container {\n\tif (ancestors.has(value)) throw new TypeError(\"Assigned JSON values cannot contain cycles\");\n\tancestors.add(value);\n\ttry {\n\t\tif (Array.isArray(value)) {\n\t\t\tassertDenseArray(value);\n\t\t\tconst clone: unknown[] = [];\n\t\t\tcontext.owned.add(clone);\n\t\t\tfor (let index = 0; index < value.length; index++) {\n\t\t\t\tclone.push(cloneAssignedValue(Reflect.get(value, String(index)), context, ancestors));\n\t\t\t}\n\t\t\treturn clone;\n\t\t}\n\n\t\tconst prototype = Object.getPrototypeOf(value);\n\t\tif (prototype !== Object.prototype && prototype !== null) {\n\t\t\tthrow new TypeError(\"Assigned JSON containers must be plain objects or arrays\");\n\t\t}\n\t\tconst clone = Object.create(prototype) as Record<string, unknown>;\n\t\tcontext.owned.add(clone);\n\t\tfor (const key of Reflect.ownKeys(value)) {\n\t\t\tif (typeof key === \"symbol\") throw new TypeError(\"Assigned JSON objects cannot have symbol properties\");\n\t\t\tconst descriptor = Reflect.getOwnPropertyDescriptor(value, key);\n\t\t\tif (descriptor === undefined || !descriptor.enumerable || !(\"value\" in descriptor)) {\n\t\t\t\tthrow new TypeError(\"Assigned JSON objects must contain enumerable data properties\");\n\t\t\t}\n\t\t\tObject.defineProperty(clone, key, {\n\t\t\t\tvalue: cloneAssignedValue(descriptor.value, context, ancestors),\n\t\t\t\twritable: true,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t}\n\t\treturn clone;\n\t} finally {\n\t\tancestors.delete(value);\n\t}\n}\n\nfunction cloneAssignedValue(value: unknown, context: DraftContext, ancestors: Set<object>): unknown {\n\tif (isContainer(value)) return cloneAssigned(value, context, ancestors);\n\tassertJsonPrimitive(value);\n\treturn value;\n}\n\nfunction assertJsonPrimitive(value: unknown): null | boolean | number | string {\n\tif (value === undefined) throw new TypeError(\"Assigned values cannot be undefined\");\n\tif (\n\t\tvalue !== null &&\n\t\ttypeof value !== \"string\" &&\n\t\ttypeof value !== \"boolean\" &&\n\t\t!(typeof value === \"number\" && Number.isFinite(value))\n\t) {\n\t\tthrow new TypeError(\"Assigned values must be strict JSON values\");\n\t}\n\treturn value;\n}\n\nfunction draftValue(context: DraftContext, value: unknown): unknown {\n\tif (!isContainer(value)) return value;\n\treturn getState(context, value).proxy;\n}\n\nfunction isContainer(value: unknown): value is Container {\n\treturn typeof value === \"object\" && value !== null;\n}\n\nfunction isPromiseLike(value: unknown): value is PromiseLike<unknown> {\n\treturn (\n\t\t((typeof value === \"object\" && value !== null) || typeof value === \"function\") &&\n\t\ttypeof (value as { then?: unknown }).then === \"function\"\n\t);\n}\n\nfunction assertActive(context: DraftContext): void {\n\tif (!context.active) throw new TypeError(\"Cannot use a draft outside its change callback\");\n}\n\nfunction assertStringWrite(property: string | symbol): asserts property is string {\n\tif (typeof property === \"symbol\") throw new TypeError(\"Symbol writes are not supported\");\n}\n\nfunction syncArrayTarget(state: DraftState): void {\n\tconst current = currentValue(state);\n\tif (Array.isArray(current)) Reflect.set(state.target!, \"length\", current.length);\n}\n\nfunction finalize(\n\tstate: DraftState,\n\tfinalizing: Set<DraftState>,\n\tfinalized: WeakMap<DraftState, Container>,\n): Container {\n\tconst cached = finalized.get(state);\n\tif (cached !== undefined) return cached;\n\tif (finalizing.has(state)) throw new TypeError(\"Cyclic draft state is not supported\");\n\tfinalizing.add(state);\n\ttry {\n\t\tif (state.copy !== undefined && shallowEqual(state.base, state.copy)) state.copy = undefined;\n\t\tconst current = currentValue(state);\n\t\tlet result = current;\n\t\tfor (const key of Object.keys(current)) {\n\t\t\tconst value = Reflect.get(current, key);\n\t\t\tif (!isContainer(value)) continue;\n\t\t\tconst child = state.context.states.get(value);\n\t\t\tif (child === undefined) continue;\n\t\t\tconst finalizedChild = finalize(child, finalizing, finalized);\n\t\t\tif (finalizedChild === value) continue;\n\t\t\tif (result === state.base) result = shallowOwnedCopy(state.base, state.context);\n\t\t\tObject.defineProperty(result, key, {\n\t\t\t\tvalue: finalizedChild,\n\t\t\t\twritable: true,\n\t\t\t\tenumerable: true,\n\t\t\t\tconfigurable: true,\n\t\t\t});\n\t\t}\n\t\tif (state.copy !== undefined && Array.isArray(result)) assertDenseArray(result);\n\t\tfinalized.set(state, result);\n\t\treturn result;\n\t} finally {\n\t\tfinalizing.delete(state);\n\t}\n}\n\nfunction shallowEqual(left: Container, right: Container): boolean {\n\tif (Array.isArray(left) !== Array.isArray(right)) return false;\n\tif (Array.isArray(left) && Array.isArray(right) && left.length !== right.length) return false;\n\tconst leftKeys = Object.keys(left);\n\tconst rightKeys = Object.keys(right);\n\tif (leftKeys.length !== rightKeys.length) return false;\n\tconst leftRecord = left as Record<string, unknown>;\n\tconst rightRecord = right as Record<string, unknown>;\n\tfor (const key of leftKeys) {\n\t\tif (!Object.hasOwn(right, key) || !Object.is(leftRecord[key], rightRecord[key])) return false;\n\t}\n\treturn true;\n}\n\nfunction assertDenseArray(value: unknown[]): void {\n\tconst keys = Reflect.ownKeys(value);\n\tif (keys.length !== value.length + 1 || keys.some((key) => typeof key !== \"string\")) {\n\t\tthrow new TypeError(\"Draft arrays must be dense and contain only indexed entries\");\n\t}\n\tfor (let index = 0; index < value.length; index++) {\n\t\tif (!Object.hasOwn(value, index) || value[index] === undefined) {\n\t\t\tthrow new TypeError(\"Draft arrays cannot contain holes or undefined entries\");\n\t\t}\n\t}\n}\n"]}
|