reactronic 0.22.306 → 0.22.309
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/build/dist/source/Buffer.d.ts +8 -0
- package/build/dist/source/Buffer.js +8 -0
- package/build/dist/source/Controller.d.ts +12 -0
- package/build/dist/source/Controller.js +6 -0
- package/build/dist/source/Logging.d.ts +38 -0
- package/build/dist/source/Logging.js +113 -0
- package/build/dist/source/Options.d.ts +38 -0
- package/build/dist/source/Options.js +21 -0
- package/build/dist/source/Ref.d.ts +34 -0
- package/build/dist/source/Ref.js +90 -0
- package/build/dist/source/Rx.d.ts +27 -0
- package/build/dist/source/Rx.js +58 -0
- package/build/dist/source/Worker.d.ts +8 -0
- package/build/dist/source/Worker.js +2 -0
- package/build/dist/source/api.d.ts +14 -0
- package/build/dist/source/api.js +42 -0
- 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 +60 -0
- package/build/dist/source/impl/Data.js +51 -0
- package/build/dist/source/impl/Hooks.d.ts +96 -0
- package/build/dist/source/impl/Hooks.js +310 -0
- package/build/dist/source/impl/Journal.d.ts +34 -0
- package/build/dist/source/impl/Journal.js +149 -0
- package/build/dist/source/impl/Meta.d.ts +13 -0
- package/build/dist/source/impl/Meta.js +33 -0
- package/build/dist/source/impl/Monitor.d.ts +32 -0
- package/build/dist/source/impl/Monitor.js +97 -0
- package/build/dist/source/impl/Operation.d.ts +93 -0
- package/build/dist/source/impl/Operation.js +722 -0
- package/build/dist/source/impl/Transaction.d.ts +30 -0
- package/build/dist/source/impl/Transaction.js +313 -0
- package/build/dist/source/util/Dbg.d.ts +15 -0
- package/build/dist/source/util/Dbg.js +96 -0
- package/build/dist/source/util/Sealant.d.ts +14 -0
- package/build/dist/source/util/Sealant.js +30 -0
- package/build/dist/source/util/SealedArray.d.ts +16 -0
- package/build/dist/source/util/SealedArray.js +28 -0
- package/build/dist/source/util/SealedMap.d.ts +13 -0
- package/build/dist/source/util/SealedMap.js +21 -0
- package/build/dist/source/util/SealedSet.d.ts +13 -0
- package/build/dist/source/util/SealedSet.js +21 -0
- package/build/dist/source/util/Utils.d.ts +9 -0
- package/build/dist/source/util/Utils.js +62 -0
- package/package.json +1 -1
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export { Meta } from './Meta';
|
|
2
|
+
export interface AbstractChangeset {
|
|
3
|
+
readonly id: number;
|
|
4
|
+
readonly hint: string;
|
|
5
|
+
readonly timestamp: number;
|
|
6
|
+
readonly sealed: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class Subscription {
|
|
9
|
+
content: any;
|
|
10
|
+
subscribers?: Set<Subscriber>;
|
|
11
|
+
get isOperation(): boolean;
|
|
12
|
+
get originSnapshotId(): number | undefined;
|
|
13
|
+
constructor(content: any);
|
|
14
|
+
}
|
|
15
|
+
export declare type StandaloneMode = boolean | 'isolated' | 'disposal';
|
|
16
|
+
export interface Subscriber {
|
|
17
|
+
readonly order: number;
|
|
18
|
+
readonly subscriptions: Map<Subscription, SubscriptionInfo> | undefined;
|
|
19
|
+
readonly obsoleteSince: number;
|
|
20
|
+
hint(nop?: boolean): string;
|
|
21
|
+
markObsoleteDueTo(subscription: Subscription, m: MemberName, changeset: AbstractChangeset, h: ObjectHandle, outer: string, since: number, reactions: Array<Subscriber>): void;
|
|
22
|
+
runIfNotUpToDate(now: boolean, nothrow: boolean): void;
|
|
23
|
+
}
|
|
24
|
+
export declare type MemberName = PropertyKey;
|
|
25
|
+
export interface SubscriptionInfo {
|
|
26
|
+
readonly memberHint: string;
|
|
27
|
+
readonly usageCount: number;
|
|
28
|
+
}
|
|
29
|
+
export declare class ObjectSnapshot {
|
|
30
|
+
readonly changeset: AbstractChangeset;
|
|
31
|
+
readonly former: {
|
|
32
|
+
snapshot: ObjectSnapshot;
|
|
33
|
+
};
|
|
34
|
+
readonly data: any;
|
|
35
|
+
readonly changes: Set<MemberName>;
|
|
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);
|
|
41
|
+
}
|
|
42
|
+
export declare class ObjectHandle {
|
|
43
|
+
private static generator;
|
|
44
|
+
readonly id: number;
|
|
45
|
+
readonly data: any;
|
|
46
|
+
readonly proxy: any;
|
|
47
|
+
head: ObjectSnapshot;
|
|
48
|
+
editing?: ObjectSnapshot;
|
|
49
|
+
editors: number;
|
|
50
|
+
hint: string;
|
|
51
|
+
constructor(data: any, proxy: any, handler: ProxyHandler<ObjectHandle>, head: ObjectSnapshot, hint: string);
|
|
52
|
+
static getHint(obj: object, full: boolean): string | undefined;
|
|
53
|
+
}
|
|
54
|
+
export declare type PatchSet = Map<object, Map<MemberName, ValuePatch>>;
|
|
55
|
+
export interface ValuePatch {
|
|
56
|
+
memberName: MemberName;
|
|
57
|
+
patchKind: 'update' | 'add' | 'remove';
|
|
58
|
+
freshValue: any;
|
|
59
|
+
formerValue: any;
|
|
60
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObjectHandle = exports.ObjectSnapshot = exports.Subscription = exports.Meta = void 0;
|
|
4
|
+
const Dbg_1 = require("../util/Dbg");
|
|
5
|
+
const Meta_1 = require("./Meta");
|
|
6
|
+
var Meta_2 = require("./Meta");
|
|
7
|
+
Object.defineProperty(exports, "Meta", { enumerable: true, get: function () { return Meta_2.Meta; } });
|
|
8
|
+
class Subscription {
|
|
9
|
+
constructor(content) { this.content = content; }
|
|
10
|
+
get isOperation() { return false; }
|
|
11
|
+
get originSnapshotId() { return 0; }
|
|
12
|
+
}
|
|
13
|
+
exports.Subscription = Subscription;
|
|
14
|
+
class ObjectSnapshot {
|
|
15
|
+
constructor(changeset, former, data) {
|
|
16
|
+
this.changeset = changeset;
|
|
17
|
+
this.former = { snapshot: former || this };
|
|
18
|
+
this.data = data;
|
|
19
|
+
this.changes = new Set();
|
|
20
|
+
this.conflicts = new Map();
|
|
21
|
+
if (Dbg_1.Log.isOn)
|
|
22
|
+
Object.freeze(this);
|
|
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
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.ObjectSnapshot = ObjectSnapshot;
|
|
35
|
+
class ObjectHandle {
|
|
36
|
+
constructor(data, proxy, handler, head, hint) {
|
|
37
|
+
this.id = ++ObjectHandle.generator;
|
|
38
|
+
this.data = data;
|
|
39
|
+
this.proxy = proxy || new Proxy(this, handler);
|
|
40
|
+
this.head = head;
|
|
41
|
+
this.editing = undefined;
|
|
42
|
+
this.editors = 0;
|
|
43
|
+
this.hint = hint;
|
|
44
|
+
}
|
|
45
|
+
static getHint(obj, full) {
|
|
46
|
+
const h = Meta_1.Meta.get(obj, Meta_1.Meta.Handle);
|
|
47
|
+
return h !== undefined ? (full ? `${h.hint}#${h.id}` : h.hint) : undefined;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.ObjectHandle = ObjectHandle;
|
|
51
|
+
ObjectHandle.generator = 19;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { F } from '../util/Utils';
|
|
2
|
+
import { MemberOptions, Kind, Reentrance } from '../Options';
|
|
3
|
+
import { LoggingOptions, ProfilingOptions } from '../Logging';
|
|
4
|
+
import { MemberName, ObjectHandle, StandaloneMode } from './Data';
|
|
5
|
+
import { Journal } from './Journal';
|
|
6
|
+
import { Monitor } from './Monitor';
|
|
7
|
+
export declare abstract class ReactiveObject {
|
|
8
|
+
constructor();
|
|
9
|
+
[Symbol.toStringTag](): string;
|
|
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
|
+
entries(): IterableIterator<[number, T]>;
|
|
39
|
+
keys(): IterableIterator<number>;
|
|
40
|
+
values(): IterableIterator<T>;
|
|
41
|
+
private get mutable();
|
|
42
|
+
}
|
|
43
|
+
export declare class ReactiveMap<K, V> extends ReactiveObject {
|
|
44
|
+
private m;
|
|
45
|
+
clear(): void;
|
|
46
|
+
delete(key: K): boolean;
|
|
47
|
+
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
|
|
48
|
+
get(key: K): V | undefined;
|
|
49
|
+
has(key: K): boolean;
|
|
50
|
+
set(key: K, value: V): this;
|
|
51
|
+
get size(): number;
|
|
52
|
+
entries(): IterableIterator<[K, V]>;
|
|
53
|
+
keys(): IterableIterator<K>;
|
|
54
|
+
values(): IterableIterator<V>;
|
|
55
|
+
private get mutable();
|
|
56
|
+
}
|
|
57
|
+
export declare class OptionsImpl implements MemberOptions {
|
|
58
|
+
readonly getter: Function;
|
|
59
|
+
readonly setter: Function;
|
|
60
|
+
readonly kind: Kind;
|
|
61
|
+
readonly standalone: StandaloneMode;
|
|
62
|
+
readonly order: number;
|
|
63
|
+
readonly noSideEffects: boolean;
|
|
64
|
+
readonly triggeringArgs: boolean;
|
|
65
|
+
readonly throttling: number;
|
|
66
|
+
readonly reentrance: Reentrance;
|
|
67
|
+
readonly journal: Journal | undefined;
|
|
68
|
+
readonly monitor: Monitor | null;
|
|
69
|
+
readonly logging?: Partial<LoggingOptions>;
|
|
70
|
+
static readonly INITIAL: Readonly<OptionsImpl>;
|
|
71
|
+
constructor(getter: Function | undefined, setter: Function | undefined, existing: OptionsImpl, patch: Partial<OptionsImpl>, implicit: boolean);
|
|
72
|
+
}
|
|
73
|
+
export declare class Hooks implements ProxyHandler<ObjectHandle> {
|
|
74
|
+
static reactionsAutoStartDisabled: boolean;
|
|
75
|
+
static repetitiveUsageWarningThreshold: number;
|
|
76
|
+
static mainThreadBlockingWarningThreshold: number;
|
|
77
|
+
static asyncActionDurationWarningThreshold: number;
|
|
78
|
+
static sensitivity: boolean;
|
|
79
|
+
static readonly handler: Hooks;
|
|
80
|
+
getPrototypeOf(h: ObjectHandle): object | null;
|
|
81
|
+
get(h: ObjectHandle, m: MemberName, receiver: any): any;
|
|
82
|
+
set(h: ObjectHandle, m: MemberName, value: any, receiver: any): boolean;
|
|
83
|
+
has(h: ObjectHandle, m: MemberName): boolean;
|
|
84
|
+
getOwnPropertyDescriptor(h: ObjectHandle, m: MemberName): PropertyDescriptor | undefined;
|
|
85
|
+
ownKeys(h: ObjectHandle): Array<string | symbol>;
|
|
86
|
+
static decorateData(reactive: boolean, proto: any, m: MemberName): any;
|
|
87
|
+
static decorateOperation(implicit: boolean, decorator: Function, options: Partial<MemberOptions>, proto: any, member: MemberName, pd: PropertyDescriptor | undefined): any;
|
|
88
|
+
static decorateOperationParametrized(decorator: Function, options: Partial<MemberOptions>): F<any>;
|
|
89
|
+
static acquireHandle(obj: any): ObjectHandle;
|
|
90
|
+
static createHandleForReactiveObject(proto: any, data: any, blank: any, hint: string): ObjectHandle;
|
|
91
|
+
static setProfilingMode(isOn: boolean, options?: Partial<ProfilingOptions>): void;
|
|
92
|
+
static sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
93
|
+
static setHint<T>(obj: T, hint: string | undefined): T;
|
|
94
|
+
static createOperation: (h: ObjectHandle, m: MemberName, options: OptionsImpl) => F<any>;
|
|
95
|
+
static rememberOperationOptions: (proto: any, m: MemberName, getter: Function | undefined, setter: Function | undefined, enumerable: boolean, configurable: boolean, options: Partial<MemberOptions>, implicit: boolean) => OptionsImpl;
|
|
96
|
+
}
|