reactronic 0.24.275 → 0.24.301

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,65 @@ 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) {
195
+ class Launch extends FieldVersion {
196
+ constructor(transaction, operation, changeset, former, clone) {
202
197
  super(undefined);
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.result = former.result;
209
+ this.error = former.error;
210
+ this.started = former.started;
211
+ this.obsoleteSince = former.obsoleteSince;
212
+ this.obsoleteDueTo = former.obsoleteDueTo;
213
+ this.successor = former.successor;
214
+ }
215
+ else {
216
+ this.result = undefined;
217
+ this.error = undefined;
218
+ this.started = 0;
219
+ this.obsoleteSince = 0;
220
+ this.obsoleteDueTo = undefined;
221
+ this.successor = undefined;
222
+ }
212
223
  }
213
224
  else {
214
225
  this.options = former;
215
- this.args = BOOT_ARGS;
216
226
  this.cause = undefined;
227
+ this.args = BOOT_ARGS;
228
+ this.result = undefined;
229
+ this.error = undefined;
230
+ this.started = 0;
231
+ this.obsoleteSince = 0;
232
+ this.obsoleteDueTo = undefined;
233
+ this.successor = undefined;
217
234
  }
218
- this.started = 0;
219
- this.obsoleteSince = 0;
220
- this.obsoleteDueTo = undefined;
221
- this.successor = undefined;
222
235
  }
223
- get isOperation() { return true; }
236
+ get isLaunch() { return true; }
224
237
  get originSnapshotId() { return this.changeset.id; }
225
- hint() { return `${Dump.snapshot2(this.reaction.objectHandle, this.changeset, this.reaction.memberName)}`; }
238
+ hint() { return `${Dump.snapshot2(this.operation.ownerHandle, this.changeset, this.operation.fieldKey)}`; }
226
239
  get order() { return this.options.order; }
227
240
  get ["#this#"]() {
228
241
  return `Operation: ${this.why()}`;
229
242
  }
