reactronic 0.22.302 → 0.22.306

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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/build/dist/source/Buffer.d.ts +0 -8
  3. package/build/dist/source/Buffer.js +0 -8
  4. package/build/dist/source/Controller.d.ts +0 -12
  5. package/build/dist/source/Controller.js +0 -6
  6. package/build/dist/source/Logging.d.ts +0 -38
  7. package/build/dist/source/Logging.js +0 -113
  8. package/build/dist/source/Options.d.ts +0 -38
  9. package/build/dist/source/Options.js +0 -21
  10. package/build/dist/source/Ref.d.ts +0 -34
  11. package/build/dist/source/Ref.js +0 -90
  12. package/build/dist/source/Rx.d.ts +0 -26
  13. package/build/dist/source/Rx.js +0 -57
  14. package/build/dist/source/Worker.d.ts +0 -8
  15. package/build/dist/source/Worker.js +0 -2
  16. package/build/dist/source/api.d.ts +0 -14
  17. package/build/dist/source/api.js +0 -40
  18. package/build/dist/source/impl/Data.d.ts +0 -58
  19. package/build/dist/source/impl/Data.js +0 -42
  20. package/build/dist/source/impl/Hooks.d.ts +0 -50
  21. package/build/dist/source/impl/Hooks.js +0 -241
  22. package/build/dist/source/impl/Journal.d.ts +0 -34
  23. package/build/dist/source/impl/Journal.js +0 -138
  24. package/build/dist/source/impl/Meta.d.ts +0 -13
  25. package/build/dist/source/impl/Meta.js +0 -33
  26. package/build/dist/source/impl/Monitor.d.ts +0 -32
  27. package/build/dist/source/impl/Monitor.js +0 -97
  28. package/build/dist/source/impl/Operation.d.ts +0 -93
  29. package/build/dist/source/impl/Operation.js +0 -721
  30. package/build/dist/source/impl/Snapshot.d.ts +0 -60
  31. package/build/dist/source/impl/Snapshot.js +0 -353
  32. package/build/dist/source/impl/Transaction.d.ts +0 -30
  33. package/build/dist/source/impl/Transaction.js +0 -313
  34. package/build/dist/source/util/Dbg.d.ts +0 -15
  35. package/build/dist/source/util/Dbg.js +0 -96
  36. package/build/dist/source/util/Sealant.d.ts +0 -14
  37. package/build/dist/source/util/Sealant.js +0 -30
  38. package/build/dist/source/util/SealedArray.d.ts +0 -16
  39. package/build/dist/source/util/SealedArray.js +0 -28
  40. package/build/dist/source/util/SealedMap.d.ts +0 -13
  41. package/build/dist/source/util/SealedMap.js +0 -21
  42. package/build/dist/source/util/SealedSet.d.ts +0 -13
  43. package/build/dist/source/util/SealedSet.js +0 -21
  44. package/build/dist/source/util/Utils.d.ts +0 -9
  45. package/build/dist/source/util/Utils.js +0 -62
