reactronic 0.24.301 → 0.24.303
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/build/dist/source/api.d.ts +1 -1
- package/build/dist/source/api.js +1 -1
- package/build/dist/source/core/Changeset.d.ts +2 -2
- package/build/dist/source/core/Changeset.js +10 -7
- package/build/dist/source/core/Data.d.ts +2 -2
- package/build/dist/source/core/Data.js +1 -2
- package/build/dist/source/core/Indicator.d.ts +2 -2
- package/build/dist/source/core/Journal.js +1 -1
- package/build/dist/source/core/Mvcc.js +2 -2
- package/build/dist/source/core/MvccArray.d.ts +1 -0
- package/build/dist/source/core/MvccArray.js +4 -4
- package/build/dist/source/core/Operation.d.ts +1 -2
- package/build/dist/source/core/Operation.js +14 -12
- package/build/dist/source/core/RxNode.d.ts +7 -6
- package/build/dist/source/core/RxNode.js +75 -55
- package/build/dist/source/core/Transaction.d.ts +2 -2
- package/build/dist/source/core/Transaction.js +22 -7
- package/build/dist/source/util/Utils.d.ts +1 -0
- package/build/dist/source/util/Utils.js +8 -0
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { all, pause } from "./util/Utils.js";
|
|
1
|
+
export { all, pause, proceedSyncOrAsync } from "./util/Utils.js";
|
|
2
2
|
export { MergeList } from "./util/MergeList.js";
|
|
3
3
|
export type { MergedItem, MergeListReader } from "./util/MergeList.js";
|
|
4
4
|
export { SealedArray } from "./util/SealedArray.js";
|
package/build/dist/source/api.js
CHANGED
|
@@ -38,7 +38,7 @@ export declare class Changeset implements AbstractChangeset {
|
|
|
38
38
|
static dispose(obj: any): void;
|
|
39
39
|
static doDispose(ctx: Changeset, h: ObjectHandle): ObjectVersion;
|
|
40
40
|
private isNewObjectVersionRequired;
|
|
41
|
-
acquire(outer: Changeset):
|
|
41
|
+
acquire(outer: Changeset): boolean;
|
|
42
42
|
bumpBy(timestamp: number): void;
|
|
43
43
|
rebase(): ObjectVersion[] | undefined;
|
|
44
44
|
private merge;
|
|
@@ -52,7 +52,7 @@ export declare class Changeset implements AbstractChangeset {
|
|
|
52
52
|
}
|
|
53
53
|
export declare class Dump {
|
|
54
54
|
static valueHint: (value: any) => string;
|
|
55
|
-
static obj(h: ObjectHandle | undefined, fk?: FieldKey | undefined, stamp?: number,
|
|
55
|
+
static obj(h: ObjectHandle | undefined, fk?: FieldKey | undefined, stamp?: number, changesetId?: number, lastEditorChangesetId?: number, value?: any): string;
|
|
56
56
|
static snapshot2(h: ObjectHandle, s: AbstractChangeset, fk?: FieldKey, o?: FieldVersion): string;
|
|
57
57
|
static snapshot(ov: ObjectVersion, fk?: FieldKey): string;
|
|
58
58
|
static conflicts(conflicts: ObjectVersion[]): string;
|
|
@@ -76,7 +76,7 @@ export class Changeset {
|
|
|
76
76
|
const revision = fk === Meta.Handle ? 1 : ov.revision + 1;
|
|
77
77
|
const data = Object.assign({}, fk === Meta.Handle ? value : ov.data);
|
|
78
78
|
Meta.set(data, Meta.Handle, h);
|
|
79
|
-
Meta.set(data, Meta.Revision, new FieldVersion(revision));
|
|
79
|
+
Meta.set(data, Meta.Revision, new FieldVersion(revision, this.id));
|
|
80
80
|
ov = new ObjectVersion(this, ov, data);
|
|
81
81
|
this.items.set(h, ov);
|
|
82
82
|
h.editing = ov;
|
|
@@ -95,11 +95,12 @@ export class Changeset {
|
|
|
95
95
|
if (existing === undefined || existing.content !== content || sensitivity) {
|
|
96
96
|
const existingContent = existing === null || existing === void 0 ? void 0 : existing.content;
|
|
97
97
|
if (ov.former.objectVersion.data[fk] === existing) {
|
|
98
|
-
existing = ov.data[fk] = new FieldVersion(content);
|
|
98
|
+
existing = ov.data[fk] = new FieldVersion(content, this.id);
|
|
99
99
|
Changeset.markEdited(existingContent, content, true, ov, fk, h);
|
|
100
100
|
}
|
|
101
101
|
else {
|
|
102
102
|
existing.content = content;
|
|
103
|
+
existing.lastEditorChangesetId = this.id;
|
|
103
104
|
Changeset.markEdited(existingContent, content, true, ov, fk, h);
|
|
104
105
|
}
|
|
105
106
|
}
|
|
@@ -136,7 +137,8 @@ export class Changeset {
|
|
|
136
137
|
return ov.changeset !== this && !this.sealed;
|
|
137
138
|
}
|
|
138
139
|
acquire(outer) {
|
|
139
|
-
|
|
140
|
+
const result = !this.sealed && this.revision === UNDEFINED_REVISION;
|
|
141
|
+
if (result) {
|
|
140
142
|
const ahead = this.options.token === undefined || outer.revision === UNDEFINED_REVISION;
|
|
141
143
|
this.revision = ahead ? Changeset.stampGen : outer.revision;
|
|
142
144
|
Changeset.pending.push(this);
|
|
@@ -145,6 +147,7 @@ export class Changeset {
|
|
|
145
147
|
if (Log.isOn && Log.opt.transaction)
|
|
146
148
|
Log.write("╔══", `s${this.revision}`, `${this.hint}`);
|
|
147
149
|
}
|
|
150
|
+
return result;
|
|
148
151
|
}
|
|
149
152
|
bumpBy(timestamp) {
|
|
150
153
|
if (timestamp > this.bumper)
|
|
@@ -313,7 +316,7 @@ Changeset.propagateAllChangesThroughSubscriptions = (changeset) => { };
|
|
|
313
316
|
Changeset.revokeAllSubscriptions = (changeset) => { };
|
|
314
317
|
Changeset.enqueueReactiveFunctionsToRun = (reactive) => { };
|
|
315
318
|
export class Dump {
|
|
316
|
-
static obj(h, fk, stamp,
|
|
319
|
+
static obj(h, fk, stamp, changesetId, lastEditorChangesetId, value) {
|
|
317
320
|
const member = fk !== undefined ? `.${fk.toString()}` : "";
|
|
318
321
|
let result;
|
|
319
322
|
if (h !== undefined) {
|
|
@@ -321,7 +324,7 @@ export class Dump {
|
|
|
321
324
|
if (stamp === undefined)
|
|
322
325
|
result = `${h.hint}${member}${v} #${h.id}`;
|
|
323
326
|
else
|
|
324
|
-
result = `${h.hint}${member}${v} #${h.id}t${
|
|
327
|
+
result = `${h.hint}${member}${v} #${h.id}t${changesetId}s${stamp}${lastEditorChangesetId !== undefined ? `e${lastEditorChangesetId}` : ""}`;
|
|
325
328
|
}
|
|
326
329
|
else
|
|
327
330
|
result = `boot${member}`;
|
|
@@ -329,12 +332,12 @@ export class Dump {
|
|
|
329
332
|
}
|
|
330
333
|
static snapshot2(h, s, fk, o) {
|
|
331
334
|
var _a;
|
|
332
|
-
return Dump.obj(h, fk, s.timestamp, s.id, o === null || o === void 0 ? void 0 : o.
|
|
335
|
+
return Dump.obj(h, fk, s.timestamp, s.id, o === null || o === void 0 ? void 0 : o.lastEditorChangesetId, (_a = o === null || o === void 0 ? void 0 : o.content) !== null && _a !== void 0 ? _a : Meta.Undefined);
|
|
333
336
|
}
|
|
334
337
|
static snapshot(ov, fk) {
|
|
335
338
|
const h = Meta.get(ov.data, Meta.Handle);
|
|
336
339
|
const fv = fk !== undefined ? ov.data[fk] : undefined;
|
|
337
|
-
return Dump.obj(h, fk, ov.changeset.timestamp, ov.changeset.id, fv === null || fv === void 0 ? void 0 : fv.
|
|
340
|
+
return Dump.obj(h, fk, ov.changeset.timestamp, ov.changeset.id, fv === null || fv === void 0 ? void 0 : fv.lastEditorChangesetId);
|
|
338
341
|
}
|
|
339
342
|
static conflicts(conflicts) {
|
|
340
343
|
return conflicts.map(ours => {
|
|
@@ -8,9 +8,9 @@ export type AbstractChangeset = {
|
|
|
8
8
|
export declare class FieldVersion<T = any> {
|
|
9
9
|
content: T;
|
|
10
10
|
observers?: Set<Observer>;
|
|
11
|
+
lastEditorChangesetId: number;
|
|
11
12
|
get isLaunch(): boolean;
|
|
12
|
-
|
|
13
|
-
constructor(content: T);
|
|
13
|
+
constructor(content: T, lastEditorChangesetId: number);
|
|
14
14
|
}
|
|
15
15
|
export type Observer = {
|
|
16
16
|
readonly order: number;
|
|
@@ -3,8 +3,7 @@ import { Meta } from "./Meta.js";
|
|
|
3
3
|
export { Meta } from "./Meta.js";
|
|
4
4
|
export class FieldVersion {
|
|
5
5
|
get isLaunch() { return false; }
|
|
6
|
-
|
|
7
|
-
constructor(content) { this.content = content; }
|
|
6
|
+
constructor(content, lastEditorChangesetId) { this.content = content; this.lastEditorChangesetId = lastEditorChangesetId; }
|
|
8
7
|
}
|
|
9
8
|
export class ObjectVersion {
|
|
10
9
|
constructor(changeset, former, data) {
|
|
@@ -16,9 +16,9 @@ export declare class IndicatorImpl extends Indicator {
|
|
|
16
16
|
busyDuration: number;
|
|
17
17
|
readonly internals: {
|
|
18
18
|
whenBusy: Promise<void> | undefined;
|
|
19
|
-
resolveWhenBusy: ((value?: void
|
|
19
|
+
resolveWhenBusy: ((value?: void) => void) | undefined;
|
|
20
20
|
whenIdle: Promise<void> | undefined;
|
|
21
|
-
resolveWhenIdle: ((value?: void
|
|
21
|
+
resolveWhenIdle: ((value?: void) => void) | undefined;
|
|
22
22
|
started: number;
|
|
23
23
|
activationDelay: number;
|
|
24
24
|
activationTimeout: undefined;
|
|
@@ -100,7 +100,7 @@ export class JournalImpl extends Journal {
|
|
|
100
100
|
const content = undoing ? vp.formerContent : vp.freshContent;
|
|
101
101
|
const ov = ctx.getEditableObjectVersion(h, fk, content);
|
|
102
102
|
if (ov.changeset === ctx) {
|
|
103
|
-
ov.data[fk] = new FieldVersion(content);
|
|
103
|
+
ov.data[fk] = new FieldVersion(content, ctx.id);
|
|
104
104
|
const existing = ov.former.objectVersion.data[fk];
|
|
105
105
|
Changeset.markEdited(existing, content, existing !== content, ov, fk, h);
|
|
106
106
|
}
|
|
@@ -122,7 +122,7 @@ export class Mvcc {
|
|
|
122
122
|
}
|
|
123
123
|
static decorateData(isObservable, proto, fk) {
|
|
124
124
|
if (isObservable) {
|
|
125
|
-
Meta.acquire(proto, Meta.Initial)[fk] = new FieldVersion(undefined);
|
|
125
|
+
Meta.acquire(proto, Meta.Initial)[fk] = new FieldVersion(undefined, 0);
|
|
126
126
|
const get = function () {
|
|
127
127
|
const h = Mvcc.acquireHandle(this);
|
|
128
128
|
return Mvcc.observable.get(h, fk, this);
|
|
@@ -181,7 +181,7 @@ export class Mvcc {
|
|
|
181
181
|
h = new ObjectHandle(obj, obj, Mvcc.observable, ov, obj.constructor.name);
|
|
182
182
|
Meta.set(ov.data, Meta.Handle, h);
|
|
183
183
|
Meta.set(obj, Meta.Handle, h);
|
|
184
|
-
Meta.set(ov.data, Meta.Revision, new FieldVersion(1));
|
|
184
|
+
Meta.set(ov.data, Meta.Revision, new FieldVersion(1, 0));
|
|
185
185
|
}
|
|
186
186
|
return h;
|
|
187
187
|
}
|
|
@@ -36,6 +36,7 @@ export declare class MvccArray<T> extends MvccObject {
|
|
|
36
36
|
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T;
|
|
37
37
|
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
|
|
38
38
|
reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
|
|
39
|
+
find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T | undefined;
|
|
39
40
|
find<S extends T>(predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined;
|
|
40
41
|
findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
|
|
41
42
|
fill(value: T, start?: number, end?: number): this;
|
|
@@ -47,12 +47,12 @@ export class MvccArray extends MvccObject {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
export class TransactionalArray extends MvccArray {
|
|
50
|
-
constructor(args) {
|
|
51
|
-
super(false,
|
|
50
|
+
constructor(...args) {
|
|
51
|
+
super(false, new Array(...args));
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
export class ObservableArray extends MvccArray {
|
|
55
|
-
constructor(args) {
|
|
56
|
-
super(true,
|
|
55
|
+
constructor(...args) {
|
|
56
|
+
super(true, new Array(...args));
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -51,7 +51,6 @@ declare class Launch extends FieldVersion implements Observer {
|
|
|
51
51
|
successor: Launch | undefined;
|
|
52
52
|
constructor(transaction: Transaction, operation: OperationImpl, changeset: AbstractChangeset, former: Launch | OptionsImpl, clone: boolean);
|
|
53
53
|
get isLaunch(): boolean;
|
|
54
|
-
get originSnapshotId(): number;
|
|
55
54
|
hint(): string;
|
|
56
55
|
get order(): number;
|
|
57
56
|
get ["#this#"](): string;
|
|
@@ -80,7 +79,7 @@ declare class Launch extends FieldVersion implements Observer {
|
|
|
80
79
|
private static revokeAllSubscriptions;
|
|
81
80
|
private static propagateFieldChangeThroughSubscriptions;
|
|
82
81
|
private static enqueueReactiveFunctionsToRun;
|
|
83
|
-
private static
|
|
82
|
+
private static migrateFieldVersion;
|
|
84
83
|
private static processQueuedReactiveOperations;
|
|
85
84
|
private unsubscribeFromAllObservables;
|
|
86
85
|
private subscribeTo;
|
|
@@ -194,7 +194,7 @@ export class OperationImpl {
|
|
|
194
194
|
}
|
|
195
195
|
class Launch extends FieldVersion {
|
|
196
196
|
constructor(transaction, operation, changeset, former, clone) {
|
|
197
|
-
super(undefined);
|
|
197
|
+
super(undefined, 0);
|
|
198
198
|
this.margin = Launch.current ? Launch.current.margin + 1 : 1;
|
|
199
199
|
this.transaction = transaction;
|
|
200
200
|
this.operation = operation;
|
|
@@ -205,6 +205,7 @@ class Launch extends FieldVersion {
|
|
|
205
205
|
this.cause = former.obsoleteDueTo;
|
|
206
206
|
this.args = former.args;
|
|
207
207
|
if (clone) {
|
|
208
|
+
this.lastEditorChangesetId = former.lastEditorChangesetId;
|
|
208
209
|
this.result = former.result;
|
|
209
210
|
this.error = former.error;
|
|
210
211
|
this.started = former.started;
|
|
@@ -213,6 +214,7 @@ class Launch extends FieldVersion {
|
|
|
213
214
|
this.successor = former.successor;
|
|
214
215
|
}
|
|
215
216
|
else {
|
|
217
|
+
this.lastEditorChangesetId = changeset.id;
|
|
216
218
|
this.result = undefined;
|
|
217
219
|
this.error = undefined;
|
|
218
220
|
this.started = 0;
|
|
@@ -222,6 +224,7 @@ class Launch extends FieldVersion {
|
|
|
222
224
|
}
|
|
223
225
|
}
|
|
224
226
|
else {
|
|
227
|
+
this.lastEditorChangesetId = changeset.id;
|
|
225
228
|
this.options = former;
|
|
226
229
|
this.cause = undefined;
|
|
227
230
|
this.args = BOOT_ARGS;
|
|
@@ -234,8 +237,7 @@ class Launch extends FieldVersion {
|
|
|
234
237
|
}
|
|
235
238
|
}
|
|
236
239
|
get isLaunch() { return true; }
|
|
237
|
-
|
|
238
|
-
hint() { return `${Dump.snapshot2(this.operation.ownerHandle, this.changeset, this.operation.fieldKey)}`; }
|
|
240
|
+
hint() { return `${Dump.snapshot2(this.operation.ownerHandle, this.changeset, this.operation.fieldKey, this)}`; }
|
|
239
241
|
get order() { return this.options.order; }
|
|
240
242
|
get ["#this#"]() {
|
|
241
243
|
return `Operation: ${this.why()}`;
|
|
@@ -287,7 +289,7 @@ class Launch extends FieldVersion {
|
|
|
287
289
|
var _a, _b, _c;
|
|
288
290
|
if (this.observables !== undefined) {
|
|
289
291
|
const skip = !observable.isLaunch &&
|
|
290
|
-
changeset === this.
|
|
292
|
+
changeset.id === this.lastEditorChangesetId;
|
|
291
293
|
if (!skip) {
|
|
292
294
|
const why = `${Dump.snapshot2(h, changeset, fk, observable)} ◀◀ ${outer}`;
|
|
293
295
|
const isReactive = this.options.kind === Kind.reactive;
|
|
@@ -309,7 +311,7 @@ class Launch extends FieldVersion {
|
|
|
309
311
|
tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Dump.snapshot2(h, changeset, fk)} changed by T${changeset.id}[${changeset.hint}]`), null);
|
|
310
312
|
}
|
|
311
313
|
else if (Log.isOn && (Log.opt.obsolete || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.obsolete)))
|
|
312
|
-
Log.write(" ", "x", `${this.hint()} is not obsolete due to its own change to ${Dump.snapshot2(h, changeset, fk)}`);
|
|
314
|
+
Log.write(" ", "x", `${this.hint()} is not obsolete due to its own change to ${Dump.snapshot2(h, changeset, fk, observable)}`);
|
|
313
315
|
}
|
|
314
316
|
}
|
|
315
317
|
relaunchIfNotUpToDate(now, nothrow) {
|
|
@@ -557,12 +559,12 @@ class Launch extends FieldVersion {
|
|
|
557
559
|
if (isReactiveLoopRequired)
|
|
558
560
|
OperationImpl.proceedWithinGivenLaunch(undefined, Launch.processQueuedReactiveOperations);
|
|
559
561
|
}
|
|
560
|
-
static
|
|
562
|
+
static migrateFieldVersion(fv, target) {
|
|
561
563
|
let result;
|
|
562
564
|
if (fv instanceof Launch)
|
|
563
565
|
result = new Launch(target, fv.operation, target.changeset, fv, true);
|
|
564
566
|
else
|
|
565
|
-
result = new FieldVersion(fv
|
|
567
|
+
result = new FieldVersion(fv.content, fv.lastEditorChangesetId);
|
|
566
568
|
return result;
|
|
567
569
|
}
|
|
568
570
|
static processQueuedReactiveOperations() {
|
|
@@ -602,14 +604,14 @@ class Launch extends FieldVersion {
|
|
|
602
604
|
observable.observers.add(this);
|
|
603
605
|
this.observables.set(observable, subscription);
|
|
604
606
|
if (Log.isOn && (Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
|
|
605
|
-
Log.write("║", " ∞", `${this.hint()} is subscribed to ${Dump.snapshot2(h, ov.changeset, fk)}${subscription.usageCount > 1 ? ` (${subscription.usageCount} times)` : ""}`);
|
|
607
|
+
Log.write("║", " ∞", `${this.hint()} is subscribed to ${Dump.snapshot2(h, ov.changeset, fk, observable)}${subscription.usageCount > 1 ? ` (${subscription.usageCount} times)` : ""}`);
|
|
606
608
|
}
|
|
607
609
|
else if (Log.isOn && (Log.opt.read || ((_b = this.options.logging) === null || _b === void 0 ? void 0 : _b.read)))
|
|
608
|
-
Log.write("║", " x", `${this.hint()} is obsolete and is NOT subscribed to ${Dump.snapshot2(h, ov.changeset, fk)}`);
|
|
610
|
+
Log.write("║", " x", `${this.hint()} is obsolete and is NOT subscribed to ${Dump.snapshot2(h, ov.changeset, fk, observable)}`);
|
|
609
611
|
}
|
|
610
612
|
else {
|
|
611
613
|
if (Log.isOn && (Log.opt.read || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.read)))
|
|
612
|
-
Log.write("║", " x", `${this.hint()} is NOT subscribed to already obsolete ${Dump.snapshot2(h, ov.changeset, fk)}`);
|
|
614
|
+
Log.write("║", " x", `${this.hint()} is NOT subscribed to already obsolete ${Dump.snapshot2(h, ov.changeset, fk, observable)}`);
|
|
613
615
|
}
|
|
614
616
|
return ok;
|
|
615
617
|
}
|
|
@@ -655,7 +657,7 @@ class Launch extends FieldVersion {
|
|
|
655
657
|
Changeset.propagateAllChangesThroughSubscriptions = Launch.propagateAllChangesThroughSubscriptions;
|
|
656
658
|
Changeset.revokeAllSubscriptions = Launch.revokeAllSubscriptions;
|
|
657
659
|
Changeset.enqueueReactiveFunctionsToRun = Launch.enqueueReactiveFunctionsToRun;
|
|
658
|
-
TransactionImpl.
|
|
660
|
+
TransactionImpl.migrateFieldVersion = Launch.migrateFieldVersion;
|
|
659
661
|
Mvcc.createOperation = Launch.createOperation;
|
|
660
662
|
Mvcc.rememberOperationOptions = Launch.rememberOperationOptions;
|
|
661
663
|
Promise.prototype.then = reactronicHookedThen;
|
|
@@ -693,7 +695,7 @@ function valueHint(value) {
|
|
|
693
695
|
else if (value instanceof Map)
|
|
694
696
|
result = `Map(${value.size})`;
|
|
695
697
|
else if (value instanceof Launch)
|
|
696
|
-
result = `#${value.operation.ownerHandle.id}t${value.changeset.id}s${value.changeset.timestamp}${value.
|
|
698
|
+
result = `#${value.operation.ownerHandle.id}t${value.changeset.id}s${value.changeset.timestamp}${value.lastEditorChangesetId !== undefined && value.lastEditorChangesetId !== 0 ? `t${value.lastEditorChangesetId}` : ""}`;
|
|
697
699
|
else if (value === Meta.Undefined)
|
|
698
700
|
result = "undefined";
|
|
699
701
|
else if (typeof (value) === "string")
|
|
@@ -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,
|
|
@@ -61,6 +61,7 @@ export type RxNodeDecl<E = unknown> = {
|
|
|
61
61
|
key?: string;
|
|
62
62
|
mode?: Mode;
|
|
63
63
|
creation?: Script<E>;
|
|
64
|
+
creationAsync?: ScriptAsync<E>;
|
|
64
65
|
destruction?: Script<E>;
|
|
65
66
|
triggers?: unknown;
|
|
66
67
|
basis?: RxNodeDecl<E>;
|
|
@@ -83,10 +84,10 @@ export type RxNodeContext<T extends Object = Object> = {
|
|
|
83
84
|
export declare abstract class BaseDriver<E = unknown> implements RxNodeDriver<E> {
|
|
84
85
|
readonly name: string;
|
|
85
86
|
readonly isPartition: boolean;
|
|
86
|
-
readonly initialize?: Handler<E
|
|
87
|
-
constructor(name: string, isPartition: boolean, initialize?: Handler<E
|
|
87
|
+
readonly initialize?: Handler<E> | undefined;
|
|
88
|
+
constructor(name: string, isPartition: boolean, initialize?: Handler<E> | undefined);
|
|
88
89
|
abstract allocate(node: RxNode<E>): E;
|
|
89
|
-
create(node: RxNode<E>): void
|
|
90
|
+
create(node: RxNode<E>): void | Promise<void>;
|
|
90
91
|
destroy(node: RxNode<E>, isLeader: boolean): boolean;
|
|
91
92
|
mount(node: RxNode<E>): void;
|
|
92
93
|
update(node: RxNode<E>): void | Promise<void>;
|
|
@@ -16,8 +16,9 @@ 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 { emitLetters, getCallerInfo, proceedSyncOrAsync } from "../util/Utils.js";
|
|
21
22
|
import { Isolation, Reentrance } from "../Options.js";
|
|
22
23
|
import { ObservableObject } from "../core/Mvcc.js";
|
|
23
24
|
import { Transaction } from "../core/Transaction.js";
|
|
@@ -105,7 +106,7 @@ export class RxNode {
|
|
|
105
106
|
triggerDeactivation(impl.seat, true, true);
|
|
106
107
|
}
|
|
107
108
|
static updateNestedNodesThenDo(action) {
|
|
108
|
-
runUpdateNestedNodesThenDo(undefined, action);
|
|
109
|
+
runUpdateNestedNodesThenDo(RxNodeImpl.ownSeat, undefined, action);
|
|
109
110
|
}
|
|
110
111
|
static markAsMounted(node, yes) {
|
|
111
112
|
const n = node;
|
|
@@ -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;
|
|
@@ -344,49 +365,50 @@ __decorate([
|
|
|
344
365
|
function getNodeKey(node) {
|
|
345
366
|
return node.stamp >= 0 ? node.key : undefined;
|
|
346
367
|
}
|
|
347
|
-
function runUpdateNestedNodesThenDo(error, action) {
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
368
|
+
function runUpdateNestedNodesThenDo(ownSeat, error, action) {
|
|
369
|
+
runInside(ownSeat, () => {
|
|
370
|
+
var _a;
|
|
371
|
+
const owner = ownSeat.instance;
|
|
372
|
+
const children = owner.children;
|
|
373
|
+
if (children.isMergeInProgress) {
|
|
374
|
+
let promised = undefined;
|
|
375
|
+
try {
|
|
376
|
+
children.endMerge(error);
|
|
377
|
+
for (const child of children.removedItems(true))
|
|
378
|
+
triggerDeactivation(child, true, true);
|
|
379
|
+
if (!error) {
|
|
380
|
+
const sequential = children.isStrict;
|
|
381
|
+
let p1 = undefined;
|
|
382
|
+
let p2 = undefined;
|
|
383
|
+
let mounting = false;
|
|
384
|
+
let partition = owner;
|
|
385
|
+
for (const child of children.items()) {
|
|
386
|
+
if (Transaction.isCanceled)
|
|
387
|
+
break;
|
|
388
|
+
const childNode = child.instance;
|
|
389
|
+
const isPart = childNode.driver.isPartition;
|
|
390
|
+
const host = isPart ? owner : partition;
|
|
391
|
+
mounting = markToMountIfNecessary(mounting, host, child, children, sequential);
|
|
392
|
+
const p = (_a = childNode.priority) !== null && _a !== void 0 ? _a : Priority.realtime;
|
|
393
|
+
if (p === Priority.realtime)
|
|
394
|
+
triggerUpdateViaSeat(child);
|
|
395
|
+
else if (p === Priority.normal)
|
|
396
|
+
p1 = push(child, p1);
|
|
397
|
+
else
|
|
398
|
+
p2 = push(child, p2);
|
|
399
|
+
if (isPart)
|
|
400
|
+
partition = childNode;
|
|
401
|
+
}
|
|
402
|
+
if (!Transaction.isCanceled && (p1 !== undefined || p2 !== undefined))
|
|
403
|
+
promised = startIncrementalUpdate(ownSeat, children, p1, p2).then(() => action(error), e => action(e));
|
|
380
404
|
}
|
|
381
|
-
|
|
382
|
-
|
|
405
|
+
}
|
|
406
|
+
finally {
|
|
407
|
+
if (!promised)
|
|
408
|
+
action(error);
|
|
383
409
|
}
|
|
384
410
|
}
|
|
385
|
-
|
|
386
|
-
if (!promised)
|
|
387
|
-
action(error);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
411
|
+
});
|
|
390
412
|
}
|
|
391
413
|
function markToMountIfNecessary(mounting, host, seat, children, sequential) {
|
|
392
414
|
const node = seat.instance;
|
|
@@ -489,13 +511,10 @@ function updateNow(seat) {
|
|
|
489
511
|
node.children.beginMerge();
|
|
490
512
|
const driver = node.driver;
|
|
491
513
|
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);
|
|
514
|
+
result = proceedSyncOrAsync(result, v => { runUpdateNestedNodesThenDo(seat, undefined, NOP); return v; }, e => { console.log(e); runUpdateNestedNodesThenDo(seat, e !== null && e !== void 0 ? e : new Error("unknown error"), NOP); });
|
|
496
515
|
}
|
|
497
516
|
catch (e) {
|
|
498
|
-
runUpdateNestedNodesThenDo(e, NOP);
|
|
517
|
+
runUpdateNestedNodesThenDo(seat, e, NOP);
|
|
499
518
|
console.log(`Update failed: ${node.key}`);
|
|
500
519
|
console.log(`${e}`);
|
|
501
520
|
}
|
|
@@ -613,6 +632,7 @@ function defaultReject(error) {
|
|
|
613
632
|
}
|
|
614
633
|
Promise.prototype.then = reactronicDomHookedThen;
|
|
615
634
|
const NOP = (...args) => { };
|
|
635
|
+
const NOP_ASYNC = (...args) => __awaiter(void 0, void 0, void 0, function* () { });
|
|
616
636
|
let gOwnSeat = undefined;
|
|
617
637
|
let gFirstToDispose = undefined;
|
|
618
638
|
let gLastToDispose = undefined;
|
|
@@ -62,7 +62,7 @@ export declare class TransactionImpl extends Transaction {
|
|
|
62
62
|
cancel(error: Error, restartAfter?: Worker | null): this;
|
|
63
63
|
get isCanceled(): boolean;
|
|
64
64
|
get isFinished(): boolean;
|
|
65
|
-
whenFinished(): Promise<void>;
|
|
65
|
+
whenFinished(includingParent?: boolean): Promise<void>;
|
|
66
66
|
static run<T>(options: SnapshotOptions | null, func: F<T>, ...args: any[]): T;
|
|
67
67
|
static isolate<T>(func: F<T>, ...args: any[]): T;
|
|
68
68
|
static outside<T>(func: F<T>, ...args: any[]): T;
|
|
@@ -84,6 +84,6 @@ export declare class TransactionImpl extends Transaction {
|
|
|
84
84
|
private acquirePromise;
|
|
85
85
|
private static getCurrentChangeset;
|
|
86
86
|
private static getEditableChangeset;
|
|
87
|
-
static
|
|
87
|
+
static migrateFieldVersion: (fv: FieldVersion, target: Transaction) => FieldVersion;
|
|
88
88
|
static _init(): void;
|
|
89
89
|
}
|
|
@@ -108,9 +108,11 @@ export class TransactionImpl extends Transaction {
|
|
|
108
108
|
get isFinished() {
|
|
109
109
|
return this.sealed && this.pending === 0;
|
|
110
110
|
}
|
|
111
|
-
whenFinished() {
|
|
111
|
+
whenFinished(includingParent) {
|
|
112
112
|
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
-
if (
|
|
113
|
+
if (includingParent && this.parent)
|
|
114
|
+
yield this.parent.whenFinished(includingParent);
|
|
115
|
+
else if (!this.isFinished)
|
|
114
116
|
yield this.acquirePromise();
|
|
115
117
|
});
|
|
116
118
|
}
|
|
@@ -209,6 +211,7 @@ export class TransactionImpl extends Transaction {
|
|
|
209
211
|
runImpl(logging, func, ...args) {
|
|
210
212
|
let result;
|
|
211
213
|
const outer = TransactionImpl.curr;
|
|
214
|
+
const p = this.parent;
|
|
212
215
|
try {
|
|
213
216
|
if (outer === TransactionImpl.none) {
|
|
214
217
|
TransactionImpl.frameStartTime = performance.now();
|
|
@@ -216,7 +219,9 @@ export class TransactionImpl extends Transaction {
|
|
|
216
219
|
}
|
|
217
220
|
TransactionImpl.curr = this;
|
|
218
221
|
this.pending++;
|
|
219
|
-
this.changeset.acquire(outer.changeset);
|
|
222
|
+
const acquired = this.changeset.acquire(outer.changeset);
|
|
223
|
+
if (acquired && p)
|
|
224
|
+
p.run(() => p.pending++);
|
|
220
225
|
result = func(...args);
|
|
221
226
|
if (this.sealed && this.pending === 1) {
|
|
222
227
|
if (!this.canceled)
|
|
@@ -234,6 +239,8 @@ export class TransactionImpl extends Transaction {
|
|
|
234
239
|
this.pending--;
|
|
235
240
|
if (this.sealed && this.pending === 0) {
|
|
236
241
|
const reactive = this.applyOrDiscard();
|
|
242
|
+
if (p)
|
|
243
|
+
p.runImpl(undefined, () => p.pending--);
|
|
237
244
|
TransactionImpl.curr = outer;
|
|
238
245
|
TransactionImpl.outside(Changeset.enqueueReactiveFunctionsToRun, reactive);
|
|
239
246
|
}
|
|
@@ -312,9 +319,17 @@ export class TransactionImpl extends Transaction {
|
|
|
312
319
|
if (Log.opt.transaction)
|
|
313
320
|
Log.write(changeset.timestamp < UNDEFINED_REVISION ? "╚══" : "═══", `s${this.timestamp}`, `${this.hint} - ${error ? "CANCEL" : "APPLY"}(${this.changeset.items.size})${error ? ` - ${error}` : ""}`);
|
|
314
321
|
}
|
|
315
|
-
|
|
322
|
+
let obsolete = changeset.obsolete;
|
|
323
|
+
if (changeset.parent) {
|
|
324
|
+
if (changeset.obsolete.length > 0) {
|
|
325
|
+
for (const o of changeset.obsolete)
|
|
326
|
+
changeset.parent.obsolete.push(o);
|
|
327
|
+
obsolete = [];
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else if (!error)
|
|
316
331
|
Changeset.propagateAllChangesThroughSubscriptions(changeset);
|
|
317
|
-
return
|
|
332
|
+
return obsolete;
|
|
318
333
|
}
|
|
319
334
|
applyObjectChanges(h, ov) {
|
|
320
335
|
const parent = this.parent;
|
|
@@ -342,7 +357,7 @@ export class TransactionImpl extends Transaction {
|
|
|
342
357
|
const fv = ov.data[fk];
|
|
343
358
|
const fvParent = ovParent.data[fk];
|
|
344
359
|
if (fv.isLaunch) {
|
|
345
|
-
const migrated = TransactionImpl.
|
|
360
|
+
const migrated = TransactionImpl.migrateFieldVersion(fv, tParent);
|
|
346
361
|
if (ovParent.former.objectVersion.data[fk] !== fvParent) {
|
|
347
362
|
let observers = fvParent.observers;
|
|
348
363
|
if (observers) {
|
|
@@ -462,7 +477,7 @@ TransactionImpl.curr = TransactionImpl.none;
|
|
|
462
477
|
TransactionImpl.inspection = false;
|
|
463
478
|
TransactionImpl.frameStartTime = 0;
|
|
464
479
|
TransactionImpl.frameOverCounter = 0;
|
|
465
|
-
TransactionImpl.
|
|
480
|
+
TransactionImpl.migrateFieldVersion = function (fv, target) {
|
|
466
481
|
throw misuse("this implementation of cloneLaunch should never be called");
|
|
467
482
|
};
|
|
468
483
|
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.303",
|
|
4
4
|
"description": "Reactronic - Transactional Reactive State Management",
|
|
5
5
|
"publisher": "Nezaboodka Software",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"eslint": "8.57.0",
|
|
41
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",
|