243
+ clone(t, cs) {
244
+ return new Launch(t, this.operation, cs, this, true);
245
+ }
230
246
  why() {
231
247
  let cause;
232
248
  if (this.cause)
233
249
  cause = ` ◀◀ ${this.cause}`;
234
- else if (this.reaction.options.kind === Kind.transactional)
250
+ else if (this.operation.options.kind === Kind.transactional)
235
251
  cause = " ◀◀ operation";
236
252
  else
237
253
  cause = ` ◀◀ T${this.changeset.id}[${this.changeset.hint}]`;
@@ -248,7 +264,7 @@ class Launch extends ValueSnapshot {
248
264
  if (Log.isOn && Log.opt.step && this.result)
249
265
  Log.writeAs({ margin2: this.margin }, "║", "‾\\", `${this.hint()} - step in `, 0, " │");
250
266
  const started = Date.now();
251
- const result = ReactionImpl.proceedWithinGivenLaunch(this, func, ...args);
267
+ const result = OperationImpl.proceedWithinGivenLaunch(this, func, ...args);
252
268
  const ms = Date.now() - started;
253
269
  if (Log.isOn && Log.opt.step && this.result)
254
270
  Log.writeAs({ margin2: this.margin }, "║", "_/", `${this.hint()} - step out `, 0, this.started > 0 ? " │" : "");
@@ -263,37 +279,37 @@ class Launch extends ValueSnapshot {
263
279
  this.args = args;
264
280
  this.obsoleteSince = MAX_REVISION;
265
281
  if (!this.error)
266
- ReactionImpl.proceedWithinGivenLaunch(this, Launch.proceed, this, proxy);
282
+ OperationImpl.proceedWithinGivenLaunch(this, Launch.proceed, this, proxy);
267
283
  else
268
284
  this.result = Promise.reject(this.error);
269
285
  }
270
- markObsoleteDueTo(observable, m, changeset, h, outer, since, obsolete) {
286
+ markObsoleteDueTo(observable, fk, changeset, h, outer, since, obsolete) {
271
287
  var _a, _b, _c;
272
288
  if (this.observables !== undefined) {
273
- const skip = !observable.isOperation &&
289
+ const skip = !observable.isLaunch &&
274
290
  changeset === this.changeset;
275
291
  if (!skip) {
276
- const why = `${Dump.snapshot2(h, changeset, m, observable)} ◀◀ ${outer}`;
292
+ const why = `${Dump.snapshot2(h, changeset, fk, observable)} ◀◀ ${outer}`;
277
293
  const isReactive = this.options.kind === Kind.reactive;
278
294
  this.obsoleteDueTo = why;
279
295
  this.obsoleteSince = since;
280
296
  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
297
+ Log.write(Log.opt.transaction && !Changeset.current().sealed ? "║" : " ", isReactive ? "█" : "▒", isReactive && changeset === EMPTY_OBJECT_VERSION.changeset
282
298
  ? `${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})` : ""}`);
299
+ : `${this.hint()} is obsolete due to ${Dump.snapshot2(h, changeset, fk)} since s${since}${isReactive ? ` and will run automatically (order ${this.options.order})` : ""}`);
284
300
  this.unsubscribeFromAllObservables();
285
301
  if (isReactive)
286
302
  obsolete.push(this);
287
303
  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));
304
+ (_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
305
  const tran = this.transaction;
290
306
  if (tran.changeset === changeset) {
291
307
  }
292
308
  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);
309
+ 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
310
  }
295
311
  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)}`);
312
+ Log.write(" ", "x", `${this.hint()} is not obsolete due to its own change to ${Dump.snapshot2(h, changeset, fk)}`);
297
313
  }
298
314
  }
299
315
  relaunchIfNotUpToDate(now, nothrow) {
@@ -303,7 +319,7 @@ class Launch extends ValueSnapshot {
303
319
  if (now || hold < 0) {
304
320
  if (this.isNotUpToDate()) {
305
321
  try {
306
- const launch = this.reaction.reuseOrRelaunch(false, undefined);
322
+ const launch = this.operation.reuseOrRelaunch(false, undefined);
307
323
  if (launch.result instanceof Promise)
308
324
  launch.result.catch(error => {
309
325
  if (launch.options.kind === Kind.reactive)
@@ -367,6 +383,8 @@ class Launch extends ValueSnapshot {
367
383
  static proceed(launch, proxy) {
368
384
  launch.enter();
369
385
  try {
386
+ if (launch.options.getter === undefined)
387
+ console.log("(!)");
370
388
  launch.result = launch.options.getter.call(proxy, ...launch.args);
371
389
  }
372
390
  finally {
@@ -377,7 +395,7 @@ class Launch extends ValueSnapshot {
377
395
  if (this.options.indicator)
378
396
  this.indicatorEnter(this.options.indicator);
379
397
  if (Log.isOn && Log.opt.operation)
380
- Log.write("║", "‾\\", `${this.hint()} - enter`, undefined, ` [ ${Dump.obj(this.reaction.objectHandle, this.reaction.memberName)} ]`);
398
+ Log.write("║", "‾\\", `${this.hint()} - enter`, undefined, ` [ ${Dump.obj(this.operation.ownerHandle, this.operation.fieldKey)} ]`);
381
399
  this.started = Date.now();
382
400
  }
383
401
  leaveOrAsync() {
@@ -417,53 +435,53 @@ class Launch extends ValueSnapshot {
417
435
  indicatorEnter(mon) {
418
436
  const options = {
419
437
  hint: "Indicator.enter",
420
- separation: "isolated",
438
+ isolation: Isolation.disjoinFromOuterAndInnerTransactions,
421
439
  logging: Log.isOn && Log.opt.indicator ? undefined : Log.global
422
440
  };
423
- ReactionImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.enter, mon, this.transaction);
441
+ OperationImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.enter, mon, this.transaction);
424
442
  }
425
443
  indicatorLeave(mon) {
426
444
  Transaction.outside(() => {
427
445
  const leave = () => {
428
446
  const options = {
429
447
  hint: "Indicator.leave",
430
- separation: "isolated",
448
+ isolation: Isolation.disjoinFromOuterAndInnerTransactions,
431
449
  logging: Log.isOn && Log.opt.indicator ? undefined : Log.DefaultLevel
432
450
  };
433
- ReactionImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.leave, mon, this.transaction);
451
+ OperationImpl.proceedWithinGivenLaunch(undefined, Transaction.run, options, IndicatorImpl.leave, mon, this.transaction);
434
452
  };
435
453
  this.transaction.whenFinished().then(leave, leave);
436
454
  });
437
455
  }
438
456
  addToDeferredReactiveFunctions() {
439
- Launch.deferredReactiveFunctions.push(this);
440
- if (Launch.deferredReactiveFunctions.length === 1)
457
+ Launch.deferredReactiveOperations.push(this);
458
+ if (Launch.deferredReactiveOperations.length === 1)
441
459
  setTimeout(Launch.processDeferredReactiveFunctions, 0);
442
460
  }
443
461
  static processDeferredReactiveFunctions() {
444
- const deferred = Launch.deferredReactiveFunctions;
445
- Launch.deferredReactiveFunctions = [];
462
+ const deferred = Launch.deferredReactiveOperations;
463
+ Launch.deferredReactiveOperations = [];
446
464
  for (const x of deferred)
447
465
  x.relaunchIfNotUpToDate(true, true);
448
466
  }
449
- static markUsed(observable, os, m, h, kind, weak) {
467
+ static markUsed(observable, ov, fk, h, kind, weak) {
450
468
  if (kind !== Kind.transactional) {
451
469
  const launch = Launch.current;
452
470
  if (launch && launch.options.kind !== Kind.transactional &&
453
- launch.transaction === Transaction.current && m !== Meta.Handle) {
471
+ launch.transaction === Transaction.current && fk !== Meta.Handle) {
454
472
  const ctx = Changeset.current();
455
- if (ctx !== os.changeset)
456
- ctx.bumpBy(os.changeset.timestamp);
473
+ if (ctx !== ov.changeset)
474
+ ctx.bumpBy(ov.changeset.timestamp);
457
475
  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);
476
+ if (!launch.subscribeTo(observable, ov, fk, h, t))
477
+ launch.markObsoleteDueTo(observable, fk, h.applied.changeset, h, BOOT_CAUSE, ctx.timestamp, ctx.obsolete);
460
478
  }
461
479
  }
462
480
  }
463
- static markEdited(oldValue, newValue, edited, os, m, h) {
464
- edited ? os.changes.add(m) : os.changes.delete(m);
481
+ static markEdited(oldValue, newValue, edited, ov, fk, h) {
482
+ edited ? ov.changes.add(fk) : ov.changes.delete(fk);
465
483
  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)");
484
+ 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
485
  }
468
486
  static isConflicting(oldValue, newValue) {
469
487
  let result = oldValue !== newValue;
@@ -475,30 +493,30 @@ class Launch extends ValueSnapshot {
475
493
  var _a;
476
494
  const since = changeset.timestamp;
477
495
  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));
496
+ changeset.items.forEach((ov, h) => {
497
+ Launch.propagateFieldChangeThroughSubscriptions(false, since, ov, Meta.Revision, h, obsolete);
498
+ if (!ov.disposed)
499
+ ov.changes.forEach((o, fk) => Launch.propagateFieldChangeThroughSubscriptions(false, since, ov, fk, h, obsolete));
482
500
  else
483
- for (const m in os.former.snapshot.data)
484
- Launch.propagateMemberChangeThroughSubscriptions(true, since, os, m, h, obsolete);
501
+ for (const fk in ov.former.objectVersion.data)
502
+ Launch.propagateFieldChangeThroughSubscriptions(true, since, ov, fk, h, obsolete);
485
503
  });
486
504
  obsolete.sort(compareObserversByOrder);
487
505
  (_a = changeset.options.journal) === null || _a === void 0 ? void 0 : _a.edited(JournalImpl.buildPatch(changeset.hint, changeset.items));
488
506
  }
489
507
  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));
508
+ changeset.items.forEach((ov, h) => {
509
+ Launch.propagateFieldChangeThroughSubscriptions(true, changeset.timestamp, ov, Meta.Revision, h, undefined);
510
+ ov.changes.forEach((o, fk) => Launch.propagateFieldChangeThroughSubscriptions(true, changeset.timestamp, ov, fk, h, undefined));
493
511
  });
494
512
  }
495
- static propagateMemberChangeThroughSubscriptions(unsubscribe, timestamp, os, m, h, obsolete) {
513
+ static propagateFieldChangeThroughSubscriptions(unsubscribe, timestamp, ov, fk, h, obsolete) {
496
514
  var _a;
497
- const curr = os.data[m];
515
+ const curr = ov.data[fk];
498
516
  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}]`;
517
+ const former = ov.former.objectVersion.data[fk];
518
+ if (former !== undefined && former instanceof FieldVersion) {
519
+ const why = `T${ov.changeset.id}[${ov.changeset.hint}]`;
502
520
  if (former instanceof Launch) {
503
521
  if ((former.obsoleteSince === MAX_REVISION || former.obsoleteSince <= 0)) {
504
522
  former.obsoleteDueTo = why;
@@ -508,16 +526,16 @@ class Launch extends ValueSnapshot {
508
526
  const formerSuccessor = former.successor;
509
527
  if (formerSuccessor !== curr) {
510
528
  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);
529
+ 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
530
  }
513
531
  else
514
532
  former.successor = undefined;
515
533
  }
516
- (_a = former.observers) === null || _a === void 0 ? void 0 : _a.forEach(s => s.markObsoleteDueTo(former, m, os.changeset, h, why, timestamp, obsolete));
534
+ (_a = former.observers) === null || _a === void 0 ? void 0 : _a.forEach(s => s.markObsoleteDueTo(former, fk, ov.changeset, h, why, timestamp, obsolete));
517
535
  }
518
536
  }
519
537
  if (curr instanceof Launch) {
520
- if (curr.changeset === os.changeset && curr.observables !== undefined) {
538
+ if (curr.changeset === ov.changeset && curr.observables !== undefined) {
521
539
  if (Mvcc.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
522
540
  curr.observables.forEach((info, v) => {
523
541
  if (info.usageCount > Mvcc.repetitiveUsageWarningThreshold)
@@ -528,26 +546,34 @@ class Launch extends ValueSnapshot {
528
546
  curr.unsubscribeFromAllObservables();
529
547
  }
530
548
  }
531
- else if (curr instanceof ValueSnapshot && curr.observers) {
549
+ else if (curr instanceof FieldVersion && curr.observers) {
532
550
  }
533
551
  }
534
552
  static enqueueReactiveFunctionsToRun(reactive) {
535
- const queue = Launch.queuedReactiveFunctions;
553
+ const queue = Launch.queuedReactiveOperations;
536
554
  const isReactiveLoopRequired = queue.length === 0;
537
555
  for (const r of reactive)
538
556
  queue.push(r);
539
557
  if (isReactiveLoopRequired)
540
- ReactionImpl.proceedWithinGivenLaunch(undefined, Launch.processQueuedReactiveFunctions);
558
+ OperationImpl.proceedWithinGivenLaunch(undefined, Launch.processQueuedReactiveOperations);
559
+ }
560
+ static createFieldVersion(fv, target) {
561
+ let result;
562
+ if (fv instanceof Launch)
563
+ result = new Launch(target, fv.operation, target.changeset, fv, true);
564
+ else
565
+ result = new FieldVersion(fv === null || fv === void 0 ? void 0 : fv.content);
566
+ return result;
541
567
  }
542
- static processQueuedReactiveFunctions() {
543
- const queue = Launch.queuedReactiveFunctions;
568
+ static processQueuedReactiveOperations() {
569
+ const queue = Launch.queuedReactiveOperations;
544
570
  let i = 0;
545
571
  while (i < queue.length) {
546
572
  const reactive = queue[i];
547
573
  reactive.relaunchIfNotUpToDate(false, true);
548
574
  i++;
549
575
  }
550
- Launch.queuedReactiveFunctions = [];
576
+ Launch.queuedReactiveOperations = [];
551
577
  }
552
578
  unsubscribeFromAllObservables() {
553
579
  var _a;
@@ -559,9 +585,10 @@ class Launch extends ValueSnapshot {
559
585
  });
560
586
  this.observables = undefined;
561
587
  }
562
- subscribeTo(observable, os, m, h, timestamp) {
588
+ subscribeTo(observable, ov, fk, h, timestamp) {
563
589
  var _a, _b, _c;
564
- const ok = Launch.canSubscribeTo(observable, os, m, h, timestamp);
590
+ const parent = this.transaction.changeset.parent;
591
+ const ok = Launch.canSubscribeTo(observable, ov, parent, fk, h, timestamp);
565
592
  if (ok) {
566
593
  let times = 0;
567
594
  if (Mvcc.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
@@ -571,49 +598,50 @@ class Launch extends ValueSnapshot {
571
598
  if (this.observables !== undefined) {
572
599
  if (!observable.observers)
573
600
  observable.observers = new Set();
574
- const subscription = { memberHint: Dump.snapshot2(h, os.changeset, m), usageCount: times };
601
+ const subscription = { memberHint: Dump.snapshot2(h, ov.changeset, fk), usageCount: times };
575
602
  observable.observers.add(this);
576
603
  this.observables.set(observable, subscription);
577
604
  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)` : ""}`);
605
+ Log.write("║", " ∞", `${this.hint()} is subscribed to ${Dump.snapshot2(h, ov.changeset, fk)}${subscription.usageCount > 1 ? ` (${subscription.usageCount} times)` : ""}`);
579
606
  }
580
607
  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)}`);
608
+ Log.write("║", " x", `${this.hint()} is obsolete and is NOT subscribed to ${Dump.snapshot2(h, ov.changeset, fk)}`);
582
609
  }
583
610
  else {
584
611
  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)}`);
612
+ Log.write("║", " x", `${this.hint()} is NOT subscribed to already obsolete ${Dump.snapshot2(h, ov.changeset, fk)}`);
586
613
  }
587
614
  return ok;
588
615
  }
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);
616
+ static canSubscribeTo(observable, ov, parent, fk, h, timestamp) {
617
+ const parentSnapshot = parent ? parent.lookupObjectVersion(h, fk, false) : h.applied;
618
+ const observableParent = parentSnapshot.data[fk];
619
+ let result = observable === observableParent || (!ov.changeset.sealed && ov.former.objectVersion.data[fk] === observableParent);
592
620
  if (result && timestamp !== -1)
593
621
  result = !(observable instanceof Launch && timestamp >= observable.obsoleteSince);
594
622
  return result;
595
623
  }
596
- static createOperation(h, m, options) {
597
- const rx = new ReactionImpl(h, m);
624
+ static createOperation(h, fk, options) {
625
+ const rx = new OperationImpl(h, fk);
598
626
  const operation = (...args) => {
599
627
  return rx.reuseOrRelaunch(false, args).result;
600
628
  };
601
629
  Meta.set(operation, Meta.Controller, rx);
602
630
  return operation;
603
631
  }
604
- static rememberOperationOptions(proto, m, getter, setter, enumerable, configurable, options, implicit) {
632
+ static rememberOperationOptions(proto, fk, getter, setter, enumerable, configurable, options, implicit) {
605
633
  const initial = Meta.acquire(proto, Meta.Initial);
606
- let launch = initial[m];
607
- const rx = launch ? launch.reaction : new ReactionImpl(EMPTY_HANDLE, m);
634
+ let launch = initial[fk];
635
+ const rx = launch ? launch.operation : new OperationImpl(EMPTY_HANDLE, fk);
608
636
  const opts = launch ? launch.options : OptionsImpl.INITIAL;
609
- initial[m] = launch = new Launch(rx, EMPTY_SNAPSHOT.changeset, new OptionsImpl(getter, setter, opts, options, implicit));
637
+ initial[fk] = launch = new Launch(Transaction.current, rx, EMPTY_OBJECT_VERSION.changeset, new OptionsImpl(getter, setter, opts, options, implicit), false);
610
638
  if (launch.options.kind === Kind.reactive && launch.options.throttling < Number.MAX_SAFE_INTEGER) {
611
639
  const reactive = Meta.acquire(proto, Meta.Reactive);
612
- reactive[m] = launch;
640
+ reactive[fk] = launch;
613
641
  }
614
642
  else if (launch.options.kind === Kind.reactive && launch.options.throttling >= Number.MAX_SAFE_INTEGER) {
615
643
  const reactive = Meta.getFrom(proto, Meta.Reactive);
616
- delete reactive[m];
644
+ delete reactive[fk];
617
645
  }
618
646
  return launch.options;
619
647
  }
@@ -627,25 +655,26 @@ class Launch extends ValueSnapshot {
627
655
  Changeset.propagateAllChangesThroughSubscriptions = Launch.propagateAllChangesThroughSubscriptions;
628
656
  Changeset.revokeAllSubscriptions = Launch.revokeAllSubscriptions;
629
657
  Changeset.enqueueReactiveFunctionsToRun = Launch.enqueueReactiveFunctionsToRun;
658
+ TransactionImpl.createFieldVersion = Launch.createFieldVersion;
630
659
  Mvcc.createOperation = Launch.createOperation;
631
660
  Mvcc.rememberOperationOptions = Launch.rememberOperationOptions;
632
661
  Promise.prototype.then = reactronicHookedThen;
633
662
  try {
634
663
  Object.defineProperty(globalThis, "rWhy", {
635
- get: ReactionImpl.why, configurable: false, enumerable: false,
664
+ get: OperationImpl.why, configurable: false, enumerable: false,
636
665
  });
637
666
  Object.defineProperty(globalThis, "rBriefWhy", {
638
- get: ReactionImpl.briefWhy, configurable: false, enumerable: false,
667
+ get: OperationImpl.briefWhy, configurable: false, enumerable: false,
639
668
  });
640
669
  }
641
670
  catch (e) {
642
671
  }
643
672
  try {
644
673
  Object.defineProperty(global, "rWhy", {
645
- get: ReactionImpl.why, configurable: false, enumerable: false,
674
+ get: OperationImpl.why, configurable: false, enumerable: false,
646
675
  });
647
676
  Object.defineProperty(global, "rBriefWhy", {
648
- get: ReactionImpl.briefWhy, configurable: false, enumerable: false,
677
+ get: OperationImpl.briefWhy, configurable: false, enumerable: false,
649
678
  });
650
679
  }
651
680
  catch (e) {
@@ -653,8 +682,8 @@ class Launch extends ValueSnapshot {
653
682
  }
654
683
  }
655
684
  Launch.current = undefined;
656
- Launch.queuedReactiveFunctions = [];
657
- Launch.deferredReactiveFunctions = [];
685
+ Launch.queuedReactiveOperations = [];
686
+ Launch.deferredReactiveOperations = [];
658
687
  function valueHint(value) {
659
688
  let result = "";
660
689
  if (Array.isArray(value))
@@ -664,7 +693,7 @@ function valueHint(value) {
664
693
  else if (value instanceof Map)
665
694
  result = `Map(${value.size})`;
666
695
  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}` : ""}`;
696
+ result = `#${value.operation.ownerHandle.id}t${value.changeset.id}s${value.changeset.timestamp}${value.originSnapshotId !== undefined && value.originSnapshotId !== 0 ? `t${value.originSnapshotId}` : ""}`;
668
697
  else if (value === Meta.Undefined)
669
698
  result = "undefined";
670
699
  else if (typeof (value) === "string")