reactronic 0.21.600 → 0.21.604
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/Trace.d.ts +1 -0
- package/build/dist/source/Trace.js +18 -0
- 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 +7 -7
- package/build/dist/source/impl/Operation.js +68 -73
- 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
|
@@ -20,6 +20,24 @@ exports.TraceLevel = {
|
|
|
20
20
|
margin1: 0,
|
|
21
21
|
margin2: 0,
|
|
22
22
|
},
|
|
23
|
+
Reactions: {
|
|
24
|
+
silent: false,
|
|
25
|
+
transaction: false,
|
|
26
|
+
operation: false,
|
|
27
|
+
step: false,
|
|
28
|
+
monitor: false,
|
|
29
|
+
read: false,
|
|
30
|
+
write: false,
|
|
31
|
+
change: false,
|
|
32
|
+
obsolete: true,
|
|
33
|
+
error: true,
|
|
34
|
+
warning: true,
|
|
35
|
+
gc: false,
|
|
36
|
+
color: 37,
|
|
37
|
+
prefix: '',
|
|
38
|
+
margin1: 0,
|
|
39
|
+
margin2: 0,
|
|
40
|
+
},
|
|
23
41
|
Transactions: {
|
|
24
42
|
silent: false,
|
|
25
43
|
transaction: true,
|
|
@@ -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,7 @@ 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
83
|
private static runQueuedReactionsLoop;
|
|
84
84
|
private unsubscribeFromAllObservables;
|
|
85
85
|
private subscribeTo;
|
|
@@ -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,10 +527,10 @@ 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
532
|
const isReactionLoopRequired = queue.length === 0;
|
|
525
|
-
for (const r of
|
|
533
|
+
for (const r of reactions)
|
|
526
534
|
queue.push(r);
|
|
527
535
|
if (isReactionLoopRequired)
|
|
528
536
|
OperationController.runWithin(undefined, Operation.runQueuedReactionsLoop);
|
|
@@ -543,7 +551,7 @@ class Operation extends Data_1.Observable {
|
|
|
543
551
|
var _a;
|
|
544
552
|
value.observers.delete(this);
|
|
545
553
|
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.read)))
|
|
546
|
-
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)}`);
|
|
547
555
|
});
|
|
548
556
|
this.observables = undefined;
|
|
549
557
|
}
|
|
@@ -559,18 +567,18 @@ class Operation extends Data_1.Observable {
|
|
|
559
567
|
if (this.observables !== undefined) {
|
|
560
568
|
if (!observable.observers)
|
|
561
569
|
observable.observers = new Set();
|
|
562
|
-
const info = {
|
|
570
|
+
const info = { holder: h, snapshot: r.snapshot, memberName: m, usageCount: times };
|
|
563
571
|
observable.observers.add(this);
|
|
564
572
|
this.observables.set(observable, info);
|
|
565
573
|
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.read)))
|
|
566
|
-
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)` : ''}`);
|
|
567
575
|
}
|
|
568
576
|
else if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_b = this.options.trace) === null || _b === void 0 ? void 0 : _b.read)))
|
|
569
|
-
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)}`);
|
|
570
578
|
}
|
|
571
579
|
else {
|
|
572
580
|
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_c = this.options.trace) === null || _c === void 0 ? void 0 : _c.read)))
|
|
573
|
-
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)}`);
|
|
574
582
|
}
|
|
575
583
|
return ok;
|
|
576
584
|
}
|
|
@@ -593,7 +601,7 @@ class Operation extends Data_1.Observable {
|
|
|
593
601
|
let op = initial[m];
|
|
594
602
|
const ctl = op ? op.controller : new OperationController(ROOT_HOLDER, m);
|
|
595
603
|
const opts = op ? op.options : Hooks_1.OptionsImpl.INITIAL;
|
|
596
|
-
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));
|
|
597
605
|
if (op.options.kind === Options_1.Kind.Reaction && op.options.throttling < Number.MAX_SAFE_INTEGER) {
|
|
598
606
|
const reactions = Data_1.Meta.acquire(proto, Data_1.Meta.Reactions);
|
|
599
607
|
reactions[m] = op;
|
|
@@ -606,14 +614,13 @@ class Operation extends Data_1.Observable {
|
|
|
606
614
|
}
|
|
607
615
|
static init() {
|
|
608
616
|
Object.freeze(ROOT_ARGS);
|
|
609
|
-
Object.freeze(ROOT_TRIGGER);
|
|
610
617
|
Dbg_1.Dbg.getMergedTraceOptions = getMergedTraceOptions;
|
|
611
618
|
Snapshot_1.Snapshot.markUsed = Operation.markUsed;
|
|
612
619
|
Snapshot_1.Snapshot.markEdited = Operation.markEdited;
|
|
613
620
|
Snapshot_1.Snapshot.isConflicting = Operation.isConflicting;
|
|
614
621
|
Snapshot_1.Snapshot.propagateAllChangesThroughSubscriptions = Operation.propagateAllChangesThroughSubscriptions;
|
|
615
622
|
Snapshot_1.Snapshot.revokeAllSubscriptions = Operation.revokeAllSubscriptions;
|
|
616
|
-
Snapshot_1.Snapshot.
|
|
623
|
+
Snapshot_1.Snapshot.enqueueReactionsToRun = Operation.enqueueReactionsToRun;
|
|
617
624
|
Hooks_1.Hooks.createControllerAndGetHook = Operation.createControllerAndGetHook;
|
|
618
625
|
Hooks_1.Hooks.rememberOperationOptions = Operation.rememberOperationOptions;
|
|
619
626
|
Promise.prototype.then = reactronicHookedThen;
|
|
@@ -642,18 +649,6 @@ class Operation extends Data_1.Observable {
|
|
|
642
649
|
Operation.current = undefined;
|
|
643
650
|
Operation.queuedReactions = [];
|
|
644
651
|
Operation.deferredReactions = [];
|
|
645
|
-
function propagationHint(cause, full) {
|
|
646
|
-
const result = [];
|
|
647
|
-
let observable = cause.revision.data[cause.memberName];
|
|
648
|
-
while (observable instanceof Operation && observable.obsoleteDueTo) {
|
|
649
|
-
full && result.push(Snapshot_1.Dump.rev(cause.revision, cause.memberName));
|
|
650
|
-
cause = observable.obsoleteDueTo;
|
|
651
|
-
observable = cause.revision.data[cause.memberName];
|
|
652
|
-
}
|
|
653
|
-
result.push(Snapshot_1.Dump.rev(cause.revision, cause.memberName));
|
|
654
|
-
full && result.push(cause.revision.snapshot.hint);
|
|
655
|
-
return result;
|
|
656
|
-
}
|
|
657
652
|
function valueHint(value, m) {
|
|
658
653
|
let result = '';
|
|
659
654
|
if (Array.isArray(value))
|
|
@@ -663,7 +658,7 @@ function valueHint(value, m) {
|
|
|
663
658
|
else if (value instanceof Map)
|
|
664
659
|
result = `Map(${value.size})`;
|
|
665
660
|
else if (value instanceof Operation)
|
|
666
|
-
result = `${Snapshot_1.Dump.
|
|
661
|
+
result = `${Snapshot_1.Dump.rev2(value.controller.ownHolder, value.snapshot, m)}`;
|
|
667
662
|
else if (value === Data_1.Meta.Disposed)
|
|
668
663
|
result = '<disposed>';
|
|
669
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))
|