reactronic 0.22.200 → 0.22.204
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 +1 -1
- package/build/dist/source/Options.d.ts +1 -1
- package/build/dist/source/impl/Hooks.d.ts +3 -3
- package/build/dist/source/impl/Hooks.js +12 -14
- package/build/dist/source/impl/Meta.d.ts +1 -0
- package/build/dist/source/impl/Meta.js +1 -0
- package/build/dist/source/impl/Monitor.d.ts +7 -2
- package/build/dist/source/impl/Monitor.js +30 -5
- package/build/dist/source/impl/Operation.d.ts +2 -2
- package/build/dist/source/impl/Operation.js +62 -45
- package/build/dist/source/impl/Snapshot.d.ts +4 -3
- package/build/dist/source/impl/Snapshot.js +18 -14
- package/build/dist/source/impl/Transaction.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -320,7 +320,7 @@ interface MemberOptions {
|
|
|
320
320
|
readonly standalone: StandaloneMode
|
|
321
321
|
readonly order: number
|
|
322
322
|
readonly noSideEffects: boolean
|
|
323
|
-
readonly
|
|
323
|
+
readonly triggeringArgs: boolean
|
|
324
324
|
readonly throttling: number // milliseconds, -1 is immediately, Number.MAX_SAFE_INTEGER is never
|
|
325
325
|
readonly reentrance: Reentrance
|
|
326
326
|
readonly journal: TransactionJournal | undefined
|
|
@@ -15,7 +15,7 @@ export interface MemberOptions {
|
|
|
15
15
|
readonly standalone: StandaloneMode;
|
|
16
16
|
readonly order: number;
|
|
17
17
|
readonly noSideEffects: boolean;
|
|
18
|
-
readonly
|
|
18
|
+
readonly triggeringArgs: boolean;
|
|
19
19
|
readonly throttling: number;
|
|
20
20
|
readonly reentrance: Reentrance;
|
|
21
21
|
readonly journal: TransactionJournal | undefined;
|
|
@@ -15,7 +15,7 @@ export declare class OptionsImpl implements MemberOptions {
|
|
|
15
15
|
readonly standalone: StandaloneMode;
|
|
16
16
|
readonly order: number;
|
|
17
17
|
readonly noSideEffects: boolean;
|
|
18
|
-
readonly
|
|
18
|
+
readonly triggeringArgs: boolean;
|
|
19
19
|
readonly throttling: number;
|
|
20
20
|
readonly reentrance: Reentrance;
|
|
21
21
|
readonly journal: TransactionJournal | undefined;
|
|
@@ -41,10 +41,10 @@ export declare class Hooks implements ProxyHandler<ObjectHolder> {
|
|
|
41
41
|
static decorateOperation(implicit: boolean, decorator: Function, options: Partial<MemberOptions>, proto: any, member: MemberName, pd: PropertyDescriptor | undefined): any;
|
|
42
42
|
static decorateOperationParametrized(decorator: Function, options: Partial<MemberOptions>): F<any>;
|
|
43
43
|
static acquireObjectHolder(obj: any): ObjectHolder;
|
|
44
|
-
static
|
|
44
|
+
static createObjectHolderForObservableObject(proto: any, unobservable: any, blank: any, hint: string): ObjectHolder;
|
|
45
45
|
static setProfilingMode(isOn: boolean, options?: Partial<ProfilingOptions>): void;
|
|
46
46
|
static sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
47
47
|
static setHint<T>(obj: T, hint: string | undefined): T;
|
|
48
|
-
static
|
|
48
|
+
static createOperation: (h: ObjectHolder, m: MemberName, options: OptionsImpl) => F<any>;
|
|
49
49
|
static rememberOperationOptions: (proto: any, m: MemberName, getter: Function | undefined, setter: Function | undefined, enumerable: boolean, configurable: boolean, options: Partial<MemberOptions>, implicit: boolean) => OptionsImpl;
|
|
50
50
|
}
|
|
@@ -10,7 +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.
|
|
13
|
+
const h = Hooks.createObjectHolderForObservableObject(proto, this, initial, new.target.name);
|
|
14
14
|
return h.proxy;
|
|
15
15
|
}
|
|
16
16
|
[Symbol.toStringTag]() {
|
|
@@ -24,7 +24,7 @@ const DEFAULT_OPTIONS = Object.freeze({
|
|
|
24
24
|
standalone: false,
|
|
25
25
|
order: 0,
|
|
26
26
|
noSideEffects: false,
|
|
27
|
-
|
|
27
|
+
triggeringArgs: false,
|
|
28
28
|
throttling: Number.MAX_SAFE_INTEGER,
|
|
29
29
|
reentrance: Options_1.Reentrance.PreventWithError,
|
|
30
30
|
journal: undefined,
|
|
@@ -39,7 +39,7 @@ class OptionsImpl {
|
|
|
39
39
|
this.standalone = merge(DEFAULT_OPTIONS.standalone, existing.standalone, patch.standalone, implicit);
|
|
40
40
|
this.order = merge(DEFAULT_OPTIONS.order, existing.order, patch.order, implicit);
|
|
41
41
|
this.noSideEffects = merge(DEFAULT_OPTIONS.noSideEffects, existing.noSideEffects, patch.noSideEffects, implicit);
|
|
42
|
-
this.
|
|
42
|
+
this.triggeringArgs = merge(DEFAULT_OPTIONS.triggeringArgs, existing.triggeringArgs, patch.triggeringArgs, implicit);
|
|
43
43
|
this.throttling = merge(DEFAULT_OPTIONS.throttling, existing.throttling, patch.throttling, implicit);
|
|
44
44
|
this.reentrance = merge(DEFAULT_OPTIONS.reentrance, existing.reentrance, patch.reentrance, implicit);
|
|
45
45
|
this.journal = merge(DEFAULT_OPTIONS.journal, existing.journal, patch.journal, implicit);
|
|
@@ -144,18 +144,18 @@ class Hooks {
|
|
|
144
144
|
if (opts.getter === opts.setter) {
|
|
145
145
|
const bootstrap = function () {
|
|
146
146
|
const h = Hooks.acquireObjectHolder(this);
|
|
147
|
-
const
|
|
148
|
-
Object.defineProperty(h.unobservable, member, { value:
|
|
149
|
-
return
|
|
147
|
+
const operation = Hooks.createOperation(h, member, opts);
|
|
148
|
+
Object.defineProperty(h.unobservable, member, { value: operation, enumerable, configurable });
|
|
149
|
+
return operation;
|
|
150
150
|
};
|
|
151
151
|
return Object.defineProperty(proto, member, { get: bootstrap, enumerable, configurable: true });
|
|
152
152
|
}
|
|
153
153
|
else if (opts.setter === Utils_1.UNDEF) {
|
|
154
154
|
const bootstrap = function () {
|
|
155
155
|
const h = Hooks.acquireObjectHolder(this);
|
|
156
|
-
const
|
|
157
|
-
Object.defineProperty(h.unobservable, member, { get:
|
|
158
|
-
return
|
|
156
|
+
const operation = Hooks.createOperation(h, member, opts);
|
|
157
|
+
Object.defineProperty(h.unobservable, member, { get: operation, enumerable, configurable });
|
|
158
|
+
return operation.call(this);
|
|
159
159
|
};
|
|
160
160
|
return Object.defineProperty(proto, member, { get: bootstrap, enumerable, configurable: true });
|
|
161
161
|
}
|
|
@@ -175,14 +175,12 @@ class Hooks {
|
|
|
175
175
|
const initial = Data_1.Meta.getFrom(Object.getPrototypeOf(obj), Data_1.Meta.Initial);
|
|
176
176
|
const rev = new Data_1.ObjectRevision(Snapshot_1.ROOT_REV.snapshot, Snapshot_1.ROOT_REV, Object.assign({}, initial));
|
|
177
177
|
Data_1.Meta.set(rev.data, Data_1.Meta.Holder, h);
|
|
178
|
-
if (Dbg_1.Log.isOn)
|
|
179
|
-
Snapshot_1.Snapshot.freezeObjectRevision(rev);
|
|
180
178
|
h = new Data_1.ObjectHolder(obj, obj, Hooks.proxy, rev, obj.constructor.name);
|
|
181
179
|
Data_1.Meta.set(obj, Data_1.Meta.Holder, h);
|
|
182
180
|
}
|
|
183
181
|
return h;
|
|
184
182
|
}
|
|
185
|
-
static
|
|
183
|
+
static createObjectHolderForObservableObject(proto, unobservable, blank, hint) {
|
|
186
184
|
const ctx = Snapshot_1.Snapshot.edit();
|
|
187
185
|
const h = new Data_1.ObjectHolder(unobservable, undefined, Hooks.proxy, Snapshot_1.ROOT_REV, hint);
|
|
188
186
|
ctx.getEditableRevision(h, Data_1.Meta.Holder, blank);
|
|
@@ -230,8 +228,8 @@ Hooks.mainThreadBlockingWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
|
230
228
|
Hooks.asyncActionDurationWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
231
229
|
Hooks.sensitivity = false;
|
|
232
230
|
Hooks.proxy = new Hooks();
|
|
233
|
-
Hooks.
|
|
234
|
-
throw (0, Dbg_1.misuse)('
|
|
231
|
+
Hooks.createOperation = function (h, m, options) {
|
|
232
|
+
throw (0, Dbg_1.misuse)('createOperation should never be called');
|
|
235
233
|
};
|
|
236
234
|
Hooks.rememberOperationOptions = function (proto, m, getter, setter, enumerable, configurable, options, implicit) {
|
|
237
235
|
throw (0, Dbg_1.misuse)('rememberOperationOptions should never be called');
|
|
@@ -5,6 +5,7 @@ export declare abstract class Meta {
|
|
|
5
5
|
static readonly Initial: unique symbol;
|
|
6
6
|
static readonly Reactions: unique symbol;
|
|
7
7
|
static readonly Unobservable: unique symbol;
|
|
8
|
+
static readonly Undefined: unique symbol;
|
|
8
9
|
static get<T>(obj: any, sym: symbol): T;
|
|
9
10
|
static set(obj: any, sym: symbol, value: any): any;
|
|
10
11
|
static acquire(proto: any, sym: symbol): any;
|
|
@@ -4,24 +4,29 @@ export declare abstract class Monitor extends ObservableObject {
|
|
|
4
4
|
abstract readonly isActive: boolean;
|
|
5
5
|
abstract readonly counter: number;
|
|
6
6
|
abstract readonly workers: ReadonlySet<Worker>;
|
|
7
|
-
|
|
7
|
+
abstract readonly duration: number;
|
|
8
|
+
static create(hint: string, activationDelay: number, deactivationDelay: number, durationResolution: number): Monitor;
|
|
8
9
|
}
|
|
9
10
|
export declare class MonitorImpl extends Monitor {
|
|
10
11
|
isActive: boolean;
|
|
11
12
|
counter: number;
|
|
12
13
|
workers: Set<Worker>;
|
|
14
|
+
duration: number;
|
|
13
15
|
internals: {
|
|
16
|
+
started: number;
|
|
14
17
|
activationDelay: number;
|
|
15
18
|
activationTimeout: undefined;
|
|
16
19
|
deactivationDelay: number;
|
|
17
20
|
deactivationTimeout: undefined;
|
|
21
|
+
durationResolution: number;
|
|
18
22
|
};
|
|
19
23
|
enter(worker: Worker): void;
|
|
20
24
|
leave(worker: Worker): void;
|
|
21
|
-
static create(hint: string, activationDelay: number, deactivationDelay: number): MonitorImpl;
|
|
25
|
+
static create(hint: string, activationDelay: number, deactivationDelay: number, durationResolution: number): MonitorImpl;
|
|
22
26
|
static enter(mon: MonitorImpl, worker: Worker): void;
|
|
23
27
|
static leave(mon: MonitorImpl, worker: Worker): void;
|
|
24
28
|
private static doCreate;
|
|
25
29
|
private static activate;
|
|
26
30
|
private static deactivate;
|
|
31
|
+
private static tick;
|
|
27
32
|
}
|
|
@@ -4,8 +4,8 @@ exports.MonitorImpl = exports.Monitor = void 0;
|
|
|
4
4
|
const Hooks_1 = require("./Hooks");
|
|
5
5
|
const Transaction_1 = require("./Transaction");
|
|
6
6
|
class Monitor extends Hooks_1.ObservableObject {
|
|
7
|
-
static create(hint, activationDelay, deactivationDelay) {
|
|
8
|
-
return MonitorImpl.create(hint, activationDelay, deactivationDelay);
|
|
7
|
+
static create(hint, activationDelay, deactivationDelay, durationResolution) {
|
|
8
|
+
return MonitorImpl.create(hint, activationDelay, deactivationDelay, durationResolution);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
exports.Monitor = Monitor;
|
|
@@ -15,11 +15,14 @@ class MonitorImpl extends Monitor {
|
|
|
15
15
|
this.isActive = false;
|
|
16
16
|
this.counter = 0;
|
|
17
17
|
this.workers = new Set();
|
|
18
|
+
this.duration = 0;
|
|
18
19
|
this.internals = {
|
|
20
|
+
started: 0,
|
|
19
21
|
activationDelay: -1,
|
|
20
22
|
activationTimeout: undefined,
|
|
21
23
|
deactivationDelay: -1,
|
|
22
24
|
deactivationTimeout: undefined,
|
|
25
|
+
durationResolution: 1,
|
|
23
26
|
};
|
|
24
27
|
}
|
|
25
28
|
enter(worker) {
|
|
@@ -34,8 +37,8 @@ class MonitorImpl extends Monitor {
|
|
|
34
37
|
workers.delete(worker);
|
|
35
38
|
MonitorImpl.deactivate(this, this.internals.deactivationDelay);
|
|
36
39
|
}
|
|
37
|
-
static create(hint, activationDelay, deactivationDelay) {
|
|
38
|
-
return Transaction_1.Transaction.run({ hint: 'Monitor.create' }, MonitorImpl.doCreate, hint, activationDelay, deactivationDelay);
|
|
40
|
+
static create(hint, activationDelay, deactivationDelay, durationResolution) {
|
|
41
|
+
return Transaction_1.Transaction.run({ hint: 'Monitor.create' }, MonitorImpl.doCreate, hint, activationDelay, deactivationDelay, durationResolution);
|
|
39
42
|
}
|
|
40
43
|
static enter(mon, worker) {
|
|
41
44
|
mon.enter(worker);
|
|
@@ -43,14 +46,20 @@ class MonitorImpl extends Monitor {
|
|
|
43
46
|
static leave(mon, worker) {
|
|
44
47
|
mon.leave(worker);
|
|
45
48
|
}
|
|
46
|
-
static doCreate(hint, activationDelay, deactivationDelay) {
|
|
49
|
+
static doCreate(hint, activationDelay, deactivationDelay, durationResolution) {
|
|
47
50
|
const m = new MonitorImpl();
|
|
48
51
|
Hooks_1.Hooks.setHint(m, hint);
|
|
49
52
|
m.internals.activationDelay = activationDelay;
|
|
50
53
|
m.internals.deactivationDelay = deactivationDelay;
|
|
54
|
+
m.internals.durationResolution = durationResolution;
|
|
51
55
|
return m;
|
|
52
56
|
}
|
|
53
57
|
static activate(mon, delay) {
|
|
58
|
+
if (mon.internals.started === 0) {
|
|
59
|
+
mon.duration = 0;
|
|
60
|
+
mon.internals.started = performance.now();
|
|
61
|
+
MonitorImpl.tick(mon);
|
|
62
|
+
}
|
|
54
63
|
if (delay >= 0) {
|
|
55
64
|
if (mon.internals.activationTimeout === undefined)
|
|
56
65
|
mon.internals.activationTimeout = setTimeout(() => Transaction_1.Transaction.run({ hint: 'Monitor.activate', standalone: 'isolated' }, MonitorImpl.activate, mon, -1), delay);
|
|
@@ -67,6 +76,22 @@ class MonitorImpl extends Monitor {
|
|
|
67
76
|
mon.isActive = false;
|
|
68
77
|
mon.internals.activationTimeout = undefined;
|
|
69
78
|
}
|
|
79
|
+
if (mon.counter === 0 && mon.internals.started !== 0) {
|
|
80
|
+
const resolution = mon.internals.durationResolution;
|
|
81
|
+
mon.duration = Math.round(resolution * (performance.now() - mon.internals.started)) / resolution;
|
|
82
|
+
mon.internals.started = 0;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
static tick(mon) {
|
|
86
|
+
if (mon.internals.started !== 0) {
|
|
87
|
+
Transaction_1.Transaction.run(null, () => {
|
|
88
|
+
const resolution = mon.internals.durationResolution;
|
|
89
|
+
mon.duration = Math.round(resolution * (performance.now() - mon.internals.started)) / resolution;
|
|
90
|
+
});
|
|
91
|
+
const t = globalThis !== null && globalThis !== void 0 ? globalThis : global;
|
|
92
|
+
if (t.requestAnimationFrame)
|
|
93
|
+
requestAnimationFrame(() => MonitorImpl.tick(mon));
|
|
94
|
+
}
|
|
70
95
|
}
|
|
71
96
|
}
|
|
72
97
|
exports.MonitorImpl = MonitorImpl;
|
|
@@ -28,7 +28,7 @@ export declare class OperationController extends Controller<any> {
|
|
|
28
28
|
private peek;
|
|
29
29
|
private use;
|
|
30
30
|
private edit;
|
|
31
|
-
private
|
|
31
|
+
private acquireFromRevision;
|
|
32
32
|
private run;
|
|
33
33
|
private static markObsolete;
|
|
34
34
|
}
|
|
@@ -84,7 +84,7 @@ declare class Operation extends Observable implements Observer {
|
|
|
84
84
|
private unsubscribeFromAllObservables;
|
|
85
85
|
private subscribeTo;
|
|
86
86
|
private static canSubscribe;
|
|
87
|
-
private static
|
|
87
|
+
private static createOperation;
|
|
88
88
|
private static rememberOperationOptions;
|
|
89
89
|
static init(): void;
|
|
90
90
|
}
|
|
@@ -10,9 +10,9 @@ const Transaction_1 = require("./Transaction");
|
|
|
10
10
|
const Monitor_1 = require("./Monitor");
|
|
11
11
|
const Hooks_1 = require("./Hooks");
|
|
12
12
|
const TransactionJournal_1 = require("./TransactionJournal");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
13
|
+
const BOOT_ARGS = [];
|
|
14
|
+
const BOOT_CAUSE = '<boot>';
|
|
15
|
+
const ROOT_HOLDER = new Data_1.ObjectHolder(undefined, undefined, Hooks_1.Hooks.proxy, Snapshot_1.ROOT_REV, '<root>');
|
|
16
16
|
class OperationController extends Controller_1.Controller {
|
|
17
17
|
constructor(ownHolder, memberName) {
|
|
18
18
|
super();
|
|
@@ -36,7 +36,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
36
36
|
const op = oc.operation;
|
|
37
37
|
const opts = op.options;
|
|
38
38
|
if (!oc.isUpToDate && oc.revision.data[Data_1.Meta.Disposed] === undefined
|
|
39
|
-
&& (!weak || op.cause ===
|
|
39
|
+
&& (!weak || op.cause === BOOT_CAUSE || !op.successor ||
|
|
40
40
|
op.successor.transaction.isFinished)) {
|
|
41
41
|
const outerOpts = (_a = Operation.current) === null || _a === void 0 ? void 0 : _a.options;
|
|
42
42
|
const standalone = weak || opts.standalone || opts.kind === Options_1.Kind.Reaction ||
|
|
@@ -68,8 +68,8 @@ class OperationController extends Controller_1.Controller {
|
|
|
68
68
|
op = self.edit().operation;
|
|
69
69
|
else
|
|
70
70
|
op = Operation.current;
|
|
71
|
-
if (!op
|
|
72
|
-
throw (0, Dbg_1.misuse)('
|
|
71
|
+
if (!op)
|
|
72
|
+
throw (0, Dbg_1.misuse)('reactronic decorator is only applicable to methods');
|
|
73
73
|
op.options = new Hooks_1.OptionsImpl(op.options.getter, op.options.setter, op.options, options, false);
|
|
74
74
|
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.write)
|
|
75
75
|
Dbg_1.Log.write('║', ' ✎', `${op.hint()}.options are changed`);
|
|
@@ -93,12 +93,12 @@ class OperationController extends Controller_1.Controller {
|
|
|
93
93
|
return result;
|
|
94
94
|
}
|
|
95
95
|
static why() {
|
|
96
|
-
|
|
97
|
-
return
|
|
96
|
+
var _a, _b;
|
|
97
|
+
return (_b = (_a = Operation.current) === null || _a === void 0 ? void 0 : _a.why()) !== null && _b !== void 0 ? _b : BOOT_CAUSE;
|
|
98
98
|
}
|
|
99
99
|
static briefWhy() {
|
|
100
|
-
|
|
101
|
-
return
|
|
100
|
+
var _a, _b;
|
|
101
|
+
return (_b = (_a = Operation.current) === null || _a === void 0 ? void 0 : _a.briefWhy()) !== null && _b !== void 0 ? _b : BOOT_CAUSE;
|
|
102
102
|
}
|
|
103
103
|
static dependencies() {
|
|
104
104
|
const op = Operation.current;
|
|
@@ -107,10 +107,10 @@ class OperationController extends Controller_1.Controller {
|
|
|
107
107
|
peek(args) {
|
|
108
108
|
const ctx = Snapshot_1.Snapshot.current();
|
|
109
109
|
const r = ctx.seekRevision(this.ownHolder, this.memberName);
|
|
110
|
-
const op = this.
|
|
111
|
-
const isValid = op.options.kind !== Options_1.Kind.Transaction && op.cause !==
|
|
110
|
+
const op = this.acquireFromRevision(r, args);
|
|
111
|
+
const isValid = op.options.kind !== Options_1.Kind.Transaction && op.cause !== BOOT_CAUSE &&
|
|
112
112
|
(ctx === op.snapshot || ctx.timestamp < op.obsoleteSince) &&
|
|
113
|
-
(!op.options.
|
|
113
|
+
(!op.options.triggeringArgs || args === undefined ||
|
|
114
114
|
op.args.length === args.length && op.args.every((t, i) => t === args[i])) ||
|
|
115
115
|
r.data[Data_1.Meta.Disposed] !== undefined;
|
|
116
116
|
return { operation: op, isUpToDate: isValid, snapshot: ctx, revision: r };
|
|
@@ -125,7 +125,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
125
125
|
const m = this.memberName;
|
|
126
126
|
const ctx = Snapshot_1.Snapshot.edit();
|
|
127
127
|
const r = ctx.getEditableRevision(h, m, Data_1.Meta.Holder, this);
|
|
128
|
-
let op = this.
|
|
128
|
+
let op = this.acquireFromRevision(r, undefined);
|
|
129
129
|
if (op.snapshot !== r.snapshot) {
|
|
130
130
|
const op2 = new Operation(this, r.snapshot, op);
|
|
131
131
|
r.data[m] = op2.reenterOver(op);
|
|
@@ -135,28 +135,40 @@ class OperationController extends Controller_1.Controller {
|
|
|
135
135
|
}
|
|
136
136
|
return { operation: op, isUpToDate: true, snapshot: ctx, revision: r };
|
|
137
137
|
}
|
|
138
|
-
|
|
138
|
+
acquireFromRevision(r, args) {
|
|
139
139
|
const m = this.memberName;
|
|
140
140
|
let op = r.data[m];
|
|
141
141
|
if (op.controller !== this) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
142
|
+
if (r.snapshot !== Snapshot_1.ROOT_REV.snapshot) {
|
|
143
|
+
const hint = Dbg_1.Log.isOn ? `${Snapshot_1.Dump.obj(this.ownHolder, m)}/boot` : 'MethodController/init';
|
|
144
|
+
const standalone = r.snapshot.sealed || r.prev.revision !== Snapshot_1.ROOT_REV;
|
|
145
|
+
op = Transaction_1.Transaction.run({ hint, standalone, token: this }, () => {
|
|
146
|
+
const h = this.ownHolder;
|
|
147
|
+
let r2 = Snapshot_1.Snapshot.current().getCurrentRevision(h, m);
|
|
148
|
+
let op2 = r2.data[m];
|
|
149
|
+
if (op2.controller !== this) {
|
|
150
|
+
r2 = Snapshot_1.Snapshot.edit().getEditableRevision(h, m, Data_1.Meta.Holder, this);
|
|
151
|
+
const t = new Operation(this, r2.snapshot, op2);
|
|
152
|
+
if (args)
|
|
153
|
+
t.args = args;
|
|
154
|
+
t.cause = BOOT_CAUSE;
|
|
155
|
+
r2.data[m] = t;
|
|
156
|
+
Snapshot_1.Snapshot.markEdited(op2, t, true, r2, m, h);
|
|
157
|
+
op2 = t;
|
|
158
|
+
}
|
|
159
|
+
return op2;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
const t = new Operation(this, r.snapshot, op);
|
|
164
|
+
if (args)
|
|
165
|
+
t.args = args;
|
|
166
|
+
t.cause = BOOT_CAUSE;
|
|
167
|
+
r.data[m] = t;
|
|
168
|
+
op = t;
|
|
169
|
+
if (Dbg_1.Log.isOn && Dbg_1.Log.opt.write)
|
|
170
|
+
Dbg_1.Log.write('║', ' ⎘', `${Snapshot_1.Dump.obj(this.ownHolder, m)} is cloned outside of transaction`);
|
|
171
|
+
}
|
|
160
172
|
}
|
|
161
173
|
return op;
|
|
162
174
|
}
|
|
@@ -188,7 +200,7 @@ class OperationController extends Controller_1.Controller {
|
|
|
188
200
|
static markObsolete(self) {
|
|
189
201
|
const oc = self.peek(undefined);
|
|
190
202
|
const ctx = oc.snapshot;
|
|
191
|
-
oc.operation.markObsoleteDueTo(oc.operation, self.memberName, Snapshot_1.ROOT_REV.snapshot, ROOT_HOLDER,
|
|
203
|
+
oc.operation.markObsoleteDueTo(oc.operation, self.memberName, Snapshot_1.ROOT_REV.snapshot, ROOT_HOLDER, BOOT_CAUSE, ctx.timestamp, ctx.reactions);
|
|
192
204
|
}
|
|
193
205
|
}
|
|
194
206
|
exports.OperationController = OperationController;
|
|
@@ -207,7 +219,7 @@ class Operation extends Data_1.Observable {
|
|
|
207
219
|
}
|
|
208
220
|
else {
|
|
209
221
|
this.options = prev;
|
|
210
|
-
this.args =
|
|
222
|
+
this.args = BOOT_ARGS;
|
|
211
223
|
this.cause = undefined;
|
|
212
224
|
}
|
|
213
225
|
this.started = 0;
|
|
@@ -268,7 +280,7 @@ class Operation extends Data_1.Observable {
|
|
|
268
280
|
const skip = !observable.isOperation &&
|
|
269
281
|
snapshot === this.snapshot;
|
|
270
282
|
if (!skip) {
|
|
271
|
-
const why = `${Snapshot_1.Dump.rev2(holder, snapshot, memberName)} << ${outer}`;
|
|
283
|
+
const why = `${Snapshot_1.Dump.rev2(holder, snapshot, memberName, observable)} << ${outer}`;
|
|
272
284
|
this.unsubscribeFromAllObservables();
|
|
273
285
|
this.obsoleteDueTo = why;
|
|
274
286
|
this.obsoleteSince = since;
|
|
@@ -451,7 +463,7 @@ class Operation extends Data_1.Observable {
|
|
|
451
463
|
ctx.bumpBy(r.snapshot.timestamp);
|
|
452
464
|
const t = weak ? -1 : ctx.timestamp;
|
|
453
465
|
if (!op.subscribeTo(observable, r, m, h, t))
|
|
454
|
-
op.markObsoleteDueTo(observable, m, r.snapshot, h,
|
|
466
|
+
op.markObsoleteDueTo(observable, m, r.snapshot, h, BOOT_CAUSE, ctx.timestamp, ctx.reactions);
|
|
455
467
|
}
|
|
456
468
|
}
|
|
457
469
|
}
|
|
@@ -463,7 +475,7 @@ class Operation extends Data_1.Observable {
|
|
|
463
475
|
static isConflicting(oldValue, newValue) {
|
|
464
476
|
let result = oldValue !== newValue;
|
|
465
477
|
if (result)
|
|
466
|
-
result = oldValue instanceof Operation && oldValue.cause !==
|
|
478
|
+
result = oldValue instanceof Operation && oldValue.cause !== BOOT_CAUSE;
|
|
467
479
|
return result;
|
|
468
480
|
}
|
|
469
481
|
static propagateAllChangesThroughSubscriptions(snapshot) {
|
|
@@ -589,13 +601,13 @@ class Operation extends Data_1.Observable {
|
|
|
589
601
|
result = !(observable instanceof Operation && timestamp >= observable.obsoleteSince);
|
|
590
602
|
return result;
|
|
591
603
|
}
|
|
592
|
-
static
|
|
604
|
+
static createOperation(h, m, options) {
|
|
593
605
|
const ctl = new OperationController(h, m);
|
|
594
|
-
const
|
|
606
|
+
const operation = (...args) => {
|
|
595
607
|
return ctl.useOrRun(false, args).result;
|
|
596
608
|
};
|
|
597
|
-
Data_1.Meta.set(
|
|
598
|
-
return
|
|
609
|
+
Data_1.Meta.set(operation, Data_1.Meta.Controller, ctl);
|
|
610
|
+
return operation;
|
|
599
611
|
}
|
|
600
612
|
static rememberOperationOptions(proto, m, getter, setter, enumerable, configurable, options, implicit) {
|
|
601
613
|
const initial = Data_1.Meta.acquire(proto, Data_1.Meta.Initial);
|
|
@@ -614,15 +626,16 @@ class Operation extends Data_1.Observable {
|
|
|
614
626
|
return op.options;
|
|
615
627
|
}
|
|
616
628
|
static init() {
|
|
617
|
-
Object.freeze(
|
|
629
|
+
Object.freeze(BOOT_ARGS);
|
|
618
630
|
Dbg_1.Log.getMergedLoggingOptions = getMergedLoggingOptions;
|
|
631
|
+
Snapshot_1.Dump.valueHint = valueHint;
|
|
619
632
|
Snapshot_1.Snapshot.markUsed = Operation.markUsed;
|
|
620
633
|
Snapshot_1.Snapshot.markEdited = Operation.markEdited;
|
|
621
634
|
Snapshot_1.Snapshot.isConflicting = Operation.isConflicting;
|
|
622
635
|
Snapshot_1.Snapshot.propagateAllChangesThroughSubscriptions = Operation.propagateAllChangesThroughSubscriptions;
|
|
623
636
|
Snapshot_1.Snapshot.revokeAllSubscriptions = Operation.revokeAllSubscriptions;
|
|
624
637
|
Snapshot_1.Snapshot.enqueueReactionsToRun = Operation.enqueueReactionsToRun;
|
|
625
|
-
Hooks_1.Hooks.
|
|
638
|
+
Hooks_1.Hooks.createOperation = Operation.createOperation;
|
|
626
639
|
Hooks_1.Hooks.rememberOperationOptions = Operation.rememberOperationOptions;
|
|
627
640
|
Promise.prototype.then = reactronicHookedThen;
|
|
628
641
|
try {
|
|
@@ -662,10 +675,14 @@ function valueHint(value, m) {
|
|
|
662
675
|
result = `${Snapshot_1.Dump.rev2(value.controller.ownHolder, value.snapshot, m)}`;
|
|
663
676
|
else if (value === Data_1.Meta.Disposed)
|
|
664
677
|
result = '<disposed>';
|
|
678
|
+
else if (value === Data_1.Meta.Undefined)
|
|
679
|
+
result = '◌';
|
|
680
|
+
else if (typeof (value) === 'string')
|
|
681
|
+
result = `"${value.toString().slice(0, 20)}"`;
|
|
665
682
|
else if (value !== undefined && value !== null)
|
|
666
683
|
result = value.toString().slice(0, 20);
|
|
667
684
|
else
|
|
668
|
-
result = '
|
|
685
|
+
result = '◌';
|
|
669
686
|
return result;
|
|
670
687
|
}
|
|
671
688
|
function getMergedLoggingOptions(local) {
|
|
@@ -35,7 +35,7 @@ export declare class Snapshot implements AbstractSnapshot {
|
|
|
35
35
|
static takeSnapshot<T>(obj: T): T;
|
|
36
36
|
static dispose(obj: any): void;
|
|
37
37
|
static doDispose(ctx: Snapshot, h: ObjectHolder): ObjectRevision;
|
|
38
|
-
private
|
|
38
|
+
private isNewRevisionRequired;
|
|
39
39
|
acquire(outer: Snapshot): void;
|
|
40
40
|
bumpBy(timestamp: number): void;
|
|
41
41
|
rebase(): ObjectRevision[] | undefined;
|
|
@@ -49,8 +49,9 @@ export declare class Snapshot implements AbstractSnapshot {
|
|
|
49
49
|
static _init(): void;
|
|
50
50
|
}
|
|
51
51
|
export declare class Dump {
|
|
52
|
-
static
|
|
53
|
-
static
|
|
52
|
+
static valueHint: (value: any, m?: PropertyKey | undefined) => string;
|
|
53
|
+
static obj(h: ObjectHolder | undefined, m?: MemberName | undefined, stamp?: number, snapshotId?: number, originSnapshotId?: number, value?: any): string;
|
|
54
|
+
static rev2(h: ObjectHolder, s: AbstractSnapshot, m?: MemberName, o?: Observable): string;
|
|
54
55
|
static rev(r: ObjectRevision, m?: MemberName): string;
|
|
55
56
|
static conflicts(conflicts: ObjectRevision[]): string;
|
|
56
57
|
static conflictingMemberHint(m: MemberName, ours: ObjectRevision, theirs: ObjectRevision): string;
|
|
@@ -65,8 +65,7 @@ class Snapshot {
|
|
|
65
65
|
let r = this.seekRevision(h, m);
|
|
66
66
|
const existing = r.data[m];
|
|
67
67
|
if (existing !== Data_1.Meta.Unobservable) {
|
|
68
|
-
this.
|
|
69
|
-
if (r.snapshot !== this) {
|
|
68
|
+
if (this.isNewRevisionRequired(h, r, m, existing, value, token)) {
|
|
70
69
|
const data = Object.assign({}, m === Data_1.Meta.Holder ? value : r.data);
|
|
71
70
|
Reflect.set(data, Data_1.Meta.Holder, h);
|
|
72
71
|
r = new Data_1.ObjectRevision(this, r, data);
|
|
@@ -98,8 +97,8 @@ class Snapshot {
|
|
|
98
97
|
}
|
|
99
98
|
return r;
|
|
100
99
|
}
|
|
101
|
-
|
|
102
|
-
if (this.sealed)
|
|
100
|
+
isNewRevisionRequired(h, r, m, existing, value, token) {
|
|
101
|
+
if (this.sealed && r.snapshot !== exports.ROOT_REV.snapshot)
|
|
103
102
|
throw (0, Dbg_1.misuse)(`observable property ${Dump.obj(h, m)} can only be modified inside transaction`);
|
|
104
103
|
if (m !== Data_1.Meta.Holder && value !== Data_1.Meta.Holder) {
|
|
105
104
|
if (r.snapshot !== this || r.prev.revision !== exports.ROOT_REV) {
|
|
@@ -109,6 +108,7 @@ class Snapshot {
|
|
|
109
108
|
if (r === exports.ROOT_REV)
|
|
110
109
|
throw (0, Dbg_1.misuse)(`member ${Dump.rev(r, m)} doesn't exist in snapshot v${this.stamp} (${this.hint})`);
|
|
111
110
|
}
|
|
111
|
+
return r.snapshot !== this && !this.sealed;
|
|
112
112
|
}
|
|
113
113
|
acquire(outer) {
|
|
114
114
|
if (!this.sealed && this.stamp === exports.UNDEFINED_TIMESTAMP) {
|
|
@@ -280,10 +280,10 @@ class Snapshot {
|
|
|
280
280
|
Object.freeze(this);
|
|
281
281
|
}
|
|
282
282
|
static _init() {
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
283
|
+
const boot = exports.ROOT_REV.snapshot;
|
|
284
|
+
boot.acquire(boot);
|
|
285
|
+
boot.applyOrDiscard();
|
|
286
|
+
boot.triggerGarbageCollection();
|
|
287
287
|
Snapshot.freezeObjectRevision(exports.ROOT_REV);
|
|
288
288
|
Snapshot.idGen = 100;
|
|
289
289
|
Snapshot.stampGen = 101;
|
|
@@ -311,14 +311,17 @@ Snapshot.propagateAllChangesThroughSubscriptions = (snapshot) => { };
|
|
|
311
311
|
Snapshot.revokeAllSubscriptions = (snapshot) => { };
|
|
312
312
|
Snapshot.enqueueReactionsToRun = (reactions) => { };
|
|
313
313
|
class Dump {
|
|
314
|
-
static obj(h, m, stamp, snapshotId, originSnapshotId,
|
|
314
|
+
static obj(h, m, stamp, snapshotId, originSnapshotId, value) {
|
|
315
315
|
const member = m !== undefined ? `.${m.toString()}` : '';
|
|
316
316
|
return h === undefined
|
|
317
|
-
? `
|
|
318
|
-
: stamp === undefined
|
|
317
|
+
? `boot${member}`
|
|
318
|
+
: stamp === undefined
|
|
319
|
+
? `${h.hint}${member}${value !== undefined ? `[=${Dump.valueHint(value)}]` : ''} #${h.id}`
|
|
320
|
+
: `${h.hint}${member}${value !== undefined ? `[=${Dump.valueHint(value)}]` : ''} #${h.id}t${snapshotId}v${stamp}${originSnapshotId !== undefined && originSnapshotId !== 0 ? `t${originSnapshotId}` : ''}`;
|
|
319
321
|
}
|
|
320
|
-
static rev2(h, s, m,
|
|
321
|
-
|
|
322
|
+
static rev2(h, s, m, o) {
|
|
323
|
+
var _a;
|
|
324
|
+
return Dump.obj(h, m, s.timestamp, s.id, o === null || o === void 0 ? void 0 : o.originSnapshotId, (_a = o === null || o === void 0 ? void 0 : o.value) !== null && _a !== void 0 ? _a : Data_1.Meta.Undefined);
|
|
322
325
|
}
|
|
323
326
|
static rev(r, m) {
|
|
324
327
|
const h = Data_1.Meta.get(r.data, Data_1.Meta.Holder);
|
|
@@ -339,7 +342,8 @@ class Dump {
|
|
|
339
342
|
}
|
|
340
343
|
}
|
|
341
344
|
exports.Dump = Dump;
|
|
342
|
-
|
|
345
|
+
Dump.valueHint = (value, m) => '???';
|
|
346
|
+
exports.ROOT_REV = new Data_1.ObjectRevision(new Snapshot({ hint: '<root>' }), undefined, {});
|
|
343
347
|
exports.DefaultSnapshotOptions = Object.freeze({
|
|
344
348
|
hint: 'noname',
|
|
345
349
|
standalone: false,
|
|
@@ -305,7 +305,7 @@ class TransactionImpl extends Transaction {
|
|
|
305
305
|
Snapshot_1.Snapshot._init();
|
|
306
306
|
}
|
|
307
307
|
}
|
|
308
|
-
TransactionImpl.none = new TransactionImpl({ hint: '
|
|
308
|
+
TransactionImpl.none = new TransactionImpl({ hint: 'Transaction.off' });
|
|
309
309
|
TransactionImpl.curr = TransactionImpl.none;
|
|
310
310
|
TransactionImpl.inspection = false;
|
|
311
311
|
TransactionImpl.frameStartTime = 0;
|