reactronic 0.24.275 → 0.24.302

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.
@@ -1,54 +1,49 @@
1
1
  import { Log, misuse } from "../util/Dbg.js";
2
- import { Kind, Reentrance } from "../Options.js";
3
- import { ObjectHandle, ValueSnapshot, Meta } from "./Data.js";
4
- import { Changeset, Dump, EMPTY_SNAPSHOT, MAX_REVISION } from "./Changeset.js";
5
- import { Transaction } from "./Transaction.js";
2
+ import { Kind, Reentrance, Isolation } from "../Options.js";
3
+ import { ObjectHandle, FieldVersion, Meta } from "./Data.js";
4
+ import { Changeset, Dump, EMPTY_OBJECT_VERSION, MAX_REVISION } from "./Changeset.js";
5
+ import { Transaction, TransactionImpl } from "./Transaction.js";
6
6
  import { IndicatorImpl } from "./Indicator.js";
7
7
  import { Mvcc, OptionsImpl } from "./Mvcc.js";
8
8
  import { JournalImpl } from "./Journal.js";
9
9
  const BOOT_ARGS = [];
10
10
  const BOOT_CAUSE = "<boot>";
11
- const EMPTY_HANDLE = new ObjectHandle(undefined, undefined, Mvcc.observable, EMPTY_SNAPSHOT, "<boot>");
12
- export class ReactionImpl {
13
- configure(options) { return ReactionImpl.configureImpl(this, options); }
11
+ const EMPTY_HANDLE = new ObjectHandle(undefined, undefined, Mvcc.observable, EMPTY_OBJECT_VERSION, "<boot>");
12
+ export class OperationImpl {
13
+ configure(options) { return OperationImpl.configureImpl(this, options); }
14
14
  get options() { return this.peek(undefined).launch.options; }
15
15
  get unobs() { return this.peek(undefined).launch.content; }
16
16
  get args() { return this.use().launch.args; }
17
17
  get result() { return this.reuseOrRelaunch(true, undefined).content; }
18
18
  get error() { return this.use().launch.error; }
19
- get stamp() { return this.use().snapshot.changeset.timestamp; }
19
+ get stamp() { return this.use().objectVersion.changeset.timestamp; }
20
20
  get isUpToDate() { return this.use().isUpToDate; }
21
- markObsolete() { Transaction.run({ hint: Log.isOn ? `markObsolete(${Dump.obj(this.objectHandle, this.memberName)})` : "markObsolete()" }, ReactionImpl.markObsolete, this); }
21
+ markObsolete() { Transaction.run({ hint: Log.isOn ? `markObsolete(${Dump.obj(this.ownerHandle, this.fieldKey)})` : "markObsolete()" }, OperationImpl.markObsolete, this); }
22
22
  pullLastResult(args) { return this.reuseOrRelaunch(true, args).content; }
23
- constructor(h, m) {
24
- this.objectHandle = h;
25
- this.memberName = m;
23
+ constructor(h, fk) {
24
+ this.ownerHandle = h;
25
+ this.fieldKey = fk;
26
26
  }
27
27
  reuseOrRelaunch(weak, args) {
28
- var _a;
29
28
  let ror = this.peek(args);
30
29
  const ctx = ror.changeset;
31
30
  const launch = ror.launch;
32
31
  const opts = launch.options;
33
- if (!ror.isUpToDate && !ror.snapshot.disposed
32
+ if (!ror.isUpToDate && !ror.objectVersion.disposed
34
33
  && (!weak || launch.cause === BOOT_CAUSE || !launch.successor ||
35
34
  launch.successor.transaction.isFinished)) {
36
- const outerOpts = (_a = Launch.current) === null || _a === void 0 ? void 0 : _a.options;
37
- const separation = weak || opts.separation !== false || opts.kind === Kind.reactive ||
38
- (opts.kind === Kind.transactional && outerOpts && (outerOpts.noSideEffects || outerOpts.kind === Kind.cached)) ||
39
- (opts.kind === Kind.cached && (ror.snapshot.changeset.sealed ||
40
- ror.snapshot.former.snapshot !== EMPTY_SNAPSHOT));
35
+ const isolation = !weak ? opts.isolation : Isolation.disjoinFromOuterTransaction;
41
36
  const token = opts.noSideEffects ? this : undefined;
42
- const ror2 = this.relaunch(ror, separation, opts, token, args);
37
+ const ror2 = this.relaunch(ror, isolation, opts, token, args);
43
38
  const ctx2 = ror2.launch.changeset;
44
39
  if (!weak || ctx === ctx2 || (ctx2.sealed && ctx.timestamp >= ctx2.timestamp))
45
40
  ror = ror2;
46
41
  }
47
42
  else if (Log.isOn && Log.opt.operation && (opts.logging === undefined ||
48
43
  opts.logging.operation === undefined || opts.logging.operation === true))
49
- Log.write(Transaction.current.isFinished ? "" : "║", " (=)", `${Dump.snapshot2(ror.launch.reaction.objectHandle, ror.changeset, this.memberName)} result is reused from T${ror.launch.transaction.id}[${ror.launch.transaction.hint}]`);
44
+ Log.write(Transaction.current.isFinished ? "" : "║", " (=)", `${Dump.snapshot2(ror.launch.operation.ownerHandle, ror.changeset, this.fieldKey)} result is reused from T${ror.launch.transaction.id}[${ror.launch.transaction.hint}]`);
50
45
  const t = ror.launch;
51
- Changeset.markUsed(t, ror.snapshot, this.memberName, this.objectHandle, t.options.kind, weak);
46
+ Changeset.markUsed(t, ror.objectVersion, this.fieldKey, this.ownerHandle, t.options.kind, weak);
52
47
  return t;
53
48
  }
54
49
  static getControllerOf(method) {
@@ -101,81 +96,81 @@ export class ReactionImpl {
101
96
  }
102
97
  peek(args) {
103
98
  const ctx = Changeset.current();
104
- const os = ctx.lookupObjectSnapshot(this.objectHandle, this.memberName);
105
- const launch = this.acquireFromSnapshot(os, args);
99
+ const ov = ctx.lookupObjectVersion(this.ownerHandle, this.fieldKey, false);
100
+ const launch = this.acquireFromObjectVersion(ov, args);
106
101
  const isValid = launch.options.kind !== Kind.transactional && launch.cause !== BOOT_CAUSE &&
107
102
  (ctx === launch.changeset || ctx.timestamp < launch.obsoleteSince) &&
108
103
  (!launch.options.triggeringArgs || args === undefined ||
109
- launch.args.length === args.length && launch.args.every((t, i) => t === args[i])) || os.disposed;
110
- return { launch, isUpToDate: isValid, changeset: ctx, snapshot: os };
104
+ launch.args.length === args.length && launch.args.every((t, i) => t === args[i])) || ov.disposed;
105
+ return { launch, isUpToDate: isValid, changeset: ctx, objectVersion: ov };
111
106
  }
112
107
  use() {
113
108
  const ror = this.peek(undefined);
114
- Changeset.markUsed(ror.launch, ror.snapshot, this.memberName, this.objectHandle, ror.launch.options.kind, true);
109
+ Changeset.markUsed(ror.launch, ror.objectVersion, this.fieldKey, this.ownerHandle, ror.launch.options.kind, true);
115
110
  return ror;
116
111
  }
117
112
  edit() {
118
- const h = this.objectHandle;
119
- const m = this.memberName;
113
+ const h = this.ownerHandle;
114
+ const fk = this.fieldKey;
120
115
  const ctx = Changeset.edit();
121
- const os = ctx.getEditableObjectSnapshot(h, m, Meta.Handle, this);
122
- let launch = this.acquireFromSnapshot(os, undefined);
123
- if (launch.changeset !== os.changeset) {
124
- const relaunch = new Launch(this, os.changeset, launch);
125
- os.data[m] = relaunch.reenterOver(launch);
126
- ctx.bumpBy(os.former.snapshot.changeset.timestamp);
127
- Changeset.markEdited(launch, relaunch, true, os, m, h);
116
+ const ov = ctx.getEditableObjectVersion(h, fk, Meta.Handle, this);
117
+ let launch = this.acquireFromObjectVersion(ov, undefined);
118
+ if (launch.changeset !== ov.changeset) {
119
+ const relaunch = new Launch(Transaction.current, this, ov.changeset, launch, false);
120
+ ov.data[fk] = relaunch.reenterOver(launch);
121
+ ctx.bumpBy(ov.former.objectVersion.changeset.timestamp);
122
+ Changeset.markEdited(launch, relaunch, true, ov, fk, h);
128
123
  launch = relaunch;
129
124
  }
130
- return { launch, isUpToDate: true, changeset: ctx, snapshot: os };
131
- }
132
- acquireFromSnapshot(os, args) {
133
- const m = this.memberName;
134
- let launch = os.data[m];
135
- if (launch.reaction !== this) {
136
- if (os.changeset !== EMPTY_SNAPSHOT.changeset) {
137
- const hint = Log.isOn ? `${Dump.obj(this.objectHandle, m)}/init` : "MethodController/init";
138
- const separation = os.changeset.sealed || os.former.snapshot !== EMPTY_SNAPSHOT;
139
- launch = Transaction.run({ hint, separation, token: this }, () => {
140
- const h = this.objectHandle;
141
- let r = Changeset.current().getObjectSnapshot(h, m);
142
- let relaunch = r.data[m];
143
- if (relaunch.reaction !== this) {
144
- r = Changeset.edit().getEditableObjectSnapshot(h, m, Meta.Handle, this);
145
- const t = new Launch(this, r.changeset, relaunch);
125
+ return { launch, isUpToDate: true, changeset: ctx, objectVersion: ov };
126
+ }
127
+ acquireFromObjectVersion(ov, args) {
128
+ const fk = this.fieldKey;
129
+ let launch = ov.data[fk];
130
+ if (launch.operation !== this) {
131
+ if (ov.changeset !== EMPTY_OBJECT_VERSION.changeset) {
132
+ const hint = Log.isOn ? `${Dump.obj(this.ownerHandle, fk)}/init` : "MethodController/init";
133
+ const isolation = Isolation.joinToCurrentTransaction;
134
+ launch = Transaction.run({ hint, isolation, token: this }, () => {
135
+ const h = this.ownerHandle;
136
+ let r = Changeset.current().getObjectVersion(h, fk);
137
+ let relaunch = r.data[fk];
138
+ if (relaunch.operation !== this) {
139
+ r = Changeset.edit().getEditableObjectVersion(h, fk, Meta.Handle, this);
140
+ const t = new Launch(Transaction.current, this, r.changeset, relaunch, false);
146
141
  if (args)
147
142
  t.args = args;
148
143
  t.cause = BOOT_CAUSE;
149
- r.data[m] = t;
150
- Changeset.markEdited(relaunch, t, true, r, m, h);
144
+ r.data[fk] = t;
145
+ Changeset.markEdited(relaunch, t, true, r, fk, h);
151
146
  relaunch = t;
152
147
  }
153
148
  return relaunch;
154
149
  });
155
150
  }
156
151
  else {
157
- const initialLaunch = new Launch(this, os.changeset, launch);
152
+ const initialLaunch = new Launch(Transaction.current, this, ov.changeset, launch, false);
158
153
  if (args)
159
154
  initialLaunch.args = args;
160
155
  initialLaunch.cause = BOOT_CAUSE;
161
- os.data[m] = initialLaunch;
156
+ ov.data[fk] = initialLaunch;
162
157
  launch = initialLaunch;
163
158
  if (Log.isOn && Log.opt.write)
164
- Log.write("║", " ++", `${Dump.obj(this.objectHandle, m)} is initialized (revision ${os.revision})`);
159
+ Log.write("║", " ++", `${Dump.obj(this.ownerHandle, fk)} is initialized (revision ${ov.revision})`);
165
160
  }
166
161
  }
167
162
  return launch;
168
163
  }
169
- relaunch(existing, separation, options, token, args) {
170
- const hint = Log.isOn ? `${Dump.obj(this.objectHandle, this.memberName)}${args && args.length > 0 && (typeof args[0] === "number" || typeof args[0] === "string") ? ` - ${args[0]}` : ""}` : `${Dump.obj(this.objectHandle, this.memberName)}`;
164
+ relaunch(existing, isolation, options, token, args) {
165
+ const hint = Log.isOn ? `${Dump.obj(this.ownerHandle, this.fieldKey)}${args && args.length > 0 && (typeof args[0] === "number" || typeof args[0] === "string") ? ` - ${args[0]}` : ""}` : `${Dump.obj(this.ownerHandle, this.fieldKey)}`;
171
166
  let ror = existing;
172
- const opts = { hint, separation, journal: options.journal, logging: options.logging, token };
167
+ const opts = { hint, isolation, journal: options.journal, logging: options.logging, token };
173
168
  const result = Transaction.run(opts, (argsx) => {
174
169
  if (!ror.launch.transaction.isCanceled) {
175
170
  ror = this.edit();
176
171
  if (Log.isOn && Log.opt.operation)
177
172
  Log.write("║", " o", `${ror.launch.why()}`);
178
- ror.launch.proceed(this.objectHandle.proxy, argsx);
173
+ ror.launch.proceed(this.ownerHandle.proxy, argsx);
179
174
  }
180
175
  else {
181
176
  ror = this.peek(argsx);
@@ -183,7 +178,7 @@ export class ReactionImpl {
183
178
  ror = this.edit();
184
179
  if (Log.isOn && Log.opt.operation)
185
180
  Log.write("║", " o", `${ror.launch.why()}`);
186
- ror.launch.proceed(this.objectHandle.proxy, argsx);
181
+ ror.launch.proceed(this.ownerHandle.proxy, argsx);
187
182
  }
188
183
  }
189
184
  return ror.launch.result;
@@ -194,44 +189,67 @@ export class ReactionImpl {
194
189
  static markObsolete(self) {
195
190
  const ror = self.peek(undefined);
196
191
  const ctx = ror.changeset;
197
- ror.launch.markObsoleteDueTo(ror.launch, self.memberName, EMPTY_SNAPSHOT.changeset, EMPTY_HANDLE, BOOT_CAUSE, ctx.timestamp, ctx.obsolete);
192
+ ror.launch.markObsoleteDueTo(ror.launch, self.fieldKey, EMPTY_OBJECT_VERSION.changeset, EMPTY_HANDLE, BOOT_CAUSE, ctx.timestamp, ctx.obsolete);
198
193
  }
199
194
  }
200
- class Launch extends ValueSnapshot {
201
- constructor(reaction, changeset, former) {
202
- super(undefined);
195
+ class Launch extends FieldVersion {
196
+ constructor(transaction, operation, changeset, former, clone) {
197
+ super(undefined, 0);
203
198
  this.margin = Launch.current ? Launch.current.margin + 1 : 1;
204
- this.transaction = Transaction.current;
205
- this.reaction = reaction;
199
+ this.transaction = transaction;
200
+ this.operation = operation;
206
201
  this.changeset = changeset;
207
202
  this.observables = new Map();
208
203
  if (former instanceof Launch) {
209
204
  this.options = former.options;
210
- this.args = former.args;
211
205
  this.cause = former.obsoleteDueTo;
206
+ this.args = former.args;
207
+ if (clone) {
208
+ this.lastEditorChangesetId = former.lastEditorChangesetId;
209
+ this.result = former.result;
210
+ this.error = former.error;
211
+ this.started = former.started;
212
+ this.obsoleteSince = former.obsoleteSince;
213
+ this.obsoleteDueTo = former.obsoleteDueTo;
214
+ this.successor = former.successor;
215
+ }
216
+ else {
217
+ this.lastEditorChangesetId = changeset.id;
218
+ this.result = undefined;
219
+ this.error = undefined;
220
+ this.started = 0;
221
+ this.obsoleteSince = 0;
222
+ this.obsoleteDueTo = undefined;
223
+ this.successor = undefined;
224
+ }
212
225
  }
213
226
  else {
227
+ this.lastEditorChangesetId = changeset.id;
214
228
  this.options = former;
215
- this.args = BOOT_ARGS;
216
229
  this.cause = undefined;
230
+ this.args = BOOT_ARGS;
231
+ this.result = undefined;
232
+ this.error = undefined;
233
+ this.started = 0;
234
+ this.obsoleteSince = 0;
235
+ this.obsoleteDueTo = undefined;
236
+ this.successor = undefined;
217
237
  }
218
- this.started = 0;
219
- this.obsoleteSince = 0;
220
- this.obsoleteDueTo = undefined;
221
- this.successor = undefined;
222
- }
223
- get isOperation() { return true; }
224
- get originSnapshotId() { return this.changeset.id; }
225
- hint() { return `${Dump.snapshot2(this.reaction.objectHandle, this.changeset, this.reaction.memberName)}`; }
238
+ }
239
+ get isLaunch() { return true; }
240
+ hint() { return `${Dump.snapshot2(this.operation.ownerHandle, this.changeset, this.operation.fieldKey, this)}`; }
226
241
  get order() { return this.options.order; }
227
242
  get ["#this#"]() {
228
243
  return `Operation: ${this.why()}`;
229
244
  }
245
+ clone(t, cs) {
246
+ return new Launch(t, this.operation, cs, this, true);
247
+ }
230
248
  why() {
231
249
  let cause;
232
250
  if (this.cause)
233
251
  cause = ` ◀◀ ${this.cause}`;
234
- else if (this.reaction.options.kind === Kind.transactional)
252
+ else if (this.operation.options.kind === Kind.transactional)
235
253
  cause = " ◀◀ operation";
236
254
  else
237
255
  cause = ` ◀◀ T${this.changeset.id}[${this.changeset.hint}]`;
@@ -248,7 +266,7 @@ class Launch extends ValueSnapshot {
248
266
  if (Log.isOn && Log.opt.step && this.result)
249
267
  Log.writeAs({ margin2: this.margin }, "║", "‾\\", `${this.hint()} - step in `, 0, " │");
250
268
  const started = Date.now();
251
- const result = ReactionImpl.proceedWithinGivenLaunch(this, func, ...args);
269
+ const result = OperationImpl.proceedWithinGivenLaunch(this, func, ...args);
252
270
  const ms = Date.now() - started;
253
271
  if (Log.isOn && Log.opt.step && this.result)
254
272
  Log.writeAs({ margin2: this.margin }, "║", "_/", `${this.hint()} - step out `, 0, this.started > 0 ? " │" : "");
@@ -263,37 +281,37 @@ class Launch extends ValueSnapshot {
263
281
  this.args = args;
264
282
  this.obsoleteSince = MAX_REVISION;
265
283
  if (!this.error)
266
- ReactionImpl.proceedWithinGivenLaunch(this, Launch.proceed, this, proxy);
284
+ OperationImpl.proceedWithinGivenLaunch(this, Launch.proceed, this, proxy);
267
285
  else
268
286
  this.result = Promise.reject(this.error);
269
287
  }
270
- markObsoleteDueTo(observable, m, changeset, h, outer, since, obsolete) {
288
+ markObsoleteDueTo(observable, fk, changeset, h, outer, since, obsolete) {
271
289
  var _a, _b, _c;
272
290
  if (this.observables !== undefined) {
273
- const skip = !observable.isOperation &&
274
- changeset === this.changeset;
291
+ const skip = !observable.isLaunch &&
292
+ changeset.id === this.lastEditorChangesetId;
275
293
  if (!skip) {
276
- const why = `${Dump.snapshot2(h, changeset, m, observable)} ◀◀ ${outer}`;
294
+ const why = `${Dump.snapshot2(h, changeset, fk, observable)} ◀◀ ${outer}`;
277
295
  const isReactive = this.options.kind === Kind.reactive;
278
296
  this.obsoleteDueTo = why;
279
297
  this.obsoleteSince = since;
280
298
  if (Log.isOn && (Log.opt.obsolete || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.obsolete)))
281
- Log.write(Log.opt.transaction && !Changeset.current().sealed ? "║" : " ", isReactive ? "█" : "▒", isReactive && changeset === EMPTY_SNAPSHOT.changeset
299
+ Log.write(Log.opt.transaction && !Changeset.current().sealed ? "║" : " ", isReactive ? "█" : "▒", isReactive && changeset === EMPTY_OBJECT_VERSION.changeset
282
300
  ? `${this.hint()} is reactive and will run automatically (order ${this.options.order})`
283
- : `${this.hint()} is obsolete due to ${Dump.snapshot2(h, changeset, m)} since s${since}${isReactive ? ` and will run automatically (order ${this.options.order})` : ""}`);
301
+ : `${this.hint()} is obsolete due to ${Dump.snapshot2(h, changeset, fk)} since s${since}${isReactive ? ` and will run automatically (order ${this.options.order})` : ""}`);
284
302
  this.unsubscribeFromAllObservables();
285
303
  if (isReactive)
286
304
  obsolete.push(this);
287
305
  else
288
- (_b = this.observers) === null || _b === void 0 ? void 0 : _b.forEach(s => s.markObsoleteDueTo(this, this.reaction.memberName, this.changeset, this.reaction.objectHandle, why, since, obsolete));
306
+ (_b = this.observers) === null || _b === void 0 ? void 0 : _b.forEach(s => s.markObsoleteDueTo(this, this.operation.fieldKey, this.changeset, this.operation.ownerHandle, why, since, obsolete));
289
307
  const tran = this.transaction;
290
308
  if (tran.changeset === changeset) {
291
309
  }
292
310
  else if (!tran.isFinished && this !== observable)
293
- tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Dump.snapshot2(h, changeset, m)} changed by T${changeset.id}[${changeset.hint}]`), null);
311
+ tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Dump.snapshot2(h, changeset, fk)} changed by T${changeset.id}[${changeset.hint}]`), null);
294
312
  }
295
313
  else if (Log.isOn && (Log.opt.obsolete || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.obsolete)))
296
- Log.write(" ", "x", `${this.hint()} is not obsolete due to its own change to ${Dump.snapshot2(h, changeset, m)}`);
314
+ Log.write(" ", "x", `${this.hint()} is not obsolete due to its own change to ${Dump.snapshot2(h, changeset, fk, observable)}`);
297
315
  }
298
316
  }
299
317
  relaunchIfNotUpToDate(now, nothrow) {
@@ -303,7 +321,7 @@ class Launch extends ValueSnapshot {
303
321
  if (now || hold < 0) {
304
322
  if (this.isNotUpToDate()) {
305
323
  try {
306
- const launch = this.reaction.reuseOrRelaunch(false, undefined);
324
+ const launch = this.operation.reuseOrRelaunch(false, undefined);
307
325
  if (launch.result instanceof Promise)
308
326
  launch.result.catch(error => {
309
327
  if (launch.options.kind === Kind.reactive)
@@ -367,6 +385,8 @@ class Launch extends ValueSnapshot {
367
385
  static proceed(launch, proxy) {
368
386
  launch.enter();
369
387
  try {
388
+ if (launch.options.getter === undefined)
389
+ console.log("(!)");
370
390
  launch.result = launch.options.getter.call(proxy, ...launch.args);
371
391
  }
372
392
  finally {
@@ -377,7 +397,7 @@ class Launch extends ValueSnapshot {
377
397
  if (this.options.indicator)
378
398
  this.indicatorEnter(this.options.indicator);
379
399
  if (Log.isOn && Log.opt.operation)
380
- Log.write("║", "‾\\", `${this.hint()} - enter`, undefined, ` [ ${Dump.obj(this.reaction.objectHandle, this.reaction.memberName)} ]`);
400
+ Log.write("║", "‾\\", `${this.hint()} - enter`, undefined, ` [ ${Dump.obj(this.operation.ownerHandle, this.operation.fieldKey)} ]`);
381
401
  this.started = Date.now();
382
402
  }
383
403
  leaveOrAsync() {
@@ -417,53 +437,53 @@ class Launch extends ValueSnapshot {
417
437
  indicatorEnter(mon) {
418
438
  const options = {
419
439
  hint: "Indicator.enter",
420
- separation: "isolated",
440
+ isolation: Isolation.disjoinFromOuterAndInnerTransactions,
421
441
  logging: Log.isOn && Log.opt.indicator ? undefined : Log.global
422
442
  };
423
- ReactionImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.enter, mon, this.transaction);
443
+ OperationImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.enter, mon, this.transaction);
424
444
  }
425
445
  indicatorLeave(mon) {
426
446
  Transaction.outside(() => {
427
447
  const leave = () => {
428
448
  const options = {
429
449
  hint: "Indicator.leave",
430
- separation: "isolated",
450
+ isolation: Isolation.disjoinFromOuterAndInnerTransactions,
431
451
  logging: Log.isOn && Log.opt.indicator ? undefined : Log.DefaultLevel
432
452
  };
433
- ReactionImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.leave, mon, this.transaction);
453
+ OperationImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.leave, mon, this.transaction);
434
454
  };
435
455
  this.transaction.whenFinished().then(leave, leave);
436
456
  });
437
457
  }
438
458
  addToDeferredReactiveFunctions() {
439
- Launch.deferredReactiveFunctions.push(this);
440
- if (Launch.deferredReactiveFunctions.length === 1)
459
+ Launch.deferredReactiveOperations.push(this);
460
+ if (Launch.deferredReactiveOperations.length === 1)
441
461
  setTimeout(Launch.processDeferredReactiveFunctions, 0);
442
462
  }
443
463
  static processDeferredReactiveFunctions() {
444
- const deferred = Launch.deferredReactiveFunctions;
445
- Launch.deferredReactiveFunctions = [];
464
+ const deferred = Launch.deferredReactiveOperations;
465
+ Launch.deferredReactiveOperations = [];
446
466
  for (const x of deferred)
447
467
  x.relaunchIfNotUpToDate(true, true);
448
468
  }
449
- static markUsed(observable, os, m, h, kind, weak) {
469
+ static markUsed(observable, ov, fk, h, kind, weak) {
450
470
  if (kind !== Kind.transactional) {
451
471
  const launch = Launch.current;
452
472
  if (launch && launch.options.kind !== Kind.transactional &&
453
- launch.transaction === Transaction.current && m !== Meta.Handle) {
473
+ launch.transaction === Transaction.current && fk !== Meta.Handle) {
454
474
  const ctx = Changeset.current();
455
- if (ctx !== os.changeset)
456
- ctx.bumpBy(os.changeset.timestamp);
475
+ if (ctx !== ov.changeset)
476
+ ctx.bumpBy(ov.changeset.timestamp);
457
477
  const t = weak ? -1 : ctx.timestamp;
458
- if (!launch.subscribeTo(observable, os, m, h, t))
459
- launch.markObsoleteDueTo(observable, m, h.head.changeset, h, BOOT_CAUSE, ctx.timestamp, ctx.obsolete);
478
+ if (!launch.subscribeTo(observable, ov, fk, h, t))
479
+ launch.markObsoleteDueTo(observable, fk, h.applied.changeset, h, BOOT_CAUSE, ctx.timestamp, ctx.obsolete);
460
480
  }
461
481
  }
462
482
  }
463
- static markEdited(oldValue, newValue, edited, os, m, h) {
464
- edited ? os.changes.add(m) : os.changes.delete(m);
483
+ static markEdited(oldValue, newValue, edited, ov, fk, h) {
484
+ edited ? ov.changes.add(fk) : ov.changes.delete(fk);
465
485
  if (Log.isOn && Log.opt.write)
466
- edited ? Log.write("║", " =", `${Dump.snapshot2(h, os.changeset, m)} is changed: ${valueHint(oldValue)} ▸▸ ${valueHint(newValue)}`) : Log.write("║", " =", `${Dump.snapshot2(h, os.changeset, m)} is changed: ${valueHint(oldValue)} ▸▸ ${valueHint(newValue)}`, undefined, " (same as previous)");
486
+ edited ? Log.write("║", " =", `${Dump.snapshot2(h, ov.changeset, fk)} is changed: ${valueHint(oldValue)} ▸▸ ${valueHint(newValue)}`) : Log.write("║", " =", `${Dump.snapshot2(h, ov.changeset, fk)} is changed: ${valueHint(oldValue)} ▸▸ ${valueHint(newValue)}`, undefined, " (same as previous)");
467
487
  }
468
488
  static isConflicting(oldValue, newValue) {
469
489
  let result = oldValue !== newValue;
@@ -475,30 +495,30 @@ class Launch extends ValueSnapshot {
475
495
  var _a;
476
496
  const since = changeset.timestamp;
477
497
  const obsolete = changeset.obsolete;
478
- changeset.items.forEach((os, h) => {
479
- Launch.propagateMemberChangeThroughSubscriptions(false, since, os, Meta.Revision, h, obsolete);
480
- if (!os.disposed)
481
- os.changes.forEach((o, m) => Launch.propagateMemberChangeThroughSubscriptions(false, since, os, m, h, obsolete));
498
+ changeset.items.forEach((ov, h) => {
499
+ Launch.propagateFieldChangeThroughSubscriptions(false, since, ov, Meta.Revision, h, obsolete);
500
+ if (!ov.disposed)
501
+ ov.changes.forEach((o, fk) => Launch.propagateFieldChangeThroughSubscriptions(false, since, ov, fk, h, obsolete));
482
502
  else
483
- for (const m in os.former.snapshot.data)
484
- Launch.propagateMemberChangeThroughSubscriptions(true, since, os, m, h, obsolete);
503
+ for (const fk in ov.former.objectVersion.data)
504
+ Launch.propagateFieldChangeThroughSubscriptions(true, since, ov, fk, h, obsolete);
485
505
  });
486
506
  obsolete.sort(compareObserversByOrder);
487
507
  (_a = changeset.options.journal) === null || _a === void 0 ? void 0 : _a.edited(JournalImpl.buildPatch(changeset.hint, changeset.items));
488
508
  }
489
509
  static revokeAllSubscriptions(changeset) {
490
- changeset.items.forEach((os, h) => {
491
- Launch.propagateMemberChangeThroughSubscriptions(true, changeset.timestamp, os, Meta.Revision, h, undefined);
492
- os.changes.forEach((o, m) => Launch.propagateMemberChangeThroughSubscriptions(true, changeset.timestamp, os, m, h, undefined));
510
+ changeset.items.forEach((ov, h) => {
511
+ Launch.propagateFieldChangeThroughSubscriptions(true, changeset.timestamp, ov, Meta.Revision, h, undefined);
512
+ ov.changes.forEach((o, fk) => Launch.propagateFieldChangeThroughSubscriptions(true, changeset.timestamp, ov, fk, h, undefined));
493
513
  });
494
514
  }
495
- static propagateMemberChangeThroughSubscriptions(unsubscribe, timestamp, os, m, h, obsolete) {
515
+ static propagateFieldChangeThroughSubscriptions(unsubscribe, timestamp, ov, fk, h, obsolete) {
496
516
  var _a;
497
- const curr = os.data[m];
517
+ const curr = ov.data[fk];
498
518
  if (obsolete !== undefined) {
499
- const former = os.former.snapshot.data[m];
500
- if (former !== undefined && former instanceof ValueSnapshot) {
501
- const why = `T${os.changeset.id}[${os.changeset.hint}]`;
519
+ const former = ov.former.objectVersion.data[fk];
520
+ if (former !== undefined && former instanceof FieldVersion) {
521
+ const why = `T${ov.changeset.id}[${ov.changeset.hint}]`;
502
522
  if (former instanceof Launch) {
503
523
  if ((former.obsoleteSince === MAX_REVISION || former.obsoleteSince <= 0)) {
504
524
  former.obsoleteDueTo = why;
@@ -508,16 +528,16 @@ class Launch extends ValueSnapshot {
508
528
  const formerSuccessor = former.successor;
509
529
  if (formerSuccessor !== curr) {
510
530
  if (formerSuccessor && !formerSuccessor.transaction.isFinished)
511
- formerSuccessor.transaction.cancel(new Error(`T${formerSuccessor.transaction.id}[${formerSuccessor.transaction.hint}] is canceled by T${os.changeset.id}[${os.changeset.hint}] and will not run anymore`), null);
531
+ formerSuccessor.transaction.cancel(new Error(`T${formerSuccessor.transaction.id}[${formerSuccessor.transaction.hint}] is canceled by T${ov.changeset.id}[${ov.changeset.hint}] and will not run anymore`), null);
512
532
  }
513
533
  else
514
534
  former.successor = undefined;
515
535
  }
516
- (_a = former.observers) === null || _a === void 0 ? void 0 : _a.forEach(s => s.markObsoleteDueTo(former, m, os.changeset, h, why, timestamp, obsolete));
536
+ (_a = former.observers) === null || _a === void 0 ? void 0 : _a.forEach(s => s.markObsoleteDueTo(former, fk, ov.changeset, h, why, timestamp, obsolete));
517
537
  }
518
538
  }
519
539
  if (curr instanceof Launch) {
520
- if (curr.changeset === os.changeset && curr.observables !== undefined) {
540
+ if (curr.changeset === ov.changeset && curr.observables !== undefined) {
521
541
  if (Mvcc.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
522
542
  curr.observables.forEach((info, v) => {
523
543
  if (info.usageCount > Mvcc.repetitiveUsageWarningThreshold)
@@ -528,26 +548,34 @@ class Launch extends ValueSnapshot {
528
548
  curr.unsubscribeFromAllObservables();
529
549
  }
530
550
  }
531
- else if (curr instanceof ValueSnapshot && curr.observers) {
551
+ else if (curr instanceof FieldVersion && curr.observers) {
532
552
  }
533
553
  }
534
554
  static enqueueReactiveFunctionsToRun(reactive) {
535
- const queue = Launch.queuedReactiveFunctions;
555
+ const queue = Launch.queuedReactiveOperations;
536
556
  const isReactiveLoopRequired = queue.length === 0;
537
557
  for (const r of reactive)
538
558
  queue.push(r);
539
559
  if (isReactiveLoopRequired)
540
- ReactionImpl.proceedWithinGivenLaunch(undefined, Launch.processQueuedReactiveFunctions);
560
+ OperationImpl.proceedWithinGivenLaunch(undefined, Launch.processQueuedReactiveOperations);
561
+ }
562
+ static migrateFieldVersion(fv, target) {
563
+ let result;
564
+ if (fv instanceof Launch)
565
+ result = new Launch(target, fv.operation, target.changeset, fv, true);
566
+ else
567
+ result = new FieldVersion(fv.content, fv.lastEditorChangesetId);
568
+ return result;
541
569
  }
542
- static processQueuedReactiveFunctions() {
543
- const queue = Launch.queuedReactiveFunctions;
570
+ static processQueuedReactiveOperations() {
571
+ const queue = Launch.queuedReactiveOperations;
544
572
  let i = 0;
545
573
  while (i < queue.length) {
546
574
  const reactive = queue[i];
547
575
  reactive.relaunchIfNotUpToDate(false, true);
548
576
  i++;
549
577
  }
550
- Launch.queuedReactiveFunctions = [];
578
+ Launch.queuedReactiveOperations = [];
551
579
  }
552
580
  unsubscribeFromAllObservables() {
553
581
  var _a;
@@ -559,9 +587,10 @@ class Launch extends ValueSnapshot {
559
587
  });
560
588
  this.observables = undefined;
561
589
  }
562
- subscribeTo(observable, os, m, h, timestamp) {
590
+ subscribeTo(observable, ov, fk, h, timestamp) {
563
591
  var _a, _b, _c;
564
- const ok = Launch.canSubscribeTo(observable, os, m, h, timestamp);
592
+ const parent = this.transaction.changeset.parent;
593
+ const ok = Launch.canSubscribeTo(observable, ov, parent, fk, h, timestamp);
565
594
  if (ok) {
566
595
  let times = 0;
567
596
  if (Mvcc.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
@@ -571,49 +600,50 @@ class Launch extends ValueSnapshot {
571
600
  if (this.observables !== undefined) {
572
601
  if (!observable.observers)
573
602
  observable.observers = new Set();
574
- const subscription = { memberHint: Dump.snapshot2(h, os.changeset, m), usageCount: times };
603
+ const subscription = { memberHint: Dump.snapshot2(h, ov.changeset, fk), usageCount: times };
575
604
  observable.observers.add(this);
576
605
  this.observables.set(observable, subscription);
577
606
  if (Log.isOn && (Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
578
- Log.write("║", " ∞", `${this.hint()} is subscribed to ${Dump.snapshot2(h, os.changeset, m)}${subscription.usageCount > 1 ? ` (${subscription.usageCount} times)` : ""}`);
607
+ Log.write("║", " ∞", `${this.hint()} is subscribed to ${Dump.snapshot2(h, ov.changeset, fk, observable)}${subscription.usageCount > 1 ? ` (${subscription.usageCount} times)` : ""}`);
579
608
  }
580
609
  else if (Log.isOn && (Log.opt.read || ((_b = this.options.logging) === null || _b === void 0 ? void 0 : _b.read)))
581
- Log.write("║", " x", `${this.hint()} is obsolete and is NOT subscribed to ${Dump.snapshot2(h, os.changeset, m)}`);
610
+ Log.write("║", " x", `${this.hint()} is obsolete and is NOT subscribed to ${Dump.snapshot2(h, ov.changeset, fk, observable)}`);
582
611
  }
583
612
  else {
584
613
  if (Log.isOn && (Log.opt.read || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.read)))
585
- Log.write("║", " x", `${this.hint()} is NOT subscribed to already obsolete ${Dump.snapshot2(h, os.changeset, m)}`);
614
+ Log.write("║", " x", `${this.hint()} is NOT subscribed to already obsolete ${Dump.snapshot2(h, ov.changeset, fk, observable)}`);
586
615
  }
587
616
  return ok;
588
617
  }
589
- static canSubscribeTo(observable, os, m, h, timestamp) {
590
- const observableHead = h.head.data[m];
591
- let result = observable === observableHead || (!os.changeset.sealed && os.former.snapshot.data[m] === observableHead);
618
+ static canSubscribeTo(observable, ov, parent, fk, h, timestamp) {
619
+ const parentSnapshot = parent ? parent.lookupObjectVersion(h, fk, false) : h.applied;
620
+ const observableParent = parentSnapshot.data[fk];
621
+ let result = observable === observableParent || (!ov.changeset.sealed && ov.former.objectVersion.data[fk] === observableParent);
592
622
  if (result && timestamp !== -1)
593
623
  result = !(observable instanceof Launch && timestamp >= observable.obsoleteSince);
594
624
  return result;
595
625
  }
596
- static createOperation(h, m, options) {
597
- const rx = new ReactionImpl(h, m);
626
+ static createOperation(h, fk, options) {
627
+ const rx = new OperationImpl(h, fk);
598
628
  const operation = (...args) => {
599
629
  return rx.reuseOrRelaunch(false, args).result;
600
630
  };
601
631
  Meta.set(operation, Meta.Controller, rx);
602
632
  return operation;
603
633
  }
604
- static rememberOperationOptions(proto, m, getter, setter, enumerable, configurable, options, implicit) {
634
+ static rememberOperationOptions(proto, fk, getter, setter, enumerable, configurable, options, implicit) {
605
635
  const initial = Meta.acquire(proto, Meta.Initial);
606
- let launch = initial[m];
607
- const rx = launch ? launch.reaction : new ReactionImpl(EMPTY_HANDLE, m);
636
+ let launch = initial[fk];
637
+ const rx = launch ? launch.operation : new OperationImpl(EMPTY_HANDLE, fk);
608
638
  const opts = launch ? launch.options : OptionsImpl.INITIAL;
609
- initial[m] = launch = new Launch(rx, EMPTY_SNAPSHOT.changeset, new OptionsImpl(getter, setter, opts, options, implicit));
639
+ initial[fk] = launch = new Launch(Transaction.current, rx, EMPTY_OBJECT_VERSION.changeset, new OptionsImpl(getter, setter, opts, options, implicit), false);
610
640
  if (launch.options.kind === Kind.reactive && launch.options.throttling < Number.MAX_SAFE_INTEGER) {
611
641
  const reactive = Meta.acquire(proto, Meta.Reactive);
612
- reactive[m] = launch;
642
+ reactive[fk] = launch;
613
643
  }
614
644
  else if (launch.options.kind === Kind.reactive && launch.options.throttling >= Number.MAX_SAFE_INTEGER) {
615
645
  const reactive = Meta.getFrom(proto, Meta.Reactive);
616
- delete reactive[m];
646
+ delete reactive[fk];
617
647
  }
618
648
  return launch.options;
619
649
  }
@@ -627,25 +657,26 @@ class Launch extends ValueSnapshot {
627
657
  Changeset.propagateAllChangesThroughSubscriptions = Launch.propagateAllChangesThroughSubscriptions;
628
658
  Changeset.revokeAllSubscriptions = Launch.revokeAllSubscriptions;
629
659
  Changeset.enqueueReactiveFunctionsToRun = Launch.enqueueReactiveFunctionsToRun;
660
+ TransactionImpl.migrateFieldVersion = Launch.migrateFieldVersion;
630
661
  Mvcc.createOperation = Launch.createOperation;
631
662
  Mvcc.rememberOperationOptions = Launch.rememberOperationOptions;
632
663
  Promise.prototype.then = reactronicHookedThen;
633
664
  try {
634
665
  Object.defineProperty(globalThis, "rWhy", {
635
- get: ReactionImpl.why, configurable: false, enumerable: false,
666
+ get: OperationImpl.why, configurable: false, enumerable: false,
636
667
  });
637
668
  Object.defineProperty(globalThis, "rBriefWhy", {
638
- get: ReactionImpl.briefWhy, configurable: false, enumerable: false,
669
+ get: OperationImpl.briefWhy, configurable: false, enumerable: false,
639
670
  });
640
671
  }
641
672
  catch (e) {
642
673
  }
643
674
  try {
644
675
  Object.defineProperty(global, "rWhy", {
645
- get: ReactionImpl.why, configurable: false, enumerable: false,
676
+ get: OperationImpl.why, configurable: false, enumerable: false,
646
677
  });
647
678
  Object.defineProperty(global, "rBriefWhy", {
648
- get: ReactionImpl.briefWhy, configurable: false, enumerable: false,
679
+ get: OperationImpl.briefWhy, configurable: false, enumerable: false,
649
680
  });
650
681
  }
651
682
  catch (e) {
@@ -653,8 +684,8 @@ class Launch extends ValueSnapshot {
653
684
  }
654
685
  }
655
686
  Launch.current = undefined;
656
- Launch.queuedReactiveFunctions = [];
657
- Launch.deferredReactiveFunctions = [];
687
+ Launch.queuedReactiveOperations = [];
688
+ Launch.deferredReactiveOperations = [];
658
689
  function valueHint(value) {
659
690
  let result = "";
660
691
  if (Array.isArray(value))
@@ -664,7 +695,7 @@ function valueHint(value) {
664
695
  else if (value instanceof Map)
665
696
  result = `Map(${value.size})`;
666
697
  else if (value instanceof Launch)
667
- result = `#${value.reaction.objectHandle.id}t${value.changeset.id}s${value.changeset.timestamp}${value.originSnapshotId !== undefined && value.originSnapshotId !== 0 ? `t${value.originSnapshotId}` : ""}`;
698
+ result = `#${value.operation.ownerHandle.id}t${value.changeset.id}s${value.changeset.timestamp}${value.lastEditorChangesetId !== undefined && value.lastEditorChangesetId !== 0 ? `t${value.lastEditorChangesetId}` : ""}`;
668
699
  else if (value === Meta.Undefined)
669
700
  result = "undefined";
670
701
  else if (typeof (value) === "string")