reactronic 0.21.602 → 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.
@@ -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, cause: MemberInfo, since: number, reactions: Observer[]): void;
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 revision: ObjectRevision;
26
+ readonly holder: ObjectHolder;
27
+ readonly snapshot: AbstractSnapshot;
27
28
  readonly memberName: MemberName;
28
29
  readonly usageCount: number;
29
30
  }
@@ -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 { ObjectRevision, MemberName, ObjectHolder, Observable, Observer, MemberInfo } from './Data';
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 revision: ObjectRevision;
42
+ readonly snapshot: AbstractSnapshot;
43
43
  observables: Map<Observable, MemberInfo> | undefined;
44
44
  options: OptionsImpl;
45
- cause: MemberInfo | undefined;
45
+ cause: string | undefined;
46
46
  args: any[];
47
47
  result: any;
48
48
  error: any;
49
49
  started: number;
50
- obsoleteDueTo: MemberInfo | undefined;
50
+ obsoleteDueTo: string | undefined;
51
51
  obsoleteSince: number;
52
52
  successor: Operation | undefined;
53
- constructor(controller: OperationController, revision: ObjectRevision, prev: Operation | OptionsImpl);
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, cause: MemberInfo, since: number, reactions: Observer[]): void;
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;
@@ -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 ROOT_TRIGGER = { revision: Snapshot_1.ROOT_REV, memberName: 'root-trigger', usageCount: 0 };
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 === ROOT_TRIGGER || !op.successor ||
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.revision.snapshot;
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.rev(oc.revision, this.memberName)} result is reused from T${oc.operation.transaction.id}[${oc.operation.transaction.hint}]`);
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 !== ROOT_TRIGGER &&
112
- (ctx === op.revision.snapshot || ctx.timestamp < op.obsoleteSince) &&
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.revision !== r) {
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 = ROOT_TRIGGER;
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, { revision: Snapshot_1.ROOT_REV, memberName: self.memberName, usageCount: 0 }, ctx.timestamp, ctx.reactions);
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, revision, prev) {
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.revision = revision;
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.revision.snapshot.id; }
220
- hint() { return `${Snapshot_1.Dump.rev(this.revision, this.controller.memberName)}`; }
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 ms = Date.now();
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
- trigger = ` << ${propagationHint(this.cause, true).join(' << ')}`;
228
+ cause = ` << ${this.cause}`;
233
229
  else if (this.controller.options.kind === Options_1.Kind.Transaction)
234
- trigger = ' << operation';
230
+ cause = ' << operation';
235
231
  else
236
- trigger = ` << T${this.revision.snapshot.id}[${this.revision.snapshot.hint}]`;
237
- return `${this.hint()}${trigger} (${ms !== Infinity ? `${ms}ms since previous run` : 'initial run'})`;
232
+ cause = ` << T${this.snapshot.id}[${this.snapshot.hint}]`;
233
+ return `${this.hint()}${cause}`;
238
234
  }
239
235
  briefWhy() {
240
- return this.cause ? propagationHint(this.cause, false)[0] : ROOT_HOLDER.hint;
236
+ return this.why();
241
237
  }
242
238
  dependencies() {
243
239
  throw (0, Dbg_1.misuse)('not implemented yet');
@@ -266,34 +262,33 @@ class Operation extends Data_1.Observable {
266
262
  else
267
263
  this.result = Promise.reject(this.error);
268
264
  }
269
- markObsoleteDueTo(observable, cause, since, reactions) {
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 &&
273
- cause.revision.snapshot === this.revision.snapshot &&
274
- cause.revision.changes.has(cause.memberName);
269
+ snapshot === this.snapshot;
275
270
  if (!skip) {
271
+ const why = `${Snapshot_1.Dump.rev2(holder, snapshot, memberName)} << ${outer}`;
276
272
  this.unsubscribeFromAllObservables();
277
- this.obsoleteDueTo = cause;
273
+ this.obsoleteDueTo = why;
278
274
  this.obsoleteSince = since;
279
275
  const isReaction = this.options.kind === Options_1.Kind.Reaction;
280
276
  if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.obsolete || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.obsolete)))
281
- Dbg_1.Dbg.log(Dbg_1.Dbg.trace.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', isReaction ? '█' : '▒', isReaction && cause.revision === Snapshot_1.ROOT_REV
277
+ Dbg_1.Dbg.log(Dbg_1.Dbg.trace.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', isReaction ? '█' : '▒', isReaction && snapshot === Snapshot_1.ROOT_REV.snapshot
282
278
  ? `${this.hint()} is a reaction and will run automatically (order ${this.options.order})`
283
- : `${this.hint()} is obsolete due to ${Snapshot_1.Dump.rev(cause.revision, cause.memberName)} since v${since}${isReaction ? ` and will run automatically (order ${this.options.order})` : ''}`);
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})` : ''}`);
284
280
  if (isReaction)
285
281
  reactions.push(this);
286
282
  else
287
- (_b = this.observers) === null || _b === void 0 ? void 0 : _b.forEach(c => c.markObsoleteDueTo(this, { revision: this.revision, memberName: this.controller.memberName, usageCount: 0 }, since, reactions));
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));
288
284
  const tran = this.transaction;
289
- if (tran.snapshot === cause.revision.snapshot) {
290
- (0, Dbg_1.misuse)('not implemented: running reactions within original transaction');
285
+ if (tran.snapshot === snapshot) {
291
286
  }
292
287
  else if (!tran.isFinished && this !== observable)
293
- tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Snapshot_1.Dump.rev(cause.revision, cause.memberName)} changed by T${cause.revision.snapshot.id}[${cause.revision.snapshot.hint}]`), null);
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);
294
289
  }
