reactronic 0.22.300 → 0.22.303
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 +20 -20
- package/build/dist/source/Buffer.d.ts +2 -2
- package/build/dist/source/Buffer.js +1 -1
- package/build/dist/source/Logging.d.ts +6 -6
- package/build/dist/source/Ref.d.ts +1 -1
- package/build/dist/source/Ref.js +2 -2
- package/build/dist/source/Rx.d.ts +3 -2
- package/build/dist/source/Rx.js +10 -9
- package/build/dist/source/api.d.ts +3 -3
- package/build/dist/source/api.js +6 -6
- package/build/dist/source/impl/Changeset.d.ts +60 -0
- package/build/dist/source/impl/Changeset.js +361 -0
- package/build/dist/source/impl/Data.d.ts +20 -15
- package/build/dist/source/impl/Data.js +20 -11
- package/build/dist/source/impl/Hooks.d.ts +43 -14
- package/build/dist/source/impl/Hooks.js +89 -49
- package/build/dist/source/impl/Journal.d.ts +4 -4
- package/build/dist/source/impl/Journal.js +57 -46
- package/build/dist/source/impl/Meta.d.ts +3 -3
- package/build/dist/source/impl/Meta.js +7 -7
- package/build/dist/source/impl/Monitor.d.ts +2 -2
- package/build/dist/source/impl/Monitor.js +1 -1
- package/build/dist/source/impl/Operation.d.ts +8 -8
- package/build/dist/source/impl/Operation.js +124 -123
- package/build/dist/source/impl/Transaction.d.ts +2 -2
- package/build/dist/source/impl/Transaction.js +23 -23
- package/package.json +1 -1
- package/build/dist/source/impl/Snapshot.d.ts +0 -60
- package/build/dist/source/impl/Snapshot.js +0 -353
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultSnapshotOptions = exports.EMPTY_SNAPSHOT = exports.Dump = exports.Changeset = exports.UNDEFINED_REVISION = exports.MAX_REVISION = void 0;
|
|
4
|
+
const Utils_1 = require("../util/Utils");
|
|
5
|
+
const Dbg_1 = require("../util/Dbg");
|
|
6
|
+
const Sealant_1 = require("../util/Sealant");
|
|
7
|
+
const SealedArray_1 = require("../util/SealedArray");
|
|
8
|
+
const SealedMap_1 = require("../util/SealedMap");
|
|
9
|
+
const SealedSet_1 = require("../util/SealedSet");
|
|
10
|
+
const Data_1 = require("./Data");
|
|
11
|
+
exports.MAX_REVISION = Number.MAX_SAFE_INTEGER;
|
|
12
|
+
exports.UNDEFINED_REVISION = exports.MAX_REVISION - 1;
|
|
13
|
+
Object.defineProperty(Data_1.ObjectHandle.prototype, '#this', {
|
|
14
|
+
configurable: false, enumerable: false,
|
|
15
|
+
get() {
|
|
16
|
+
const result = {};
|
|
17
|
+
const data = Changeset.current().getRelevantSnapshot(this, '#this').data;
|
|
18
|
+
for (const m in data) {
|
|
19
|
+
const v = data[m];
|
|
20
|
+
if (v instanceof Data_1.Subscription)
|
|
21
|
+
result[m] = v.content;
|
|
22
|
+
else if (v === Data_1.Meta.Nonreactive)
|
|
23
|
+
result[m] = this.data[m];
|
|
24
|
+
else
|
|
25
|
+
result[m] = v;
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const EMPTY_ARRAY = Object.freeze([]);
|
|
31
|
+
const EMPTY_MAP = Utils_1.Utils.freezeMap(new Map());
|
|
32
|
+
class Changeset {
|
|
33
|
+
constructor(options) {
|
|
34
|
+
this.id = ++Changeset.idGen;
|
|
35
|
+
this.options = options !== null && options !== void 0 ? options : exports.DefaultSnapshotOptions;
|
|
36
|
+
this.revision = exports.UNDEFINED_REVISION;
|
|
37
|
+
this.bumper = 100;
|
|
38
|
+
this.items = new Map();
|
|
39
|
+
this.reactions = [];
|
|
40
|
+
this.sealed = false;
|
|
41
|
+
}
|
|
42
|
+
get hint() { var _a; return (_a = this.options.hint) !== null && _a !== void 0 ? _a : 'noname'; }
|
|
43
|
+
get timestamp() { return this.revision; }
|
|
44
|
+
seekSnapshot(h, m) {
|
|
45
|
+
let os = h.editing;
|
|
46
|
+
if (os && os.changeset !== this) {
|
|
47
|
+
os = this.items.get(h);
|
|
48
|
+
if (os)
|
|
49
|
+
h.editing = os;
|
|
50
|
+
}
|
|
51
|
+
if (!os) {
|
|
52
|
+
os = h.head;
|
|
53
|
+
while (os !== exports.EMPTY_SNAPSHOT && os.changeset.timestamp > this.timestamp)
|
|
54
|
+
os = os.former.snapshot;
|
|
55
|
+
}
|
|
56
|
+
return os;
|
|
57
|
+
}
|
|
58
|
+
getRelevantSnapshot(h, m) {
|
|
59
|
+
const r = this.seekSnapshot(h, m);
|
|
60
|
+
if (r === exports.EMPTY_SNAPSHOT)
|
|
61
|
+
throw (0, Dbg_1.misuse)(`object ${Dump.obj(h)} doesn't exist in snapshot v${this.revision} (${this.hint})`);
|
|
62
|
+
return r;
|
|
63
|
+
}
|
|
64
|
+
getEditableSnapshot(h, m, value, token) {
|
|
65
|
+
let os = this.seekSnapshot(h, m);
|
|
66
|
+
const existing = os.data[m];
|
|
67
|
+
if (existing !== Data_1.Meta.Nonreactive) {
|
|
68
|
+
if (this.isNewSnapshotRequired(h, os, m, existing, value, token)) {
|
|
69
|
+
this.bumpBy(os.changeset.timestamp);
|
|
70
|
+
const revision = m === Data_1.Meta.Handle ? 1 : os.revision + 1;
|
|
71
|
+
const data = Object.assign({}, m === Data_1.Meta.Handle ? value : os.data);
|
|
72
|
+
Data_1.Meta.set(data, Data_1.Meta.Handle, h);
|
|
73
|
+
Data_1.Meta.set(data, Data_1.Meta.Revision, new Data_1.Subscription(revision));
|
|
74
|
+
os = new Data_1.ObjectSnapshot(this, os, data);
|
|
75
|
+
this.items.set(h, os);
|
|
76
|
+
h.editing = os;
|
|
77
|
+
h.editors++;
|
|
78
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.write)
|
|
79
|
+
Dbg_1.Log.write('║', ' ⎘⎘', `${Dump.obj(h)} - new snapshot is created (revision ${revision})`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else
|
|
83
|
+
os = exports.EMPTY_SNAPSHOT;
|
|
84
|
+
return os;
|
|
85
|
+
}
|
|
86
|
+
static takeSnapshot(obj) {
|
|
87
|
+
return obj[Data_1.Meta.Handle]['#this'];
|
|
88
|
+
}
|
|
89
|
+
static dispose(obj) {
|
|
90
|
+
const ctx = Changeset.edit();
|
|
91
|
+
const h = Data_1.Meta.get(obj, Data_1.Meta.Handle);
|
|
92
|
+
if (h !== undefined)
|
|
93
|
+
Changeset.doDispose(ctx, h);
|
|
94
|
+
}
|
|
95
|
+
static doDispose(ctx, h) {
|
|
96
|
+
const os = ctx.getEditableSnapshot(h, Data_1.Meta.Revision, Data_1.Meta.Undefined);
|
|
97
|
+
if (os !== exports.EMPTY_SNAPSHOT)
|
|
98
|
+
os.disposed = true;
|
|
99
|
+
return os;
|
|
100
|
+
}
|
|
101
|
+
isNewSnapshotRequired(h, os, m, existing, value, token) {
|
|
102
|
+
if (this.sealed && os.changeset !== exports.EMPTY_SNAPSHOT.changeset)
|
|
103
|
+
throw (0, Dbg_1.misuse)(`reactive property ${Dump.obj(h, m)} can only be modified inside transaction`);
|
|
104
|
+
if (m !== Data_1.Meta.Handle && value !== Data_1.Meta.Handle) {
|
|
105
|
+
if (os.changeset !== this || os.former.snapshot !== exports.EMPTY_SNAPSHOT) {
|
|
106
|
+
if (this.options.token !== undefined && token !== this.options.token)
|
|
107
|
+
throw (0, Dbg_1.misuse)(`${this.hint} should not have side effects (trying to change ${Dump.snapshot(os, m)})`);
|
|
108
|
+
}
|
|
109
|
+
if (os === exports.EMPTY_SNAPSHOT)
|
|
110
|
+
throw (0, Dbg_1.misuse)(`member ${Dump.snapshot(os, m)} doesn't exist in snapshot v${this.revision} (${this.hint})`);
|
|
111
|
+
}
|
|
112
|
+
return os.changeset !== this && !this.sealed;
|
|
113
|
+
}
|
|
114
|
+
acquire(outer) {
|
|
115
|
+
if (!this.sealed && this.revision === exports.UNDEFINED_REVISION) {
|
|
116
|
+
const ahead = this.options.token === undefined || outer.revision === exports.UNDEFINED_REVISION;
|
|
117
|
+
this.revision = ahead ? Changeset.stampGen : outer.revision;
|
|
118
|
+
Changeset.pending.push(this);
|
|
119
|
+
if (Changeset.oldest === undefined)
|
|
120
|
+
Changeset.oldest = this;
|
|
121
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.transaction)
|
|
122
|
+
Dbg_1.Log.write('╔══', `v${this.revision}`, `${this.hint}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
bumpBy(timestamp) {
|
|
126
|
+
if (timestamp > this.bumper)
|
|
127
|
+
this.bumper = timestamp;
|
|
128
|
+
}
|
|
129
|
+
rebase() {
|
|
130
|
+
let conflicts = undefined;
|
|
131
|
+
if (this.items.size > 0) {
|
|
132
|
+
this.items.forEach((os, h) => {
|
|
133
|
+
if (os.former.snapshot !== h.head) {
|
|
134
|
+
const merged = this.merge(h, os);
|
|
135
|
+
if (os.conflicts.size > 0) {
|
|
136
|
+
if (!conflicts)
|
|
137
|
+
conflicts = [];
|
|
138
|
+
conflicts.push(os);
|
|
139
|
+
}
|
|
140
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.transaction)
|
|
141
|
+
Dbg_1.Log.write('╠╝', '', `${Dump.snapshot2(h, os.changeset)} is merged with ${Dump.snapshot2(h, h.head.changeset)} among ${merged} properties with ${os.conflicts.size} conflicts.`);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
if (this.options.token === undefined) {
|
|
145
|
+
if (this.bumper > 100) {
|
|
146
|
+
this.bumper = this.revision;
|
|
147
|
+
this.revision = ++Changeset.stampGen;
|
|
148
|
+
}
|
|
149
|
+
else
|
|
150
|
+
this.revision = this.bumper + 1;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.revision = this.bumper;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return conflicts;
|
|
157
|
+
}
|
|
158
|
+
merge(h, ours) {
|
|
159
|
+
let counter = 0;
|
|
160
|
+
const head = h.head;
|
|
161
|
+
const headDisposed = head.disposed;
|
|
162
|
+
const oursDisposed = ours.disposed;
|
|
163
|
+
const merged = Object.assign({}, head.data);
|
|
164
|
+
ours.changes.forEach((o, m) => {
|
|
165
|
+
counter++;
|
|
166
|
+
merged[m] = ours.data[m];
|
|
167
|
+
if (headDisposed || oursDisposed) {
|
|
168
|
+
if (headDisposed !== oursDisposed) {
|
|
169
|
+
if (headDisposed || this.options.standalone !== 'disposal') {
|
|
170
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.change)
|
|
171
|
+
Dbg_1.Log.write('║╠', '', `${Dump.snapshot2(h, ours.changeset, m)} <> ${Dump.snapshot2(h, head.changeset, m)}`, 0, ' *** CONFLICT ***');
|
|
172
|
+
ours.conflicts.set(m, head);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const conflict = Changeset.isConflicting(head.data[m], ours.former.snapshot.data[m]);
|
|
178
|
+
if (conflict)
|
|
179
|
+
ours.conflicts.set(m, head);
|
|
180
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.change)
|
|
181
|
+
Dbg_1.Log.write('║╠', '', `${Dump.snapshot2(h, ours.changeset, m)} ${conflict ? '<>' : '=='} ${Dump.snapshot2(h, head.changeset, m)}`, 0, conflict ? ' *** CONFLICT ***' : undefined);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
Utils_1.Utils.copyAllMembers(merged, ours.data);
|
|
185
|
+
ours.former.snapshot = head;
|
|
186
|
+
return counter;
|
|
187
|
+
}
|
|
188
|
+
applyOrDiscard(error) {
|
|
189
|
+
this.sealed = true;
|
|
190
|
+
this.items.forEach((os, h) => {
|
|
191
|
+
Changeset.sealObjectSnapshot(h, os);
|
|
192
|
+
h.editors--;
|
|
193
|
+
if (h.editors === 0)
|
|
194
|
+
h.editing = undefined;
|
|
195
|
+
if (!error) {
|
|
196
|
+
h.head = os;
|
|
197
|
+
if (Changeset.garbageCollectionSummaryInterval < Number.MAX_SAFE_INTEGER) {
|
|
198
|
+
Changeset.totalObjectSnapshotCount++;
|
|
199
|
+
if (os.former.snapshot === exports.EMPTY_SNAPSHOT)
|
|
200
|
+
Changeset.totalObjectHandleCount++;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (Dbg_1.Log.isOn) {
|
|
205
|
+
if (Dbg_1.Log.opt.change && !error) {
|
|
206
|
+
this.items.forEach((os, h) => {
|
|
207
|
+
const members = [];
|
|
208
|
+
os.changes.forEach((o, m) => members.push(m.toString()));
|
|
209
|
+
const s = members.join(', ');
|
|
210
|
+
Dbg_1.Log.write('║', '√', `${Dump.snapshot2(h, os.changeset)} (${s}) is ${os.former.snapshot === exports.EMPTY_SNAPSHOT ? 'constructed' : `applied on top of ${Dump.snapshot2(h, os.former.snapshot.changeset)}`}`);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
if (Dbg_1.Log.opt.transaction)
|
|
214
|
+
Dbg_1.Log.write(this.revision < exports.UNDEFINED_REVISION ? '╚══' : '═══', `v${this.revision}`, `${this.hint} - ${error ? 'CANCEL' : 'APPLY'}(${this.items.size})${error ? ` - ${error}` : ''}`);
|
|
215
|
+
}
|
|
216
|
+
if (!error)
|
|
217
|
+
Changeset.propagateAllChangesThroughSubscriptions(this);
|
|
218
|
+
return this.reactions;
|
|
219
|
+
}
|
|
220
|
+
static sealObjectSnapshot(h, os) {
|
|
221
|
+
if (!os.disposed)
|
|
222
|
+
os.changes.forEach((o, m) => Changeset.sealSubscription(os.data[m], m, h.proxy.constructor.name));
|
|
223
|
+
else
|
|
224
|
+
for (const m in os.former.snapshot.data)
|
|
225
|
+
os.data[m] = Data_1.Meta.Undefined;
|
|
226
|
+
if (Dbg_1.Log.isOn)
|
|
227
|
+
Changeset.freezeObjectSnapshot(os);
|
|
228
|
+
}
|
|
229
|
+
static sealSubscription(subscription, m, typeName) {
|
|
230
|
+
if (subscription instanceof Data_1.Subscription) {
|
|
231
|
+
const value = subscription.content;
|
|
232
|
+
if (value !== undefined && value !== null) {
|
|
233
|
+
const sealedType = Object.getPrototypeOf(value)[Sealant_1.Sealant.SealedType];
|
|
234
|
+
if (sealedType)
|
|
235
|
+
subscription.content = Sealant_1.Sealant.seal(value, sealedType, typeName, m);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
static freezeObjectSnapshot(os) {
|
|
240
|
+
Object.freeze(os.data);
|
|
241
|
+
Utils_1.Utils.freezeSet(os.changes);
|
|
242
|
+
Utils_1.Utils.freezeMap(os.conflicts);
|
|
243
|
+
return os;
|
|
244
|
+
}
|
|
245
|
+
triggerGarbageCollection() {
|
|
246
|
+
if (this.revision !== 0) {
|
|
247
|
+
if (this === Changeset.oldest) {
|
|
248
|
+
const p = Changeset.pending;
|
|
249
|
+
p.sort((a, b) => a.revision - b.revision);
|
|
250
|
+
let i = 0;
|
|
251
|
+
while (i < p.length && p[i].sealed) {
|
|
252
|
+
p[i].unlinkHistory();
|
|
253
|
+
i++;
|
|
254
|
+
}
|
|
255
|
+
Changeset.pending = p.slice(i);
|
|
256
|
+
Changeset.oldest = Changeset.pending[0];
|
|
257
|
+
const now = Date.now();
|
|
258
|
+
if (now - Changeset.lastGarbageCollectionSummaryTimestamp > Changeset.garbageCollectionSummaryInterval) {
|
|
259
|
+
Dbg_1.Log.write('', '[G]', `Total object/snapshot count: ${Changeset.totalObjectHandleCount}/${Changeset.totalObjectSnapshotCount}`);
|
|
260
|
+
Changeset.lastGarbageCollectionSummaryTimestamp = now;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
unlinkHistory() {
|
|
266
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.gc)
|
|
267
|
+
Dbg_1.Log.write('', '[G]', `Dismiss history below v${this.revision}t${this.id} (${this.hint})`);
|
|
268
|
+
this.items.forEach((os, h) => {
|
|
269
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.gc && os.former.snapshot !== exports.EMPTY_SNAPSHOT)
|
|
270
|
+
Dbg_1.Log.write(' ', ' ', `${Dump.snapshot2(h, os.former.snapshot.changeset)} is ready for GC because overwritten by ${Dump.snapshot2(h, os.changeset)}`);
|
|
271
|
+
if (Changeset.garbageCollectionSummaryInterval < Number.MAX_SAFE_INTEGER) {
|
|
272
|
+
if (os.former.snapshot !== exports.EMPTY_SNAPSHOT)
|
|
273
|
+
Changeset.totalObjectSnapshotCount--;
|
|
274
|
+
if (os.disposed)
|
|
275
|
+
Changeset.totalObjectHandleCount--;
|
|
276
|
+
}
|
|
277
|
+
os.former.snapshot = exports.EMPTY_SNAPSHOT;
|
|
278
|
+
});
|
|
279
|
+
this.items = EMPTY_MAP;
|
|
280
|
+
this.reactions = EMPTY_ARRAY;
|
|
281
|
+
if (Dbg_1.Log.isOn)
|
|
282
|
+
Object.freeze(this);
|
|
283
|
+
}
|
|
284
|
+
static _init() {
|
|
285
|
+
const boot = exports.EMPTY_SNAPSHOT.changeset;
|
|
286
|
+
boot.acquire(boot);
|
|
287
|
+
boot.applyOrDiscard();
|
|
288
|
+
boot.triggerGarbageCollection();
|
|
289
|
+
Changeset.freezeObjectSnapshot(exports.EMPTY_SNAPSHOT);
|
|
290
|
+
Changeset.idGen = 100;
|
|
291
|
+
Changeset.stampGen = 101;
|
|
292
|
+
Changeset.oldest = undefined;
|
|
293
|
+
SealedArray_1.SealedArray.prototype;
|
|
294
|
+
SealedMap_1.SealedMap.prototype;
|
|
295
|
+
SealedSet_1.SealedSet.prototype;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
exports.Changeset = Changeset;
|
|
299
|
+
Changeset.idGen = -1;
|
|
300
|
+
Changeset.stampGen = 1;
|
|
301
|
+
Changeset.pending = [];
|
|
302
|
+
Changeset.oldest = undefined;
|
|
303
|
+
Changeset.garbageCollectionSummaryInterval = Number.MAX_SAFE_INTEGER;
|
|
304
|
+
Changeset.lastGarbageCollectionSummaryTimestamp = Date.now();
|
|
305
|
+
Changeset.totalObjectHandleCount = 0;
|
|
306
|
+
Changeset.totalObjectSnapshotCount = 0;
|
|
307
|
+
Changeset.current = Utils_1.UNDEF;
|
|
308
|
+
Changeset.edit = Utils_1.UNDEF;
|
|
309
|
+
Changeset.markUsed = Utils_1.UNDEF;
|
|
310
|
+
Changeset.markEdited = Utils_1.UNDEF;
|
|
311
|
+
Changeset.isConflicting = Utils_1.UNDEF;
|
|
312
|
+
Changeset.propagateAllChangesThroughSubscriptions = (changeset) => { };
|
|
313
|
+
Changeset.revokeAllSubscriptions = (changeset) => { };
|
|
314
|
+
Changeset.enqueueReactionsToRun = (reactions) => { };
|
|
315
|
+
class Dump {
|
|
316
|
+
static obj(h, m, stamp, snapshotId, originSnapshotId, value) {
|
|
317
|
+
const member = m !== undefined ? `.${m.toString()}` : '';
|
|
318
|
+
let result;
|
|
319
|
+
if (h !== undefined) {
|
|
320
|
+
const v = value !== undefined && value !== Data_1.Meta.Undefined ? `[=${Dump.valueHint(value)}]` : '';
|
|
321
|
+
if (stamp === undefined)
|
|
322
|
+
result = `${h.hint}${member}${v} #${h.id}`;
|
|
323
|
+
else
|
|
324
|
+
result = `${h.hint}${member}${v} #${h.id}t${snapshotId}v${stamp}${originSnapshotId !== undefined && originSnapshotId !== 0 ? `t${originSnapshotId}` : ''}`;
|
|
325
|
+
}
|
|
326
|
+
else
|
|
327
|
+
result = `boot${member}`;
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
static snapshot2(h, s, m, o) {
|
|
331
|
+
var _a;
|
|
332
|
+
return Dump.obj(h, m, s.timestamp, s.id, o === null || o === void 0 ? void 0 : o.originSnapshotId, (_a = o === null || o === void 0 ? void 0 : o.content) !== null && _a !== void 0 ? _a : Data_1.Meta.Undefined);
|
|
333
|
+
}
|
|
334
|
+
static snapshot(os, m) {
|
|
335
|
+
const h = Data_1.Meta.get(os.data, Data_1.Meta.Handle);
|
|
336
|
+
const value = m !== undefined ? os.data[m] : undefined;
|
|
337
|
+
return Dump.obj(h, m, os.changeset.timestamp, os.changeset.id, value === null || value === void 0 ? void 0 : value.originSnapshotId);
|
|
338
|
+
}
|
|
339
|
+
static conflicts(conflicts) {
|
|
340
|
+
return conflicts.map(ours => {
|
|
341
|
+
const items = [];
|
|
342
|
+
ours.conflicts.forEach((theirs, m) => {
|
|
343
|
+
items.push(Dump.conflictingMemberHint(m, ours, theirs));
|
|
344
|
+
});
|
|
345
|
+
return items.join(', ');
|
|
346
|
+
}).join(', ');
|
|
347
|
+
}
|
|
348
|
+
static conflictingMemberHint(m, ours, theirs) {
|
|
349
|
+
return `${theirs.changeset.hint} (${Dump.snapshot(theirs, m)})`;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
exports.Dump = Dump;
|
|
353
|
+
Dump.valueHint = (value, m) => '???';
|
|
354
|
+
exports.EMPTY_SNAPSHOT = new Data_1.ObjectSnapshot(new Changeset({ hint: '<empty>' }), undefined, {});
|
|
355
|
+
exports.DefaultSnapshotOptions = Object.freeze({
|
|
356
|
+
hint: 'noname',
|
|
357
|
+
standalone: false,
|
|
358
|
+
journal: undefined,
|
|
359
|
+
logging: undefined,
|
|
360
|
+
token: undefined,
|
|
361
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Meta } from './Meta';
|
|
2
|
-
export interface
|
|
2
|
+
export interface AbstractChangeset {
|
|
3
3
|
readonly id: number;
|
|
4
4
|
readonly hint: string;
|
|
5
5
|
readonly timestamp: number;
|
|
@@ -18,7 +18,7 @@ export interface Subscriber {
|
|
|
18
18
|
readonly subscriptions: Map<Subscription, SubscriptionInfo> | undefined;
|
|
19
19
|
readonly obsoleteSince: number;
|
|
20
20
|
hint(nop?: boolean): string;
|
|
21
|
-
markObsoleteDueTo(subscription: Subscription,
|
|
21
|
+
markObsoleteDueTo(subscription: Subscription, m: MemberName, changeset: AbstractChangeset, h: ObjectHandle, outer: string, since: number, reactions: Array<Subscriber>): void;
|
|
22
22
|
runIfNotUpToDate(now: boolean, nothrow: boolean): void;
|
|
23
23
|
}
|
|
24
24
|
export declare type MemberName = PropertyKey;
|
|
@@ -26,33 +26,38 @@ export interface SubscriptionInfo {
|
|
|
26
26
|
readonly memberHint: string;
|
|
27
27
|
readonly usageCount: number;
|
|
28
28
|
}
|
|
29
|
-
export declare class
|
|
30
|
-
readonly
|
|
29
|
+
export declare class ObjectSnapshot {
|
|
30
|
+
readonly changeset: AbstractChangeset;
|
|
31
31
|
readonly former: {
|
|
32
|
-
|
|
32
|
+
snapshot: ObjectSnapshot;
|
|
33
33
|
};
|
|
34
34
|
readonly data: any;
|
|
35
35
|
readonly changes: Set<MemberName>;
|
|
36
|
-
readonly conflicts: Map<MemberName,
|
|
37
|
-
constructor(
|
|
36
|
+
readonly conflicts: Map<MemberName, ObjectSnapshot>;
|
|
37
|
+
constructor(changeset: AbstractChangeset, former: ObjectSnapshot | undefined, data: object);
|
|
38
|
+
get revision(): number;
|
|
39
|
+
get disposed(): boolean;
|
|
40
|
+
set disposed(value: boolean);
|
|
38
41
|
}
|
|
39
|
-
export declare class
|
|
42
|
+
export declare class ObjectHandle {
|
|
40
43
|
private static generator;
|
|
41
44
|
readonly id: number;
|
|
42
45
|
readonly data: any;
|
|
43
46
|
readonly proxy: any;
|
|
44
|
-
head:
|
|
45
|
-
editing?:
|
|
47
|
+
head: ObjectSnapshot;
|
|
48
|
+
editing?: ObjectSnapshot;
|
|
46
49
|
editors: number;
|
|
47
50
|
hint: string;
|
|
48
|
-
constructor(data: any, proxy: any, handler: ProxyHandler<
|
|
51
|
+
constructor(data: any, proxy: any, handler: ProxyHandler<ObjectHandle>, head: ObjectSnapshot, hint: string);
|
|
49
52
|
static getHint(obj: object, full: boolean): string | undefined;
|
|
50
53
|
}
|
|
51
54
|
export interface PatchSet {
|
|
52
55
|
hint: string;
|
|
53
|
-
|
|
56
|
+
items: Map<object, Map<MemberName, ValuePatch>>;
|
|
54
57
|
}
|
|
55
|
-
export interface
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
export interface ValuePatch {
|
|
59
|
+
memberName: MemberName;
|
|
60
|
+
patchKind: 'update' | 'add' | 'remove';
|
|
61
|
+
freshValue: any;
|
|
62
|
+
formerValue: any;
|
|
58
63
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ObjectHandle = exports.ObjectSnapshot = exports.Subscription = exports.Meta = void 0;
|
|
4
4
|
const Dbg_1 = require("../util/Dbg");
|
|
5
5
|
const Meta_1 = require("./Meta");
|
|
6
6
|
var Meta_2 = require("./Meta");
|
|
@@ -11,21 +11,30 @@ class Subscription {
|
|
|
11
11
|
get originSnapshotId() { return 0; }
|
|
12
12
|
}
|
|
13
13
|
exports.Subscription = Subscription;
|
|
14
|
-
class
|
|
15
|
-
constructor(
|
|
16
|
-
this.
|
|
17
|
-
this.former = {
|
|
14
|
+
class ObjectSnapshot {
|
|
15
|
+
constructor(changeset, former, data) {
|
|
16
|
+
this.changeset = changeset;
|
|
17
|
+
this.former = { snapshot: former || this };
|
|
18
18
|
this.data = data;
|
|
19
19
|
this.changes = new Set();
|
|
20
20
|
this.conflicts = new Map();
|
|
21
21
|
if (Dbg_1.Log.isOn)
|
|
22
22
|
Object.freeze(this);
|
|
23
23
|
}
|
|
24
|
+
get revision() {
|
|
25
|
+
return this.data[Meta_1.Meta.Revision].content;
|
|
26
|
+
}
|
|
27
|
+
get disposed() { return this.revision < 0; }
|
|
28
|
+
set disposed(value) {
|
|
29
|
+
const rev = this.revision;
|
|
30
|
+
if (rev < 0 !== value)
|
|
31
|
+
this.data[Meta_1.Meta.Revision].content = ~rev;
|
|
32
|
+
}
|
|
24
33
|
}
|
|
25
|
-
exports.
|
|
26
|
-
class
|
|
34
|
+
exports.ObjectSnapshot = ObjectSnapshot;
|
|
35
|
+
class ObjectHandle {
|
|
27
36
|
constructor(data, proxy, handler, head, hint) {
|
|
28
|
-
this.id = ++
|
|
37
|
+
this.id = ++ObjectHandle.generator;
|
|
29
38
|
this.data = data;
|
|
30
39
|
this.proxy = proxy || new Proxy(this, handler);
|
|
31
40
|
this.head = head;
|
|
@@ -34,9 +43,9 @@ class DataHolder {
|
|
|
34
43
|
this.hint = hint;
|
|
35
44
|
}
|
|
36
45
|
static getHint(obj, full) {
|
|
37
|
-
const h = Meta_1.Meta.get(obj, Meta_1.Meta.
|
|
46
|
+
const h = Meta_1.Meta.get(obj, Meta_1.Meta.Handle);
|
|
38
47
|
return h !== undefined ? (full ? `${h.hint}#${h.id}` : h.hint) : undefined;
|
|
39
48
|
}
|
|
40
49
|
}
|
|
41
|
-
exports.
|
|
42
|
-
|
|
50
|
+
exports.ObjectHandle = ObjectHandle;
|
|
51
|
+
ObjectHandle.generator = 19;
|
|
@@ -1,13 +1,42 @@
|
|
|
1
1
|
import { F } from '../util/Utils';
|
|
2
2
|
import { MemberOptions, Kind, Reentrance } from '../Options';
|
|
3
3
|
import { LoggingOptions, ProfilingOptions } from '../Logging';
|
|
4
|
-
import { MemberName,
|
|
4
|
+
import { MemberName, ObjectHandle, StandaloneMode } from './Data';
|
|
5
5
|
import { Journal } from './Journal';
|
|
6
6
|
import { Monitor } from './Monitor';
|
|
7
|
-
export declare abstract class
|
|
7
|
+
export declare abstract class ReactiveObject {
|
|
8
8
|
constructor();
|
|
9
9
|
[Symbol.toStringTag](): string;
|
|
10
10
|
}
|
|
11
|
+
export declare class ReactiveArray<T> extends ReactiveObject {
|
|
12
|
+
private a;
|
|
13
|
+
get length(): number;
|
|
14
|
+
set length(n: number);
|
|
15
|
+
get(n: number): T;
|
|
16
|
+
set(n: number, item: T): void;
|
|
17
|
+
toString(): string;
|
|
18
|
+
toLocaleString(): string;
|
|
19
|
+
pop(): T | undefined;
|
|
20
|
+
push(...items: T[]): number;
|
|
21
|
+
concat(...items: (T | ConcatArray<T>)[]): T[];
|
|
22
|
+
join(separator?: string): string;
|
|
23
|
+
reverse(): T[];
|
|
24
|
+
shift(): T | undefined;
|
|
25
|
+
slice(start?: number, end?: number): T[];
|
|
26
|
+
sort(compareFn?: (a: T, b: T) => number): this;
|
|
27
|
+
splice(start: number, deleteCount?: number): T[];
|
|
28
|
+
unshift(...items: T[]): number;
|
|
29
|
+
indexOf(searchElement: T, fromIndex?: number): number;
|
|
30
|
+
lastIndexOf(searchElement: T, fromIndex?: number): number;
|
|
31
|
+
every(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean;
|
|
32
|
+
some(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean;
|
|
33
|
+
forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
|
|
34
|
+
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
|
|
35
|
+
filter(predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): T[];
|
|
36
|
+
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
|
|
37
|
+
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
|
|
38
|
+
private get mutable();
|
|
39
|
+
}
|
|
11
40
|
export declare class OptionsImpl implements MemberOptions {
|
|
12
41
|
readonly getter: Function;
|
|
13
42
|
readonly setter: Function;
|
|
@@ -24,27 +53,27 @@ export declare class OptionsImpl implements MemberOptions {
|
|
|
24
53
|
static readonly INITIAL: Readonly<OptionsImpl>;
|
|
25
54
|
constructor(getter: Function | undefined, setter: Function | undefined, existing: OptionsImpl, patch: Partial<OptionsImpl>, implicit: boolean);
|
|
26
55
|
}
|
|
27
|
-
export declare class Hooks implements ProxyHandler<
|
|
56
|
+
export declare class Hooks implements ProxyHandler<ObjectHandle> {
|
|
28
57
|
static reactionsAutoStartDisabled: boolean;
|
|
29
58
|
static repetitiveUsageWarningThreshold: number;
|
|
30
59
|
static mainThreadBlockingWarningThreshold: number;
|
|
31
60
|
static asyncActionDurationWarningThreshold: number;
|
|
32
61
|
static sensitivity: boolean;
|
|
33
|
-
static readonly
|
|
34
|
-
getPrototypeOf(h:
|
|
35
|
-
get(h:
|
|
36
|
-
set(h:
|
|
37
|
-
has(h:
|
|
38
|
-
getOwnPropertyDescriptor(h:
|
|
39
|
-
ownKeys(h:
|
|
40
|
-
static decorateData(
|
|
62
|
+
static readonly handler: Hooks;
|
|
63
|
+
getPrototypeOf(h: ObjectHandle): object | null;
|
|
64
|
+
get(h: ObjectHandle, m: MemberName, receiver: any): any;
|
|
65
|
+
set(h: ObjectHandle, m: MemberName, value: any, receiver: any): boolean;
|
|
66
|
+
has(h: ObjectHandle, m: MemberName): boolean;
|
|
67
|
+
getOwnPropertyDescriptor(h: ObjectHandle, m: MemberName): PropertyDescriptor | undefined;
|
|
68
|
+
ownKeys(h: ObjectHandle): Array<string | symbol>;
|
|
69
|
+
static decorateData(reactive: boolean, proto: any, m: MemberName): any;
|
|
41
70
|
static decorateOperation(implicit: boolean, decorator: Function, options: Partial<MemberOptions>, proto: any, member: MemberName, pd: PropertyDescriptor | undefined): any;
|
|
42
71
|
static decorateOperationParametrized(decorator: Function, options: Partial<MemberOptions>): F<any>;
|
|
43
|
-
static
|
|
44
|
-
static
|
|
72
|
+
static acquireHandle(obj: any): ObjectHandle;
|
|
73
|
+
static createHandleForReactiveObject(proto: any, data: any, blank: any, hint: string): ObjectHandle;
|
|
45
74
|
static setProfilingMode(isOn: boolean, options?: Partial<ProfilingOptions>): void;
|
|
46
75
|
static sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
47
76
|
static setHint<T>(obj: T, hint: string | undefined): T;
|
|
48
|
-
static createOperation: (h:
|
|
77
|
+
static createOperation: (h: ObjectHandle, m: MemberName, options: OptionsImpl) => F<any>;
|
|
49
78
|
static rememberOperationOptions: (proto: any, m: MemberName, getter: Function | undefined, setter: Function | undefined, enumerable: boolean, configurable: boolean, options: Partial<MemberOptions>, implicit: boolean) => OptionsImpl;
|
|
50
79
|
}
|