reactronic 0.21.520 → 0.21.524
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 +15 -1
- package/build/dist/source/Options.d.ts +3 -1
- package/build/dist/source/Reactronic.d.ts +1 -1
- package/build/dist/source/Reactronic.js +1 -1
- package/build/dist/source/Trace.d.ts +1 -1
- package/build/dist/source/Trace.js +1 -1
- package/build/dist/source/api.d.ts +1 -1
- package/build/dist/source/api.js +2 -2
- package/build/dist/source/impl/Data.d.ts +2 -0
- package/build/dist/source/impl/Data.js +1 -0
- package/build/dist/source/impl/Hooks.d.ts +4 -3
- package/build/dist/source/impl/Hooks.js +10 -9
- package/build/dist/source/impl/Monitor.js +2 -2
- package/build/dist/source/impl/Operation.d.ts +3 -1
- package/build/dist/source/impl/Operation.js +49 -35
- package/build/dist/source/impl/Snapshot.d.ts +2 -2
- package/build/dist/source/impl/Snapshot.js +14 -11
- package/build/dist/source/impl/Transaction.d.ts +3 -0
- package/build/dist/source/impl/Transaction.js +29 -5
- package/build/dist/source/impl/TransactionJournal.js +6 -6
- package/build/dist/source/util/Utils.d.ts +1 -1
- package/build/dist/source/util/Utils.js +3 -3
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -300,6 +300,7 @@ function unobservable(proto, prop) // field only
|
|
|
300
300
|
function transaction(proto, prop, pd) // method only
|
|
301
301
|
function reaction(proto, prop, pd) // method only
|
|
302
302
|
function cached(proto, prop, pd) // method only
|
|
303
|
+
function options(value: Partial<MemberOptions>): F<any>
|
|
303
304
|
|
|
304
305
|
function noSideEffects(value: boolean) // transaction & cached & reaction
|
|
305
306
|
function sensitiveArgs(value: boolean) // cached & reaction
|
|
@@ -324,6 +325,19 @@ interface Options {
|
|
|
324
325
|
readonly trace?: Partial<TraceOptions>
|
|
325
326
|
}
|
|
326
327
|
|
|
328
|
+
export interface MemberOptions {
|
|
329
|
+
readonly kind: Kind
|
|
330
|
+
readonly standalone: StandaloneMode
|
|
331
|
+
readonly order: number
|
|
332
|
+
readonly noSideEffects: boolean
|
|
333
|
+
readonly sensitiveArgs: boolean
|
|
334
|
+
readonly throttling: number // milliseconds, -1 is immediately, Number.MAX_SAFE_INTEGER is never
|
|
335
|
+
readonly reentrance: Reentrance
|
|
336
|
+
readonly journal: TransactionJournal | undefined
|
|
337
|
+
readonly monitor: Monitor | null
|
|
338
|
+
readonly trace?: Partial<TraceOptions>
|
|
339
|
+
}
|
|
340
|
+
|
|
327
341
|
enum Kind {
|
|
328
342
|
Plain = 0,
|
|
329
343
|
Transaction = 1,
|
|
@@ -430,7 +444,7 @@ abstract class Controller<T> {
|
|
|
430
444
|
class Reactronic {
|
|
431
445
|
static why(short: boolean = false): string
|
|
432
446
|
static getMethodCache<T>(method: F<T>): Cache<T>
|
|
433
|
-
static
|
|
447
|
+
static configureCurrentOperation(options: Partial<Options>): Options
|
|
434
448
|
// static configureObject<T extends object>(obj: T, options: Partial<ObjectOptions>): void
|
|
435
449
|
// static assign<T, P extends keyof T>(obj: T, prop: P, value: T[P], sensitivity: Sensitivity)
|
|
436
450
|
static takeSnapshot<T>(obj: T): T
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { TraceOptions } from './Trace';
|
|
2
|
+
import { StandaloneMode } from './impl/Data';
|
|
2
3
|
export { TraceOptions, ProfilingOptions, TraceLevel } from './Trace';
|
|
3
4
|
import { TransactionJournal } from './impl/TransactionJournal';
|
|
4
5
|
import { Monitor } from './impl/Monitor';
|
|
5
6
|
export interface SnapshotOptions {
|
|
6
7
|
readonly hint?: string;
|
|
7
|
-
readonly standalone?:
|
|
8
|
+
readonly standalone?: StandaloneMode;
|
|
8
9
|
readonly journal?: TransactionJournal;
|
|
9
10
|
readonly trace?: Partial<TraceOptions>;
|
|
10
11
|
readonly token?: any;
|
|
11
12
|
}
|
|
12
13
|
export interface MemberOptions {
|
|
13
14
|
readonly kind: Kind;
|
|
15
|
+
readonly standalone: StandaloneMode;
|
|
14
16
|
readonly order: number;
|
|
15
17
|
readonly noSideEffects: boolean;
|
|
16
18
|
readonly sensitiveArgs: boolean;
|
|
@@ -5,7 +5,7 @@ export declare class Reactronic {
|
|
|
5
5
|
static why(brief?: boolean): string;
|
|
6
6
|
static getController<T>(method: F<T>): Controller<T>;
|
|
7
7
|
static pullLastResult<T>(method: F<Promise<T>>, args?: any[]): T | undefined;
|
|
8
|
-
static
|
|
8
|
+
static configureCurrentOperation(options: Partial<MemberOptions>): MemberOptions;
|
|
9
9
|
static takeSnapshot<T>(obj: T): T;
|
|
10
10
|
static dispose(obj: any): void;
|
|
11
11
|
static get reactionsAutoStartDisabled(): boolean;
|
|
@@ -12,7 +12,7 @@ class Reactronic {
|
|
|
12
12
|
static why(brief = false) { return brief ? Operation_1.OperationController.briefWhy() : Operation_1.OperationController.why(); }
|
|
13
13
|
static getController(method) { return Operation_1.OperationController.of(method); }
|
|
14
14
|
static pullLastResult(method, args) { return Reactronic.getController(method).pullLastResult(args); }
|
|
15
|
-
static
|
|
15
|
+
static configureCurrentOperation(options) { return Operation_1.OperationController.configureImpl(undefined, options); }
|
|
16
16
|
static takeSnapshot(obj) { return Snapshot_1.Snapshot.takeSnapshot(obj); }
|
|
17
17
|
static dispose(obj) { Snapshot_1.Snapshot.dispose(obj); }
|
|
18
18
|
static get reactionsAutoStartDisabled() { return Hooks_1.Hooks.reactionsAutoStartDisabled; }
|
|
@@ -23,7 +23,7 @@ export interface ProfilingOptions {
|
|
|
23
23
|
garbageCollectionSummaryInterval: number;
|
|
24
24
|
}
|
|
25
25
|
export declare const TraceLevel: {
|
|
26
|
-
|
|
26
|
+
ErrorsOnly: TraceOptions;
|
|
27
27
|
Transactions: TraceOptions;
|
|
28
28
|
Operations: TraceOptions;
|
|
29
29
|
Debug: TraceOptions;
|
package/build/dist/source/api.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.options = exports.cached = exports.reaction = exports.transaction = exports.unobservable = exports.sensitive = exports.standalone = exports.nonreactive = exports.Reactronic = exports.TransactionJournal = exports.Monitor = exports.Transaction = exports.Snapshot = exports.ObservableObject = exports.ToggleRef = exports.Ref = exports.Controller = exports.TraceLevel = exports.Reentrance = exports.Kind = exports.SealedSet = exports.SealedMap = exports.SealedArray = exports.
|
|
3
|
+
exports.options = exports.cached = exports.reaction = exports.transaction = exports.unobservable = exports.sensitive = exports.standalone = exports.nonreactive = exports.Reactronic = exports.TransactionJournal = exports.Monitor = exports.Transaction = exports.Snapshot = exports.ObservableObject = exports.ToggleRef = exports.Ref = exports.Controller = exports.TraceLevel = exports.Reentrance = exports.Kind = exports.SealedSet = exports.SealedMap = exports.SealedArray = exports.pause = exports.all = void 0;
|
|
4
4
|
var Utils_1 = require("./util/Utils");
|
|
5
5
|
Object.defineProperty(exports, "all", { enumerable: true, get: function () { return Utils_1.all; } });
|
|
6
|
-
Object.defineProperty(exports, "
|
|
6
|
+
Object.defineProperty(exports, "pause", { enumerable: true, get: function () { return Utils_1.pause; } });
|
|
7
7
|
var SealedArray_1 = require("./util/SealedArray");
|
|
8
8
|
Object.defineProperty(exports, "SealedArray", { enumerable: true, get: function () { return SealedArray_1.SealedArray; } });
|
|
9
9
|
var SealedMap_1 = require("./util/SealedMap");
|
|
@@ -9,8 +9,10 @@ export declare class Observable {
|
|
|
9
9
|
value: any;
|
|
10
10
|
observers?: Set<Observer>;
|
|
11
11
|
get isOperation(): boolean;
|
|
12
|
+
get selfSnapshotId(): number | undefined;
|
|
12
13
|
constructor(value: any);
|
|
13
14
|
}
|
|
15
|
+
export declare type StandaloneMode = boolean | 'isolated';
|
|
14
16
|
export interface Observer {
|
|
15
17
|
readonly order: number;
|
|
16
18
|
readonly observables: Map<Observable, MemberInfo> | undefined;
|
|
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "Meta", { enumerable: true, get: function () { re
|
|
|
8
8
|
class Observable {
|
|
9
9
|
constructor(value) { this.value = value; }
|
|
10
10
|
get isOperation() { return false; }
|
|
11
|
+
get selfSnapshotId() { return 0; }
|
|
11
12
|
}
|
|
12
13
|
exports.Observable = Observable;
|
|
13
14
|
class ObjectRevision {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { F } from '../util/Utils';
|
|
2
2
|
import { MemberOptions, Kind, Reentrance } from '../Options';
|
|
3
3
|
import { TraceOptions, ProfilingOptions } from '../Trace';
|
|
4
|
-
import { MemberName, ObjectHolder } from './Data';
|
|
4
|
+
import { MemberName, ObjectHolder, StandaloneMode } from './Data';
|
|
5
5
|
import { TransactionJournal } from './TransactionJournal';
|
|
6
6
|
import { Monitor } from './Monitor';
|
|
7
7
|
export declare abstract class ObservableObject {
|
|
@@ -12,6 +12,7 @@ export declare class OptionsImpl implements MemberOptions {
|
|
|
12
12
|
readonly getter: Function;
|
|
13
13
|
readonly setter: Function;
|
|
14
14
|
readonly kind: Kind;
|
|
15
|
+
readonly standalone: StandaloneMode;
|
|
15
16
|
readonly order: number;
|
|
16
17
|
readonly noSideEffects: boolean;
|
|
17
18
|
readonly sensitiveArgs: boolean;
|
|
@@ -37,10 +38,10 @@ export declare class Hooks implements ProxyHandler<ObjectHolder> {
|
|
|
37
38
|
getOwnPropertyDescriptor(h: ObjectHolder, m: MemberName): PropertyDescriptor | undefined;
|
|
38
39
|
ownKeys(h: ObjectHolder): Array<string | symbol>;
|
|
39
40
|
static decorateData(observable: boolean, proto: any, m: MemberName): any;
|
|
40
|
-
static decorateOperation(implicit: boolean, decorator: Function, options: Partial<MemberOptions>, proto: any, member: MemberName, pd: PropertyDescriptor): any;
|
|
41
|
+
static decorateOperation(implicit: boolean, decorator: Function, options: Partial<MemberOptions>, proto: any, member: MemberName, pd: PropertyDescriptor | undefined): any;
|
|
41
42
|
static decorateOperationParametrized(decorator: Function, options: Partial<MemberOptions>): F<any>;
|
|
42
43
|
static acquireObjectHolder(obj: any): ObjectHolder;
|
|
43
|
-
static createObjectHolder(unobservable: any, blank: any, hint: string): ObjectHolder;
|
|
44
|
+
static createObjectHolder(proto: any, unobservable: any, blank: any, hint: string): ObjectHolder;
|
|
44
45
|
static setProfilingMode(enabled: boolean, options?: Partial<ProfilingOptions>): void;
|
|
45
46
|
static sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
46
47
|
static setHint<T>(obj: T, hint: string | undefined): T;
|
|
@@ -10,12 +10,7 @@ class ObservableObject {
|
|
|
10
10
|
constructor() {
|
|
11
11
|
const proto = new.target.prototype;
|
|
12
12
|
const initial = Data_1.Meta.getFrom(proto, Data_1.Meta.Initial);
|
|
13
|
-
const h = Hooks.createObjectHolder(this, initial, new.target.name);
|
|
14
|
-
if (!Hooks.reactionsAutoStartDisabled) {
|
|
15
|
-
const reactions = Data_1.Meta.getFrom(proto, Data_1.Meta.Reactions);
|
|
16
|
-
for (const member in reactions)
|
|
17
|
-
h.proxy[member][Data_1.Meta.Controller].markObsolete();
|
|
18
|
-
}
|
|
13
|
+
const h = Hooks.createObjectHolder(proto, this, initial, new.target.name);
|
|
19
14
|
return h.proxy;
|
|
20
15
|
}
|
|
21
16
|
[Symbol.toStringTag]() {
|
|
@@ -26,6 +21,7 @@ class ObservableObject {
|
|
|
26
21
|
exports.ObservableObject = ObservableObject;
|
|
27
22
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
28
23
|
kind: Options_1.Kind.Plain,
|
|
24
|
+
standalone: false,
|
|
29
25
|
order: 0,
|
|
30
26
|
noSideEffects: false,
|
|
31
27
|
sensitiveArgs: false,
|
|
@@ -40,6 +36,7 @@ class OptionsImpl {
|
|
|
40
36
|
this.getter = getter !== undefined ? getter : existing.getter;
|
|
41
37
|
this.setter = setter !== undefined ? setter : existing.setter;
|
|
42
38
|
this.kind = merge(DEFAULT_OPTIONS.kind, existing.kind, patch.kind, implicit);
|
|
39
|
+
this.standalone = merge(DEFAULT_OPTIONS.standalone, existing.standalone, patch.standalone, implicit);
|
|
43
40
|
this.order = merge(DEFAULT_OPTIONS.order, existing.order, patch.order, implicit);
|
|
44
41
|
this.noSideEffects = merge(DEFAULT_OPTIONS.noSideEffects, existing.noSideEffects, patch.noSideEffects, implicit);
|
|
45
42
|
this.sensitiveArgs = merge(DEFAULT_OPTIONS.sensitiveArgs, existing.sensitiveArgs, patch.sensitiveArgs, implicit);
|
|
@@ -81,13 +78,14 @@ class Hooks {
|
|
|
81
78
|
let curr = r.data[m];
|
|
82
79
|
if (curr !== undefined || (r.prev.revision.snapshot === Snapshot_1.ROOT_REV.snapshot && (m in h.unobservable) === false)) {
|
|
83
80
|
if (curr === undefined || curr.value !== value || Hooks.sensitivity) {
|
|
81
|
+
const old = curr === null || curr === void 0 ? void 0 : curr.value;
|
|
84
82
|
if (r.prev.revision.data[m] === curr) {
|
|
85
83
|
curr = r.data[m] = new Data_1.Observable(value);
|
|
86
|
-
Snapshot_1.Snapshot.markEdited(value, true, r, m, h);
|
|
84
|
+
Snapshot_1.Snapshot.markEdited(old, value, true, r, m, h);
|
|
87
85
|
}
|
|
88
86
|
else {
|
|
89
87
|
curr.value = value;
|
|
90
|
-
Snapshot_1.Snapshot.markEdited(value, true, r, m, h);
|
|
88
|
+
Snapshot_1.Snapshot.markEdited(old, value, true, r, m, h);
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
91
|
}
|
|
@@ -184,10 +182,13 @@ class Hooks {
|
|
|
184
182
|
}
|
|
185
183
|
return h;
|
|
186
184
|
}
|
|
187
|
-
static createObjectHolder(unobservable, blank, hint) {
|
|
185
|
+
static createObjectHolder(proto, unobservable, blank, hint) {
|
|
188
186
|
const ctx = Snapshot_1.Snapshot.edit();
|
|
189
187
|
const h = new Data_1.ObjectHolder(unobservable, undefined, Hooks.proxy, Snapshot_1.ROOT_REV, hint);
|
|
190
188
|
ctx.getEditableRevision(h, Data_1.Meta.Holder, blank);
|
|
189
|
+
if (!Hooks.reactionsAutoStartDisabled)
|
|
190
|
+
for (const m in Data_1.Meta.getFrom(proto, Data_1.Meta.Reactions))
|
|
191
|
+
h.proxy[m][Data_1.Meta.Controller].markObsolete();
|
|
191
192
|
return h;
|
|
192
193
|
}
|
|
193
194
|
static setProfilingMode(enabled, options) {
|
|
@@ -53,7 +53,7 @@ class MonitorImpl extends Monitor {
|
|
|
53
53
|
static activate(mon, delay) {
|
|
54
54
|
if (delay >= 0) {
|
|
55
55
|
if (mon.internals.activationTimeout === undefined)
|
|
56
|
-
mon.internals.activationTimeout = setTimeout(() => Transaction_1.Transaction.runAs({ hint: 'Monitor.activate', standalone:
|
|
56
|
+
mon.internals.activationTimeout = setTimeout(() => Transaction_1.Transaction.runAs({ hint: 'Monitor.activate', standalone: 'isolated' }, MonitorImpl.activate, mon, -1), delay);
|
|
57
57
|
}
|
|
58
58
|
else if (mon.counter > 0)
|
|
59
59
|
mon.isActive = true;
|
|
@@ -61,7 +61,7 @@ class MonitorImpl extends Monitor {
|
|
|
61
61
|
static deactivate(mon, delay) {
|
|
62
62
|
if (delay >= 0) {
|
|
63
63
|
clearTimeout(mon.internals.deactivationTimeout);
|
|
64
|
-
mon.internals.deactivationTimeout = setTimeout(() => Transaction_1.Transaction.runAs({ hint: 'Monitor.deactivate', standalone:
|
|
64
|
+
mon.internals.deactivationTimeout = setTimeout(() => Transaction_1.Transaction.runAs({ hint: 'Monitor.deactivate', standalone: 'isolated' }, MonitorImpl.deactivate, mon, -1), delay);
|
|
65
65
|
}
|
|
66
66
|
else if (mon.counter <= 0) {
|
|
67
67
|
mon.isActive = false;
|
|
@@ -51,8 +51,10 @@ declare class Operation extends Observable implements Observer {
|
|
|
51
51
|
successor: Operation | undefined;
|
|
52
52
|
constructor(controller: OperationController, revision: ObjectRevision, prev: Operation | OptionsImpl);
|
|
53
53
|
get isOperation(): boolean;
|
|
54
|
+
get selfSnapshotId(): number;
|
|
54
55
|
hint(): string;
|
|
55
56
|
get order(): number;
|
|
57
|
+
get ['#this'](): string;
|
|
56
58
|
why(): string;
|
|
57
59
|
briefWhy(): string;
|
|
58
60
|
dependencies(): string[];
|
|
@@ -77,7 +79,7 @@ declare class Operation extends Observable implements Observer {
|
|
|
77
79
|
private static propagateMemberChangeThroughSubscriptions;
|
|
78
80
|
private unsubscribeFromAllObservables;
|
|
79
81
|
private subscribeTo;
|
|
80
|
-
private static
|
|
82
|
+
private static canSubscribe;
|
|
81
83
|
private static createControllerAndGetHook;
|
|
82
84
|
private static rememberOperationOptions;
|
|
83
85
|
static init(): void;
|
|
@@ -30,6 +30,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
30
30
|
markObsolete() { Transaction_1.Transaction.runAs({ hint: Dbg_1.Dbg.isOn ? `markObsolete(${Snapshot_1.Dump.obj(this.ownHolder, this.memberName)})` : 'markObsolete()' }, OperationController.markObsolete, this); }
|
|
31
31
|
pullLastResult(args) { return this.useOrRun(true, args).value; }
|
|
32
32
|
useOrRun(weak, args) {
|
|
33
|
+
var _a;
|
|
33
34
|
let oc = this.peek(args);
|
|
34
35
|
const ctx = oc.snapshot;
|
|
35
36
|
const op = oc.operation;
|
|
@@ -37,7 +38,9 @@ class OperationController extends Controller_1.Controller {
|
|
|
37
38
|
if (!oc.isUpToDate && oc.revision.data[Data_1.Meta.Disposed] === undefined
|
|
38
39
|
&& (!weak || op.cause === ROOT_TRIGGER || !op.successor ||
|
|
39
40
|
op.successor.transaction.isFinished)) {
|
|
40
|
-
const
|
|
41
|
+
const outerOpts = (_a = Operation.current) === null || _a === void 0 ? void 0 : _a.options;
|
|
42
|
+
const standalone = weak || opts.standalone || opts.kind === Options_1.Kind.Reaction ||
|
|
43
|
+
(opts.kind === Options_1.Kind.Transaction && outerOpts && (outerOpts.noSideEffects || outerOpts.kind === Options_1.Kind.Cache)) ||
|
|
41
44
|
(opts.kind === Options_1.Kind.Cache && (oc.revision.snapshot.sealed ||
|
|
42
45
|
oc.revision.prev.revision !== Snapshot_1.ROOT_REV));
|
|
43
46
|
const token = opts.noSideEffects ? this : undefined;
|
|
@@ -69,7 +72,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
69
72
|
throw (0, Dbg_1.misuse)('a method is expected with reactronic decorator');
|
|
70
73
|
op.options = new Hooks_1.OptionsImpl(op.options.getter, op.options.setter, op.options, options, false);
|
|
71
74
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.write)
|
|
72
|
-
Dbg_1.Dbg.log('║', ' ✎', `${op.hint()}.options
|
|
75
|
+
Dbg_1.Dbg.log('║', ' ✎', `${op.hint()}.options are changed`);
|
|
73
76
|
return op.options;
|
|
74
77
|
}
|
|
75
78
|
static runWithin(op, func, ...args) {
|
|
@@ -125,9 +128,10 @@ class OperationController extends Controller_1.Controller {
|
|
|
125
128
|
let op = this.peekFromRevision(r);
|
|
126
129
|
if (op.revision !== r) {
|
|
127
130
|
const op2 = new Operation(this, r, op);
|
|
128
|
-
|
|
131
|
+
r.data[m] = op2.reenterOver(op);
|
|
129
132
|
ctx.bumpBy(r.prev.revision.snapshot.timestamp);
|
|
130
|
-
Snapshot_1.Snapshot.markEdited(op, true, r, m, h);
|
|
133
|
+
Snapshot_1.Snapshot.markEdited(op, op2, true, r, m, h);
|
|
134
|
+
op = op2;
|
|
131
135
|
}
|
|
132
136
|
return { operation: op, isUpToDate: true, snapshot: ctx, revision: r };
|
|
133
137
|
}
|
|
@@ -143,9 +147,11 @@ class OperationController extends Controller_1.Controller {
|
|
|
143
147
|
let op2 = r2.data[m];
|
|
144
148
|
if (op2.controller !== this) {
|
|
145
149
|
r2 = Snapshot_1.Snapshot.edit().getEditableRevision(h, m, Data_1.Meta.Holder, this);
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
150
|
+
const t = new Operation(this, r2, op2);
|
|
151
|
+
t.cause = ROOT_TRIGGER;
|
|
152
|
+
r2.data[m] = t;
|
|
153
|
+
Snapshot_1.Snapshot.markEdited(op2, t, true, r2, m, h);
|
|
154
|
+
op2 = t;
|
|
149
155
|
}
|
|
150
156
|
return op2;
|
|
151
157
|
});
|
|
@@ -159,7 +165,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
159
165
|
const result = Transaction_1.Transaction.runAs(opts, (argsx) => {
|
|
160
166
|
if (!oc.operation.transaction.isCanceled) {
|
|
161
167
|
oc = this.edit();
|
|
162
|
-
if (Dbg_1.Dbg.isOn &&
|
|
168
|
+
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.operation)
|
|
163
169
|
Dbg_1.Dbg.log('║', ' 𝑓', `${oc.operation.why()}`);
|
|
164
170
|
oc.operation.run(this.ownHolder.proxy, argsx);
|
|
165
171
|
}
|
|
@@ -167,7 +173,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
167
173
|
oc = this.peek(argsx);
|
|
168
174
|
if (oc.operation.options.kind === Options_1.Kind.Transaction || !oc.isUpToDate) {
|
|
169
175
|
oc = this.edit();
|
|
170
|
-
if (Dbg_1.Dbg.isOn &&
|
|
176
|
+
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.operation)
|
|
171
177
|
Dbg_1.Dbg.log('║', ' 𝑓', `${oc.operation.why()}`);
|
|
172
178
|
oc.operation.run(this.ownHolder.proxy, argsx);
|
|
173
179
|
}
|
|
@@ -208,8 +214,12 @@ class Operation extends Data_1.Observable {
|
|
|
208
214
|
this.successor = undefined;
|
|
209
215
|
}
|
|
210
216
|
get isOperation() { return true; }
|
|
217
|
+
get selfSnapshotId() { return this.revision.snapshot.id; }
|
|
211
218
|
hint() { return `${Snapshot_1.Dump.rev(this.revision, this.controller.memberName)}`; }
|
|
212
219
|
get order() { return this.options.order; }
|
|
220
|
+
get ['#this']() {
|
|
221
|
+
return `Operation: ${this.why()}`;
|
|
222
|
+
}
|
|
213
223
|
why() {
|
|
214
224
|
let ms = Date.now();
|
|
215
225
|
const prev = this.revision.prev.revision.data[this.controller.memberName];
|
|
@@ -221,7 +231,7 @@ class Operation extends Data_1.Observable {
|
|
|
221
231
|
else if (this.controller.options.kind === Options_1.Kind.Transaction)
|
|
222
232
|
trigger = ' << operation';
|
|
223
233
|
else
|
|
224
|
-
trigger = ` <<
|
|
234
|
+
trigger = ` << T${this.revision.snapshot.id}[${this.revision.snapshot.hint}]`;
|
|
225
235
|
return `${this.hint()}${trigger} (${ms !== Infinity ? `${ms}ms since previous run` : 'initial run'})`;
|
|
226
236
|
}
|
|
227
237
|
briefWhy() {
|
|
@@ -366,18 +376,18 @@ class Operation extends Data_1.Observable {
|
|
|
366
376
|
if (this.result instanceof Promise) {
|
|
367
377
|
this.result = this.result.then(value => {
|
|
368
378
|
this.value = value;
|
|
369
|
-
this.leave(false, '
|
|
379
|
+
this.leave(false, ' ⚐', '- finished ', ' OK ──┘');
|
|
370
380
|
return value;
|
|
371
381
|
}, error => {
|
|
372
382
|
this.error = error;
|
|
373
|
-
this.leave(false, '
|
|
383
|
+
this.leave(false, ' ⚐', '- finished ', 'ERR ──┘');
|
|
374
384
|
throw error;
|
|
375
385
|
});
|
|
376
386
|
if (Dbg_1.Dbg.isOn) {
|
|
377
387
|
if (Dbg_1.Dbg.trace.operation)
|
|
378
388
|
Dbg_1.Dbg.log('║', '_/', `${this.hint()} - leave... `, 0, 'ASYNC ──┐');
|
|
379
389
|
else if (Dbg_1.Dbg.trace.transaction)
|
|
380
|
-
Dbg_1.Dbg.log('║', ' ', `${this.
|
|
390
|
+
Dbg_1.Dbg.log('║', ' ', `${this.why()} ...`, 0, 'ASYNC');
|
|
381
391
|
}
|
|
382
392
|
}
|
|
383
393
|
else {
|
|
@@ -398,8 +408,8 @@ class Operation extends Data_1.Observable {
|
|
|
398
408
|
monitorEnter(mon) {
|
|
399
409
|
const options = {
|
|
400
410
|
hint: 'Monitor.enter',
|
|
401
|
-
standalone:
|
|
402
|
-
trace: Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.monitor ? undefined : Dbg_1.Dbg.global
|
|
411
|
+
standalone: 'isolated',
|
|
412
|
+
trace: Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.monitor ? undefined : Dbg_1.Dbg.global
|
|
403
413
|
};
|
|
404
414
|
OperationController.runWithin(undefined, Transaction_1.Transaction.runAs, options, Monitor_1.MonitorImpl.enter, mon, this.transaction);
|
|
405
415
|
}
|
|
@@ -408,8 +418,8 @@ class Operation extends Data_1.Observable {
|
|
|
408
418
|
const leave = () => {
|
|
409
419
|
const options = {
|
|
410
420
|
hint: 'Monitor.leave',
|
|
411
|
-
standalone:
|
|
412
|
-
trace: Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.monitor ? undefined : Dbg_1.Dbg.DefaultLevel
|
|
421
|
+
standalone: 'isolated',
|
|
422
|
+
trace: Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.monitor ? undefined : Dbg_1.Dbg.DefaultLevel
|
|
413
423
|
};
|
|
414
424
|
OperationController.runWithin(undefined, Transaction_1.Transaction.runAs, options, Monitor_1.MonitorImpl.leave, mon, this.transaction);
|
|
415
425
|
};
|
|
@@ -440,10 +450,10 @@ class Operation extends Data_1.Observable {
|
|
|
440
450
|
}
|
|
441
451
|
}
|
|
442
452
|
}
|
|
443
|
-
static markEdited(
|
|
453
|
+
static markEdited(oldValue, newValue, edited, r, m, h) {
|
|
444
454
|
edited ? r.changes.set(m, Operation.current) : r.changes.delete(m);
|
|
445
455
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.write)
|
|
446
|
-
edited ? Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.rev(r, m)}
|
|
456
|
+
edited ? Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.rev(r, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`) : Dbg_1.Dbg.log('║', ' ✎', `${Snapshot_1.Dump.rev(r, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`, undefined, ' (same as previous)');
|
|
447
457
|
}
|
|
448
458
|
static isConflicting(oldValue, newValue) {
|
|
449
459
|
let result = oldValue !== newValue;
|
|
@@ -515,29 +525,33 @@ class Operation extends Data_1.Observable {
|
|
|
515
525
|
this.observables = undefined;
|
|
516
526
|
}
|
|
517
527
|
subscribeTo(observable, r, m, h, timestamp) {
|
|
518
|
-
var _a, _b;
|
|
519
|
-
const
|
|
520
|
-
if (
|
|
528
|
+
var _a, _b, _c;
|
|
529
|
+
const ok = Operation.canSubscribe(observable, r, m, h, timestamp);
|
|
530
|
+
if (ok) {
|
|
521
531
|
let times = 0;
|
|
522
532
|
if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
|
|
523
533
|
const existing = this.observables.get(observable);
|
|
524
534
|
times = existing ? existing.usageCount + 1 : 1;
|
|
525
535
|
}
|
|
526
|
-
if (
|
|
527
|
-
observable.observers
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
Dbg_1.Dbg.
|
|
536
|
+
if (this.observables !== undefined) {
|
|
537
|
+
if (!observable.observers)
|
|
538
|
+
observable.observers = new Set();
|
|
539
|
+
const info = { revision: r, memberName: m, usageCount: times };
|
|
540
|
+
observable.observers.add(this);
|
|
541
|
+
this.observables.set(observable, info);
|
|
542
|
+
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_a = this.options.trace) === null || _a === void 0 ? void 0 : _a.read)))
|
|
543
|
+
Dbg_1.Dbg.log('║', ' ∞ ', `${this.hint()} is subscribed to ${Snapshot_1.Dump.rev(r, m)}${info.usageCount > 1 ? ` (${info.usageCount} times)` : ''}`);
|
|
544
|
+
}
|
|
545
|
+
else if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_b = this.options.trace) === null || _b === void 0 ? void 0 : _b.read)))
|
|
546
|
+
Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Snapshot_1.Dump.rev(r, m)}`);
|
|
533
547
|
}
|
|
534
548
|
else {
|
|
535
|
-
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((
|
|
549
|
+
if (Dbg_1.Dbg.isOn && (Dbg_1.Dbg.trace.read || ((_c = this.options.trace) === null || _c === void 0 ? void 0 : _c.read)))
|
|
536
550
|
Dbg_1.Dbg.log('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Snapshot_1.Dump.rev(r, m)}`);
|
|
537
551
|
}
|
|
538
|
-
return
|
|
552
|
+
return ok;
|
|
539
553
|
}
|
|
540
|
-
static
|
|
554
|
+
static canSubscribe(observable, r, m, h, timestamp) {
|
|
541
555
|
let result = !r.snapshot.sealed || observable === h.head.data[m];
|
|
542
556
|
if (result && timestamp !== -1)
|
|
543
557
|
result = !(observable instanceof Operation && timestamp >= observable.obsoleteSince);
|
|
@@ -615,7 +629,7 @@ function propagationHint(cause, full) {
|
|
|
615
629
|
full && result.push(cause.revision.snapshot.hint);
|
|
616
630
|
return result;
|
|
617
631
|
}
|
|
618
|
-
function valueHint(value) {
|
|
632
|
+
function valueHint(value, m) {
|
|
619
633
|
let result = '';
|
|
620
634
|
if (Array.isArray(value))
|
|
621
635
|
result = `Array(${value.length})`;
|
|
@@ -624,13 +638,13 @@ function valueHint(value) {
|
|
|
624
638
|
else if (value instanceof Map)
|
|
625
639
|
result = `Map(${value.size})`;
|
|
626
640
|
else if (value instanceof Operation)
|
|
627
|
-
result =
|
|
641
|
+
result = `${Snapshot_1.Dump.rev(value.revision, m)}`;
|
|
628
642
|
else if (value === Data_1.Meta.Disposed)
|
|
629
643
|
result = '<disposed>';
|
|
630
644
|
else if (value !== undefined && value !== null)
|
|
631
645
|
result = value.toString().slice(0, 20);
|
|
632
646
|
else
|
|
633
|
-
result = '
|
|
647
|
+
result = '∅';
|
|
634
648
|
return result;
|
|
635
649
|
}
|
|
636
650
|
function getMergedTraceOptions(local) {
|
|
@@ -24,7 +24,7 @@ export declare class Snapshot implements AbstractSnapshot {
|
|
|
24
24
|
static current: () => Snapshot;
|
|
25
25
|
static edit: () => Snapshot;
|
|
26
26
|
static markUsed: (observable: Observable, r: ObjectRevision, m: MemberName, h: ObjectHolder, kind: Kind, weak: boolean) => void;
|
|
27
|
-
static markEdited: (
|
|
27
|
+
static markEdited: (oldValue: any, newValue: any, edited: boolean, r: ObjectRevision, m: MemberName, h: ObjectHolder) => void;
|
|
28
28
|
static isConflicting: (oldValue: any, newValue: any) => boolean;
|
|
29
29
|
static propagateAllChangesThroughSubscriptions: (snapshot: Snapshot) => void;
|
|
30
30
|
static revokeAllSubscriptions: (snapshot: Snapshot) => void;
|
|
@@ -49,7 +49,7 @@ export declare class Snapshot implements AbstractSnapshot {
|
|
|
49
49
|
static _init(): void;
|
|
50
50
|
}
|
|
51
51
|
export declare class Dump {
|
|
52
|
-
static obj(h: ObjectHolder | undefined, m?: MemberName | undefined, stamp?: number, op?: number, typeless?: boolean): string;
|
|
52
|
+
static obj(h: ObjectHolder | undefined, m?: MemberName | undefined, stamp?: number, op?: number, xop?: number, typeless?: boolean): string;
|
|
53
53
|
static rev(r: ObjectRevision, m?: MemberName): string;
|
|
54
54
|
static conflicts(conflicts: ObjectRevision[]): string;
|
|
55
55
|
static conflictingMemberHint(m: MemberName, ours: ObjectRevision, theirs: ObjectRevision): string;
|
|
@@ -10,11 +10,11 @@ const SealedSet_1 = require("../util/SealedSet");
|
|
|
10
10
|
const Data_1 = require("./Data");
|
|
11
11
|
exports.MAX_TIMESTAMP = Number.MAX_SAFE_INTEGER;
|
|
12
12
|
exports.UNDEFINED_TIMESTAMP = exports.MAX_TIMESTAMP - 1;
|
|
13
|
-
Object.defineProperty(Data_1.ObjectHolder.prototype, '
|
|
13
|
+
Object.defineProperty(Data_1.ObjectHolder.prototype, '#this', {
|
|
14
14
|
configurable: false, enumerable: false,
|
|
15
15
|
get() {
|
|
16
16
|
const result = {};
|
|
17
|
-
const data = Snapshot.current().getCurrentRevision(this, '
|
|
17
|
+
const data = Snapshot.current().getCurrentRevision(this, '#this').data;
|
|
18
18
|
for (const m in data) {
|
|
19
19
|
const v = data[m];
|
|
20
20
|
if (v instanceof Data_1.Observable)
|
|
@@ -71,6 +71,8 @@ class Snapshot {
|
|
|
71
71
|
this.changeset.set(h, r);
|
|
72
72
|
h.editing = r;
|
|
73
73
|
h.editors++;
|
|
74
|
+
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.write)
|
|
75
|
+
Dbg_1.Dbg.log('║', ' ⎘', `${Dump.obj(h)} is cloned`);
|
|
74
76
|
}
|
|
75
77
|
}
|
|
76
78
|
else
|
|
@@ -78,7 +80,7 @@ class Snapshot {
|
|
|
78
80
|
return r;
|
|
79
81
|
}
|
|
80
82
|
static takeSnapshot(obj) {
|
|
81
|
-
return obj[Data_1.Meta.Holder]['
|
|
83
|
+
return obj[Data_1.Meta.Holder]['#this'];
|
|
82
84
|
}
|
|
83
85
|
static dispose(obj) {
|
|
84
86
|
const ctx = Snapshot.edit();
|
|
@@ -90,7 +92,7 @@ class Snapshot {
|
|
|
90
92
|
const r = ctx.getEditableRevision(h, Data_1.Meta.Disposed, Data_1.Meta.Disposed);
|
|
91
93
|
if (r !== exports.ROOT_REV) {
|
|
92
94
|
r.data[Data_1.Meta.Disposed] = Data_1.Meta.Disposed;
|
|
93
|
-
Snapshot.markEdited(Data_1.Meta.Disposed, true, r, Data_1.Meta.Disposed, h);
|
|
95
|
+
Snapshot.markEdited(Data_1.Meta.Disposed, Data_1.Meta.Disposed, true, r, Data_1.Meta.Disposed, h);
|
|
94
96
|
}
|
|
95
97
|
return r;
|
|
96
98
|
}
|
|
@@ -132,7 +134,7 @@ class Snapshot {
|
|
|
132
134
|
conflicts = [];
|
|
133
135
|
conflicts.push(r);
|
|
134
136
|
}
|
|
135
|
-
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.
|
|
137
|
+
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.transaction)
|
|
136
138
|
Dbg_1.Dbg.log('╠╝', '', `${Dump.rev(r)} is merged with ${Dump.rev(h.head)} among ${merged} properties with ${r.conflicts.size} conflicts.`);
|
|
137
139
|
}
|
|
138
140
|
});
|
|
@@ -193,7 +195,7 @@ class Snapshot {
|
|
|
193
195
|
}
|
|
194
196
|
});
|
|
195
197
|
if (Dbg_1.Dbg.isOn) {
|
|
196
|
-
if (Dbg_1.Dbg.trace.change) {
|
|
198
|
+
if (Dbg_1.Dbg.trace.change && !error) {
|
|
197
199
|
this.changeset.forEach((r, h) => {
|
|
198
200
|
const members = [];
|
|
199
201
|
r.changes.forEach((o, m) => members.push(m.toString()));
|
|
@@ -308,15 +310,16 @@ Snapshot.isConflicting = Utils_1.UNDEF;
|
|
|
308
310
|
Snapshot.propagateAllChangesThroughSubscriptions = (snapshot) => { };
|
|
309
311
|
Snapshot.revokeAllSubscriptions = (snapshot) => { };
|
|
310
312
|
class Dump {
|
|
311
|
-
static obj(h, m, stamp, op, typeless) {
|
|
313
|
+
static obj(h, m, stamp, op, xop, typeless) {
|
|
312
314
|
const member = m !== undefined ? `.${m.toString()}` : '';
|
|
313
315
|
return h === undefined
|
|
314
316
|
? `root${member}`
|
|
315
|
-
: stamp === undefined ? `${h.hint}${member} #${h.id}` : `${h.hint}${member} #${h.id}t${op}v${stamp}`;
|
|
317
|
+
: stamp === undefined ? `${h.hint}${member} #${h.id}` : `${h.hint}${member} #${h.id}t${op}v${stamp}${xop !== undefined && xop !== 0 ? `t${xop}` : ''}`;
|
|
316
318
|
}
|
|
317
319
|
static rev(r, m) {
|
|
318
320
|
const h = Data_1.Meta.get(r.data, Data_1.Meta.Holder);
|
|
319
|
-
|
|
321
|
+
const value = m !== undefined ? r.data[m] : undefined;
|
|
322
|
+
return Dump.obj(h, m, r.snapshot.timestamp, r.snapshot.id, value === null || value === void 0 ? void 0 : value.selfSnapshotId);
|
|
320
323
|
}
|
|
321
324
|
static conflicts(conflicts) {
|
|
322
325
|
return conflicts.map(ours => {
|
|
@@ -328,11 +331,11 @@ class Dump {
|
|
|
328
331
|
}).join(', ');
|
|
329
332
|
}
|
|
330
333
|
static conflictingMemberHint(m, ours, theirs) {
|
|
331
|
-
return `${theirs.snapshot.hint}
|
|
334
|
+
return `${theirs.snapshot.hint} (${Dump.rev(theirs, m)})`;
|
|
332
335
|
}
|
|
333
336
|
}
|
|
334
337
|
exports.Dump = Dump;
|
|
335
|
-
exports.ROOT_REV = new Data_1.ObjectRevision(new Snapshot({ hint: 'root' }), undefined, {});
|
|
338
|
+
exports.ROOT_REV = new Data_1.ObjectRevision(new Snapshot({ hint: 'root-rev' }), undefined, {});
|
|
336
339
|
exports.DefaultSnapshotOptions = Object.freeze({
|
|
337
340
|
hint: 'noname',
|
|
338
341
|
standalone: false,
|
|
@@ -24,4 +24,7 @@ export declare abstract class Transaction implements Worker {
|
|
|
24
24
|
static run<T>(func: F<T>, ...args: any[]): T;
|
|
25
25
|
static runAs<T>(options: SnapshotOptions | null, func: F<T>, ...args: any[]): T;
|
|
26
26
|
static standalone<T>(func: F<T>, ...args: any[]): T;
|
|
27
|
+
static isTimeOver(everyN?: number): boolean;
|
|
28
|
+
static requestMoreTime(): Promise<void>;
|
|
29
|
+
static get isCanceled(): boolean;
|
|
27
30
|
}
|
|
@@ -22,6 +22,9 @@ class Transaction {
|
|
|
22
22
|
static run(func, ...args) { return TransactionImpl.run(func, ...args); }
|
|
23
23
|
static runAs(options, func, ...args) { return TransactionImpl.runAs(options, func, ...args); }
|
|
24
24
|
static standalone(func, ...args) { return TransactionImpl.standalone(func, ...args); }
|
|
25
|
+
static isTimeOver(everyN = 1) { return TransactionImpl.isTimeOver(everyN); }
|
|
26
|
+
static requestMoreTime() { return TransactionImpl.requestMoreTime(); }
|
|
27
|
+
static get isCanceled() { return TransactionImpl.current.isCanceled; }
|
|
25
28
|
}
|
|
26
29
|
exports.Transaction = Transaction;
|
|
27
30
|
class TransactionImpl extends Transaction {
|
|
@@ -139,10 +142,24 @@ class TransactionImpl extends Transaction {
|
|
|
139
142
|
TransactionImpl.curr = outer;
|
|
140
143
|
}
|
|
141
144
|
}
|
|
145
|
+
static isTimeOver(everyN = 1) {
|
|
146
|
+
TransactionImpl.checkCount++;
|
|
147
|
+
let result = TransactionImpl.checkCount % everyN === 0;
|
|
148
|
+
if (result) {
|
|
149
|
+
const ms = performance.now() - TransactionImpl.startTime;
|
|
150
|
+
result = ms > TransactionImpl.timeLimit;
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
static requestMoreTime(sleepTime = 0) {
|
|
155
|
+
return (0, Utils_1.pause)(sleepTime);
|
|
156
|
+
}
|
|
142
157
|
static acquire(options) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
158
|
+
const curr = TransactionImpl.curr;
|
|
159
|
+
if ((options === null || options === void 0 ? void 0 : options.standalone) || curr.isFinished || curr.options.standalone === 'isolated')
|
|
160
|
+
return new TransactionImpl(options);
|
|
161
|
+
else
|
|
162
|
+
return TransactionImpl.curr;
|
|
146
163
|
}
|
|
147
164
|
guard() {
|
|
148
165
|
if (this.sealed && TransactionImpl.curr !== this)
|
|
@@ -162,7 +179,7 @@ class TransactionImpl extends Transaction {
|
|
|
162
179
|
yield this.after.whenFinished();
|
|
163
180
|
const options = {
|
|
164
181
|
hint: `${this.hint} - restart after T${this.after.id}`,
|
|
165
|
-
standalone: true,
|
|
182
|
+
standalone: this.options.standalone === 'isolated' ? 'isolated' : true,
|
|
166
183
|
trace: this.snapshot.options.trace,
|
|
167
184
|
token: this.snapshot.options.token,
|
|
168
185
|
};
|
|
@@ -187,6 +204,10 @@ class TransactionImpl extends Transaction {
|
|
|
187
204
|
let result;
|
|
188
205
|
const outer = TransactionImpl.curr;
|
|
189
206
|
try {
|
|
207
|
+
if (outer === TransactionImpl.none) {
|
|
208
|
+
TransactionImpl.startTime = performance.now();
|
|
209
|
+
TransactionImpl.checkCount = 0;
|
|
210
|
+
}
|
|
190
211
|
TransactionImpl.curr = this;
|
|
191
212
|
this.pending++;
|
|
192
213
|
this.snapshot.acquire(outer.snapshot);
|
|
@@ -242,7 +263,7 @@ class TransactionImpl extends Transaction {
|
|
|
242
263
|
applyOrDiscard() {
|
|
243
264
|
try {
|
|
244
265
|
if (Dbg_1.Dbg.isOn && Dbg_1.Dbg.trace.change)
|
|
245
|
-
Dbg_1.Dbg.log('
|
|
266
|
+
Dbg_1.Dbg.log('╠═', '', '', undefined, 'changes');
|
|
246
267
|
this.snapshot.applyOrDiscard(this.canceled);
|
|
247
268
|
this.snapshot.collectGarbage();
|
|
248
269
|
if (this.promise) {
|
|
@@ -287,4 +308,7 @@ class TransactionImpl extends Transaction {
|
|
|
287
308
|
TransactionImpl.none = new TransactionImpl({ hint: '<none>' });
|
|
288
309
|
TransactionImpl.curr = TransactionImpl.none;
|
|
289
310
|
TransactionImpl.inspection = false;
|
|
311
|
+
TransactionImpl.startTime = 0;
|
|
312
|
+
TransactionImpl.timeLimit = 14;
|
|
313
|
+
TransactionImpl.checkCount = 0;
|
|
290
314
|
TransactionImpl._init();
|
|
@@ -24,7 +24,7 @@ class TransactionJournalImpl extends TransactionJournal {
|
|
|
24
24
|
get canUndo() { return this._items.length > 0 && this._position > 0; }
|
|
25
25
|
get canRedo() { return this._position < this._items.length; }
|
|
26
26
|
remember(p) {
|
|
27
|
-
Transaction_1.Transaction.runAs({ hint: 'TransactionJournal.remember', standalone:
|
|
27
|
+
Transaction_1.Transaction.runAs({ hint: 'TransactionJournal.remember', standalone: 'isolated' }, () => {
|
|
28
28
|
const items = this._items = this._items.toMutable();
|
|
29
29
|
if (items.length >= this._capacity)
|
|
30
30
|
items.shift();
|
|
@@ -35,7 +35,7 @@ class TransactionJournalImpl extends TransactionJournal {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
undo(count = 1) {
|
|
38
|
-
Transaction_1.Transaction.runAs({ hint: 'TransactionJournal.undo', standalone:
|
|
38
|
+
Transaction_1.Transaction.runAs({ hint: 'TransactionJournal.undo', standalone: 'isolated' }, () => {
|
|
39
39
|
let i = this._position - 1;
|
|
40
40
|
while (i >= 0 && count > 0) {
|
|
41
41
|
const patch = this._items[i];
|
|
@@ -46,7 +46,7 @@ class TransactionJournalImpl extends TransactionJournal {
|
|
|
46
46
|
});
|
|
47
47
|
}
|
|
48
48
|
redo(count = 1) {
|
|
49
|
-
Transaction_1.Transaction.runAs({ hint: 'TransactionJournal.redo', standalone:
|
|
49
|
+
Transaction_1.Transaction.runAs({ hint: 'TransactionJournal.redo', standalone: 'isolated' }, () => {
|
|
50
50
|
let i = this._position;
|
|
51
51
|
while (i < this._items.length && count > 0) {
|
|
52
52
|
const patch = this._items[i];
|
|
@@ -61,7 +61,7 @@ class TransactionJournalImpl extends TransactionJournal {
|
|
|
61
61
|
changeset.forEach((r, h) => {
|
|
62
62
|
const p = { current: {}, former: {} };
|
|
63
63
|
const old = r.prev.revision !== Snapshot_1.ROOT_REV ? r.prev.revision.data : undefined;
|
|
64
|
-
r.changes.forEach((
|
|
64
|
+
r.changes.forEach((episode, m) => {
|
|
65
65
|
p.current[m] = unseal(r.data[m]);
|
|
66
66
|
if (old)
|
|
67
67
|
p.former[m] = unseal(old[m]);
|
|
@@ -79,14 +79,14 @@ class TransactionJournalImpl extends TransactionJournal {
|
|
|
79
79
|
patch.objects.forEach((p, obj) => {
|
|
80
80
|
const h = Data_1.Meta.get(obj, Data_1.Meta.Holder);
|
|
81
81
|
const data = undo ? p.former : p.current;
|
|
82
|
-
if (data[Data_1.Meta.Disposed]
|
|
82
|
+
if (data[Data_1.Meta.Disposed] === undefined) {
|
|
83
83
|
for (const m in data) {
|
|
84
84
|
const value = data[m];
|
|
85
85
|
const r = ctx.getEditableRevision(h, m, value);
|
|
86
86
|
if (r.snapshot === ctx) {
|
|
87
87
|
r.data[m] = new Data_1.Observable(value);
|
|
88
88
|
const v = r.prev.revision.data[m];
|
|
89
|
-
Snapshot_1.Snapshot.markEdited(value, v !== value, r, m, h);
|
|
89
|
+
Snapshot_1.Snapshot.markEdited(v, value, v !== value, r, m, h);
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -6,4 +6,4 @@ export declare class Utils {
|
|
|
6
6
|
}
|
|
7
7
|
export declare function UNDEF(...args: any[]): never;
|
|
8
8
|
export declare function all(promises: Array<Promise<any>>): Promise<any[]>;
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function pause<T>(timeout: number): Promise<T>;
|
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.pause = exports.all = exports.UNDEF = exports.Utils = void 0;
|
|
13
13
|
class Utils {
|
|
14
14
|
static freezeSet(obj) {
|
|
15
15
|
if (obj instanceof Set) {
|
|
@@ -52,9 +52,9 @@ function all(promises) {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
exports.all = all;
|
|
55
|
-
function
|
|
55
|
+
function pause(timeout) {
|
|
56
56
|
return new Promise(function (resolve) {
|
|
57
57
|
setTimeout(resolve.bind(null, () => resolve), timeout);
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
-
exports.
|
|
60
|
+
exports.pause = pause;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reactronic",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.524",
|
|
4
4
|
"description": "Reactronic - Transactional Reactive State Management",
|
|
5
5
|
"main": "build/dist/source/api.js",
|
|
6
6
|
"types": "build/dist/source/api.d.ts",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
},
|
|
30
30
|
"homepage": "https://github.com/nezaboodka/reactronic/blob/master/README.md#readme",
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@types/node": "16.11.
|
|
32
|
+
"@types/node": "16.11.11",
|
|
33
33
|
"@types/react": "17.0.37",
|
|
34
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
35
|
-
"@typescript-eslint/parser": "5.
|
|
34
|
+
"@typescript-eslint/eslint-plugin": "5.5.0",
|
|
35
|
+
"@typescript-eslint/parser": "5.5.0",
|
|
36
36
|
"ava": "3.15.0",
|
|
37
37
|
"eslint": "8.3.0",
|
|
38
38
|
"nyc": "15.1.0",
|