reactronic 0.24.274 → 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,8 +1,9 @@
1
1
  import { LoggingOptions } from "../Logging.js";
2
2
  import { MergeListReader, MergedItem } from "../util/MergeList.js";
3
3
  import { MemberOptions } from "../Options.js";
4
- export type Delegate<T> = (el: T, basis: () => void) => void;
5
- export type SimpleDelegate<T = unknown, R = void> = (el: T) => R;
4
+ export type Script<T> = (el: T, basis: () => void) => void;
5
+ export type ScriptAsync<T> = (el: T, basis: () => Promise<void>) => Promise<void>;
6
+ export type Handler<T = unknown, R = void> = (el: T) => R;
6
7
  export declare enum Mode {
7
8
  default = 0,
8
9
  independentUpdate = 1,
@@ -35,7 +36,7 @@ export declare abstract class RxNode<E = unknown> {
35
36
  static readonly longFrameDuration = 300;
36
37
  static currentUpdatePriority: Priority;
37
38
  static frameDuration: number;
38
- static declare<E = void>(driver: RxNodeDriver<E>, declaration?: RxNodeDecl<E>, preset?: RxNodeDecl<E>): RxNode<E>;
39
+ static declare<E = void>(driver: RxNodeDriver<E>, declaration?: RxNodeDecl<E>, basis?: RxNodeDecl<E>): RxNode<E>;
39
40
  static get isFirstUpdate(): boolean;
40
41
  static get key(): string;
41
42
  static get stamp(): number;
@@ -48,31 +49,32 @@ export declare abstract class RxNode<E = unknown> {
48
49
  static triggerDeactivation(node: RxNode<any>): void;
49
50
  static updateNestedNodesThenDo(action: (error: unknown) => void): void;
50
51
  static markAsMounted(node: RxNode<any>, yes: boolean): void;
51
- static findMatchingHost<E = unknown, R = unknown>(node: RxNode<E>, match: SimpleDelegate<RxNode<E>, boolean>): RxNode<R> | undefined;
52
- static findMatchingPrevSibling<E = unknown, R = unknown>(node: RxNode<E>, match: SimpleDelegate<RxNode<E>, boolean>): RxNode<R> | undefined;
53
- static forEachChildRecursively<E = unknown>(node: RxNode<E>, action: SimpleDelegate<RxNode<E>>): void;
52
+ static findMatchingHost<E = unknown, R = unknown>(node: RxNode<E>, match: Handler<RxNode<E>, boolean>): RxNode<R> | undefined;
53
+ static findMatchingPrevSibling<E = unknown, R = unknown>(node: RxNode<E>, match: Handler<RxNode<E>, boolean>): RxNode<R> | undefined;
54
+ static forEachChildRecursively<E = unknown>(node: RxNode<E>, action: Handler<RxNode<E>>): void;
54
55
  static getDefaultLoggingOptions(): LoggingOptions | undefined;
55
56
  static setDefaultLoggingOptions(logging?: LoggingOptions): void;
56
57
  }
57
58
  export type RxNodeDecl<E = unknown> = {
58
- script?: Delegate<E>;
59
+ script?: Script<E>;
60
+ scriptAsync?: ScriptAsync<E>;
59
61
  key?: string;
60
62
  mode?: Mode;
61
- creation?: Delegate<E>;
62
- destruction?: Delegate<E>;
63
+ creation?: Script<E>;
64
+ destruction?: Script<E>;
63
65
  triggers?: unknown;
64
- preset?: RxNodeDecl<E>;
66
+ basis?: RxNodeDecl<E>;
65
67
  };
66
68
  export type RxNodeDriver<E = unknown> = {
67
69
  readonly name: string;
68
70
  readonly isPartition: boolean;
69
- readonly predefine?: SimpleDelegate<E>;
71
+ readonly initialize?: Handler<E>;
70
72
  allocate(node: RxNode<E>): E;
71
73
  create(node: RxNode<E>): void;
72
74
  destroy(node: RxNode<E>, isLeader: boolean): boolean;
73
75
  mount(node: RxNode<E>): void;
74
76
  update(node: RxNode<E>): void | Promise<void>;
75
- child(ownerNode: RxNode<E>, childDriver: RxNodeDriver<any>, childDeclaration?: RxNodeDecl<any>, childPreset?: RxNodeDecl<any>): MergedItem<RxNode> | undefined;
77
+ child(ownerNode: RxNode<E>, childDriver: RxNodeDriver<any>, childDeclaration?: RxNodeDecl<any>, childBasis?: RxNodeDecl<any>): MergedItem<RxNode> | undefined;
76
78
  getHost(node: RxNode<E>): RxNode<E>;
77
79
  };
78
80
  export type RxNodeContext<T extends Object = Object> = {
@@ -81,14 +83,14 @@ export type RxNodeContext<T extends Object = Object> = {
81
83
  export declare abstract class BaseDriver<E = unknown> implements RxNodeDriver<E> {
82
84
  readonly name: string;
83
85
  readonly isPartition: boolean;
84
- readonly predefine?: SimpleDelegate<E, void> | undefined;
85
- constructor(name: string, isPartition: boolean, predefine?: SimpleDelegate<E, void> | undefined);
86
+ readonly initialize?: Handler<E, void> | undefined;
87
+ constructor(name: string, isPartition: boolean, initialize?: Handler<E, void> | undefined);
86
88
  abstract allocate(node: RxNode<E>): E;
87
89
  create(node: RxNode<E>): void;
88
90
  destroy(node: RxNode<E>, isLeader: boolean): boolean;
89
91
  mount(node: RxNode<E>): void;
90
92
  update(node: RxNode<E>): void | Promise<void>;
91
- child(ownerNode: RxNode<E>, childDriver: RxNodeDriver<any>, childDeclaration?: RxNodeDecl<any>, childPreset?: RxNodeDecl<any>): MergedItem<RxNode> | undefined;
93
+ child(ownerNode: RxNode<E>, childDriver: RxNodeDriver<any>, childDeclaration?: RxNodeDecl<any>, childBasis?: RxNodeDecl<any>): MergedItem<RxNode> | undefined;
92
94
  getHost(node: RxNode<E>): RxNode<E>;
93
95
  }
94
96
  export declare class RxNodeVariable<T extends Object = Object> {
@@ -18,7 +18,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
18
18
  };
19
19
  import { MergeList } from "../util/MergeList.js";
20
20
  import { emitLetters, getCallerInfo } from "../util/Utils.js";
21
- import { Reentrance } from "../Options.js";
21
+ import { Isolation, Reentrance } from "../Options.js";
22
22
  import { ObservableObject } from "../core/Mvcc.js";
23
23
  import { Transaction } from "../core/Transaction.js";
24
24
  import { RxSystem, options, raw, reactive, unobs } from "../RxSystem.js";
@@ -35,16 +35,16 @@ export var Priority;
35
35
  Priority[Priority["background"] = 2] = "background";
36
36
  })(Priority || (Priority = {}));
37
37
  export class RxNode {
38
- static declare(driver, declaration, preset) {
38
+ static declare(driver, declaration, basis) {
39
39
  let result;
40
40
  if (declaration)
41
- declaration.preset = preset;
41
+ declaration.basis = basis;
42
42
  else
43
- declaration = preset !== null && preset !== void 0 ? preset : {};
43
+ declaration = basis !== null && basis !== void 0 ? basis : {};
44
44
  let key = declaration.key;
45
45
  const owner = gOwnSeat === null || gOwnSeat === void 0 ? void 0 : gOwnSeat.instance;
46
46
  if (owner) {
47
- let existing = owner.driver.child(owner, driver, declaration, preset);
47
+ let existing = owner.driver.child(owner, driver, declaration, basis);
48
48
  const children = owner.children;
49
49
  existing !== null && existing !== void 0 ? existing : (existing = children.tryMergeAsExisting(key = key || generateKey(owner), undefined, "nested elements can be declared inside update function only"));
50
50
  if (existing) {
@@ -144,26 +144,26 @@ RxNode.longFrameDuration = 300;
144
144
  RxNode.currentUpdatePriority = Priority.realtime;
145
145
  RxNode.frameDuration = RxNode.longFrameDuration;
146
146
  export class BaseDriver {
147
- constructor(name, isPartition, predefine) {
147
+ constructor(name, isPartition, initialize) {
148
148
  this.name = name;
149
149
  this.isPartition = isPartition;
150
- this.predefine = predefine;
150
+ this.initialize = initialize;
151
151
  }
152
152
  create(node) {
153
153
  var _a;
154
- (_a = this.predefine) === null || _a === void 0 ? void 0 : _a.call(this, node.element);
155
- invokeOnCreateViaPresetChain(node.element, node.declaration);
154
+ (_a = this.initialize) === null || _a === void 0 ? void 0 : _a.call(this, node.element);
155
+ invokeCreationUsingBasisChain(node.element, node.declaration);
156
156
  }
157
157
  destroy(node, isLeader) {
158
- invokeOnDestroyViaPresetChain(node.element, node.declaration);
158
+ invokeDestructionUsingBasisChain(node.element, node.declaration);
159
159
  return isLeader;
160
160
  }
161
161
  mount(node) {
162
162
  }
163
163
  update(node) {
164
- invokeScriptViaPresetChain(node.element, node.declaration);
164
+ invokeScriptUsingBasisChain(node.element, node.declaration);
165
165
  }
166
- child(ownerNode, childDriver, childDeclaration, childPreset) {
166
+ child(ownerNode, childDriver, childDeclaration, childBasis) {
167
167
  return undefined;
168
168
  }
169
169
  getHost(node) {
@@ -194,33 +194,33 @@ function generateKey(owner) {
194
194
  result = `·${lettered}`;
195
195
  return result;
196
196
  }
197
- function getModeViaPresetChain(declaration) {
197
+ function getModeUsingBasisChain(declaration) {
198
198
  var _a;
199
- return (_a = declaration === null || declaration === void 0 ? void 0 : declaration.mode) !== null && _a !== void 0 ? _a : ((declaration === null || declaration === void 0 ? void 0 : declaration.preset) ? getModeViaPresetChain(declaration === null || declaration === void 0 ? void 0 : declaration.preset) : Mode.default);
199
+ return (_a = declaration === null || declaration === void 0 ? void 0 : declaration.mode) !== null && _a !== void 0 ? _a : ((declaration === null || declaration === void 0 ? void 0 : declaration.basis) ? getModeUsingBasisChain(declaration === null || declaration === void 0 ? void 0 : declaration.basis) : Mode.default);
200
200
  }
201
- function invokeOnCreateViaPresetChain(element, declaration) {
202
- const preset = declaration.preset;
203
- const creation = declaration.creation;
204
- if (creation)
205
- creation(element, preset ? () => invokeOnCreateViaPresetChain(element, preset) : NOP);
206
- else if (preset)
207
- invokeOnCreateViaPresetChain(element, preset);
208
- }
209
- function invokeScriptViaPresetChain(element, declaration) {
210
- const preset = declaration.preset;
201
+ function invokeScriptUsingBasisChain(element, declaration) {
202
+ const basis = declaration.basis;
211
203
  const script = declaration.script;
212
204
  if (script)
213
- script(element, preset ? () => invokeScriptViaPresetChain(element, preset) : NOP);
214
- else if (preset)
215
- invokeScriptViaPresetChain(element, preset);
205
+ script(element, basis ? () => invokeScriptUsingBasisChain(element, basis) : NOP);
206
+ else if (basis)
207
+ invokeScriptUsingBasisChain(element, basis);
208
+ }
209
+ function invokeCreationUsingBasisChain(element, declaration) {
210
+ const basis = declaration.basis;
211
+ const creation = declaration.creation;
212
+ if (creation)
213
+ creation(element, basis ? () => invokeCreationUsingBasisChain(element, basis) : NOP);
214
+ else if (basis)
215
+ invokeCreationUsingBasisChain(element, basis);
216
216
  }
217
- function invokeOnDestroyViaPresetChain(element, declaration) {
218
- const preset = declaration.preset;
217
+ function invokeDestructionUsingBasisChain(element, declaration) {
218
+ const basis = declaration.basis;
219
219
  const destruction = declaration.destruction;
220
220
  if (destruction)
221
- destruction(element, preset ? () => invokeOnDestroyViaPresetChain(element, preset) : NOP);
222
- else if (preset)
223
- invokeOnDestroyViaPresetChain(element, preset);
221
+ destruction(element, basis ? () => invokeDestructionUsingBasisChain(element, basis) : NOP);
222
+ else if (basis)
223
+ invokeDestructionUsingBasisChain(element, basis);
224
224
  }
225
225
  class RxNodeContextImpl extends ObservableObject {
226
226
  constructor(variable, value) {
@@ -273,7 +273,7 @@ class RxNodeImpl extends RxNode {
273
273
  set strictOrder(value) { this.children.isStrict = value; }
274
274
  get isMoved() { return this.owner.children.isMoved(this.seat); }
275
275
  has(mode) {
276
- return (getModeViaPresetChain(this.declaration) & mode) === mode;
276
+ return (getModeUsingBasisChain(this.declaration) & mode) === mode;
277
277
  }
278
278
  update(_triggers) {
279
279
  updateNow(this.seat);
@@ -281,7 +281,7 @@ class RxNodeImpl extends RxNode {
281
281
  configureReactronic(options) {
282
282
  if (this.stamp < Number.MAX_SAFE_INTEGER - 1 || !this.has(Mode.independentUpdate))
283
283
  throw new Error("reactronic can be configured only for elements with independent update mode and only during activation");
284
- return RxSystem.getReaction(this.update).configure(options);
284
+ return RxSystem.getOperation(this.update).configure(options);
285
285
  }
286
286
  static get ownSeat() {
287
287
  if (!gOwnSeat)
@@ -311,7 +311,7 @@ class RxNodeImpl extends RxNode {
311
311
  node.outer = owner;
312
312
  else
313
313
  node.outer = owner.outer;
314
- Transaction.run({ separation: true }, () => {
314
+ Transaction.run({ isolation: Isolation.joinAsNestedTransaction }, () => {
315
315
  const ctx = node.context;
316
316
  if (ctx) {
317
317
  ctx.variable = variable;
@@ -449,7 +449,7 @@ function triggerUpdateViaSeat(seat) {
449
449
  Transaction.outside(() => {
450
450
  if (RxSystem.isLogging)
451
451
  RxSystem.setLoggingHint(node.element, node.key);
452
- RxSystem.getReaction(node.update).configure({
452
+ RxSystem.getOperation(node.update).configure({
453
453
  order: node.level,
454
454
  });
455
455
  });
@@ -519,7 +519,7 @@ function triggerDeactivation(seat, isLeader, individual) {
519
519
  else
520
520
  gFirstToDispose = gLastToDispose = seat;
521
521
  if (gFirstToDispose === seat)
522
- Transaction.run({ separation: "disposal", hint: `runDisposalLoop(initiator=${seat.instance.key})` }, () => {
522
+ Transaction.run({ isolation: Isolation.disjoinForInternalDisposal, hint: `runDisposalLoop(initiator=${seat.instance.key})` }, () => {
523
523
  void runDisposalLoop().then(NOP, error => console.log(error));
524
524
  });
525
525
  }
@@ -1,6 +1,7 @@
1
1
  import { F } from "../util/Utils.js";
2
2
  import { Worker } from "../Worker.js";
3
3
  import { SnapshotOptions } from "../Options.js";
4
+ import { ObjectHandle, ObjectVersion, Observer, FieldVersion, FieldKey } from "./Data.js";
4
5
  import { Changeset } from "./Changeset.js";
5
6
  export declare abstract class Transaction implements Worker {
6
7
  static get current(): Transaction;
@@ -20,11 +21,69 @@ export declare abstract class Transaction implements Worker {
20
21
  abstract readonly isCanceled: boolean;
21
22
  abstract readonly isFinished: boolean;
22
23
  whenFinished(): Promise<void>;
23
- static create(options: SnapshotOptions | null): Transaction;
24
+ static create(options: SnapshotOptions | null, parent?: Transaction): Transaction;
24
25
  static run<T>(options: SnapshotOptions | null, func: F<T>, ...args: any[]): T;
25
- static separate<T>(func: F<T>, ...args: any[]): T;
26
+ static isolate<T>(func: F<T>, ...args: any[]): T;
26
27
  static outside<T>(func: F<T>, ...args: any[]): T;
27
28
  static isFrameOver(everyN?: number, timeLimit?: number): boolean;
28
29
  static requestNextFrame(sleepTime?: number): Promise<void>;
29
30
  static get isCanceled(): boolean;
30
31
  }
32
+ export declare class TransactionImpl extends Transaction {
33
+ private static readonly none;
34
+ private static curr;
35
+ private static inspection;
36
+ private static frameStartTime;
37
+ private static frameOverCounter;
38
+ readonly margin: number;
39
+ readonly parent?: TransactionImpl;
40
+ readonly changeset: Changeset;
41
+ private pending;
42
+ private sealed;
43
+ private canceled?;
44
+ private after?;
45
+ private promise?;
46
+ private resolve;
47
+ private reject;
48
+ constructor(options: SnapshotOptions | null, parent?: TransactionImpl);
49
+ static get current(): TransactionImpl;
50
+ get id(): number;
51
+ get hint(): string;
52
+ get options(): SnapshotOptions;
53
+ get timestamp(): number;
54
+ get error(): Error | undefined;
55
+ run<T>(func: F<T>, ...args: any[]): T;
56
+ inspect<T>(func: F<T>, ...args: any[]): T;
57
+ apply(): void;
58
+ seal(): this;
59
+ wrap<T>(func: F<T>, error: boolean): F<T>;
60
+ private static wrapperEnter;
61
+ private static wrapperLeave;
62
+ cancel(error: Error, restartAfter?: Worker | null): this;
63
+ get isCanceled(): boolean;
64
+ get isFinished(): boolean;
65
+ whenFinished(): Promise<void>;
66
+ static run<T>(options: SnapshotOptions | null, func: F<T>, ...args: any[]): T;
67
+ static isolate<T>(func: F<T>, ...args: any[]): T;
68
+ static outside<T>(func: F<T>, ...args: any[]): T;
69
+ static isFrameOver(everyN?: number, timeLimit?: number): boolean;
70
+ static requestNextFrame(sleepTime?: number): Promise<void>;
71
+ private static acquire;
72
+ private guard;
73
+ private wrapToRetry;
74
+ private wrapToWaitUntilFinish;
75
+ private runImpl;
76
+ private static seal;
77
+ private checkForConflicts;
78
+ private tryResolveConflicts;
79
+ private applyOrDiscard;
80
+ applyOrDiscardChangeset(): Array<Observer>;
81
+ applyObjectChanges(h: ObjectHandle, ov: ObjectVersion): void;
82
+ static migrateObjectChangesToAnotherTransaction(h: ObjectHandle, ov: ObjectVersion, tParent: Transaction): void;
83
+ static migrateFieldVersionToAnotherTransaction(h: ObjectHandle, fk: FieldKey, ov: ObjectVersion, ovParent: ObjectVersion, tParent: Transaction): void;
84
+ private acquirePromise;
85
+ private static getCurrentChangeset;
86
+ private static getEditableChangeset;
87
+ static createFieldVersion: (fv: FieldVersion, target: Transaction) => FieldVersion;
88
+ static _init(): void;
89
+ }
@@ -9,25 +9,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { UNDEF, pause } from "../util/Utils.js";
11
11
  import { Log, misuse, error, fatal } from "../util/Dbg.js";
12
- import { Changeset, Dump } from "./Changeset.js";
12
+ import { Isolation } from "../Options.js";
13
+ import { Meta } from "./Data.js";
14
+ import { Changeset, Dump, EMPTY_OBJECT_VERSION, UNDEFINED_REVISION } from "./Changeset.js";
13
15
  export class Transaction {
14
16
  static get current() { return TransactionImpl.current; }
15
17
  whenFinished() {
16
18
  return __awaiter(this, void 0, void 0, function* () { });
17
19
  }
18
- static create(options) { return new TransactionImpl(options); }
20
+ static create(options, parent) { return new TransactionImpl(options, parent); }
19
21
  static run(options, func, ...args) { return TransactionImpl.run(options, func, ...args); }
20
- static separate(func, ...args) { return TransactionImpl.separate(func, ...args); }
22
+ static isolate(func, ...args) { return TransactionImpl.isolate(func, ...args); }
21
23
  static outside(func, ...args) { return TransactionImpl.outside(func, ...args); }
22
24
  static isFrameOver(everyN = 1, timeLimit = 10) { return TransactionImpl.isFrameOver(everyN, timeLimit); }
23
25
  static requestNextFrame(sleepTime = 0) { return TransactionImpl.requestNextFrame(sleepTime); }
24
26
  static get isCanceled() { return TransactionImpl.current.isCanceled; }
25
27
  }
26
- class TransactionImpl extends Transaction {
27
- constructor(options) {
28
+ export class TransactionImpl extends Transaction {
29
+ constructor(options, parent) {
28
30
  super();
29
31
  this.margin = TransactionImpl.curr !== undefined ? TransactionImpl.curr.margin + 1 : -1;
30
- this.changeset = new Changeset(options);
32
+ this.parent = parent;
33
+ this.changeset = new Changeset(options, parent === null || parent === void 0 ? void 0 : parent.changeset);
31
34
  this.pending = 0;
32
35
  this.sealed = false;
33
36
  this.canceled = undefined;
@@ -126,8 +129,8 @@ class TransactionImpl extends Transaction {
126
129
  }
127
130
  return result;
128
131
  }
129
- static separate(func, ...args) {
130
- return TransactionImpl.run({ separation: true }, func, ...args);
132
+ static isolate(func, ...args) {
133
+ return TransactionImpl.run({ isolation: Isolation.disjoinFromOuterTransaction }, func, ...args);
131
134
  }
132
135
  static outside(func, ...args) {
133
136
  const outer = TransactionImpl.curr;
@@ -152,11 +155,17 @@ class TransactionImpl extends Transaction {
152
155
  return pause(sleepTime);
153
156
  }
154
157
  static acquire(options) {
155
- const curr = TransactionImpl.curr;
156
- if ((options === null || options === void 0 ? void 0 : options.separation) || curr.isFinished || curr.options.separation === "isolated")
158
+ var _a;
159
+ const outer = TransactionImpl.curr;
160
+ const isolation = (_a = options === null || options === void 0 ? void 0 : options.isolation) !== null && _a !== void 0 ? _a : Isolation.joinToCurrentTransaction;
161
+ if (outer.isFinished || outer.options.isolation === Isolation.disjoinFromOuterAndInnerTransactions)
162
+ return new TransactionImpl(options);
163
+ else if (isolation === Isolation.joinAsNestedTransaction)
164
+ return new TransactionImpl(options, outer);
165
+ else if (isolation !== Isolation.joinToCurrentTransaction)
157
166
  return new TransactionImpl(options);
158
167
  else
159
- return TransactionImpl.curr;
168
+ return outer;
160
169
  }
161
170
  guard() {
162
171
  if (this.sealed && TransactionImpl.curr !== this)
@@ -176,7 +185,7 @@ class TransactionImpl extends Transaction {
176
185
  yield this.after.whenFinished();
177
186
  const options = {
178
187
  hint: `${this.hint} - restart after T${this.after.id}`,
179
- separation: this.options.separation === "isolated" ? "isolated" : true,
188
+ isolation: this.options.isolation === Isolation.joinToCurrentTransaction ? Isolation.disjoinFromOuterTransaction : this.options.isolation,
180
189
  logging: this.changeset.options.logging,
181
190
  token: this.changeset.options.token,
182
191
  };
@@ -255,11 +264,12 @@ class TransactionImpl extends Transaction {
255
264
  throw error(`T${this.id}[${this.hint}] conflicts with: ${Dump.conflicts(conflicts)}`, undefined);
256
265
  }
257
266
  applyOrDiscard() {
258
- let reactive;
267
+ let observers;
259
268
  try {
260
269
  if (Log.isOn && Log.opt.change)
261
270
  Log.write("╠═", "", "", undefined, "changes");
262
- reactive = this.changeset.applyOrDiscard(this.canceled);
271
+ this.changeset.seal();
272
+ observers = this.applyOrDiscardChangeset();
263
273
  this.changeset.triggerGarbageCollection();
264
274
  if (this.promise) {
265
275
  if (this.canceled && !this.after)
@@ -274,7 +284,153 @@ class TransactionImpl extends Transaction {
274
284
  fatal(e);
275
285
  throw e;
276
286
  }
277
- return reactive;
287
+ return observers;
288
+ }
289
+ applyOrDiscardChangeset() {
290
+ const error = this.canceled;
291
+ const changeset = this.changeset;
292
+ changeset.items.forEach((ov, h) => {
293
+ changeset.sealObjectVersion(h, ov);
294
+ if (!error) {
295
+ this.applyObjectChanges(h, ov);
296
+ if (Changeset.garbageCollectionSummaryInterval < Number.MAX_SAFE_INTEGER) {
297
+ Changeset.totalObjectSnapshotCount++;
298
+ if (ov.former.objectVersion === EMPTY_OBJECT_VERSION)
299
+ Changeset.totalObjectHandleCount++;
300
+ }
301
+ }
302
+ });
303
+ if (Log.isOn) {
304
+ if (Log.opt.change && !error && !changeset.parent) {
305
+ changeset.items.forEach((ov, h) => {
306
+ const fields = [];
307
+ ov.changes.forEach((o, fk) => fields.push(fk.toString()));
308
+ const s = fields.join(", ");
309
+ Log.write("║", "√", `${Dump.snapshot2(h, ov.changeset)} (${s}) is ${ov.former.objectVersion === EMPTY_OBJECT_VERSION ? "constructed" : `applied over #${h.id}t${ov.former.objectVersion.changeset.id}s${ov.former.objectVersion.changeset.timestamp}`}`);
310
+ });
311
+ }
312
+ if (Log.opt.transaction)
313
+ Log.write(changeset.timestamp < UNDEFINED_REVISION ? "╚══" : "═══", `s${this.timestamp}`, `${this.hint} - ${error ? "CANCEL" : "APPLY"}(${this.changeset.items.size})${error ? ` - ${error}` : ""}`);
314
+ }
315
+ if (!error && !this.parent)
316
+ Changeset.propagateAllChangesThroughSubscriptions(changeset);
317
+ return changeset.obsolete;
318
+ }
319
+ applyObjectChanges(h, ov) {
320
+ const parent = this.parent;
321
+ if (parent)
322
+ TransactionImpl.migrateObjectChangesToAnotherTransaction(h, ov, parent);
323
+ else
324
+ h.applied = ov;
325
+ }
326
+ static migrateObjectChangesToAnotherTransaction(h, ov, tParent) {
327
+ const csParent = tParent.changeset;
328
+ const ovParent = csParent.getEditableObjectVersion(h, Meta.Undefined, undefined);
329
+ if (ov.former.objectVersion.changeset === EMPTY_OBJECT_VERSION.changeset) {
330
+ for (const fk in ov.data) {
331
+ TransactionImpl.migrateFieldVersionToAnotherTransaction(h, fk, ov, ovParent, tParent);
332
+ }
333
+ }
334
+ else {
335
+ ov.changes.forEach((o, fk) => {
336
+ TransactionImpl.migrateFieldVersionToAnotherTransaction(h, fk, ov, ovParent, tParent);
337
+ });
338
+ }
339
+ }
340
+ static migrateFieldVersionToAnotherTransaction(h, fk, ov, ovParent, tParent) {
341
+ const csParent = tParent.changeset;
342
+ const fv = ov.data[fk];
343
+ const fvParent = ovParent.data[fk];
344
+ if (fv.isLaunch) {
345
+ const migrated = TransactionImpl.createFieldVersion(fv, tParent);
346
+ if (ovParent.former.objectVersion.data[fk] !== fvParent) {
347
+ let observers = fvParent.observers;
348
+ if (observers) {
349
+ const migratedObservers = migrated.observers = new Set();
350
+ observers.forEach(o => {
351
+ var _a, _b;
352
+ const sub = o.observables.get(fvParent);
353
+ (_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fvParent);
354
+ (_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(migrated, sub);
355
+ migratedObservers.add(o);
356
+ });
357
+ fvParent.observers = undefined;
358
+ }
359
+ observers = fv.observers;
360
+ if (observers) {
361
+ let migratedObservers = migrated.observers;
362
+ if (migratedObservers === undefined)
363
+ migratedObservers = migrated.observers = new Set();
364
+ observers.forEach(o => {
365
+ var _a, _b;
366
+ const sub = o.observables.get(fv);
367
+ (_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fv);
368
+ (_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(migrated, sub);
369
+ migratedObservers === null || migratedObservers === void 0 ? void 0 : migratedObservers.add(o);
370
+ });
371
+ fv.observers = undefined;
372
+ }
373
+ const observables = fv.observables;
374
+ const migratedObservables = migrated.observables;
375
+ if (observables) {
376
+ observables.forEach((s, o) => {
377
+ var _a, _b;
378
+ (_a = o.observers) === null || _a === void 0 ? void 0 : _a.delete(fv);
379
+ (_b = o.observers) === null || _b === void 0 ? void 0 : _b.add(migrated);
380
+ migratedObservables === null || migratedObservables === void 0 ? void 0 : migratedObservables.set(o, s);
381
+ });
382
+ observables.clear();
383
+ }
384
+ ovParent.data[fk] = migrated;
385
+ }
386
+ else {
387
+ const observers = fv.observers;
388
+ if (observers) {
389
+ const migratedObservers = migrated.observers = new Set();
390
+ observers.forEach(o => {
391
+ var _a, _b;
392
+ const sub = o.observables.get(fv);
393
+ (_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fv);
394
+ (_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(migrated, sub);
395
+ migratedObservers.add(o);
396
+ });
397
+ fv.observers = undefined;
398
+ }
399
+ const observables = fv.observables;
400
+ const migratedObservables = migrated.observables;
401
+ if (observables) {
402
+ observables.forEach((s, o) => {
403
+ var _a, _b;
404
+ (_a = o.observers) === null || _a === void 0 ? void 0 : _a.delete(fv);
405
+ (_b = o.observers) === null || _b === void 0 ? void 0 : _b.add(migrated);
406
+ migratedObservables === null || migratedObservables === void 0 ? void 0 : migratedObservables.set(o, s);
407
+ });
408
+ observables.clear();
409
+ }
410
+ ovParent.data[fk] = migrated;
411
+ }
412
+ csParent.bumpBy(ovParent.former.objectVersion.changeset.timestamp);
413
+ Changeset.markEdited(undefined, migrated, true, ovParent, fk, h);
414
+ }
415
+ else {
416
+ const parentContent = fvParent === null || fvParent === void 0 ? void 0 : fvParent.content;
417
+ if (ovParent.former.objectVersion.data[fk] !== fvParent) {
418
+ fvParent.content = fv.content;
419
+ const observers = fv.observers;
420
+ if (observers) {
421
+ observers.forEach(o => {
422
+ var _a, _b, _c;
423
+ const sub = o.observables.get(fv);
424
+ (_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fv);
425
+ (_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(fvParent, sub);
426
+ (_c = fvParent.observers) === null || _c === void 0 ? void 0 : _c.add(o);
427
+ });
428
+ }
429
+ }
430
+ else
431
+ ovParent.data[fk] = fv;
432
+ Changeset.markEdited(parentContent, fv.content, true, ovParent, fk, h);
433
+ }
278
434
  }
279
435
  acquirePromise() {
280
436
  if (!this.promise) {
@@ -297,7 +453,7 @@ class TransactionImpl extends Transaction {
297
453
  Changeset.current = TransactionImpl.getCurrentChangeset;
298
454
  Changeset.edit = TransactionImpl.getEditableChangeset;
299
455
  TransactionImpl.none.sealed = true;
300
- TransactionImpl.none.changeset.applyOrDiscard();
456
+ TransactionImpl.none.changeset.seal();
301
457
  Changeset._init();
302
458
  }
303
459
  }
@@ -306,4 +462,7 @@ TransactionImpl.curr = TransactionImpl.none;
306
462
  TransactionImpl.inspection = false;
307
463
  TransactionImpl.frameStartTime = 0;
308
464
  TransactionImpl.frameOverCounter = 0;
465
+ TransactionImpl.createFieldVersion = function (fv, target) {
466
+ throw misuse("this implementation of cloneLaunch should never be called");
467
+ };
309
468
  TransactionImpl._init();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactronic",
3
- "version": "0.24.274",
3
+ "version": "0.24.301",
4
4
  "description": "Reactronic - Transactional Reactive State Management",
5
5
  "publisher": "Nezaboodka Software",
6
6
  "license": "Apache-2.0",
@@ -32,13 +32,13 @@
32
32
  "homepage": "https://github.com/nezaboodka/reactronic/blob/master/README.md#readme",
33
33
  "devDependencies": {
34
34
  "@types/node": "20.11.28",
35
- "@types/react": "18.2.66",
35
+ "@types/react": "18.3.4",
36
36
  "@typescript-eslint/eslint-plugin": "7.2.0",
37
37
  "@typescript-eslint/parser": "7.2.0",
38
38
  "ava": "6.1.2",
39
39
  "c8": "9.1.0",
40
40
  "eslint": "8.57.0",
41
- "react": "18.2.0",
41
+ "react": "18.3.1",
42
42
  "ts-node": "10.9.2",
43
43
  "typescript": "5.3.2"
44
44
  },