295
290
  else if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.obsolete || ((_c = this.options.trace) === null || _c === void 0 ? void 0 : _c.obsolete)))
296
- Dbg_1.Dbg.log(' ', 'x', `${this.hint()} is not obsolete due to its own change to ${Snapshot_1.Dump.rev(cause.revision, cause.memberName)}`);
291
+ Dbg_1.Dbg.log(' ', 'x', `${this.hint()} is not obsolete due to its own change to ${Snapshot_1.Dump.rev2(holder, snapshot, memberName)}`);
297
292
  }
298
293
  }
299
294
  runIfNotUpToDate(now, nothrow) {
@@ -455,19 +450,19 @@ class Operation extends Data_1.Observable {
455
450
  ctx.bumpBy(r.snapshot.timestamp);
456
451
  const t = weak ? -1 : ctx.timestamp;
457
452
  if (!op.subscribeTo(observable, r, m, h, t))
458
- op.markObsoleteDueTo(observable, { revision: r, memberName: m, usageCount: 0 }, ctx.timestamp, ctx.reactions);
453
+ op.markObsoleteDueTo(observable, m, r.snapshot, h, INITIAL_CAUSE, ctx.timestamp, ctx.reactions);
459
454
  }
460
455
  }
461
456
  }
462
457
  static markEdited(oldValue, newValue, edited, r, m, h) {
463
458
  edited ? r.changes.add(m) : r.changes.delete(m);
464
459
  if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.write)
465
- edited ? Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.rev(r, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`) : Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.rev(r, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`, undefined, ' (same as previous)');
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)');
466
461
  }
467
462
  static isConflicting(oldValue, newValue) {
468
463
  let result = oldValue !== newValue;
469
464
  if (result)
470
- result = oldValue instanceof Operation && oldValue.cause !== ROOT_TRIGGER;
465
+ result = oldValue instanceof Operation && oldValue.cause !== INITIAL_CAUSE;
471
466
  return result;
472
467
  }
