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.
- package/README.md +2 -2
- package/build/dist/source/Options.d.ts +10 -4
- package/build/dist/source/Options.js +8 -0
- package/build/dist/source/RxSystem.d.ts +2 -2
- package/build/dist/source/RxSystem.js +21 -10
- package/build/dist/source/api.d.ts +3 -3
- package/build/dist/source/api.js +2 -2
- package/build/dist/source/core/Changeset.d.ts +23 -21
- package/build/dist/source/core/Changeset.js +147 -144
- package/build/dist/source/core/Data.d.ts +19 -20
- package/build/dist/source/core/Data.js +9 -9
- package/build/dist/source/core/Indicator.d.ts +2 -2
- package/build/dist/source/core/Indicator.js +9 -8
- package/build/dist/source/core/Journal.d.ts +2 -2
- package/build/dist/source/core/Journal.js +36 -35
- package/build/dist/source/core/Mvcc.d.ts +12 -12
- package/build/dist/source/core/Mvcc.js +47 -62
- package/build/dist/source/core/MvccArray.d.ts +1 -0
- package/build/dist/source/core/MvccArray.js +4 -4
- package/build/dist/source/core/{Reaction.d.ts → Operation.d.ts} +21 -20
- package/build/dist/source/core/{Reaction.js → Operation.js} +187 -156
- package/build/dist/source/core/RxNode.d.ts +8 -6
- package/build/dist/source/core/RxNode.js +37 -18
- package/build/dist/source/core/Transaction.d.ts +61 -2
- package/build/dist/source/core/Transaction.js +181 -16
- package/build/dist/source/util/Utils.d.ts +1 -0
- package/build/dist/source/util/Utils.js +8 -0
- package/package.json +4 -4
|
@@ -1,9 +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 Script<
|
|
5
|
-
export type ScriptAsync<
|
|
6
|
-
export type Handler<
|
|
4
|
+
export type Script<E> = (el: E, basis: () => void) => void;
|
|
5
|
+
export type ScriptAsync<E> = (el: E, basis: () => Promise<void>) => Promise<void>;
|
|
6
|
+
export type Handler<E = unknown, R = void> = (el: E) => R;
|
|
7
7
|
export declare enum Mode {
|
|
8
8
|
default = 0,
|
|
9
9
|
independentUpdate = 1,
|
|
@@ -56,11 +56,13 @@ export declare abstract class RxNode<E = unknown> {
|
|
|
56
56
|
static setDefaultLoggingOptions(logging?: LoggingOptions): void;
|
|
57
57
|
}
|
|
58
58
|
export type RxNodeDecl<E = unknown> = {
|
|
59
|
+
isAsync?: boolean;
|
|
59
60
|
script?: Script<E>;
|
|
60
61
|
scriptAsync?: ScriptAsync<E>;
|
|
61
62
|
key?: string;
|
|
62
63
|
mode?: Mode;
|
|
63
64
|
creation?: Script<E>;
|
|
65
|
+
creationAsync?: ScriptAsync<E>;
|
|
64
66
|
destruction?: Script<E>;
|
|
65
67
|
triggers?: unknown;
|
|
66
68
|
basis?: RxNodeDecl<E>;
|
|
@@ -83,10 +85,10 @@ export type RxNodeContext<T extends Object = Object> = {
|
|
|
83
85
|
export declare abstract class BaseDriver<E = unknown> implements RxNodeDriver<E> {
|
|
84
86
|
readonly name: string;
|
|
85
87
|
readonly isPartition: boolean;
|
|
86
|
-
readonly initialize?: Handler<E
|
|
87
|
-
constructor(name: string, isPartition: boolean, initialize?: Handler<E
|
|
88
|
+
readonly initialize?: Handler<E> | undefined;
|
|
89
|
+
constructor(name: string, isPartition: boolean, initialize?: Handler<E> | undefined);
|
|
88
90
|
abstract allocate(node: RxNode<E>): E;
|
|
89
|
-
create(node: RxNode<E>): void
|
|
91
|
+
create(node: RxNode<E>): void | Promise<void>;
|
|
90
92
|
destroy(node: RxNode<E>, isLeader: boolean): boolean;
|
|
91
93
|
mount(node: RxNode<E>): void;
|
|
92
94
|
update(node: RxNode<E>): void | Promise<void>;
|
|
@@ -16,9 +16,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
16
16
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
17
17
|
});
|
|
18
18
|
};
|
|
19
|
+
import { misuse } from "../util/Dbg.js";
|
|
19
20
|
import { MergeList } from "../util/MergeList.js";
|
|
20
|
-
import { emitLetters, getCallerInfo } from "../util/Utils.js";
|
|
21
|
-
import { Reentrance } from "../Options.js";
|
|
21
|
+
import { emitLetters, getCallerInfo, proceedSyncOrAsync } from "../util/Utils.js";
|
|
22
|
+
import { Isolation, Reentrance } from "../Options.js";
|
|
22
23
|
import { ObservableObject } from "../core/Mvcc.js";
|
|
23
24
|
import { Transaction } from "../core/Transaction.js";
|
|
24
25
|
import { RxSystem, options, raw, reactive, unobs } from "../RxSystem.js";
|
|
@@ -152,7 +153,7 @@ export class BaseDriver {
|
|
|
152
153
|
create(node) {
|
|
153
154
|
var _a;
|
|
154
155
|
(_a = this.initialize) === null || _a === void 0 ? void 0 : _a.call(this, node.element);
|
|
155
|
-
invokeCreationUsingBasisChain(node.element, node.declaration);
|
|
156
|
+
return invokeCreationUsingBasisChain(node.element, node.declaration);
|
|
156
157
|
}
|
|
157
158
|
destroy(node, isLeader) {
|
|
158
159
|
invokeDestructionUsingBasisChain(node.element, node.declaration);
|
|
@@ -161,7 +162,7 @@ export class BaseDriver {
|
|
|
161
162
|
mount(node) {
|
|
162
163
|
}
|
|
163
164
|
update(node) {
|
|
164
|
-
invokeScriptUsingBasisChain(node.element, node.declaration);
|
|
165
|
+
return invokeScriptUsingBasisChain(node.element, node.declaration);
|
|
165
166
|
}
|
|
166
167
|
child(ownerNode, childDriver, childDeclaration, childBasis) {
|
|
167
168
|
return undefined;
|
|
@@ -199,20 +200,40 @@ function getModeUsingBasisChain(declaration) {
|
|
|
199
200
|
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
201
|
}
|
|
201
202
|
function invokeScriptUsingBasisChain(element, declaration) {
|
|
203
|
+
let result = undefined;
|
|
202
204
|
const basis = declaration.basis;
|
|
203
205
|
const script = declaration.script;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
const scriptAsync = declaration.scriptAsync;
|
|
207
|
+
if (script && scriptAsync) {
|
|
208
|
+
throw misuse("'script' and 'scriptAsync' cannot be defined together");
|
|
209
|
+
}
|
|
210
|
+
if (script) {
|
|
211
|
+
result = script(element, basis ? () => invokeScriptUsingBasisChain(element, basis) : NOP);
|
|
212
|
+
}
|
|
213
|
+
else if (scriptAsync) {
|
|
214
|
+
result = scriptAsync(element, basis ? () => invokeScriptUsingBasisChain(element, basis) : NOP_ASYNC);
|
|
215
|
+
}
|
|
206
216
|
else if (basis)
|
|
207
|
-
invokeScriptUsingBasisChain(element, basis);
|
|
217
|
+
result = invokeScriptUsingBasisChain(element, basis);
|
|
218
|
+
return result;
|
|
208
219
|
}
|
|
209
220
|
function invokeCreationUsingBasisChain(element, declaration) {
|
|
221
|
+
let result = undefined;
|
|
210
222
|
const basis = declaration.basis;
|
|
211
223
|
const creation = declaration.creation;
|
|
212
|
-
|
|
213
|
-
|
|
224
|
+
const creationAsync = declaration.creationAsync;
|
|
225
|
+
if (creation && creationAsync) {
|
|
226
|
+
throw misuse("'creation' and 'creationAsync' cannot be defined together");
|
|
227
|
+
}
|
|
228
|
+
if (creation) {
|
|
229
|
+
result = creation(element, basis ? () => invokeCreationUsingBasisChain(element, basis) : NOP);
|
|
230
|
+
}
|
|
231
|
+
else if (creationAsync) {
|
|
232
|
+
result = creationAsync(element, basis ? () => invokeCreationUsingBasisChain(element, basis) : NOP_ASYNC);
|
|
233
|
+
}
|
|
214
234
|
else if (basis)
|
|
215
|
-
invokeCreationUsingBasisChain(element, basis);
|
|
235
|
+
result = invokeCreationUsingBasisChain(element, basis);
|
|
236
|
+
return result;
|
|
216
237
|
}
|
|
217
238
|
function invokeDestructionUsingBasisChain(element, declaration) {
|
|
218
239
|
const basis = declaration.basis;
|
|
@@ -281,7 +302,7 @@ class RxNodeImpl extends RxNode {
|
|
|
281
302
|
configureReactronic(options) {
|
|
282
303
|
if (this.stamp < Number.MAX_SAFE_INTEGER - 1 || !this.has(Mode.independentUpdate))
|
|
283
304
|
throw new Error("reactronic can be configured only for elements with independent update mode and only during activation");
|
|
284
|
-
return RxSystem.
|
|
305
|
+
return RxSystem.getOperation(this.update).configure(options);
|
|
285
306
|
}
|
|
286
307
|
static get ownSeat() {
|
|
287
308
|
if (!gOwnSeat)
|
|
@@ -311,7 +332,7 @@ class RxNodeImpl extends RxNode {
|
|
|
311
332
|
node.outer = owner;
|
|
312
333
|
else
|
|
313
334
|
node.outer = owner.outer;
|
|
314
|
-
Transaction.run({
|
|
335
|
+
Transaction.run({ isolation: Isolation.joinAsNestedTransaction }, () => {
|
|
315
336
|
const ctx = node.context;
|
|
316
337
|
if (ctx) {
|
|
317
338
|
ctx.variable = variable;
|
|
@@ -449,7 +470,7 @@ function triggerUpdateViaSeat(seat) {
|
|
|
449
470
|
Transaction.outside(() => {
|
|
450
471
|
if (RxSystem.isLogging)
|
|
451
472
|
RxSystem.setLoggingHint(node.element, node.key);
|
|
452
|
-
RxSystem.
|
|
473
|
+
RxSystem.getOperation(node.update).configure({
|
|
453
474
|
order: node.level,
|
|
454
475
|
});
|
|
455
476
|
});
|
|
@@ -489,10 +510,7 @@ function updateNow(seat) {
|
|
|
489
510
|
node.children.beginMerge();
|
|
490
511
|
const driver = node.driver;
|
|
491
512
|
result = driver.update(node);
|
|
492
|
-
|
|
493
|
-
result.then(v => { runUpdateNestedNodesThenDo(undefined, NOP); return v; }, e => { console.log(e); runUpdateNestedNodesThenDo(e !== null && e !== void 0 ? e : new Error("unknown error"), NOP); });
|
|
494
|
-
else
|
|
495
|
-
runUpdateNestedNodesThenDo(undefined, NOP);
|
|
513
|
+
result = proceedSyncOrAsync(result, v => { runUpdateNestedNodesThenDo(undefined, NOP); return v; }, e => { console.log(e); runUpdateNestedNodesThenDo(e !== null && e !== void 0 ? e : new Error("unknown error"), NOP); });
|
|
496
514
|
}
|
|
497
515
|
catch (e) {
|
|
498
516
|
runUpdateNestedNodesThenDo(e, NOP);
|
|
@@ -519,7 +537,7 @@ function triggerDeactivation(seat, isLeader, individual) {
|
|
|
519
537
|
else
|
|
520
538
|
gFirstToDispose = gLastToDispose = seat;
|
|
521
539
|
if (gFirstToDispose === seat)
|
|
522
|
-
Transaction.run({
|
|
540
|
+
Transaction.run({ isolation: Isolation.disjoinForInternalDisposal, hint: `runDisposalLoop(initiator=${seat.instance.key})` }, () => {
|
|
523
541
|
void runDisposalLoop().then(NOP, error => console.log(error));
|
|
524
542
|
});
|
|
525
543
|
}
|
|
@@ -613,6 +631,7 @@ function defaultReject(error) {
|
|
|
613
631
|
}
|
|
614
632
|
Promise.prototype.then = reactronicDomHookedThen;
|
|
615
633
|
const NOP = (...args) => { };
|
|
634
|
+
const NOP_ASYNC = (...args) => __awaiter(void 0, void 0, void 0, function* () { });
|
|
616
635
|
let gOwnSeat = undefined;
|
|
617
636
|
let gFirstToDispose = undefined;
|
|
618
637
|
let gLastToDispose = undefined;
|
|
@@ -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
|
|
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 migrateFieldVersion: (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 {
|
|
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
|
|
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.
|
|
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
|
|
130
|
-
return TransactionImpl.run({
|
|
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
|
-
|
|
156
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
267
|
+
let observers;
|
|
259
268
|
try {
|
|
260
269
|
if (Log.isOn && Log.opt.change)
|
|
261
270
|
Log.write("╠═", "", "", undefined, "changes");
|
|
262
|
-
|
|
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,159 @@ class TransactionImpl extends Transaction {
|
|
|
274
284
|
fatal(e);
|
|
275
285
|
throw e;
|
|
276
286
|
}
|
|
277
|
-
return
|
|
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
|
+
if (fk === Meta.Revision) {
|
|
332
|
+
console.log("(!)");
|
|
333
|
+
}
|
|
334
|
+
TransactionImpl.migrateFieldVersionToAnotherTransaction(h, fk, ov, ovParent, tParent);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
ov.changes.forEach((o, fk) => {
|
|
339
|
+
if (fk === Meta.Revision) {
|
|
340
|
+
console.log("(!)");
|
|
341
|
+
}
|
|
342
|
+
TransactionImpl.migrateFieldVersionToAnotherTransaction(h, fk, ov, ovParent, tParent);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
static migrateFieldVersionToAnotherTransaction(h, fk, ov, ovParent, tParent) {
|
|
347
|
+
const csParent = tParent.changeset;
|
|
348
|
+
const fv = ov.data[fk];
|
|
349
|
+
const fvParent = ovParent.data[fk];
|
|
350
|
+
if (fv.isLaunch) {
|
|
351
|
+
const migrated = TransactionImpl.migrateFieldVersion(fv, tParent);
|
|
352
|
+
if (ovParent.former.objectVersion.data[fk] !== fvParent) {
|
|
353
|
+
let observers = fvParent.observers;
|
|
354
|
+
if (observers) {
|
|
355
|
+
const migratedObservers = migrated.observers = new Set();
|
|
356
|
+
observers.forEach(o => {
|
|
357
|
+
var _a, _b;
|
|
358
|
+
const sub = o.observables.get(fvParent);
|
|
359
|
+
(_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fvParent);
|
|
360
|
+
(_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(migrated, sub);
|
|
361
|
+
migratedObservers.add(o);
|
|
362
|
+
});
|
|
363
|
+
fvParent.observers = undefined;
|
|
364
|
+
}
|
|
365
|
+
observers = fv.observers;
|
|
366
|
+
if (observers) {
|
|
367
|
+
let migratedObservers = migrated.observers;
|
|
368
|
+
if (migratedObservers === undefined)
|
|
369
|
+
migratedObservers = migrated.observers = new Set();
|
|
370
|
+
observers.forEach(o => {
|
|
371
|
+
var _a, _b;
|
|
372
|
+
const sub = o.observables.get(fv);
|
|
373
|
+
(_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fv);
|
|
374
|
+
(_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(migrated, sub);
|
|
375
|
+
migratedObservers === null || migratedObservers === void 0 ? void 0 : migratedObservers.add(o);
|
|
376
|
+
});
|
|
377
|
+
fv.observers = undefined;
|
|
378
|
+
}
|
|
379
|
+
const observables = fv.observables;
|
|
380
|
+
const migratedObservables = migrated.observables;
|
|
381
|
+
if (observables) {
|
|
382
|
+
observables.forEach((s, o) => {
|
|
383
|
+
var _a, _b;
|
|
384
|
+
(_a = o.observers) === null || _a === void 0 ? void 0 : _a.delete(fv);
|
|
385
|
+
(_b = o.observers) === null || _b === void 0 ? void 0 : _b.add(migrated);
|
|
386
|
+
migratedObservables === null || migratedObservables === void 0 ? void 0 : migratedObservables.set(o, s);
|
|
387
|
+
});
|
|
388
|
+
observables.clear();
|
|
389
|
+
}
|
|
390
|
+
ovParent.data[fk] = migrated;
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
const observers = fv.observers;
|
|
394
|
+
if (observers) {
|
|
395
|
+
const migratedObservers = migrated.observers = new Set();
|
|
396
|
+
observers.forEach(o => {
|
|
397
|
+
var _a, _b;
|
|
398
|
+
const sub = o.observables.get(fv);
|
|
399
|
+
(_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fv);
|
|
400
|
+
(_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(migrated, sub);
|
|
401
|
+
migratedObservers.add(o);
|
|
402
|
+
});
|
|
403
|
+
fv.observers = undefined;
|
|
404
|
+
}
|
|
405
|
+
const observables = fv.observables;
|
|
406
|
+
const migratedObservables = migrated.observables;
|
|
407
|
+
if (observables) {
|
|
408
|
+
observables.forEach((s, o) => {
|
|
409
|
+
var _a, _b;
|
|
410
|
+
(_a = o.observers) === null || _a === void 0 ? void 0 : _a.delete(fv);
|
|
411
|
+
(_b = o.observers) === null || _b === void 0 ? void 0 : _b.add(migrated);
|
|
412
|
+
migratedObservables === null || migratedObservables === void 0 ? void 0 : migratedObservables.set(o, s);
|
|
413
|
+
});
|
|
414
|
+
observables.clear();
|
|
415
|
+
}
|
|
416
|
+
ovParent.data[fk] = migrated;
|
|
417
|
+
}
|
|
418
|
+
csParent.bumpBy(ovParent.former.objectVersion.changeset.timestamp);
|
|
419
|
+
Changeset.markEdited(undefined, migrated, true, ovParent, fk, h);
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
const parentContent = fvParent === null || fvParent === void 0 ? void 0 : fvParent.content;
|
|
423
|
+
if (ovParent.former.objectVersion.data[fk] !== fvParent) {
|
|
424
|
+
fvParent.content = fv.content;
|
|
425
|
+
const observers = fv.observers;
|
|
426
|
+
if (observers) {
|
|
427
|
+
observers.forEach(o => {
|
|
428
|
+
var _a, _b, _c;
|
|
429
|
+
const sub = o.observables.get(fv);
|
|
430
|
+
(_a = o.observables) === null || _a === void 0 ? void 0 : _a.delete(fv);
|
|
431
|
+
(_b = o.observables) === null || _b === void 0 ? void 0 : _b.set(fvParent, sub);
|
|
432
|
+
(_c = fvParent.observers) === null || _c === void 0 ? void 0 : _c.add(o);
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
else
|
|
437
|
+
ovParent.data[fk] = fv;
|
|
438
|
+
Changeset.markEdited(parentContent, fv.content, true, ovParent, fk, h);
|
|
439
|
+
}
|
|
278
440
|
}
|
|
279
441
|
acquirePromise() {
|
|
280
442
|
if (!this.promise) {
|
|
@@ -297,7 +459,7 @@ class TransactionImpl extends Transaction {
|
|
|
297
459
|
Changeset.current = TransactionImpl.getCurrentChangeset;
|
|
298
460
|
Changeset.edit = TransactionImpl.getEditableChangeset;
|
|
299
461
|
TransactionImpl.none.sealed = true;
|
|
300
|
-
TransactionImpl.none.changeset.
|
|
462
|
+
TransactionImpl.none.changeset.seal();
|
|
301
463
|
Changeset._init();
|
|
302
464
|
}
|
|
303
465
|
}
|
|
@@ -306,4 +468,7 @@ TransactionImpl.curr = TransactionImpl.none;
|
|
|
306
468
|
TransactionImpl.inspection = false;
|
|
307
469
|
TransactionImpl.frameStartTime = 0;
|
|
308
470
|
TransactionImpl.frameOverCounter = 0;
|
|
471
|
+
TransactionImpl.migrateFieldVersion = function (fv, target) {
|
|
472
|
+
throw misuse("this implementation of cloneLaunch should never be called");
|
|
473
|
+
};
|
|
309
474
|
TransactionImpl._init();
|
|
@@ -7,6 +7,7 @@ export declare class Utils {
|
|
|
7
7
|
export declare function UNDEF(...args: any[]): never;
|
|
8
8
|
export declare function all(promises: Array<Promise<any>>): Promise<any[]>;
|
|
9
9
|
export declare function pause<T>(timeout: number): Promise<T>;
|
|
10
|
+
export declare function proceedSyncOrAsync<T>(result: T | Promise<T>, success: (v: any) => T, failure: (e: any) => T): T | Promise<T>;
|
|
10
11
|
export declare function emitLetters(n: number): string;
|
|
11
12
|
export declare function objectHasMember<T>(obj: any, member: string): obj is T;
|
|
12
13
|
export declare function getCallerInfo(prefix: string): string;
|
|
@@ -53,6 +53,14 @@ export function pause(timeout) {
|
|
|
53
53
|
setTimeout(resolve.bind(null, () => resolve), timeout);
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
|
+
export function proceedSyncOrAsync(result, success, failure) {
|
|
57
|
+
let r;
|
|
58
|
+
if (result instanceof Promise)
|
|
59
|
+
r = result.then(v => success(v), e => failure(e));
|
|
60
|
+
else
|
|
61
|
+
r = success(result);
|
|
62
|
+
return r;
|
|
63
|
+
}
|
|
56
64
|
export function emitLetters(n) {
|
|
57
65
|
if (n < 0)
|
|
58
66
|
throw new Error(`emitLetters: argument (${n}) should not be negative or zero`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reactronic",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.302",
|
|
4
4
|
"description": "Reactronic - Transactional Reactive State Management",
|
|
5
5
|
"publisher": "Nezaboodka Software",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -32,15 +32,15 @@
|
|
|
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.
|
|
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.
|
|
41
|
+
"react": "18.3.1",
|
|
42
42
|
"ts-node": "10.9.2",
|
|
43
|
-
"typescript": "5.
|
|
43
|
+
"typescript": "5.5.4"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "eslint source/**.ts test/**.test.ts react/**.tsx && tsc",
|