@@ -1,721 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.rejectRethrow = exports.resolveReturn = exports.OperationController = void 0;
4
- const Dbg_1 = require("../util/Dbg");
5
- const Options_1 = require("../Options");
6
- const Controller_1 = require("../Controller");
7
- const Data_1 = require("./Data");
8
- const Snapshot_1 = require("./Snapshot");
9
- const Transaction_1 = require("./Transaction");
10
- const Monitor_1 = require("./Monitor");
11
- const Hooks_1 = require("./Hooks");
12
- const Journal_1 = require("./Journal");
13
- const BOOT_ARGS = [];
14
- const BOOT_CAUSE = '<boot>';
15
- const ROOT_HOLDER = new Data_1.DataHolder(undefined, undefined, Hooks_1.Hooks.proxy, Snapshot_1.ROOT_REV, '<root>');
16
- class OperationController extends Controller_1.Controller {
17
- constructor(ownHolder, memberName) {
18
- super();
19
- this.ownHolder = ownHolder;
20
- this.memberName = memberName;
21
- }
22
- configure(options) { return OperationController.configureImpl(this, options); }
23
- get options() { return this.peek(undefined).operation.options; }
24
- get nonreactive() { return this.peek(undefined).operation.content; }
25
- get args() { return this.use().operation.args; }
26
- get result() { return this.useOrRun(true, undefined).content; }
27
- get error() { return this.use().operation.error; }
28
- get stamp() { return this.use().revision.snapshot.timestamp; }
29
- get isUpToDate() { return this.use().isUpToDate; }
30
- markObsolete() { Transaction_1.Transaction.run({ hint: Dbg_1.Log.isOn ? `markObsolete(${Snapshot_1.Dump.obj(this.ownHolder, this.memberName)})` : 'markObsolete()' }, OperationController.markObsolete, this); }
31
- pullLastResult(args) { return this.useOrRun(true, args).content; }
32
- useOrRun(weak, args) {
33
- var _a;
34
- let oc = this.peek(args);
35
- const ctx = oc.snapshot;
36
- const op = oc.operation;
37
- const opts = op.options;
38
- if (!oc.isUpToDate && oc.revision.data[Data_1.Meta.Disposed] === undefined
39
- && (!weak || op.cause === BOOT_CAUSE || !op.successor ||
40
- op.successor.transaction.isFinished)) {
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)) ||
44
- (opts.kind === Options_1.Kind.Cache && (oc.revision.snapshot.sealed ||
45
- oc.revision.former.revision !== Snapshot_1.ROOT_REV));
46
- const token = opts.noSideEffects ? this : undefined;
47
- const oc2 = this.run(oc, standalone, opts, token, args);
48
- const ctx2 = oc2.operation.snapshot;
49
- if (!weak || ctx === ctx2 || (ctx2.sealed && ctx.timestamp >= ctx2.timestamp))
50
- oc = oc2;
51
- }
52
- else if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation && (opts.logging === undefined ||
53
- opts.logging.operation === undefined || opts.logging.operation === true))
54
- Dbg_1.Log.write(Transaction_1.Transaction.current.isFinished ? '' : '║', ' (=)', `${Snapshot_1.Dump.rev2(oc.operation.controller.ownHolder, oc.snapshot, this.memberName)} result is reused from T${oc.operation.transaction.id}[${oc.operation.transaction.hint}]`);
55
- const t = oc.operation;
56
- Snapshot_1.Snapshot.markUsed(t, oc.revision, this.memberName, this.ownHolder, t.options.kind, weak);
57
- return t;
58
- }
59
- static of(method) {
60
- const ctl = Data_1.Meta.get(method, Data_1.Meta.Controller);
61
- if (!ctl)
62
- throw (0, Dbg_1.misuse)(`given method is not decorated as reactronic one: ${method.name}`);
63
- return ctl;
64
- }
65
- static configureImpl(self, options) {
66
- let op;
67
- if (self)
68
- op = self.edit().operation;
69
- else
70
- op = Operation.current;
71
- if (!op)
72
- throw (0, Dbg_1.misuse)('reactronic decorator is only applicable to methods');
73
- op.options = new Hooks_1.OptionsImpl(op.options.getter, op.options.setter, op.options, options, false);
74
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.write)
75
- Dbg_1.Log.write('║', ' ✎', `${op.hint()}.options are changed`);
76
- return op.options;
77
- }
78
- static runWithin(op, func, ...args) {
79
- let result = undefined;
80
- const outer = Operation.current;
81
- try {
82
- Operation.current = op;
83
- result = func(...args);
84
- }
85
- catch (e) {
86
- if (op)
87
- op.error = e;
88
- throw e;
89
- }
90
- finally {
91
- Operation.current = outer;
92
- }
93
- return result;
94
- }
95
- static why() {
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
- }
99
- static briefWhy() {
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
- }
103
- static dependencies() {
104
- const op = Operation.current;
105
- return op ? op.dependencies() : ['Rx.dependencies should be called from inside of reactive method'];
106
- }
107
- peek(args) {
108
- const ctx = Snapshot_1.Snapshot.current();
109
- const r = ctx.seekRevision(this.ownHolder, this.memberName);
110
- const op = this.acquireFromRevision(r, args);
111
- const isValid = op.options.kind !== Options_1.Kind.Transaction && op.cause !== BOOT_CAUSE &&
112
- (ctx === op.snapshot || ctx.timestamp < op.obsoleteSince) &&
113
- (!op.options.triggeringArgs || args === undefined ||
114
- op.args.length === args.length && op.args.every((t, i) => t === args[i])) ||
115
- r.data[Data_1.Meta.Disposed] !== undefined;
116
- return { operation: op, isUpToDate: isValid, snapshot: ctx, revision: r };
117
- }
118
- use() {
119
- const oc = this.peek(undefined);
120
- Snapshot_1.Snapshot.markUsed(oc.operation, oc.revision, this.memberName, this.ownHolder, oc.operation.options.kind, true);
121
- return oc;
122
- }
123
- edit() {
124
- const h = this.ownHolder;
125
- const m = this.memberName;
126
- const ctx = Snapshot_1.Snapshot.edit();
127
- const r = ctx.getEditableRevision(h, m, Data_1.Meta.Holder, this);
128
- let op = this.acquireFromRevision(r, undefined);
129
- if (op.snapshot !== r.snapshot) {
130
- const op2 = new Operation(this, r.snapshot, op);
131
- r.data[m] = op2.reenterOver(op);
132
- ctx.bumpBy(r.former.revision.snapshot.timestamp);
133
- Snapshot_1.Snapshot.markEdited(op, op2, true, r, m, h);
134
- op = op2;
135
- }
136
- return { operation: op, isUpToDate: true, snapshot: ctx, revision: r };
137
- }
138
- acquireFromRevision(r, args) {
139
- const m = this.memberName;
140
- let op = r.data[m];
141
- if (op.controller !== this) {
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.former.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
- }
172
- }
173
- return op;
174
- }
175
- run(existing, standalone, options, token, args) {
176
- const hint = Dbg_1.Log.isOn ? `${Snapshot_1.Dump.obj(this.ownHolder, this.memberName)}${args && args.length > 0 && (typeof args[0] === 'number' || typeof args[0] === 'string') ? ` - ${args[0]}` : ''}` : `${Snapshot_1.Dump.obj(this.ownHolder, this.memberName)}`;
177
- let oc = existing;
178
- const opts = { hint, standalone, journal: options.journal, logging: options.logging, token };
179
- const result = Transaction_1.Transaction.run(opts, (argsx) => {
180
- if (!oc.operation.transaction.isCanceled) {
181
- oc = this.edit();
182
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation)
183
- Dbg_1.Log.write('║', ' 𝑓', `${oc.operation.why()}`);
184
- oc.operation.run(this.ownHolder.proxy, argsx);
185
- }
186
- else {
187
- oc = this.peek(argsx);
188
- if (oc.operation.options.kind === Options_1.Kind.Transaction || !oc.isUpToDate) {
189
- oc = this.edit();
190
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation)
191
- Dbg_1.Log.write('║', ' 𝑓', `${oc.operation.why()}`);
192
- oc.operation.run(this.ownHolder.proxy, argsx);
193
- }
194
- }
195
- return oc.operation.result;
196
- }, args);
197
- oc.operation.result = result;
198
- return oc;
199
- }
200
- static markObsolete(self) {
201
- const oc = self.peek(undefined);
202
- const ctx = oc.snapshot;
203
- oc.operation.markObsoleteDueTo(oc.operation, self.memberName, Snapshot_1.ROOT_REV.snapshot, ROOT_HOLDER, BOOT_CAUSE, ctx.timestamp, ctx.reactions);
204
- }
205
- }
206
- exports.OperationController = OperationController;
207
- class Operation extends Data_1.Subscription {
208
- constructor(controller, snapshot, former) {
209
- super(undefined);
210
- this.margin = Operation.current ? Operation.current.margin + 1 : 1;
211
- this.transaction = Transaction_1.Transaction.current;
212
- this.controller = controller;
213
- this.snapshot = snapshot;
214
- this.subscriptions = new Map();
215
- if (former instanceof Operation) {
216
- this.options = former.options;
217
- this.args = former.args;
218
- this.cause = former.obsoleteDueTo;
219
- }
220
- else {
221
- this.options = former;
222
- this.args = BOOT_ARGS;
223
- this.cause = undefined;
224
- }
225
- this.started = 0;
226
- this.obsoleteSince = 0;
227
- this.obsoleteDueTo = undefined;
228
- this.successor = undefined;
229
- }
230
- get isOperation() { return true; }
231
- get originSnapshotId() { return this.snapshot.id; }
232
- hint() { return `${Snapshot_1.Dump.rev2(this.controller.ownHolder, this.snapshot, this.controller.memberName)}`; }
233
- get order() { return this.options.order; }
234
- get ['#this']() {
235
- return `Operation: ${this.why()}`;
236
- }
237
- why() {
238
- let cause;
239
- if (this.cause)
240
- cause = ` << ${this.cause}`;
241
- else if (this.controller.options.kind === Options_1.Kind.Transaction)
242
- cause = ' << operation';
243
- else
244
- cause = ` << T${this.snapshot.id}[${this.snapshot.hint}]`;
245
- return `${this.hint()}${cause}`;
246
- }
247
- briefWhy() {
248
- return this.why();
249
- }
250
- dependencies() {
251
- throw (0, Dbg_1.misuse)('not implemented yet');
252
- }
253
- wrap(func) {
254
- const wrappedForOperation = (...args) => {
255
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.step && this.result)
256
- Dbg_1.Log.writeAs({ margin2: this.margin }, '║', '‾\\', `${this.hint()} - step in `, 0, ' │');
257
- const started = Date.now();
258
- const result = OperationController.runWithin(this, func, ...args);
259
- const ms = Date.now() - started;
260
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.step && this.result)
261
- Dbg_1.Log.writeAs({ margin2: this.margin }, '║', '_/', `${this.hint()} - step out `, 0, this.started > 0 ? ' │' : '');
262
- if (ms > Hooks_1.Hooks.mainThreadBlockingWarningThreshold)
263
- Dbg_1.Log.write('', '[!]', this.why(), ms, ' *** main thread is too busy ***');
264
- return result;
265
- };
266
- return wrappedForOperation;
267
- }
268
- run(proxy, args) {
269
- if (args)
270
- this.args = args;
271
- this.obsoleteSince = Snapshot_1.MAX_TIMESTAMP;
272
- if (!this.error)
273
- OperationController.runWithin(this, Operation.run, this, proxy);
274
- else
275
- this.result = Promise.reject(this.error);
276
- }
277
- markObsoleteDueTo(subscription, memberName, snapshot, holder, outer, since, reactions) {
278
- var _a, _b, _c;
279
- if (this.subscriptions !== undefined) {
280
- const skip = !subscription.isOperation &&
281
- snapshot === this.snapshot;
282
- if (!skip) {
283
- const why = `${Snapshot_1.Dump.rev2(holder, snapshot, memberName, subscription)} << ${outer}`;
284
- this.unsubscribeFromAllSubscriptions();
285
- this.obsoleteDueTo = why;
286
- this.obsoleteSince = since;
287
- const isReaction = this.options.kind === Options_1.Kind.Reaction;
288
- if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.obsolete || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.obsolete)))
289
- Dbg_1.Log.write(Dbg_1.Log.opt.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', isReaction ? '█' : '▒', isReaction && snapshot === Snapshot_1.ROOT_REV.snapshot
290
- ? `${this.hint()} is a reaction and will run automatically (order ${this.options.order})`
291
- : `${this.hint()} is obsolete due to ${Snapshot_1.Dump.rev2(holder, snapshot, memberName)} since v${since}${isReaction ? ` and will run automatically (order ${this.options.order})` : ''}`);
292
- if (isReaction)
293
- reactions.push(this);
294
- else
295
- (_b = this.subscribers) === null || _b === void 0 ? void 0 : _b.forEach(s => s.markObsoleteDueTo(this, this.controller.memberName, this.snapshot, this.controller.ownHolder, why, since, reactions));
296
- const tran = this.transaction;
297
- if (tran.snapshot === snapshot) {
298
- }
299
- else if (!tran.isFinished && this !== subscription)
300
- tran.cancel(new Error(`T${tran.id}[${tran.hint}] is canceled due to obsolete ${Snapshot_1.Dump.rev2(holder, snapshot, memberName)} changed by T${snapshot.id}[${snapshot.hint}]`), null);
301
- }
302
- else if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.obsolete || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.obsolete)))
303
- Dbg_1.Log.write(' ', 'x', `${this.hint()} is not obsolete due to its own change to ${Snapshot_1.Dump.rev2(holder, snapshot, memberName)}`);
304
- }
305
- }
306
- runIfNotUpToDate(now, nothrow) {
307
- const t = this.options.throttling;
308
- const interval = Date.now() + this.started;
309
- const hold = t ? t - interval : 0;
310
- if (now || hold < 0) {
311
- if (this.isNotUpToDate()) {
312
- try {
313
- const op = this.controller.useOrRun(false, undefined);
314
- if (op.result instanceof Promise)
315
- op.result.catch(error => {
316
- if (op.options.kind === Options_1.Kind.Reaction)
317
- (0, Dbg_1.misuse)(`reaction ${op.hint()} failed and will not run anymore: ${error}`, error);
318
- });
319
- }
320
- catch (e) {
321
- if (!nothrow)
322
- throw e;
323
- else if (this.options.kind === Options_1.Kind.Reaction)
324
- (0, Dbg_1.misuse)(`reaction ${this.hint()} failed and will not run anymore: ${e}`, e);
325
- }
326
- }
327
- }
328
- else if (t < Number.MAX_SAFE_INTEGER) {
329
- if (hold > 0)
330
- setTimeout(() => this.runIfNotUpToDate(true, true), hold);
331
- else
332
- this.addToDeferredReactions();
333
- }
334
- }
335
- isNotUpToDate() {
336
- return !this.error && (this.options.kind === Options_1.Kind.Transaction ||
337
- !this.successor || this.successor.transaction.isCanceled);
338
- }
339
- reenterOver(head) {
340
- let error = undefined;
341
- const opponent = head.successor;
342
- if (opponent && !opponent.transaction.isFinished) {
343
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.obsolete)
344
- Dbg_1.Log.write('║', ' [!]', `${this.hint()} is trying to re-enter over ${opponent.hint()}`);
345
- switch (head.options.reentrance) {
346
- case Options_1.Reentrance.PreventWithError:
347
- if (!opponent.transaction.isCanceled)
348
- throw (0, Dbg_1.misuse)(`${head.hint()} (${head.why()}) is not reentrant over ${opponent.hint()} (${opponent.why()})`);
349
- error = new Error(`T${this.transaction.id}[${this.transaction.hint}] is on hold/PreventWithError due to canceled T${opponent.transaction.id}[${opponent.transaction.hint}]`);
350
- this.transaction.cancel(error, opponent.transaction);
351
- break;
352
- case Options_1.Reentrance.WaitAndRestart:
353
- error = new Error(`T${this.transaction.id}[${this.transaction.hint}] is on hold/WaitAndRestart due to active T${opponent.transaction.id}[${opponent.transaction.hint}]`);
354
- this.transaction.cancel(error, opponent.transaction);
355
- break;
356
- case Options_1.Reentrance.CancelAndWaitPrevious:
357
- error = new Error(`T${this.transaction.id}[${this.transaction.hint}] is on hold/CancelAndWaitPrevious due to active T${opponent.transaction.id}[${opponent.transaction.hint}]`);
358
- this.transaction.cancel(error, opponent.transaction);
359
- opponent.transaction.cancel(new Error(`T${opponent.transaction.id}[${opponent.transaction.hint}] is canceled due to re-entering T${this.transaction.id}[${this.transaction.hint}]`), null);
360
- break;
361
- case Options_1.Reentrance.CancelPrevious:
362
- opponent.transaction.cancel(new Error(`T${opponent.transaction.id}[${opponent.transaction.hint}] is canceled due to re-entering T${this.transaction.id}[${this.transaction.hint}]`), null);
363
- break;
364
- case Options_1.Reentrance.RunSideBySide:
365
- break;
366
- }
367
- }
368
- if (!error)
369
- head.successor = this;
370
- else
371
- this.error = error;
372
- return this;
373
- }
374
- static run(op, proxy) {
375
- op.enter();
376
- try {
377
- op.result = op.options.getter.call(proxy, ...op.args);
378
- }
379
- finally {
380
- op.leaveOrAsync();
381
- }
382
- }
383
- enter() {
384
- if (this.options.monitor)
385
- this.monitorEnter(this.options.monitor);
386
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation)
387
- Dbg_1.Log.write('║', '‾\\', `${this.hint()} - enter`, undefined, ` [ ${Snapshot_1.Dump.obj(this.controller.ownHolder, this.controller.memberName)} ]`);
388
- this.started = Date.now();
389
- }
390
- leaveOrAsync() {
391
- if (this.result instanceof Promise) {
392
- this.result = this.result.then(value => {
393
- this.content = value;
394
- this.leave(false, ' ⚐', '- finished ', ' OK ──┘');
395
- return value;
396
- }, error => {
397
- this.error = error;
398
- this.leave(false, ' ⚐', '- finished ', 'ERR ──┘');
399
- throw error;
400
- });
401
- if (Dbg_1.Log.isOn) {
402
- if (Dbg_1.Log.opt.operation)
403
- Dbg_1.Log.write('║', '_/', `${this.hint()} - leave... `, 0, 'ASYNC ──┐');
404
- else if (Dbg_1.Log.opt.transaction)
405
- Dbg_1.Log.write('║', ' ', `${this.why()} ...`, 0, 'ASYNC');
406
- }
407
- }
408
- else {
409
- this.content = this.result;
410
- this.leave(true, '_/', '- leave');
411
- }
412
- }
413
- leave(main, op, message, highlight = undefined) {
414
- const ms = Date.now() - this.started;
415
- this.started = -this.started;
416
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.operation)
417
- Dbg_1.Log.write('║', `${op}`, `${this.hint()} ${message}`, ms, highlight);
418
- if (ms > (main ? Hooks_1.Hooks.mainThreadBlockingWarningThreshold : Hooks_1.Hooks.asyncActionDurationWarningThreshold))
419
- Dbg_1.Log.write('', '[!]', this.why(), ms, main ? ' *** main thread is too busy ***' : ' *** async is too long ***');
420
- this.cause = undefined;
421
- if (this.options.monitor)
422
- this.monitorLeave(this.options.monitor);
423
- }
424
- monitorEnter(mon) {
425
- const options = {
426
- hint: 'Monitor.enter',
427
- standalone: 'isolated',
428
- logging: Dbg_1.Log.isOn && Dbg_1.Log.opt.monitor ? undefined : Dbg_1.Log.global
429
- };
430
- OperationController.runWithin(undefined, Transaction_1.Transaction.run, options, Monitor_1.MonitorImpl.enter, mon, this.transaction);
431
- }
432
- monitorLeave(mon) {
433
- Transaction_1.Transaction.off(() => {
434
- const leave = () => {
435
- const options = {
436
- hint: 'Monitor.leave',
437
- standalone: 'isolated',
438
- logging: Dbg_1.Log.isOn && Dbg_1.Log.opt.monitor ? undefined : Dbg_1.Log.DefaultLevel
439
- };
440
- OperationController.runWithin(undefined, Transaction_1.Transaction.run, options, Monitor_1.MonitorImpl.leave, mon, this.transaction);
441
- };
442
- this.transaction.whenFinished().then(leave, leave);
443
- });
444
- }
445
- addToDeferredReactions() {
446
- Operation.deferredReactions.push(this);
447
- if (Operation.deferredReactions.length === 1)
448
- setTimeout(Operation.processDeferredReactions, 0);
449
- }
450
- static processDeferredReactions() {
451
- const reactions = Operation.deferredReactions;
452
- Operation.deferredReactions = [];
453
- for (const x of reactions)
454
- x.runIfNotUpToDate(true, true);
455
- }
456
- static markUsed(subscription, r, m, h, kind, weak) {
457
- if (kind !== Options_1.Kind.Transaction) {
458
- const op = Operation.current;
459
- if (op && op.options.kind !== Options_1.Kind.Transaction &&
460
- op.transaction === Transaction_1.Transaction.current && m !== Data_1.Meta.Holder) {
461
- const ctx = Snapshot_1.Snapshot.current();
462
- if (ctx !== r.snapshot)
463
- ctx.bumpBy(r.snapshot.timestamp);
464
- const t = weak ? -1 : ctx.timestamp;
465
- if (!op.subscribeTo(subscription, r, m, h, t))
466
- op.markObsoleteDueTo(subscription, m, r.snapshot, h, BOOT_CAUSE, ctx.timestamp, ctx.reactions);
467
- }
468
- }
469
- }
470
- static markEdited(oldValue, newValue, edited, r, m, h) {
471
- edited ? r.changes.add(m) : r.changes.delete(m);
472
- if (Dbg_1.Log.isOn && Dbg_1.Log.opt.write)
473
- edited ? Dbg_1.Log.write('║', ' ✎', `${Snapshot_1.Dump.rev2(h, r.snapshot, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`) : Dbg_1.Log.write('║', ' ✎', `${Snapshot_1.Dump.rev2(h, r.snapshot, m)} is changed from ${valueHint(oldValue, m)} to ${valueHint(newValue, m)}`, undefined, ' (same as previous)');
474
- }
475
- static isConflicting(oldValue, newValue) {
476
- let result = oldValue !== newValue;
477
- if (result)
478
- result = oldValue instanceof Operation && oldValue.cause !== BOOT_CAUSE;
479
- return result;
480
- }
481
- static propagateAllChangesThroughSubscriptions(snapshot) {
482
- var _a;
483
- const since = snapshot.timestamp;
484
- const reactions = snapshot.reactions;
485
- snapshot.changeset.forEach((r, h) => {
486
- if (!r.changes.has(Data_1.Meta.Disposed))
487
- r.changes.forEach((o, m) => Operation.propagateMemberChangeThroughSubscriptions(false, since, r, m, h, reactions));
488
- else
489
- for (const m in r.former.revision.data)
490
- Operation.propagateMemberChangeThroughSubscriptions(true, since, r, m, h, reactions);
491
- });
492
- reactions.sort(compareReactionsByOrder);
493
- (_a = snapshot.options.journal) === null || _a === void 0 ? void 0 : _a.edited(Journal_1.JournalImpl.buildPatch(snapshot.hint, snapshot.changeset));
494
- }
495
- static revokeAllSubscriptions(snapshot) {
496
- snapshot.changeset.forEach((r, h) => r.changes.forEach((o, m) => Operation.propagateMemberChangeThroughSubscriptions(true, snapshot.timestamp, r, m, h, undefined)));
497
- }
498
- static propagateMemberChangeThroughSubscriptions(unsubscribe, timestamp, r, m, h, reactions) {
499
- var _a;
500
- const curr = r.data[m];
501
- if (reactions) {
502
- const former = r.former.revision.data[m];
503
- if (former !== undefined && former instanceof Data_1.Subscription) {
504
- const why = `T${r.snapshot.id}[${r.snapshot.hint}]`;
505
- if (former instanceof Operation) {
506
- if ((former.obsoleteSince === Snapshot_1.MAX_TIMESTAMP || former.obsoleteSince <= 0)) {
507
- former.obsoleteDueTo = why;
508
- former.obsoleteSince = timestamp;
509
- former.unsubscribeFromAllSubscriptions();
510
- }
511
- const formerSuccessor = former.successor;
512
- if (formerSuccessor !== curr) {
513
- if (formerSuccessor && !formerSuccessor.transaction.isFinished)
514
- formerSuccessor.transaction.cancel(new Error(`T${formerSuccessor.transaction.id}[${formerSuccessor.transaction.hint}] is canceled by T${r.snapshot.id}[${r.snapshot.hint}] and will not run anymore`), null);
515
- }
516
- else
517
- former.successor = undefined;
518
- }
519
- (_a = former.subscribers) === null || _a === void 0 ? void 0 : _a.forEach(s => s.markObsoleteDueTo(former, m, r.snapshot, h, why, timestamp, reactions));
520
- }
521
- }
522
- if (curr instanceof Operation) {
523
- if (curr.snapshot === r.snapshot && curr.subscriptions !== undefined) {
524
- if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
525
- curr.subscriptions.forEach((info, v) => {
526
- if (info.usageCount > Hooks_1.Hooks.repetitiveUsageWarningThreshold)
527
- Dbg_1.Log.write('', '[!]', `${curr.hint()} uses ${info.memberHint} ${info.usageCount} times (consider remembering it in a local variable)`, 0, ' *** WARNING ***');
528
- });
529
- }
530
- if (unsubscribe)
531
- curr.unsubscribeFromAllSubscriptions();
532
- }
533
- }
534
- else if (curr instanceof Data_1.Subscription && curr.subscribers) {
535
- }
536
- }
537
- static enqueueReactionsToRun(reactions) {
538
- const queue = Operation.queuedReactions;
539
- const isReactionLoopRequired = queue.length === 0;
540
- for (const r of reactions)
541
- queue.push(r);
542
- if (isReactionLoopRequired)
543
- OperationController.runWithin(undefined, Operation.runQueuedReactionsLoop);
544
- }
545
- static runQueuedReactionsLoop() {
546
- const queue = Operation.queuedReactions;
547
- let i = 0;
548
- while (i < queue.length) {
549
- const reaction = queue[i];
550
- reaction.runIfNotUpToDate(false, true);
551
- i++;
552
- }
553
- Operation.queuedReactions = [];
554
- }
555
- unsubscribeFromAllSubscriptions() {
556
- var _a;
557
- (_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.forEach((info, value) => {
558
- var _a;
559
- value.subscribers.delete(this);
560
- if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
561
- Dbg_1.Log.write(Dbg_1.Log.opt.transaction && !Snapshot_1.Snapshot.current().sealed ? '║' : ' ', '-', `${this.hint()} is unsubscribed from ${info.memberHint}`);
562
- });
563
- this.subscriptions = undefined;
564
- }
565
- subscribeTo(subscription, r, m, h, timestamp) {
566
- var _a, _b, _c;
567
- const ok = Operation.canSubscribe(subscription, r, m, h, timestamp);
568
- if (ok) {
569
- let times = 0;
570
- if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
571
- const existing = this.subscriptions.get(subscription);
572
- times = existing ? existing.usageCount + 1 : 1;
573
- }
574
- if (this.subscriptions !== undefined) {
575
- if (!subscription.subscribers)
576
- subscription.subscribers = new Set();
577
- const info = { memberHint: Snapshot_1.Dump.rev2(h, r.snapshot, m), usageCount: times };
578
- subscription.subscribers.add(this);
579
- this.subscriptions.set(subscription, info);
580
- if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.read)))
581
- Dbg_1.Log.write('║', ' ∞ ', `${this.hint()} is subscribed to ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}${info.usageCount > 1 ? ` (${info.usageCount} times)` : ''}`);
582
- }
583
- else if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_b = this.options.logging) === null || _b === void 0 ? void 0 : _b.read)))
584
- Dbg_1.Log.write('║', ' x ', `${this.hint()} is obsolete and is NOT subscribed to ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}`);
585
- }
586
- else {
587
- if (Dbg_1.Log.isOn && (Dbg_1.Log.opt.read || ((_c = this.options.logging) === null || _c === void 0 ? void 0 : _c.read)))
588
- Dbg_1.Log.write('║', ' x ', `${this.hint()} is NOT subscribed to already obsolete ${Snapshot_1.Dump.rev2(h, r.snapshot, m)}`);
589
- }
590
- return ok;
591
- }
592
- static canSubscribe(subscription, r, m, h, timestamp) {
593
- let result = !r.snapshot.sealed || subscription === h.head.data[m];
594
- if (result && timestamp !== -1)
595
- result = !(subscription instanceof Operation && timestamp >= subscription.obsoleteSince);
596
- return result;
597
- }
598
- static createOperation(h, m, options) {
599
- const ctl = new OperationController(h, m);
600
- const operation = (...args) => {
601
- return ctl.useOrRun(false, args).result;
602
- };
603
- Data_1.Meta.set(operation, Data_1.Meta.Controller, ctl);
604
- return operation;
605
- }
606
- static rememberOperationOptions(proto, m, getter, setter, enumerable, configurable, options, implicit) {
607
- const initial = Data_1.Meta.acquire(proto, Data_1.Meta.Initial);
608
- let op = initial[m];
609
- const ctl = op ? op.controller : new OperationController(ROOT_HOLDER, m);
610
- const opts = op ? op.options : Hooks_1.OptionsImpl.INITIAL;
611
- initial[m] = op = new Operation(ctl, Snapshot_1.ROOT_REV.snapshot, new Hooks_1.OptionsImpl(getter, setter, opts, options, implicit));
612
- if (op.options.kind === Options_1.Kind.Reaction && op.options.throttling < Number.MAX_SAFE_INTEGER) {
613
- const reactions = Data_1.Meta.acquire(proto, Data_1.Meta.Reactions);
614
- reactions[m] = op;
615
- }
616
- else if (op.options.kind === Options_1.Kind.Reaction && op.options.throttling >= Number.MAX_SAFE_INTEGER) {
617
- const reactions = Data_1.Meta.getFrom(proto, Data_1.Meta.Reactions);
618
- delete reactions[m];
619
- }
620
- return op.options;
621
- }
622
- static init() {
623
- Object.freeze(BOOT_ARGS);
624
- Dbg_1.Log.getMergedLoggingOptions = getMergedLoggingOptions;
625
- Snapshot_1.Dump.valueHint = valueHint;
626
- Snapshot_1.Snapshot.markUsed = Operation.markUsed;
627
- Snapshot_1.Snapshot.markEdited = Operation.markEdited;
628
- Snapshot_1.Snapshot.isConflicting = Operation.isConflicting;
629
- Snapshot_1.Snapshot.propagateAllChangesThroughSubscriptions = Operation.propagateAllChangesThroughSubscriptions;
630
- Snapshot_1.Snapshot.revokeAllSubscriptions = Operation.revokeAllSubscriptions;
631
- Snapshot_1.Snapshot.enqueueReactionsToRun = Operation.enqueueReactionsToRun;
632
- Hooks_1.Hooks.createOperation = Operation.createOperation;
633
- Hooks_1.Hooks.rememberOperationOptions = Operation.rememberOperationOptions;
634
- Promise.prototype.then = reactronicHookedThen;
635
- try {
636
- Object.defineProperty(globalThis, 'rWhy', {
637
- get: OperationController.why, configurable: false, enumerable: false,
638
- });
639
- Object.defineProperty(globalThis, 'rBriefWhy', {
640
- get: OperationController.briefWhy, configurable: false, enumerable: false,
641
- });
642
- }
643
- catch (e) {
644
- }
645
- try {
646
- Object.defineProperty(global, 'rWhy', {
647
- get: OperationController.why, configurable: false, enumerable: false,
648
- });
649
- Object.defineProperty(global, 'rBriefWhy', {
650
- get: OperationController.briefWhy, configurable: false, enumerable: false,
651
- });
652
- }
653
- catch (e) {
654
- }
655
- }
656
- }
657
- Operation.current = undefined;
658
- Operation.queuedReactions = [];
659
- Operation.deferredReactions = [];
660
- function valueHint(value, m) {
661
- let result = '';
662
- if (Array.isArray(value))
663
- result = `Array(${value.length})`;
664
- else if (value instanceof Set)
665
- result = `Set(${value.size})`;
666
- else if (value instanceof Map)
667
- result = `Map(${value.size})`;
668
- else if (value instanceof Operation)
669
- result = `${Snapshot_1.Dump.rev2(value.controller.ownHolder, value.snapshot, m)}`;
670
- else if (value === Data_1.Meta.Disposed)
671
- result = '<disposed>';
672
- else if (value === Data_1.Meta.Undefined)
673
- result = '◌';
674
- else if (typeof (value) === 'string')
675
- result = `"${value.toString().slice(0, 20)}"`;
676
- else if (value !== undefined && value !== null)
677
- result = value.toString().slice(0, 20);
678
- else
679
- result = '◌';
680
- return result;
681
- }
682
- function getMergedLoggingOptions(local) {
683
- const t = Transaction_1.Transaction.current;
684
- let res = Dbg_1.Log.merge(t.options.logging, t.id > 1 ? 31 + t.id % 6 : 37, t.id > 1 ? `T${t.id}` : `-${Snapshot_1.Snapshot.idGen.toString().replace(/[0-9]/g, '-')}`, Dbg_1.Log.global);
685
- res = Dbg_1.Log.merge({ margin1: t.margin }, undefined, undefined, res);
686
- if (Operation.current)
687
- res = Dbg_1.Log.merge({ margin2: Operation.current.margin }, undefined, undefined, res);
688
- if (local)
689
- res = Dbg_1.Log.merge(local, undefined, undefined, res);
690
- return res;
691
- }
692
- const ORIGINAL_PROMISE_THEN = Promise.prototype.then;
693
- function reactronicHookedThen(resolve, reject) {
694
- const tran = Transaction_1.Transaction.current;
695
- if (!tran.isFinished) {
696
- if (!resolve)
697
- resolve = resolveReturn;
698
- if (!reject)
699
- reject = rejectRethrow;
700
- const op = Operation.current;
701
- if (op) {
702
- resolve = op.wrap(resolve);
703
- reject = op.wrap(reject);
704
- }
705
- resolve = tran.wrap(resolve, false);
706
- reject = tran.wrap(reject, true);
707
- }
708
- return ORIGINAL_PROMISE_THEN.call(this, resolve, reject);
709
- }
710
- function compareReactionsByOrder(a, b) {
711
- return a.order - b.order;
712
- }
713
- function resolveReturn(value) {
714
- return value;
715
- }
716
- exports.resolveReturn = resolveReturn;
717
- function rejectRethrow(error) {
718
- throw error;
719
- }
720
- exports.rejectRethrow = rejectRethrow;
721
- Operation.init();