473
468
  static propagateAllChangesThroughSubscriptions(snapshot) {
@@ -493,26 +488,30 @@ class Operation extends Data_1.Observable {
493
488
  if (reactions) {
494
489
  const prev = r.prev.revision.data[m];
495
490
  if (prev !== undefined && prev instanceof Data_1.Observable) {
496
- const cause = { revision: r, memberName: m, usageCount: 0 };
491
+ const why = `T${r.snapshot.id}[${r.snapshot.hint}]`;
497
492
  if (prev instanceof Operation) {
498
493
  if ((prev.obsoleteSince === Snapshot_1.MAX_TIMESTAMP || prev.obsoleteSince <= 0)) {
499
- prev.obsoleteDueTo = cause;
494
+ prev.obsoleteDueTo = why;
500
495
  prev.obsoleteSince = timestamp;
501
496
  prev.unsubscribeFromAllObservables();
502
497
  }
503
- const opponent = prev.successor;
504
- if (opponent !== curr && opponent && !opponent.transaction.isFinished)
505
- opponent.transaction.cancel(new Error(`T${opponent.transaction.id}[${opponent.transaction.hint}] is canceled by T${r.snapshot.id}[${r.snapshot.hint}] and will not run anymore`), null);
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;
506
505
  }
507
- (_a = prev.observers) === null || _a === void 0 ? void 0 : _a.forEach(c => c.markObsoleteDueTo(prev, cause, timestamp, reactions));
506
+ (_a = prev.observers) === null || _a === void 0 ? void 0 : _a.forEach(c => c.markObsoleteDueTo(prev, m, r.snapshot, h, why, timestamp, reactions));
508
507
  }
509
508
  }
510
509
  if (curr instanceof Operation) {
511
- if (curr.revision === r && curr.observables !== undefined) {
510
+ if (curr.snapshot === r.snapshot && curr.observables !== undefined) {
512
511
  if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
513
512
  curr.observables.forEach((hint, v) => {
514
513
  if (hint.usageCount > Hooks_1.Hooks.repetitiveUsageWarningThreshold)
515
- Dbg_1.Dbg.log('', '[!]', `${curr.hint()} uses ${Snapshot_1.Dump.rev(hint.revision, hint.memberName)} ${hint.usageCount} times (consider remembering it in a local variable)`, 0, ' *** WARNING ***');
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 ***');
516
515
  });
517
516
  }
518
517
  if (unsubscribe)
@@ -552,7 +551,7 @@ class Operation extends Data_1.Observable {
552
551
  var _a;
553
552
  value.observers.delete(this);
554
553
  if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.read)))
555
- Dbg_1.Dbg.log(Dbg_1.Dbg.trace.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', '-', `${this.hint()} is unsubscribed from ${Snapshot_1.Dump.rev(hint.revision, hint.memberName)}`);
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)}`);
556
555
  });
557
556
  this.observables = undefined;
558
557
  }
@@ -568,18 +567,18 @@ class Operation extends Data_1.Observable {
568
567
  if (this.observables !== undefined) {
569
568
  if (!observable.observers)
570
569
  observable.observers = new Set();
571
- const info = { revision: r, memberName: m, usageCount: times };
570
+ const info = { holder: h, snapshot: r.snapshot, memberName: m, usageCount: times };
572
571
  observable.observers.add(this);
573
572
  this.observables.set(observable, info);
574
573
  if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.read)))
575
- Dbg_1.Dbg.log('║', ' ∞ ', `${this.hint()} is subscribed to ${Snapshot_1.Dump.rev(r, m)}${info.usageCount > 1 ? ` (${info.usageCount} times)` : ''}`);
574
+ Dbg_1.Dbg.log('║', ' ∞ ', `${this.hint()} is subscribed to ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}${info.usageCount > 1 ? ` (${info.usageCount} times)` : ''}`);
576
575
  }
577
576
  else if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_b = this.options.trace) === null || _b === void 0 ? void 0 : _b.read)))
578
- Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Snapshot_1.Dump.rev(r, m)}`);
577
+ Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}`);
579
578
  }
580
579
  else {
581
580
  if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_c = this.options.trace) === null || _c === void 0 ? void 0 : _c.read)))
582
- Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Snapshot_1.Dump.rev(r, m)}`);
581
+ Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}`);
583
582
  }
584
583
  return ok;
585
584
  }
@@ -602,7 +601,7 @@ class Operation extends Data_1.Observable {
602
601
  let op = initial[m];
603
602
  const ctl = op ? op.controller : new OperationController(ROOT_HOLDER, m);
604
603
  const opts = op ? op.options : Hooks_1.OptionsImpl.INITIAL;
605
- 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));
606
605
  if (op.options.kind === Options_1.Kind.Reaction && op.options.throttling < Number.MAX_SAFE_INTEGER) {
607
606
  const reactions = Data_1.Meta.acquire(proto, Data_1.Meta.Reactions);
608
607
  reactions[m] = op;
@@ -615,7 +614,6 @@ class Operation extends Data_1.Observable {
615
614
  }
616
615
  static init() {
617
616
  Object.freeze(ROOT_ARGS);
618
- Object.freeze(ROOT_TRIGGER);
619
617
  Dbg_1.Dbg.getMergedTraceOptions = getMergedTraceOptions;
620
618
  Snapshot_1.Snapshot.markUsed = Operation.markUsed;
621
619
  Snapshot_1.Snapshot.markEdited = Operation.markEdited;
@@ -651,18 +649,6 @@ class Operation extends Data_1.Observable {
651
649
  Operation.current = undefined;
652
650
  Operation.queuedReactions = [];
653
651
  Operation.deferredReactions = [];
654
- function propagationHint(cause, full) {
655
- const result = [];
656
- let observable = cause.revision.data[cause.memberName];
657
- while (observable instanceof Operation && observable.obsoleteDueTo) {
658
- full && result.push(Snapshot_1.Dump.rev(cause.revision, cause.memberName));
659
- cause = observable.obsoleteDueTo;
660
- observable = cause.revision.data[cause.memberName];
661
- }
662
- result.push(Snapshot_1.Dump.rev(cause.revision, cause.memberName));
663
- full && result.push(cause.revision.snapshot.hint);
664
- return result;
665
- }
666
652
  function valueHint(value, m) {
667
653
  let result = '';
668
654
  if (Array.isArray(value))
@@ -672,7 +658,7 @@ function valueHint(value, m) {
672
658
  else if (value instanceof Map)
673
659
  result = `Map(${value.size})`;
674
660
  else if (value instanceof Operation)
675
- result = `${Snapshot_1.Dump.rev(value.revision, m)}`;
661
+ result = `${Snapshot_1.Dump.rev2(value.controller.ownHolder, value.snapshot, m)}`;
676
662
  else if (value === Data_1.Meta.Disposed)
677
663
  result = '<disposed>';
678
664
  else if (value !== undefined && value !== null)
@@ -43,14 +43,14 @@ export declare class Snapshot implements AbstractSnapshot {
43
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
- private triggerGarbageCollection;
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;
@@ -130,14 +130,14 @@ class Snapshot {
130
130
  if (this.changeset.size > 0) {
131
131
  this.changeset.forEach((r, h) => {
132
132
  if (r.prev.revision !== h.head) {
133
- const merged = Snapshot.merge(r, h.head);
133
+ const merged = Snapshot.merge(h, r);
134
134
  if (r.conflicts.size > 0) {
135
135
  if (!conflicts)
136
136
  conflicts = [];
137
137
  conflicts.push(r);
138
138
  }
139
139
  if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.transaction)
140
- Dbg_1.Dbg.log('╠╝', '', `${Dump.rev(r)} is merged with ${Dump.rev(h.head)} among ${merged} properties with ${r.conflicts.size} conflicts.`);
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.`);
141
141
  }
