reactronic 0.21.527 → 0.21.601

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 CHANGED
@@ -200,7 +200,7 @@ class Component<P> extends React.Component<P> {
200
200
  } // ensureUpToDate is subscribed to render
201
201
 
202
202
  shouldComponentUpdate(): boolean {
203
- return !Reactronic.getController(this.render).isUpToDate
203
+ return !Rx.getController(this.render).isUpToDate
204
204
  }
205
205
 
206
206
  componentDidMount(): void {
@@ -208,7 +208,7 @@ class Component<P> extends React.Component<P> {
208
208
  }
209
209
 
210
210
  componentWillUnmount(): void {
211
- standalone(Reactronic.dispose, this)
211
+ standalone(Rx.dispose, this)
212
212
  }
213
213
  }
214
214
  ```
@@ -14,10 +14,10 @@ export declare class Ref<T = any> {
14
14
  nonreactiveValue(): T;
15
15
  observe(): T;
16
16
  unobserve(): T;
17
- static to<O = any>(owner: O): {
17
+ static to<O extends object = object>(owner: O): {
18
18
  readonly [P in keyof O]-?: Ref<O[P]>;
19
19
  };
20
- static toToggle<O = any>(owner: O): {
20
+ static toToggle<O extends object = object>(owner: O): {
21
21
  readonly [P in keyof BoolOnly<O>]: ToggleRef<O[P]>;
22
22
  };
23
23
  static toCustomToggle<T, O extends object = any>(owner: O, value1: T, value2: T): {
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ToggleRef = exports.Ref = void 0;
4
4
  const Transaction_1 = require("./impl/Transaction");
5
- const Reactronic_1 = require("./Reactronic");
5
+ const Rx_1 = require("./Rx");
6
6
  class Ref {
7
7
  constructor(owner, name, index = -1) {
8
8
  this.owner = owner;
@@ -22,7 +22,7 @@ class Ref {
22
22
  this.owner[this.name][this.index] = value;
23
23
  }
24
24
  nonreactiveValue() {
25
- return (0, Reactronic_1.nonreactive)(() => this.value);
25
+ return (0, Rx_1.nonreactive)(() => this.value);
26
26
  }
27
27
  observe() {
28
28
  return this.value;
@@ -1,7 +1,7 @@
1
1
  import { F } from './util/Utils';
2
2
  import { Controller } from './Controller';
3
3
  import { MemberOptions, TraceOptions, ProfilingOptions } from './Options';
4
- export declare class Reactronic {
4
+ export declare class Rx {
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;
@@ -1,6 +1,6 @@
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 = void 0;
3
+ exports.options = exports.cached = exports.reaction = exports.transaction = exports.unobservable = exports.sensitive = exports.standalone = exports.nonreactive = exports.Rx = void 0;
4
4
  const Dbg_1 = require("./util/Dbg");
5
5
  const Options_1 = require("./Options");
6
6
  const Data_1 = require("./impl/Data");
@@ -8,10 +8,10 @@ const Snapshot_1 = require("./impl/Snapshot");
8
8
  const Hooks_1 = require("./impl/Hooks");
9
9
  const Operation_1 = require("./impl/Operation");
10
10
  const Transaction_1 = require("./impl/Transaction");
11
- class Reactronic {
11
+ class Rx {
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
- static pullLastResult(method, args) { return Reactronic.getController(method).pullLastResult(args); }
14
+ static pullLastResult(method, args) { return Rx.getController(method).pullLastResult(args); }
15
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); }
@@ -24,7 +24,7 @@ class Reactronic {
24
24
  static getTraceHint(obj, full = false) { return Data_1.ObjectHolder.getHint(obj, full); }
25
25
  static setProfilingMode(enabled, options) { Hooks_1.Hooks.setProfilingMode(enabled, options); }
26
26
  }
27
- exports.Reactronic = Reactronic;
27
+ exports.Rx = Rx;
28
28
  function nonreactive(func, ...args) {
29
29
  return Operation_1.OperationController.runWithin(undefined, func, ...args);
30
30
  }
@@ -11,4 +11,4 @@ export { Snapshot } from './impl/Snapshot';
11
11
  export { Transaction } from './impl/Transaction';
12
12
  export { Monitor } from './impl/Monitor';
13
13
  export { TransactionJournal } from './impl/TransactionJournal';
14
- export { Reactronic, nonreactive, standalone, sensitive, unobservable, transaction, reaction, cached, options } from './Reactronic';
14
+ export { Rx, nonreactive, standalone, sensitive, unobservable, transaction, reaction, cached, options } from './Rx';
@@ -1,6 +1,6 @@
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.pause = exports.all = void 0;
3
+ exports.options = exports.cached = exports.reaction = exports.transaction = exports.unobservable = exports.sensitive = exports.standalone = exports.nonreactive = exports.Rx = 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
6
  Object.defineProperty(exports, "pause", { enumerable: true, get: function () { return Utils_1.pause; } });
@@ -29,13 +29,13 @@ var Monitor_1 = require("./impl/Monitor");
29
29
  Object.defineProperty(exports, "Monitor", { enumerable: true, get: function () { return Monitor_1.Monitor; } });
30
30
  var TransactionJournal_1 = require("./impl/TransactionJournal");
31
31
  Object.defineProperty(exports, "TransactionJournal", { enumerable: true, get: function () { return TransactionJournal_1.TransactionJournal; } });
32
- var Reactronic_1 = require("./Reactronic");
33
- Object.defineProperty(exports, "Reactronic", { enumerable: true, get: function () { return Reactronic_1.Reactronic; } });
34
- Object.defineProperty(exports, "nonreactive", { enumerable: true, get: function () { return Reactronic_1.nonreactive; } });
35
- Object.defineProperty(exports, "standalone", { enumerable: true, get: function () { return Reactronic_1.standalone; } });
36
- Object.defineProperty(exports, "sensitive", { enumerable: true, get: function () { return Reactronic_1.sensitive; } });
37
- Object.defineProperty(exports, "unobservable", { enumerable: true, get: function () { return Reactronic_1.unobservable; } });
38
- Object.defineProperty(exports, "transaction", { enumerable: true, get: function () { return Reactronic_1.transaction; } });
39
- Object.defineProperty(exports, "reaction", { enumerable: true, get: function () { return Reactronic_1.reaction; } });
40
- Object.defineProperty(exports, "cached", { enumerable: true, get: function () { return Reactronic_1.cached; } });
41
- Object.defineProperty(exports, "options", { enumerable: true, get: function () { return Reactronic_1.options; } });
32
+ var Rx_1 = require("./Rx");
33
+ Object.defineProperty(exports, "Rx", { enumerable: true, get: function () { return Rx_1.Rx; } });
34
+ Object.defineProperty(exports, "nonreactive", { enumerable: true, get: function () { return Rx_1.nonreactive; } });
35
+ Object.defineProperty(exports, "standalone", { enumerable: true, get: function () { return Rx_1.standalone; } });
36
+ Object.defineProperty(exports, "sensitive", { enumerable: true, get: function () { return Rx_1.sensitive; } });
37
+ Object.defineProperty(exports, "unobservable", { enumerable: true, get: function () { return Rx_1.unobservable; } });
38
+ Object.defineProperty(exports, "transaction", { enumerable: true, get: function () { return Rx_1.transaction; } });
39
+ Object.defineProperty(exports, "reaction", { enumerable: true, get: function () { return Rx_1.reaction; } });
40
+ Object.defineProperty(exports, "cached", { enumerable: true, get: function () { return Rx_1.cached; } });
41
+ Object.defineProperty(exports, "options", { enumerable: true, get: function () { return Rx_1.options; } });
@@ -34,7 +34,8 @@ export declare class OperationController extends Controller<any> {
34
34
  }
35
35
  declare class Operation extends Observable implements Observer {
36
36
  static current?: Operation;
37
- static deferredReactions: Operation[];
37
+ static queuedReactions: Array<Observer>;
38
+ static deferredReactions: Array<Operation>;
38
39
  readonly margin: number;
39
40
  readonly transaction: Transaction;
40
41
  readonly controller: OperationController;
@@ -62,6 +63,7 @@ declare class Operation extends Observable implements Observer {
62
63
  run(proxy: any, args: any[] | undefined): void;
63
64
  markObsoleteDueTo(observable: Observable, cause: MemberInfo, since: number, reactions: Observer[]): void;
64
65
  runIfNotUpToDate(now: boolean, nothrow: boolean): void;
66
+ isNotUpToDate(): boolean;
65
67
  reenterOver(head: Operation): this;
66
68
  private static run;
67
69
  private enter;
@@ -77,6 +79,8 @@ declare class Operation extends Observable implements Observer {
77
79
  private static propagateAllChangesThroughSubscriptions;
78
80
  private static revokeAllSubscriptions;
79
81
  private static propagateMemberChangeThroughSubscriptions;
82
+ private static enqueueDetectedReactions;
83
+ private static runQueuedReactionsLoop;
80
84
  private unsubscribeFromAllObservables;
81
85
  private subscribeTo;
82
86
  private static canSubscribe;
@@ -102,7 +102,7 @@ class OperationController extends Controller_1.Controller {
102
102
  }
103
103
  static dependencies() {
104
104
  const op = Operation.current;
105
- return op ? op.dependencies() : ['Reactronic.dependencies should be called from inside of reactive method'];
105
+ return op ? op.dependencies() : ['Rx.dependencies should be called from inside of reactive method'];
106
106
  }
107
107
  peek(args) {
108
108
  const ctx = Snapshot_1.Snapshot.current();
@@ -298,8 +298,7 @@ class Operation extends Data_1.Observable {
298
298
  const interval = Date.now() + this.started;
299
299
  const hold = t ? t - interval : 0;
300
300
  if (now || hold < 0) {
301
- if (!this.error && (this.options.kind === Options_1.Kind.Transaction ||
302
- !this.successor || this.successor.transaction.isCanceled)) {
301
+ if (this.isNotUpToDate()) {
303
302
  try {
304
303
  const op = this.controller.useOrRun(false, undefined);
305
304
  if (op.result instanceof Promise)
@@ -323,6 +322,10 @@ class Operation extends Data_1.Observable {
323
322
  this.addToDeferredReactions();
324
323
  }
325
324
  }
325
+ isNotUpToDate() {
326
+ return !this.error && (this.options.kind === Options_1.Kind.Transaction ||
327
+ !this.successor || this.successor.transaction.isCanceled);
328
+ }
326
329
  reenterOver(head) {
327
330
  let error = undefined;
328
331
  const opponent = head.successor;
@@ -480,21 +483,26 @@ class Operation extends Data_1.Observable {
480
483
  static revokeAllSubscriptions(snapshot) {
481
484
  snapshot.changeset.forEach((r, h) => r.changes.forEach((o, m) => Operation.propagateMemberChangeThroughSubscriptions(true, snapshot.timestamp, r, m, h, undefined)));
482
485
  }
483
- static propagateMemberChangeThroughSubscriptions(discard, timestamp, r, m, h, reactions) {
486
+ static propagateMemberChangeThroughSubscriptions(unsubscribe, timestamp, r, m, h, reactions) {
484
487
  var _a;
488
+ const curr = r.data[m];
485
489
  if (reactions) {
486
490
  const prev = r.prev.revision.data[m];
487
491
  if (prev !== undefined && prev instanceof Data_1.Observable) {
488
492
  const cause = { revision: r, memberName: m, usageCount: 0 };
489
- if (prev instanceof Operation && (prev.obsoleteSince === Snapshot_1.MAX_TIMESTAMP || prev.obsoleteSince <= 0)) {
490
- prev.obsoleteDueTo = cause;
491
- prev.obsoleteSince = timestamp;
492
- prev.unsubscribeFromAllObservables();
493
+ if (prev instanceof Operation) {
494
+ if ((prev.obsoleteSince === Snapshot_1.MAX_TIMESTAMP || prev.obsoleteSince <= 0)) {
495
+ prev.obsoleteDueTo = cause;
496
+ prev.obsoleteSince = timestamp;
497
+ prev.unsubscribeFromAllObservables();
498
+ }
499
+ const opponent = prev.successor;
500
+ if (opponent !== curr && opponent && !opponent.transaction.isFinished)
501
+ opponent.transaction.cancel(new Error(`T${opponent.transaction.id}[${opponent.transaction.hint}] is canceled by T${r.snapshot.id}[${r.snapshot.hint}] and will not run anymore`), null);
493
502
  }
494
503
  (_a = prev.observers) === null || _a === void 0 ? void 0 : _a.forEach(c => c.markObsoleteDueTo(prev, cause, timestamp, reactions));
495
504
  }
496
505
  }
497
- const curr = r.data[m];
498
506
  if (curr instanceof Operation) {
499
507
  if (curr.revision === r && curr.observables !== undefined) {
500
508
  if (Hooks_1.Hooks.repetitiveUsageWarningThreshold < Number.MAX_SAFE_INTEGER) {
@@ -503,7 +511,7 @@ class Operation extends Data_1.Observable {
503
511
  Dbg_1.Dbg.log('', '[!]', `${curr.hint()} uses ${Snapshot_1.Dump.rev(hint.revision, hint.memberName)} ${hint.usageCount} times (consider remembering it in a local variable)`, 0, ' *** WARNING ***');
504
512
  });
505
513
  }
506
- if (discard)
514
+ if (unsubscribe)
507
515
  curr.unsubscribeFromAllObservables();
508
516
  }
509
517
  }
@@ -516,6 +524,24 @@ class Operation extends Data_1.Observable {
516
524
  curr.observers = undefined;
517
525
  }
518
526
  }
527
+ static enqueueDetectedReactions(snapshot) {
528
+ const queue = Operation.queuedReactions;
529
+ const isReactionLoopRequired = queue.length === 0;
530
+ for (const r of snapshot.reactions)
531
+ queue.push(r);
532
+ if (isReactionLoopRequired)
533
+ OperationController.runWithin(undefined, Operation.runQueuedReactionsLoop);
534
+ }
535
+ static runQueuedReactionsLoop() {
536
+ const queue = Operation.queuedReactions;
537
+ let i = 0;
538
+ while (i < queue.length) {
539
+ const reaction = queue[i];
540
+ reaction.runIfNotUpToDate(false, true);
541
+ i++;
542
+ }
543
+ Operation.queuedReactions = [];
544
+ }
519
545
  unsubscribeFromAllObservables() {
520
546
  var _a;
521
547
  (_a = this.observables) === null || _a === void 0 ? void 0 : _a.forEach((hint, value) => {
@@ -592,6 +618,7 @@ class Operation extends Data_1.Observable {
592
618
  Snapshot_1.Snapshot.isConflicting = Operation.isConflicting;
593
619
  Snapshot_1.Snapshot.propagateAllChangesThroughSubscriptions = Operation.propagateAllChangesThroughSubscriptions;
594
620
  Snapshot_1.Snapshot.revokeAllSubscriptions = Operation.revokeAllSubscriptions;
621
+ Snapshot_1.Snapshot.enqueueDetectedReactions = Operation.enqueueDetectedReactions;
595
622
  Hooks_1.Hooks.createControllerAndGetHook = Operation.createControllerAndGetHook;
596
623
  Hooks_1.Hooks.rememberOperationOptions = Operation.rememberOperationOptions;
597
624
  Promise.prototype.then = reactronicHookedThen;
@@ -618,6 +645,7 @@ class Operation extends Data_1.Observable {
618
645
  }
619
646
  }
620
647
  Operation.current = undefined;
648
+ Operation.queuedReactions = [];
621
649
  Operation.deferredReactions = [];
622
650
  function propagationHint(cause, full) {
623
651
  const result = [];
@@ -28,6 +28,7 @@ export declare class Snapshot implements AbstractSnapshot {
28
28
  static isConflicting: (oldValue: any, newValue: any) => boolean;
29
29
  static propagateAllChangesThroughSubscriptions: (snapshot: Snapshot) => void;
30
30
  static revokeAllSubscriptions: (snapshot: Snapshot) => void;
31
+ static enqueueDetectedReactions: (snapshot: Snapshot) => void;
31
32
  seekRevision(h: ObjectHolder, m: MemberName): ObjectRevision;
32
33
  getCurrentRevision(h: ObjectHolder, m: MemberName): ObjectRevision;
33
34
  getEditableRevision(h: ObjectHolder, m: MemberName, value: any, token?: any): ObjectRevision;
@@ -309,6 +309,7 @@ Snapshot.markEdited = Utils_1.UNDEF;
309
309
  Snapshot.isConflicting = Utils_1.UNDEF;
310
310
  Snapshot.propagateAllChangesThroughSubscriptions = (snapshot) => { };
311
311
  Snapshot.revokeAllSubscriptions = (snapshot) => { };
312
+ Snapshot.enqueueDetectedReactions = (snapshot) => { };
312
313
  class Dump {
313
314
  static obj(h, m, stamp, op, xop, typeless) {
314
315
  const member = m !== undefined ? `.${m.toString()}` : '';
@@ -230,16 +230,13 @@ class TransactionImpl extends Transaction {
230
230
  if (this.sealed && this.pending === 0) {
231
231
  this.applyOrDiscard();
232
232
  TransactionImpl.curr = outer;
233
- TransactionImpl.standalone(TransactionImpl.runReactions, this);
233
+ TransactionImpl.standalone(Snapshot_1.Snapshot.enqueueDetectedReactions, this.snapshot);
234
234
  }
235
235
  else
236
236
  TransactionImpl.curr = outer;
237
237
  }
238
238
  return result;
239
239
  }
240
- static runReactions(t) {
241
- t.snapshot.reactions.forEach(x => x.runIfNotUpToDate(false, true));
242
- }
243
240
  static seal(t, error, after) {
244
241
  if (!t.canceled && error) {
245
242
  t.canceled = error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactronic",
3
- "version": "0.21.527",
3
+ "version": "0.21.601",
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,17 +29,17 @@
29
29
  },
30
30
  "homepage": "https://github.com/nezaboodka/reactronic/blob/master/README.md#readme",
31
31
  "devDependencies": {
32
- "@types/node": "16.11.11",
32
+ "@types/node": "17.0.0",
33
33
  "@types/react": "17.0.37",
34
- "@typescript-eslint/eslint-plugin": "5.5.0",
35
- "@typescript-eslint/parser": "5.5.0",
34
+ "@typescript-eslint/eslint-plugin": "5.7.0",
35
+ "@typescript-eslint/parser": "5.7.0",
36
36
  "ava": "3.15.0",
37
- "eslint": "8.3.0",
37
+ "eslint": "8.4.1",
38
38
  "nyc": "15.1.0",
39
39
  "react": "17.0.2",
40
40
  "ts-node": "10.4.0",
41
41
  "tsconfig-paths": "3.12.0",
42
- "typescript": "4.4.3"
42
+ "typescript": "4.5.4"
43
43
  },
44
44
  "scripts": {
45
45
  "build": "eslint source/**/*.ts test/**/*.ts react/**/*.tsx && tsc",