reactronic 0.21.529 → 0.21.603
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/impl/Data.d.ts +4 -3
- package/build/dist/source/impl/Data.js +1 -1
- package/build/dist/source/impl/Operation.d.ts +8 -7
- package/build/dist/source/impl/Operation.js +80 -82
- package/build/dist/source/impl/Snapshot.d.ts +6 -6
- package/build/dist/source/impl/Snapshot.js +23 -22
- package/build/dist/source/impl/Transaction.js +6 -4
- package/build/dist/source/util/Utils.d.ts +2 -2
- package/build/dist/source/util/Utils.js +2 -0
- package/package.json +1 -1
|
@@ -18,12 +18,13 @@ export interface Observer {
|
|
|
18
18
|
readonly observables: Map<Observable, MemberInfo> | undefined;
|
|
19
19
|
readonly obsoleteSince: number;
|
|
20
20
|
hint(nop?: boolean): string;
|
|
21
|
-
markObsoleteDueTo(observable: Observable,
|
|
21
|
+
markObsoleteDueTo(observable: Observable, memberName: MemberName, snapshot: AbstractSnapshot, holder: ObjectHolder, outer: string, since: number, reactions: Observer[]): void;
|
|
22
22
|
runIfNotUpToDate(now: boolean, nothrow: boolean): void;
|
|
23
23
|
}
|
|
24
24
|
export declare type MemberName = PropertyKey;
|
|
25
25
|
export interface MemberInfo {
|
|
26
|
-
readonly
|
|
26
|
+
readonly holder: ObjectHolder;
|
|
27
|
+
readonly snapshot: AbstractSnapshot;
|
|
27
28
|
readonly memberName: MemberName;
|
|
28
29
|
readonly usageCount: number;
|
|
29
30
|
}
|
|
@@ -33,7 +34,7 @@ export declare class ObjectRevision {
|
|
|
33
34
|
revision: ObjectRevision;
|
|
34
35
|
};
|
|
35
36
|
readonly data: any;
|
|
36
|
-
readonly changes:
|
|
37
|
+
readonly changes: Set<MemberName>;
|
|
37
38
|
readonly conflicts: Map<MemberName, ObjectRevision>;
|
|
38
39
|
constructor(snapshot: AbstractSnapshot, prev: ObjectRevision | undefined, data: object);
|
|
39
40
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { F } from '../util/Utils';
|
|
2
2
|
import { MemberOptions } from '../Options';
|
|
3
3
|
import { Controller } from '../Controller';
|
|
4
|
-
import {
|
|
4
|
+
import { MemberName, ObjectHolder, Observable, Observer, MemberInfo, AbstractSnapshot } from './Data';
|
|
5
5
|
import { Transaction } from './Transaction';
|
|
6
6
|
import { OptionsImpl } from './Hooks';
|
|
7
7
|
export declare class OperationController extends Controller<any> {
|
|
@@ -39,18 +39,18 @@ declare class Operation extends Observable implements Observer {
|
|
|
39
39
|
readonly margin: number;
|
|
40
40
|
readonly transaction: Transaction;
|
|
41
41
|
readonly controller: OperationController;
|
|
42
|
-
readonly
|
|
42
|
+
readonly snapshot: AbstractSnapshot;
|
|
43
43
|
observables: Map<Observable, MemberInfo> | undefined;
|
|
44
44
|
options: OptionsImpl;
|
|
45
|
-
cause:
|
|
45
|
+
cause: string | undefined;
|
|
46
46
|
args: any[];
|
|
47
47
|
result: any;
|
|
48
48
|
error: any;
|
|
49
49
|
started: number;
|
|
50
|
-
obsoleteDueTo:
|
|
50
|
+
obsoleteDueTo: string | undefined;
|
|
51
51
|
obsoleteSince: number;
|
|
52
52
|
successor: Operation | undefined;
|
|
53
|
-
constructor(controller: OperationController,
|
|
53
|
+
constructor(controller: OperationController, snapshot: AbstractSnapshot, prev: Operation | OptionsImpl);
|
|
54
54
|
get isOperation(): boolean;
|
|
55
55
|
get selfSnapshotId(): number;
|
|
56
56
|
hint(): string;
|
|
@@ -61,7 +61,7 @@ declare class Operation extends Observable implements Observer {
|
|
|
61
61
|
dependencies(): string[];
|
|
62
62
|
wrap<T>(func: F<T>): F<T>;
|
|
63
63
|
run(proxy: any, args: any[] | undefined): void;
|
|
64
|
-
markObsoleteDueTo(observable: Observable,
|
|
64
|
+
markObsoleteDueTo(observable: Observable, memberName: MemberName, snapshot: AbstractSnapshot, holder: ObjectHolder, outer: string, since: number, reactions: Observer[]): void;
|
|
65
65
|
runIfNotUpToDate(now: boolean, nothrow: boolean): void;
|
|
66
66
|
isNotUpToDate(): boolean;
|
|
67
67
|
reenterOver(head: Operation): this;
|
|
@@ -79,7 +79,8 @@ declare class Operation extends Observable implements Observer {
|
|
|
79
79
|
private static propagateAllChangesThroughSubscriptions;
|
|
80
80
|
private static revokeAllSubscriptions;
|
|
81
81
|
private static propagateMemberChangeThroughSubscriptions;
|
|
82
|
-
private static
|
|
82
|
+
private static enqueueReactionsToRun;
|
|
83
|
+
private static runQueuedReactionsLoop;
|
|
83
84
|
private unsubscribeFromAllObservables;
|
|
84
85
|
private subscribeTo;
|
|
85
86
|
private static canSubscribe;
|
|
@@ -12,7 +12,7 @@ const Hooks_1 = require("./Hooks");
|
|
|
12
12
|
const TransactionJournal_1 = require("./TransactionJournal");
|
|
13
13
|
const ROOT_ARGS = [];
|
|
14
14
|
const ROOT_HOLDER = new Data_1.ObjectHolder(undefined, undefined, Hooks_1.Hooks.proxy, Snapshot_1.ROOT_REV, 'root-holder');
|
|
15
|
-
const
|
|
15
|
+
const INITIAL_CAUSE = 'initial';
|
|
16
16
|
class OperationController extends Controller_1.Controller {
|
|
17
17
|
constructor(ownHolder, memberName) {
|
|
18
18
|
super();
|
|
@@ -36,7 +36,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
36
36
|
const op = oc.operation;
|
|
37
37
|
const opts = op.options;
|
|
38
38
|
if (!oc.isUpToDate && oc.revision.data[Data_1.Meta.Disposed] === undefined
|
|
39
|
-
&& (!weak || op.cause ===
|
|
39
|
+
&& (!weak || op.cause === INITIAL_CAUSE || !op.successor ||
|
|
40
40
|
op.successor.transaction.isFinished)) {
|
|
41
41
|
const outerOpts = (_a = Operation.current) === null || _a === void 0 ? void 0 : _a.options;
|
|
42
42
|
const standalone = weak || opts.standalone || opts.kind === Options_1.Kind.Reaction ||
|
|
@@ -45,13 +45,13 @@ class OperationController extends Controller_1.Controller {
|
|
|
45
45
|
oc.revision.prev.revision !== Snapshot_1.ROOT_REV));
|
|
46
46
|
const token = opts.noSideEffects ? this : undefined;
|
|
47
47
|
const oc2 = this.run(oc, standalone, opts, token, args);
|
|
48
|
-
const ctx2 = oc2.operation.
|
|
48
|
+
const ctx2 = oc2.operation.snapshot;
|
|
49
49
|
if (!weak || ctx === ctx2 || (ctx2.sealed && ctx.timestamp >= ctx2.timestamp))
|
|
50
50
|
oc = oc2;
|
|
51
51
|
}
|
|
52
52
|
else if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.operation && (opts.trace === undefined ||
|
|
53
53
|
opts.trace.operation === undefined || opts.trace.operation === true))
|
|
54
|
-
Dbg_1.Dbg.log(Transaction_1.Transaction.current.isFinished ? '' : '║', ' (=)', `${Snapshot_1.Dump.
|
|
54
|
+
Dbg_1.Dbg.log(Transaction_1.Transaction.current.isFinished ? '' : '║', ' (=)', `${Snapshot_1.Dump.rev2(oc.operation.controller.ownHolder, oc.snapshot, this.memberName)} result is reused from T${oc.operation.transaction.id}[${oc.operation.transaction.hint}]`);
|
|
55
55
|
const t = oc.operation;
|
|
56
56
|
Snapshot_1.Snapshot.markUsed(t, oc.revision, this.memberName, this.ownHolder, t.options.kind, weak);
|
|
57
57
|
return t;
|
|
@@ -108,8 +108,8 @@ class OperationController extends Controller_1.Controller {
|
|
|
108
108
|
const ctx = Snapshot_1.Snapshot.current();
|
|
109
109
|
const r = ctx.seekRevision(this.ownHolder, this.memberName);
|
|
110
110
|
const op = this.peekFromRevision(r, args);
|
|
111
|
-
const isValid = op.options.kind !== Options_1.Kind.Transaction && op.cause !==
|
|
112
|
-
(ctx === op.
|
|
111
|
+
const isValid = op.options.kind !== Options_1.Kind.Transaction && op.cause !== INITIAL_CAUSE &&
|
|
112
|
+
(ctx === op.snapshot || ctx.timestamp < op.obsoleteSince) &&
|
|
113
113
|
(!op.options.sensitiveArgs || args === undefined ||
|
|
114
114
|
op.args.length === args.length && op.args.every((t, i) => t === args[i])) ||
|
|
115
115
|
r.data[Data_1.Meta.Disposed] !== undefined;
|
|
@@ -126,8 +126,8 @@ class OperationController extends Controller_1.Controller {
|
|
|
126
126
|
const ctx = Snapshot_1.Snapshot.edit();
|
|
127
127
|
const r = ctx.getEditableRevision(h, m, Data_1.Meta.Holder, this);
|
|
128
128
|
let op = this.peekFromRevision(r, undefined);
|
|
129
|
-
if (op.
|
|
130
|
-
const op2 = new Operation(this, r, op);
|
|
129
|
+
if (op.snapshot !== r.snapshot) {
|
|
130
|
+
const op2 = new Operation(this, r.snapshot, op);
|
|
131
131
|
r.data[m] = op2.reenterOver(op);
|
|
132
132
|
ctx.bumpBy(r.prev.revision.snapshot.timestamp);
|
|
133
133
|
Snapshot_1.Snapshot.markEdited(op, op2, true, r, m, h);
|
|
@@ -147,10 +147,10 @@ class OperationController extends Controller_1.Controller {
|
|
|
147
147
|
let op2 = r2.data[m];
|
|
148
148
|
if (op2.controller !== this) {
|
|
149
149
|
r2 = Snapshot_1.Snapshot.edit().getEditableRevision(h, m, Data_1.Meta.Holder, this);
|
|
150
|
-
const t = new Operation(this, r2, op2);
|
|
150
|
+
const t = new Operation(this, r2.snapshot, op2);
|
|
151
151
|
if (args)
|
|
152
152
|
t.args = args;
|
|
153
|
-
t.cause =
|
|
153
|
+
t.cause = INITIAL_CAUSE;
|
|
154
154
|
r2.data[m] = t;
|
|
155
155
|
Snapshot_1.Snapshot.markEdited(op2, t, true, r2, m, h);
|
|
156
156
|
op2 = t;
|
|
@@ -188,17 +188,17 @@ class OperationController extends Controller_1.Controller {
|
|
|
188
188
|
static markObsolete(self) {
|
|
189
189
|
const oc = self.peek(undefined);
|
|
190
190
|
const ctx = oc.snapshot;
|
|
191
|
-
oc.operation.markObsoleteDueTo(oc.operation,
|
|
191
|
+
oc.operation.markObsoleteDueTo(oc.operation, self.memberName, Snapshot_1.ROOT_REV.snapshot, ROOT_HOLDER, INITIAL_CAUSE, ctx.timestamp, ctx.reactions);
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
exports.OperationController = OperationController;
|
|
195
195
|
class Operation extends Data_1.Observable {
|
|
196
|
-
constructor(controller,
|
|
196
|
+
constructor(controller, snapshot, prev) {
|
|
197
197
|
super(undefined);
|
|
198
198
|
this.margin = Operation.current ? Operation.current.margin + 1 : 1;
|
|
199
199
|
this.transaction = Transaction_1.Transaction.current;
|
|
200
200
|
this.controller = controller;
|
|
201
|
-
this.
|
|
201
|
+
this.snapshot = snapshot;
|
|
202
202
|
this.observables = new Map();
|
|
203
203
|
if (prev instanceof Operation) {
|
|
204
204
|
this.options = prev.options;
|
|
@@ -216,28 +216,24 @@ class Operation extends Data_1.Observable {
|
|
|
216
216
|
this.successor = undefined;
|
|
217
217
|
}
|
|
218
218
|
get isOperation() { return true; }
|
|
219
|
-
get selfSnapshotId() { return this.
|
|
220
|
-
hint() { return `${Snapshot_1.Dump.
|
|
219
|
+
get selfSnapshotId() { return this.snapshot.id; }
|
|
220
|
+
hint() { return `${Snapshot_1.Dump.rev2(this.controller.ownHolder, this.snapshot, this.controller.memberName)}`; }
|
|
221
221
|
get order() { return this.options.order; }
|
|
222
222
|
get ['#this']() {
|
|
223
223
|
return `Operation: ${this.why()}`;
|
|
224
224
|
}
|
|
225
225
|
why() {
|
|
226
|
-
let
|
|
227
|
-
const prev = this.revision.prev.revision.data[this.controller.memberName];
|
|
228
|
-
if (prev instanceof Operation)
|
|
229
|
-
ms = prev.started !== 0 ? Math.abs(this.started || ms) - Math.abs(prev.started) : Infinity;
|
|
230
|
-
let trigger;
|
|
226
|
+
let cause;
|
|
231
227
|
if (this.cause)
|
|
232
|
-
|
|
228
|
+
cause = ` << ${this.cause}`;
|
|
233
229
|
else if (this.controller.options.kind === Options_1.Kind.Transaction)
|
|
234
|
-
|
|
230
|
+
cause = ' << operation';
|
|
235
231
|
else
|
|
236
|
-
|
|
237
|
-
return `${this.hint()}${
|
|
232
|
+
cause = ` << T${this.snapshot.id}[${this.snapshot.hint}]`;
|
|
233
|
+
return `${this.hint()}${cause}`;
|
|
238
234
|
}
|
|
239
235
|
briefWhy() {
|
|
240
|
-
return this.
|
|
236
|
+
return this.why();
|
|
241
237
|
}
|
|
242
238
|
dependencies() {
|
|
243
239
|
throw (0, Dbg_1.misuse)('not implemented yet');
|
|
@@ -266,31 +262,33 @@ class Operation extends Data_1.Observable {
|
|
|
266
262
|
else
|
|
267
263
|
this.result = Promise.reject(this.error);
|
|
268
264
|
}
|
|
269
|
-
markObsoleteDueTo(observable,
|
|
265
|
+
markObsoleteDueTo(observable, memberName, snapshot, holder, outer, since, reactions) {
|
|
270
266
|
var _a, _b, _c;
|
|
271
267
|
if (this.observables !== undefined) {
|
|
272
|
-
|
|
268
|
+
const skip = !observable.isOperation &&
|
|
269
|
+
snapshot === this.snapshot;
|
|
270
|
+
if (!skip) {
|
|
271
|
+
const why = `${Snapshot_1.Dump.rev2(holder, snapshot, memberName)} << ${outer}`;
|
|
273
272
|
this.unsubscribeFromAllObservables();
|
|
274
|
-
this.obsoleteDueTo =
|
|
273
|
+
this.obsoleteDueTo = why;
|
|
275
274
|
this.obsoleteSince = since;
|
|
276
275
|
const isReaction = this.options.kind === Options_1.Kind.Reaction;
|
|
277
276
|
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.obsolete || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.obsolete)))
|
|
278
|
-
Dbg_1.Dbg.log(Dbg_1.Dbg.trace.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', isReaction ? '█' : '▒', isReaction &&
|
|
277
|
+
Dbg_1.Dbg.log(Dbg_1.Dbg.trace.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', isReaction ? '█' : '▒', isReaction && snapshot === Snapshot_1.ROOT_REV.snapshot
|
|
279
278
|
? `${this.hint()} is a reaction and will run automatically (order ${this.options.order})`
|
|
280
|
-
: `${this.hint()} is obsolete due to ${Snapshot_1.Dump.
|
|
279
|
+
: `${this.hint()} is obsolete due to ${Snapshot_1.Dump.rev2(holder, snapshot, memberName)} since v${since}${isReaction ? ` and will run automatically (order ${this.options.order})` : ''}`);
|
|
281
280
|
if (isReaction)
|
|
282
281
|
reactions.push(this);
|
|
283
282
|
else
|
|
284
|
-
(_b = this.observers) === null || _b === void 0 ? void 0 : _b.forEach(c => c.markObsoleteDueTo(this,
|
|
283
|
+
(_b = this.observers) === null || _b === void 0 ? void 0 : _b.forEach(c => c.markObsoleteDueTo(this, this.controller.memberName, this.snapshot, this.controller.ownHolder, why, since, reactions));
|
|
285
284
|
const tran = this.transaction;
|
|
286
|
-
if (tran.snapshot ===
|
|
287
|
-
(0, Dbg_1.misuse)('not implemented: running reactions within original transaction');
|
|
285
|
+
if (tran.snapshot === snapshot) {
|
|
288
286
|
}
|
|
289
287
|
else if (!tran.isFinished && this !== observable)
|
|
290
|
-
tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Snapshot_1.Dump.
|
|
288
|
+
tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Snapshot_1.Dump.rev2(holder, snapshot, memberName)} changed by T${snapshot.id}[${snapshot.hint}]`), null);
|
|
291
289
|
}
|
|
292
290
|
else if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.obsolete || ((_c = this.options.trace) === null || _c === void 0 ? void 0 : _c.obsolete)))
|
|
293
|
-
Dbg_1.Dbg.log(' ', 'x', `${this.hint()} is not obsolete due to its own change to ${Snapshot_1.Dump.
|
|
291
|
+
Dbg_1.Dbg.log(' ', 'x', `${this.hint()} is not obsolete due to its own change to ${Snapshot_1.Dump.rev2(holder, snapshot, memberName)}`);
|
|
294
292
|
}
|
|
295
293
|
}
|
|
296
294
|
runIfNotUpToDate(now, nothrow) {
|
|
@@ -407,6 +405,7 @@ class Operation extends Data_1.Observable {
|
|
|
407
405
|
Dbg_1.Dbg.log('║', `${op}`, `${this.hint()} ${message}`, ms, highlight);
|
|
408
406
|
if (ms > (main ? Hooks_1.Hooks.mainThreadBlockingWarningThreshold : Hooks_1.Hooks.asyncActionDurationWarningThreshold))
|
|
409
407
|
Dbg_1.Dbg.log('', '[!]', this.why(), ms, main ? ' *** main thread is too busy ***' : ' *** async is too long ***');
|
|
408
|
+
this.cause = undefined;
|
|
410
409
|
if (this.options.monitor)
|
|
411
410
|
this.monitorLeave(this.options.monitor);
|
|
412
411
|
}
|
|
@@ -451,19 +450,19 @@ class Operation extends Data_1.Observable {
|
|
|
451
450
|
ctx.bumpBy(r.snapshot.timestamp);
|
|
452
451
|
const t = weak ? -1 : ctx.timestamp;
|
|
453
452
|
if (!op.subscribeTo(observable, r, m, h, t))
|
|
454
|
-
op.markObsoleteDueTo(observable,
|
|
453
|
+
op.markObsoleteDueTo(observable, m, r.snapshot, h, INITIAL_CAUSE, ctx.timestamp, ctx.reactions);
|
|
455
454
|
}
|
|
456
455
|
}
|
|
457
456
|
}
|
|
458
457
|
static markEdited(oldValue, newValue, edited, r, m, h) {
|
|
459
|
-
edited ? r.changes.
|
|
458
|
+
edited ? r.changes.add(m) : r.changes.delete(m);
|
|
460
459
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.write)
|
|
461
|
-
edited ? Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.
|
|
460
|
+
edited ? Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.rev2(h, r.snapshot, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`) : Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.rev2(h, r.snapshot, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`, undefined, ' (same as previous)');
|
|
462
461
|
}
|
|
463
462
|
static isConflicting(oldValue, newValue) {
|
|
464
463
|
let result = oldValue !== newValue;
|
|
465
464
|
if (result)
|
|
466
|
-
result = oldValue instanceof Operation && oldValue.cause !==
|
|
465
|
+
result = oldValue instanceof Operation && oldValue.cause !== INITIAL_CAUSE;
|
|
467
466
|
return result;
|
|
468
467
|
}
|
|
469
468
|
static propagateAllChangesThroughSubscriptions(snapshot) {
|
|
@@ -483,30 +482,39 @@ class Operation extends Data_1.Observable {
|
|
|
483
482
|
static revokeAllSubscriptions(snapshot) {
|
|
484
483
|
snapshot.changeset.forEach((r, h) => r.changes.forEach((o, m) => Operation.propagateMemberChangeThroughSubscriptions(true, snapshot.timestamp, r, m, h, undefined)));
|
|
485
484
|
}
|
|
486
|
-
static propagateMemberChangeThroughSubscriptions(
|
|
485
|
+
static propagateMemberChangeThroughSubscriptions(unsubscribe, timestamp, r, m, h, reactions) {
|
|
487
486
|
var _a;
|
|
487
|
+
const curr = r.data[m];
|
|
488
488
|
if (reactions) {
|
|
489
489
|
const prev = r.prev.revision.data[m];
|
|
490
490
|
if (prev !== undefined && prev instanceof Data_1.Observable) {
|
|
491
|
-
const
|
|
492
|
-
if (prev instanceof Operation
|
|
493
|
-
prev.
|
|
494
|
-
|
|
495
|
-
|
|
491
|
+
const why = `T${r.snapshot.id}[${r.snapshot.hint}]`;
|
|
492
|
+
if (prev instanceof Operation) {
|
|
493
|
+
if ((prev.obsoleteSince === Snapshot_1.MAX_TIMESTAMP || prev.obsoleteSince <= 0)) {
|
|
494
|
+
prev.obsoleteDueTo = why;
|
|
495
|
+
prev.obsoleteSince = timestamp;
|
|
496
|
+
prev.unsubscribeFromAllObservables();
|
|
497
|
+
}
|
|
498
|
+
const prevSuccessor = prev.successor;
|
|
499
|
+
if (prevSuccessor !== curr) {
|
|
500
|
+
if (prevSuccessor && !prevSuccessor.transaction.isFinished)
|
|
501
|
+
prevSuccessor.transaction.cancel(new Error(`T${prevSuccessor.transaction.id}[${prevSuccessor.transaction.hint}] is canceled by T${r.snapshot.id}[${r.snapshot.hint}] and will not run anymore`), null);
|
|
502
|
+
}
|
|
503
|
+
else
|
|
504
|
+
prev.successor = undefined;
|
|
496
505
|
}
|
|
497
|
-
(_a = prev.observers) === null || _a === void 0 ? void 0 : _a.forEach(c => c.markObsoleteDueTo(prev,
|
|
506
|
+
(_a = prev.observers) === null || _a === void 0 ? void 0 : _a.forEach(c => c.markObsoleteDueTo(prev, m, r.snapshot, h, why, timestamp, reactions));
|
|
498
507
|
}
|
|
499
508
|
}
|
|
500
|
-
const curr = r.data[m];
|
|
501
509
|
if (curr instanceof Operation) {
|
|
502
|
-
if (curr.
|
|
510
|
+
if (curr.snapshot === r.snapshot && curr.observables !== undefined) {
|
|
503
511
|
if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
|
|
504
512
|
curr.observables.forEach((hint, v) => {
|
|
505
513
|
if (hint.usageCount > Hooks_1.Hooks.repetitiveUsageWarningThreshold)
|
|
506
|
-
Dbg_1.Dbg.log('', '[!]', `${curr.hint()} uses ${Snapshot_1.Dump.
|
|
514
|
+
Dbg_1.Dbg.log('', '[!]', `${curr.hint()} uses ${Snapshot_1.Dump.rev2(hint.holder, hint.snapshot, hint.memberName)} ${hint.usageCount} times (consider remembering it in a local variable)`, 0, ' *** WARNING ***');
|
|
507
515
|
});
|
|
508
516
|
}
|
|
509
|
-
if (
|
|
517
|
+
if (unsubscribe)
|
|
510
518
|
curr.unsubscribeFromAllObservables();
|
|
511
519
|
}
|
|
512
520
|
}
|
|
@@ -519,20 +527,23 @@ class Operation extends Data_1.Observable {
|
|
|
519
527
|
curr.observers = undefined;
|
|
520
528
|
}
|
|
521
529
|
}
|
|
522
|
-
static
|
|
530
|
+
static enqueueReactionsToRun(reactions) {
|
|
523
531
|
const queue = Operation.queuedReactions;
|
|
524
|
-
const
|
|
525
|
-
for (const r of
|
|
532
|
+
const isReactionLoopRequired = queue.length === 0;
|
|
533
|
+
for (const r of reactions)
|
|
526
534
|
queue.push(r);
|
|
527
|
-
if (
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
+
if (isReactionLoopRequired)
|
|
536
|
+
OperationController.runWithin(undefined, Operation.runQueuedReactionsLoop);
|
|
537
|
+
}
|
|
538
|
+
static runQueuedReactionsLoop() {
|
|
539
|
+
const queue = Operation.queuedReactions;
|
|
540
|
+
let i = 0;
|
|
541
|
+
while (i < queue.length) {
|
|
542
|
+
const reaction = queue[i];
|
|
543
|
+
reaction.runIfNotUpToDate(false, true);
|
|
544
|
+
i++;
|
|
535
545
|
}
|
|
546
|
+
Operation.queuedReactions = [];
|
|
536
547
|
}
|
|
537
548
|
unsubscribeFromAllObservables() {
|
|
538
549
|
var _a;
|
|
@@ -540,7 +551,7 @@ class Operation extends Data_1.Observable {
|
|
|
540
551
|
var _a;
|
|
541
552
|
value.observers.delete(this);
|
|
542
553
|
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.read)))
|
|
543
|
-
Dbg_1.Dbg.log(Dbg_1.Dbg.trace.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', '-', `${this.hint()} is unsubscribed from ${Snapshot_1.Dump.
|
|
554
|
+
Dbg_1.Dbg.log(Dbg_1.Dbg.trace.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', '-', `${this.hint()} is unsubscribed from ${Snapshot_1.Dump.rev2(hint.holder, hint.snapshot, hint.memberName)}`);
|
|
544
555
|
});
|
|
545
556
|
this.observables = undefined;
|
|
546
557
|
}
|
|
@@ -556,18 +567,18 @@ class Operation extends Data_1.Observable {
|
|
|
556
567
|
if (this.observables !== undefined) {
|
|
557
568
|
if (!observable.observers)
|
|
558
569
|
observable.observers = new Set();
|
|
559
|
-
const info = {
|
|
570
|
+
const info = { holder: h, snapshot: r.snapshot, memberName: m, usageCount: times };
|
|
560
571
|
observable.observers.add(this);
|
|
561
572
|
this.observables.set(observable, info);
|
|
562
573
|
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.read)))
|
|
563
|
-
Dbg_1.Dbg.log('║', ' ∞ ', `${this.hint()} is subscribed to ${Snapshot_1.Dump.
|
|
574
|
+
Dbg_1.Dbg.log('║', ' ∞ ', `${this.hint()} is subscribed to ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}${info.usageCount > 1 ? ` (${info.usageCount} times)` : ''}`);
|
|
564
575
|
}
|
|
565
576
|
else if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_b = this.options.trace) === null || _b === void 0 ? void 0 : _b.read)))
|
|
566
|
-
Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Snapshot_1.Dump.
|
|
577
|
+
Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}`);
|
|
567
578
|
}
|
|
568
579
|
else {
|
|
569
580
|
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_c = this.options.trace) === null || _c === void 0 ? void 0 : _c.read)))
|
|
570
|
-
Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Snapshot_1.Dump.
|
|
581
|
+
Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}`);
|
|
571
582
|
}
|
|
572
583
|
return ok;
|
|
573
584
|
}
|
|
@@ -590,7 +601,7 @@ class Operation extends Data_1.Observable {
|
|
|
590
601
|
let op = initial[m];
|
|
591
602
|
const ctl = op ? op.controller : new OperationController(ROOT_HOLDER, m);
|
|
592
603
|
const opts = op ? op.options : Hooks_1.OptionsImpl.INITIAL;
|
|
593
|
-
initial[m] = op = new Operation(ctl, Snapshot_1.ROOT_REV, new Hooks_1.OptionsImpl(getter, setter, opts, options, implicit));
|
|
604
|
+
initial[m] = op = new Operation(ctl, Snapshot_1.ROOT_REV.snapshot, new Hooks_1.OptionsImpl(getter, setter, opts, options, implicit));
|
|
594
605
|
if (op.options.kind === Options_1.Kind.Reaction && op.options.throttling < Number.MAX_SAFE_INTEGER) {
|
|
595
606
|
const reactions = Data_1.Meta.acquire(proto, Data_1.Meta.Reactions);
|
|
596
607
|
reactions[m] = op;
|
|
@@ -603,14 +614,13 @@ class Operation extends Data_1.Observable {
|
|
|
603
614
|
}
|
|
604
615
|
static init() {
|
|
605
616
|
Object.freeze(ROOT_ARGS);
|
|
606
|
-
Object.freeze(ROOT_TRIGGER);
|
|
607
617
|
Dbg_1.Dbg.getMergedTraceOptions = getMergedTraceOptions;
|
|
608
618
|
Snapshot_1.Snapshot.markUsed = Operation.markUsed;
|
|
609
619
|
Snapshot_1.Snapshot.markEdited = Operation.markEdited;
|
|
610
620
|
Snapshot_1.Snapshot.isConflicting = Operation.isConflicting;
|
|
611
621
|
Snapshot_1.Snapshot.propagateAllChangesThroughSubscriptions = Operation.propagateAllChangesThroughSubscriptions;
|
|
612
622
|
Snapshot_1.Snapshot.revokeAllSubscriptions = Operation.revokeAllSubscriptions;
|
|
613
|
-
Snapshot_1.Snapshot.
|
|
623
|
+
Snapshot_1.Snapshot.enqueueReactionsToRun = Operation.enqueueReactionsToRun;
|
|
614
624
|
Hooks_1.Hooks.createControllerAndGetHook = Operation.createControllerAndGetHook;
|
|
615
625
|
Hooks_1.Hooks.rememberOperationOptions = Operation.rememberOperationOptions;
|
|
616
626
|
Promise.prototype.then = reactronicHookedThen;
|
|
@@ -639,18 +649,6 @@ class Operation extends Data_1.Observable {
|
|
|
639
649
|
Operation.current = undefined;
|
|
640
650
|
Operation.queuedReactions = [];
|
|
641
651
|
Operation.deferredReactions = [];
|
|
642
|
-
function propagationHint(cause, full) {
|
|
643
|
-
const result = [];
|
|
644
|
-
let observable = cause.revision.data[cause.memberName];
|
|
645
|
-
while (observable instanceof Operation && observable.obsoleteDueTo) {
|
|
646
|
-
full && result.push(Snapshot_1.Dump.rev(cause.revision, cause.memberName));
|
|
647
|
-
cause = observable.obsoleteDueTo;
|
|
648
|
-
observable = cause.revision.data[cause.memberName];
|
|
649
|
-
}
|
|
650
|
-
result.push(Snapshot_1.Dump.rev(cause.revision, cause.memberName));
|
|
651
|
-
full && result.push(cause.revision.snapshot.hint);
|
|
652
|
-
return result;
|
|
653
|
-
}
|
|
654
652
|
function valueHint(value, m) {
|
|
655
653
|
let result = '';
|
|
656
654
|
if (Array.isArray(value))
|
|
@@ -660,7 +658,7 @@ function valueHint(value, m) {
|
|
|
660
658
|
else if (value instanceof Map)
|
|
661
659
|
result = `Map(${value.size})`;
|
|
662
660
|
else if (value instanceof Operation)
|
|
663
|
-
result = `${Snapshot_1.Dump.
|
|
661
|
+
result = `${Snapshot_1.Dump.rev2(value.controller.ownHolder, value.snapshot, m)}`;
|
|
664
662
|
else if (value === Data_1.Meta.Disposed)
|
|
665
663
|
result = '<disposed>';
|
|
666
664
|
else if (value !== undefined && value !== null)
|
|
@@ -17,8 +17,8 @@ export declare class Snapshot implements AbstractSnapshot {
|
|
|
17
17
|
get timestamp(): number;
|
|
18
18
|
private stamp;
|
|
19
19
|
private bumper;
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
changeset: Map<ObjectHolder, ObjectRevision>;
|
|
21
|
+
reactions: Observer[];
|
|
22
22
|
sealed: boolean;
|
|
23
23
|
constructor(options: SnapshotOptions | null);
|
|
24
24
|
static current: () => Snapshot;
|
|
@@ -28,7 +28,7 @@ export declare class Snapshot implements AbstractSnapshot {
|
|
|
28
28
|
static isConflicting: (oldValue: any, newValue: any) => boolean;
|
|
29
29
|
static propagateAllChangesThroughSubscriptions: (snapshot: Snapshot) => void;
|
|
30
30
|
static revokeAllSubscriptions: (snapshot: Snapshot) => void;
|
|
31
|
-
static
|
|
31
|
+
static enqueueReactionsToRun: (reactions: Array<Observer>) => void;
|
|
32
32
|
seekRevision(h: ObjectHolder, m: MemberName): ObjectRevision;
|
|
33
33
|
getCurrentRevision(h: ObjectHolder, m: MemberName): ObjectRevision;
|
|
34
34
|
getEditableRevision(h: ObjectHolder, m: MemberName, value: any, token?: any): ObjectRevision;
|
|
@@ -40,17 +40,17 @@ export declare class Snapshot implements AbstractSnapshot {
|
|
|
40
40
|
bumpBy(timestamp: number): void;
|
|
41
41
|
rebase(): ObjectRevision[] | undefined;
|
|
42
42
|
private static merge;
|
|
43
|
-
applyOrDiscard(error?: any):
|
|
43
|
+
applyOrDiscard(error?: any): Array<Observer>;
|
|
44
44
|
static sealObjectRevision(h: ObjectHolder, r: ObjectRevision): void;
|
|
45
45
|
static sealObservable(observable: Observable | symbol, m: MemberName, typeName: string): void;
|
|
46
|
-
collectGarbage(): void;
|
|
47
46
|
static freezeObjectRevision(r: ObjectRevision): ObjectRevision;
|
|
48
|
-
|
|
47
|
+
triggerGarbageCollection(): void;
|
|
49
48
|
private unlinkHistory;
|
|
50
49
|
static _init(): void;
|
|
51
50
|
}
|
|
52
51
|
export declare class Dump {
|
|
53
52
|
static obj(h: ObjectHolder | undefined, m?: MemberName | undefined, stamp?: number, op?: number, xop?: number, typeless?: boolean): string;
|
|
53
|
+
static rev2(h: ObjectHolder, s: AbstractSnapshot, m?: MemberName, value?: Observable): string;
|
|
54
54
|
static rev(r: ObjectRevision, m?: MemberName): string;
|
|
55
55
|
static conflicts(conflicts: ObjectRevision[]): string;
|
|
56
56
|
static conflictingMemberHint(m: MemberName, ours: ObjectRevision, theirs: ObjectRevision): string;
|
|
@@ -27,6 +27,8 @@ Object.defineProperty(Data_1.ObjectHolder.prototype, '#this', {
|
|
|
27
27
|
return result;
|
|
28
28
|
},
|
|
29
29
|
});
|
|
30
|
+
const EMPTY_ARRAY = Object.freeze([]);
|
|
31
|
+
const EMPTY_MAP = Utils_1.Utils.freezeMap(new Map());
|
|
30
32
|
class Snapshot {
|
|
31
33
|
constructor(options) {
|
|
32
34
|
this.id = ++Snapshot.idGen;
|
|
@@ -128,14 +130,14 @@ class Snapshot {
|
|
|
128
130
|
if (this.changeset.size > 0) {
|
|
129
131
|
this.changeset.forEach((r, h) => {
|
|
130
132
|
if (r.prev.revision !== h.head) {
|
|
131
|
-
const merged = Snapshot.merge(
|
|
133
|
+
const merged = Snapshot.merge(h, r);
|
|
132
134
|
if (r.conflicts.size > 0) {
|
|
133
135
|
if (!conflicts)
|
|
134
136
|
conflicts = [];
|
|
135
137
|
conflicts.push(r);
|
|
136
138
|
}
|
|
137
139
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.transaction)
|
|
138
|
-
Dbg_1.Dbg.log('╠╝', '', `${Dump.
|
|
140
|
+
Dbg_1.Dbg.log('╠╝', '', `${Dump.rev2(h, r.snapshot)} is merged with ${Dump.rev2(h, h.head.snapshot)} among ${merged} properties with ${r.conflicts.size} conflicts.`);
|
|
139
141
|
}
|
|
140
142
|
});
|
|
141
143
|
if (this.options.token === undefined) {
|
|
@@ -152,8 +154,9 @@ class Snapshot {
|
|
|
152
154
|
}
|
|
153
155
|
return conflicts;
|
|
154
156
|
}
|
|
155
|
-
static merge(
|
|
157
|
+
static merge(h, ours) {
|
|
156
158
|
let counter = 0;
|
|
159
|
+
const head = h.head;
|
|
157
160
|
const disposed = head.changes.has(Data_1.Meta.Disposed);
|
|
158
161
|
const merged = Object.assign({}, head.data);
|
|
159
162
|
ours.changes.forEach((o, m) => {
|
|
@@ -162,7 +165,7 @@ class Snapshot {
|
|
|
162
165
|
if (disposed || m === Data_1.Meta.Disposed) {
|
|
163
166
|
if (disposed !== (m === Data_1.Meta.Disposed)) {
|
|
164
167
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.change)
|
|
165
|
-
Dbg_1.Dbg.log('║╠', '', `${Dump.
|
|
168
|
+
Dbg_1.Dbg.log('║╠', '', `${Dump.rev2(h, ours.snapshot, m)} <> ${Dump.rev2(h, head.snapshot, m)}`, 0, ' *** CONFLICT ***');
|
|
166
169
|
ours.conflicts.set(m, head);
|
|
167
170
|
}
|
|
168
171
|
}
|
|
@@ -171,7 +174,7 @@ class Snapshot {
|
|
|
171
174
|
if (conflict)
|
|
172
175
|
ours.conflicts.set(m, head);
|
|
173
176
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.change)
|
|
174
|
-
Dbg_1.Dbg.log('║╠', '', `${Dump.
|
|
177
|
+
Dbg_1.Dbg.log('║╠', '', `${Dump.rev2(h, ours.snapshot, m)} ${conflict ? '<>' : '=='} ${Dump.rev2(h, head.snapshot, m)}`, 0, conflict ? ' *** CONFLICT ***' : undefined);
|
|
175
178
|
}
|
|
176
179
|
});
|
|
177
180
|
Utils_1.Utils.copyAllMembers(merged, ours.data);
|
|
@@ -200,7 +203,7 @@ class Snapshot {
|
|
|
200
203
|
const members = [];
|
|
201
204
|
r.changes.forEach((o, m) => members.push(m.toString()));
|
|
202
205
|
const s = members.join(', ');
|
|
203
|
-
Dbg_1.Dbg.log('║', '√', `${Dump.
|
|
206
|
+
Dbg_1.Dbg.log('║', '√', `${Dump.rev2(h, r.snapshot)} (${s}) is ${r.prev.revision === exports.ROOT_REV ? 'constructed' : `applied on top of ${Dump.rev2(h, r.prev.revision.snapshot)}`}`);
|
|
204
207
|
});
|
|
205
208
|
}
|
|
206
209
|
if (Dbg_1.Dbg.trace.transaction)
|
|
@@ -208,6 +211,7 @@ class Snapshot {
|
|
|
208
211
|
}
|
|
209
212
|
if (!error)
|
|
210
213
|
Snapshot.propagateAllChangesThroughSubscriptions(this);
|
|
214
|
+
return this.reactions;
|
|
211
215
|
}
|
|
212
216
|
static sealObjectRevision(h, r) {
|
|
213
217
|
if (!r.changes.has(Data_1.Meta.Disposed))
|
|
@@ -228,17 +232,9 @@ class Snapshot {
|
|
|
228
232
|
}
|
|
229
233
|
}
|
|
230
234
|
}
|
|
231
|
-
collectGarbage() {
|
|
232
|
-
if (Dbg_1.Dbg.isOn) {
|
|
233
|
-
Utils_1.Utils.freezeMap(this.changeset);
|
|
234
|
-
Object.freeze(this.reactions);
|
|
235
|
-
Object.freeze(this);
|
|
236
|
-
}
|
|
237
|
-
this.triggerGarbageCollection();
|
|
238
|
-
}
|
|
239
235
|
static freezeObjectRevision(r) {
|
|
240
236
|
Object.freeze(r.data);
|
|
241
|
-
Utils_1.Utils.
|
|
237
|
+
Utils_1.Utils.freezeSet(r.changes);
|
|
242
238
|
Utils_1.Utils.freezeMap(r.conflicts);
|
|
243
239
|
return r;
|
|
244
240
|
}
|
|
@@ -267,23 +263,25 @@ class Snapshot {
|
|
|
267
263
|
Dbg_1.Dbg.log('', '[G]', `Dismiss history below v${this.stamp}t${this.id} (${this.hint})`);
|
|
268
264
|
this.changeset.forEach((r, h) => {
|
|
269
265
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.gc && r.prev.revision !== exports.ROOT_REV)
|
|
270
|
-
Dbg_1.Dbg.log(' ', ' ', `${Dump.
|
|
266
|
+
Dbg_1.Dbg.log(' ', ' ', `${Dump.rev2(h, r.prev.revision.snapshot)} is ready for GC because overwritten by ${Dump.rev2(h, r.snapshot)}`);
|
|
271
267
|
if (Snapshot.garbageCollectionSummaryInterval < Number.MAX_SAFE_INTEGER) {
|
|
272
|
-
if (r.prev.revision !== exports.ROOT_REV)
|
|
268
|
+
if (r.prev.revision !== exports.ROOT_REV)
|
|
273
269
|
Snapshot.totalObjectRevisionCount--;
|
|
274
|
-
|
|
275
|
-
if (r.changes.has(Data_1.Meta.Disposed)) {
|
|
270
|
+
if (r.changes.has(Data_1.Meta.Disposed))
|
|
276
271
|
Snapshot.totalObjectHolderCount--;
|
|
277
|
-
}
|
|
278
272
|
}
|
|
279
273
|
r.prev.revision = exports.ROOT_REV;
|
|
280
274
|
});
|
|
275
|
+
this.changeset = EMPTY_MAP;
|
|
276
|
+
this.reactions = EMPTY_ARRAY;
|
|
277
|
+
if (Dbg_1.Dbg.isOn)
|
|
278
|
+
Object.freeze(this);
|
|
281
279
|
}
|
|
282
280
|
static _init() {
|
|
283
281
|
const root = exports.ROOT_REV.snapshot;
|
|
284
282
|
root.acquire(root);
|
|
285
283
|
root.applyOrDiscard();
|
|
286
|
-
root.
|
|
284
|
+
root.triggerGarbageCollection();
|
|
287
285
|
Snapshot.freezeObjectRevision(exports.ROOT_REV);
|
|
288
286
|
Snapshot.idGen = 100;
|
|
289
287
|
Snapshot.stampGen = 101;
|
|
@@ -309,7 +307,7 @@ Snapshot.markEdited = Utils_1.UNDEF;
|
|
|
309
307
|
Snapshot.isConflicting = Utils_1.UNDEF;
|
|
310
308
|
Snapshot.propagateAllChangesThroughSubscriptions = (snapshot) => { };
|
|
311
309
|
Snapshot.revokeAllSubscriptions = (snapshot) => { };
|
|
312
|
-
Snapshot.
|
|
310
|
+
Snapshot.enqueueReactionsToRun = (reactions) => { };
|
|
313
311
|
class Dump {
|
|
314
312
|
static obj(h, m, stamp, op, xop, typeless) {
|
|
315
313
|
const member = m !== undefined ? `.${m.toString()}` : '';
|
|
@@ -317,6 +315,9 @@ class Dump {
|
|
|
317
315
|
? `root${member}`
|
|
318
316
|
: stamp === undefined ? `${h.hint}${member} #${h.id}` : `${h.hint}${member} #${h.id}t${op}v${stamp}${xop !== undefined && xop !== 0 ? `t${xop}` : ''}`;
|
|
319
317
|
}
|
|
318
|
+
static rev2(h, s, m, value) {
|
|
319
|
+
return Dump.obj(h, m, s.timestamp, s.id, value === null || value === void 0 ? void 0 : value.selfSnapshotId);
|
|
320
|
+
}
|
|
320
321
|
static rev(r, m) {
|
|
321
322
|
const h = Data_1.Meta.get(r.data, Data_1.Meta.Holder);
|
|
322
323
|
const value = m !== undefined ? r.data[m] : undefined;
|
|
@@ -228,9 +228,9 @@ class TransactionImpl extends Transaction {
|
|
|
228
228
|
finally {
|
|
229
229
|
this.pending--;
|
|
230
230
|
if (this.sealed && this.pending === 0) {
|
|
231
|
-
this.applyOrDiscard();
|
|
231
|
+
const reactions = this.applyOrDiscard();
|
|
232
232
|
TransactionImpl.curr = outer;
|
|
233
|
-
TransactionImpl.standalone(Snapshot_1.Snapshot.
|
|
233
|
+
TransactionImpl.standalone(Snapshot_1.Snapshot.enqueueReactionsToRun, reactions);
|
|
234
234
|
}
|
|
235
235
|
else
|
|
236
236
|
TransactionImpl.curr = outer;
|
|
@@ -259,11 +259,12 @@ class TransactionImpl extends Transaction {
|
|
|
259
259
|
throw (0, Dbg_1.error)(`T${this.id}[${this.hint}] conflicts with: ${Snapshot_1.Dump.conflicts(conflicts)}`, undefined);
|
|
260
260
|
}
|
|
261
261
|
applyOrDiscard() {
|
|
262
|
+
let reactions;
|
|
262
263
|
try {
|
|
263
264
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.change)
|
|
264
265
|
Dbg_1.Dbg.log('╠═', '', '', undefined, 'changes');
|
|
265
|
-
this.snapshot.applyOrDiscard(this.canceled);
|
|
266
|
-
this.snapshot.
|
|
266
|
+
reactions = this.snapshot.applyOrDiscard(this.canceled);
|
|
267
|
+
this.snapshot.triggerGarbageCollection();
|
|
267
268
|
if (this.promise) {
|
|
268
269
|
if (this.canceled && !this.after)
|
|
269
270
|
this.reject(this.canceled);
|
|
@@ -277,6 +278,7 @@ class TransactionImpl extends Transaction {
|
|
|
277
278
|
(0, Dbg_1.fatal)(e);
|
|
278
279
|
throw e;
|
|
279
280
|
}
|
|
281
|
+
return reactions;
|
|
280
282
|
}
|
|
281
283
|
acquirePromise() {
|
|
282
284
|
if (!this.promise) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare type F<T> = (...args: any[]) => T;
|
|
2
2
|
export declare class Utils {
|
|
3
|
-
static freezeSet<T>(obj?: Set<T>):
|
|
4
|
-
static freezeMap<K, V>(obj?: Map<K, V>):
|
|
3
|
+
static freezeSet<T>(obj?: Set<T>): Set<T> | undefined;
|
|
4
|
+
static freezeMap<K, V>(obj?: Map<K, V>): Map<K, V> | undefined;
|
|
5
5
|
static copyAllMembers(source: any, target: any): any;
|
|
6
6
|
}
|
|
7
7
|
export declare function UNDEF(...args: any[]): never;
|
|
@@ -19,6 +19,7 @@ class Utils {
|
|
|
19
19
|
Object.defineProperty(obj, 'clear', pd);
|
|
20
20
|
Object.freeze(obj);
|
|
21
21
|
}
|
|
22
|
+
return obj;
|
|
22
23
|
}
|
|
23
24
|
static freezeMap(obj) {
|
|
24
25
|
if (obj instanceof Map) {
|
|
@@ -28,6 +29,7 @@ class Utils {
|
|
|
28
29
|
Object.defineProperty(obj, 'clear', pd);
|
|
29
30
|
Object.freeze(obj);
|
|
30
31
|
}
|
|
32
|
+
return obj;
|
|
31
33
|
}
|
|
32
34
|
static copyAllMembers(source, target) {
|
|
33
35
|
for (const m of Object.getOwnPropertyNames(source))
|