142
142
  });
143
143
  if (this.options.token === undefined) {
@@ -154,8 +154,9 @@ class Snapshot {
154
154
  }
155
155
  return conflicts;
156
156
  }
157
- static merge(ours, head) {
157
+ static merge(h, ours) {
158
158
  let counter = 0;
159
+ const head = h.head;
159
160
  const disposed = head.changes.has(Data_1.Meta.Disposed);
160
161
  const merged = Object.assign({}, head.data);
161
162
  ours.changes.forEach((o, m) => {
@@ -164,7 +165,7 @@ class Snapshot {
164
165
  if (disposed || m === Data_1.Meta.Disposed) {
165
166
  if (disposed !== (m === Data_1.Meta.Disposed)) {
166
167
  if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.change)
167
- Dbg_1.Dbg.log('║╠', '', `${Dump.rev(ours, m)} <> ${Dump.rev(head, m)}`, 0, ' *** CONFLICT ***');
168
+ Dbg_1.Dbg.log('║╠', '', `${Dump.rev2(h, ours.snapshot, m)} <> ${Dump.rev2(h, head.snapshot, m)}`, 0, ' *** CONFLICT ***');
168
169
  ours.conflicts.set(m, head);
169
170
  }
170
171
  }
@@ -173,7 +174,7 @@ class Snapshot {
173
174
  if (conflict)
174
175
  ours.conflicts.set(m, head);
175
176
  if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.change)
176
- Dbg_1.Dbg.log('║╠', '', `${Dump.rev(ours, m)} ${conflict ? '<>' : '=='} ${Dump.rev(head, m)}`, 0, conflict ? ' *** CONFLICT ***' : undefined);
177
+ Dbg_1.Dbg.log('║╠', '', `${Dump.rev2(h, ours.snapshot, m)} ${conflict ? '<>' : '=='} ${Dump.rev2(h, head.snapshot, m)}`, 0, conflict ? ' *** CONFLICT ***' : undefined);
177
178
  }
178
179
  });
179
180
  Utils_1.Utils.copyAllMembers(merged, ours.data);
@@ -202,7 +203,7 @@ class Snapshot {
202
203
  const members = [];
203
204
  r.changes.forEach((o, m) => members.push(m.toString()));
204
205
  const s = members.join(', ');
205
- Dbg_1.Dbg.log('║', '√', `${Dump.rev(r)} (${s}) is ${r.prev.revision === exports.ROOT_REV ? 'constructed' : `applied on top of ${Dump.rev(r.prev.revision)}`}`);
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)}`}`);
206
207
  });
207
208
  }
208
209
  if (Dbg_1.Dbg.trace.transaction)
@@ -231,16 +232,6 @@ class Snapshot {
231
232
  }
232
233
  }
233
234
  }
234
- collectGarbage() {
235
- this.changeset = EMPTY_MAP;
236
- this.reactions = EMPTY_ARRAY;
237
- if (Dbg_1.Dbg.isOn) {
238
- Utils_1.Utils.freezeMap(this.changeset);
239
- Object.freeze(this.reactions);
240
- Object.freeze(this);
241
- }
242
- this.triggerGarbageCollection();
243
- }
244
235
  static freezeObjectRevision(r) {
245
236
  Object.freeze(r.data);
246
237
  Utils_1.Utils.freezeSet(r.changes);
@@ -272,7 +263,7 @@ class Snapshot {
272
263
  Dbg_1.Dbg.log('', '[G]', `Dismiss history below v${this.stamp}t${this.id} (${this.hint})`);
273
264
  this.changeset.forEach((r, h) => {
274
265
  if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.gc && r.prev.revision !== exports.ROOT_REV)
275
- Dbg_1.Dbg.log(' ', ' ', `${Dump.rev(r.prev.revision)} is ready for GC because overwritten by ${Dump.rev(r)}`);
266
+ Dbg_1.Dbg.log(' ', ' ', `${Dump.rev2(h, r.prev.revision.snapshot)} is ready for GC because overwritten by ${Dump.rev2(h, r.snapshot)}`);
276
267
  if (Snapshot.garbageCollectionSummaryInterval < Number.MAX_SAFE_INTEGER) {
277
268
  if (r.prev.revision !== exports.ROOT_REV)
278
269
  Snapshot.totalObjectRevisionCount--;
@@ -281,12 +272,16 @@ class Snapshot {
281
272
  }
282
273
  r.prev.revision = exports.ROOT_REV;
283
274
  });
275
+ this.changeset = EMPTY_MAP;
276
+ this.reactions = EMPTY_ARRAY;
277
+ if (Dbg_1.Dbg.isOn)
278
+ Object.freeze(this);
284
279
  }
285
280
  static _init() {
286
281
  const root = exports.ROOT_REV.snapshot;
287
282
  root.acquire(root);
288
283
  root.applyOrDiscard();
289
- root.collectGarbage();
284
+ root.triggerGarbageCollection();
290
285
  Snapshot.freezeObjectRevision(exports.ROOT_REV);
291
286
  Snapshot.idGen = 100;
292
287
  Snapshot.stampGen = 101;
@@ -320,6 +315,9 @@ class Dump {
320
315
  ? `root${member}`
321
316
  : stamp === undefined ? `${h.hint}${member} #${h.id}` : `${h.hint}${member} #${h.id}t${op}v${stamp}${xop !== undefined && xop !== 0 ? `t${xop}` : ''}`;
322
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
+ }
323
321
  static rev(r, m) {
324
322
  const h = Data_1.Meta.get(r.data, Data_1.Meta.Holder);
325
323
  const value = m !== undefined ? r.data[m] : undefined;
@@ -264,7 +264,7 @@ class TransactionImpl extends Transaction {
264
264
  if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.change)
265
265
  Dbg_1.Dbg.log('╠═', '', '', undefined, 'changes');
266
266
  reactions = this.snapshot.applyOrDiscard(this.canceled);
267
- this.snapshot.collectGarbage();
267
+ this.snapshot.triggerGarbageCollection();
268
268
  if (this.promise) {
269
269
  if (this.canceled && !this.after)
270
270
  this.reject(this.canceled);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactronic",
3
- "version": "0.21.602",
3
+ "version": "0.21.603",
4
4
  "description": "Reactronic - Transactional Reactive State Management",
5
5
  "main": "build/dist/source/api.js",
6
6
  "types": "build/dist/source/api.d.ts",