reactronic 0.92.25004 → 0.92.25006

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
@@ -24,12 +24,12 @@ Transactional reactivity is based on four fundamental concepts:
24
24
 
25
25
  - **Observable Objects** - a set of objects that store data of an
26
26
  application (state);
27
- - **Applying Function** - it makes changes in observable
27
+ - **Atomic Action** - a function that makes changes in observable
28
28
  objects in atomic way ("all or nothing");
29
- - **Reaction Function** - it is executed automatically in
29
+ - **Reactive Process** - a function that is executed automatically in
30
30
  response to changes made by a transaction;
31
- - **Cache Function** - its result is remembered and, if the becomes
32
- obsolete, recomputed on-demand.
31
+ - **Cached Result** - function result that is remembered and, if the becomes
32
+ obsolete, causes its function to re-execute on-demand.
33
33
 
34
34
  Demo application built with Reactronic: https://nevod.io/#/playground.
35
35
  Source code of the demo: https://gitlab.com/nezaboodka/nevod.web.public/-/blob/master/README.md.
@@ -45,13 +45,13 @@ class Demo extends ObservableObject {
45
45
  name: string = 'Nezaboodka Software'
46
46
  email: string = 'contact@nezaboodka.com'
47
47
 
48
- @apply
48
+ @atomicAction
49
49
  saveContact(name: string, email: string): void {
50
50
  this.name = name
51
51
  this.email = email
52
52
  }
53
53
 
54
- @reaction
54
+ @reactiveProcess
55
55
  printContact(): void {
56
56
  // depends on `name` and `email` and reacts to their changes
57
57
  if (this.email.indexOf('@') >= 0)
@@ -63,25 +63,26 @@ class Demo extends ObservableObject {
63
63
 
64
64
  In the example above, `Demo` is an observable object,
65
65
  meaning that access to its fields are seamlessly tracked
66
- to determine dependent reactions and caches. Reaction
67
- function `printContact` reads `name` and `email` fields,
68
- thus depends on them. It is executed automatically in
69
- response to changes of these fields made by the applying
70
- function `saveContact`.
66
+ to determine dependent reactive processes and cached
67
+ results. Reactive process `printContact` reads `name`
68
+ and `email` fields, thus depends on them. It is executed
69
+ automatically in response to changes of these fields
70
+ made by the atomic action `saveContact`.
71
71
 
72
- Here is an example of a cached value (re-)computed on-demand:
72
+ Here is an example of a cached result that is
73
+ (re-)computed on-demand:
73
74
 
74
75
  ``` typescript
75
76
  class Demo extends ObservableObject {
76
77
  name: string = 'Nezaboodka Software'
77
78
  email: string = 'contact@nezaboodka.com'
78
79
 
79
- @cache
80
+ @cachedResult
80
81
  get contact(): string {
81
82
  return this.name + ' <' + this.email + '>'
82
83
  }
83
84
 
84
- @reaction
85
+ @reactiveProcess
85
86
  printContact(): void {
86
87
  if (this.contact !== '')
87
88
  Console.log(this.contact)
@@ -89,19 +90,22 @@ class Demo extends ObservableObject {
89
90
  }
90
91
  ```
91
92
 
92
- In the example above, the value of `contact` is computed from
93
- source fields `name` and `email` upon first use. Once computed,
94
- the result is cached and is reused until source fields `name`
95
- and `email` are changed. Once source fields changed, `contact`
96
- value becomes obsolete, thus causing execution of depending
97
- reaction function `printContact`. When `printContact` function
98
- runs it reads `contact` and causes its re-computation.
93
+ In the example above, the result of `contact` getter is
94
+ computed from source fields `name` and `email`. Once
95
+ computed, the result is cached and is reused until
96
+ source fields `name` and `email` are changed. Once
97
+ source fields changed, `contact` result becomes obsolete,
98
+ thus causing execution of depending reactive process
99
+ `printContact`. When function of reactive process
100
+ `printContact` runs it reads `contact` and causes its
101
+ re-computation.
99
102
 
100
103
  ## Observable Objects
101
104
 
102
- Observable objects store data of an application. All such objects
103
- are transparently hooked to track access to their properties,
104
- both on reads and writes.
105
+ Observable objects are aimed to store data of an
106
+ application. All such objects are transparently hooked
107
+ to track access to their properties, both on reads and
108
+ writes.
105
109
 
106
110
  ``` typescript
107
111
  class MyModel extends ObservableObject {
@@ -111,23 +115,23 @@ class MyModel extends ObservableObject {
111
115
  }
112
116
  ```
113
117
 
114
- In the example above, the class `MyModel` is based on Reactronic's
115
- `ObservableObject` class and all its properties `url`, `content`,
116
- and `timestamp` are hooked.
118
+ In the example above, the class `MyModel` is based on
119
+ Reactronic's `ObservableObject` class and all its
120
+ properties `url`, `content`, and `timestamp` are hooked.
117
121
 
118
- ## Apply
122
+ ## Atomic Action
119
123
 
120
- Applying function makes changes in observable objects
121
- in transactional (atomic) way, thus provoking execution
122
- of dependent reactions and recalculation of dependent
123
- caches. Applying function is instrumented with hooks to
124
- provide transparent atomicity (by implicit context
125
- switching and isolation).
124
+ Atomic action makes changes in observable objects
125
+ in atomic (transactional) way, thus provoking execution
126
+ of dependent reactive processes and recalculation of
127
+ dependent cached results. Atomic action function is
128
+ instrumented with hooks to provide transparent atomicity
129
+ (by implicit context switching and isolation).
126
130
 
127
131
  ``` typescript
128
132
  class MyModel extends ObservableObject {
129
133
  // ...
130
- @apply
134
+ @atomicAction
131
135
  async load(url: string): Promise<void> {
132
136
  this.url = url
133
137
  this.content = await fetch(url)
@@ -136,49 +140,54 @@ class MyModel extends ObservableObject {
136
140
  }
137
141
  ```
138
142
 
139
- In the example above, the applying function `load` makes
140
- changes to `url`, `content` and `timestamp` properties. While
141
- applying transaction is running, the changes are visible only inside the
142
- transaction itself. The new values become atomically visible outside
143
- of the transaction only upon its completion.
144
-
145
- Atomicity is achieved by making changes in an isolated data
146
- snapshot that is not visible outside of the running transaction
147
- until it is fully finished and applied. Multiple objects
148
- and their properties can be changed with full respect
149
- to the all-or-nothing principle. To do so, separate data
150
- snapshot is automatically maintained for each transaction.
151
- That is a logical snapshot that does not create a full copy
152
- of all the data.
153
-
154
- Compensating rollback operations are not needed in case of the
155
- transaction failure, because all the changes made by the transaction
156
- in its logical snapshot are simply discarded. In case the transaction
157
- is successfully applied, affected caches are marked as obsolete
158
- and corresponding caching functions are re-executed in a proper
159
- order (but only when all the data changes are fully applied).
160
-
161
- Asynchronous operations (promises) are supported out of the box
162
- during transaction execution. The transaction may consist of a set of
163
- asynchronous calls prolonging the transaction until completion of
164
- all of them. An asynchronous call may spawn other asynchronous
165
- calls, which prolong transaction execution until the whole chain
166
- of asynchronous operations is fully completed.
167
-
168
- ## Reaction & Cache
169
-
170
- Reaction function is automatically and immediately called in
171
- response to changes in observable objects made by an applying function.
172
- Cache function is called on-demand to renew the value if it was
173
- marked as obsolete due to changes made by an applying function.
174
- Reaction and cache functions are instrumented with hooks
175
- to seamlessly subscribe to those observable objects and
176
- other cache functions (dependencies), which are used
177
- during their execution.
143
+ In the example above, the atomic action `load` makes
144
+ changes to `url`, `content` and `timestamp` properties.
145
+ While atomic action is running, the changes are visible
146
+ only inside the action itself. The new values become
147
+ atomically visible outside of the action only upon its
148
+ completion.
149
+
150
+ Atomicity is achieved by making changes in an isolated
151
+ data snapshot that is not visible outside of the running
152
+ action until it is fully finished and applied. Multiple
153
+ objects and their properties can be changed with full
154
+ respect to the all-or-nothing principle. To do so,
155
+ separate data snapshot is automatically maintained for
156
+ each atomic action. That is a logical snapshot that does
157
+ not create a full copy of all the data.
158
+
159
+ Compensating rollback operations are not needed in case
160
+ of the atomic action failure, because all the changes
161
+ made by the atomic action in its logical snapshot are
162
+ simply discarded. In case the atomic action is
163
+ successfully applied, affected cached results are marked
164
+ as obsolete and corresponding caching functions are
165
+ re-executed in a proper order (but only when all the
166
+ data changes are fully applied).
167
+
168
+ Asynchronous operations (promises) are supported out of
169
+ the box during atomic action execution. Atomic action
170
+ may consist of a set of asynchronous calls prolonging
171
+ the action until completion of all of them. An
172
+ asynchronous call may spawn other asynchronous calls,
173
+ which prolong atomic atomic execution until the whole
174
+ chain of asynchronous operations is fully completed.
175
+
176
+ ## Reactive Process & Cached Result
177
+
178
+ Reactive process function is automatically and
179
+ immediately called in response to changes in observable
180
+ objects made by atomic actions. Function of cached result
181
+ is called on-demand to renew the result if it was marked
182
+ as obsolete due to changes made by an atomic action.
183
+ Functions of reactive processes and cached results are
184
+ instrumented with hooks to seamlessly subscribe to those
185
+ observable objects and other cached results
186
+ (dependencies), which are used during their execution.
178
187
 
179
188
  ``` tsx
180
189
  class MyView extends Component<{model: MyModel}> {
181
- @cache
190
+ @cachedResult
182
191
  render(): React.JSX.Element {
183
192
  return (
184
193
  <div>
@@ -192,72 +201,83 @@ class MyView extends Component<{model: MyModel}> {
192
201
 
193
202
  ``` tsx
194
203
  class Component<P> extends React.Component<P> {
195
- @cache
204
+ @cachedResult
196
205
  render(): React.JSX.Element {
197
206
  throw new Error('render method is undefined')
198
207
  }
199
208
 
200
- @reaction // called immediately in response to changes
209
+ @reactiveProcess // called in response to changes
201
210
  ensureUpToDate(): void {
202
- if (this.shouldComponentUpdate())
203
- Transaction.outside(() => this.setState({})) // ask React to re-render
204
- } // ensureUpToDate is subscribed to render
211
+ if (this.shouldComponentUpdate()) {
212
+ // Ask React to re-render
213
+ Transaction.outside(() => this.setState({}))
214
+ }
215
+ } // EnsureUpToDate is subscribed to render
205
216
 
206
217
  shouldComponentUpdate(): boolean {
207
218
  return !RxSystem.getController(this.render).isUpToDate
208
219
  }
209
220
 
210
221
  componentDidMount(): void {
211
- this.ensureUpToDate() // run to subscribe for the first time
222
+ // Run to subscribe for the first time
223
+ this.ensureUpToDate()
212
224
  }
213
225
 
214
226
  componentWillUnmount(): void {
215
- apply(RxSystem.dispose, this)
227
+ atomicAction(RxSystem.dispose, this)
216
228
  }
217
229
  }
218
230
  ```
219
231
 
220
- In the example above, reaction function `refresh` is transparently subscribed
221
- to the cache function `render`. In turn, cache function `render` is
222
- subscribed to the properties `url` and `content` of a corresponding
223
- `MyModel` object. Once `url` or `content` values are changed, the
224
- `render` cache becomes obsolete and causes the reaction function `refresh` to become
225
- obsolete as well and re-executed. While being executed, the reaction function `refresh`
226
- enqueues re-rendering request to React, which calls
227
- `render` function causing it to renew its cached value.
228
-
229
- In general case, all reactions and caches are automatically and
230
- immediately marked as obsolete when changes are made in those observable
231
- objects and other cached functions that were used during their execution.
232
- And once marked, the functions are automatically executed again,
233
- either immediately (for reaction functions) or on-demand
234
- (for cache functions).
235
-
236
- Reactronic takes full care of tracking dependencies between
237
- all the observable objects and reaction/caches.
238
- With Reactronic, you no longer need to create data change events
239
- in one set of objects, subscribe to these events in other objects,
240
- and manually maintain switching from the previous object version
241
- to a new one.
232
+ In the example above, reactive process `refresh` is
233
+ transparently subscribed to the cached result of
234
+ function `render`. In turn, cached result of function
235
+ `render` is subscribed to the properties `url` and
236
+ `content` of a corresponding `MyModel` object. Once
237
+ `url` or `content` values are changed, the `render`
238
+ cached result becomes obsolete and causes the reactive
239
+ process `refresh` to become obsolete and re-executed.
240
+ While being executed, the reactive process function
241
+ `refresh` enqueues re-rendering request to React, which
242
+ calls `render` function causing it to renew its cached
243
+ value.
244
+
245
+ In general case, all reactive processes and cached
246
+ results are automatically and immediately marked as
247
+ obsolete when changes are made in those observable
248
+ objects and other cached results that were used during
249
+ their execution. And once marked, the functions are
250
+ automatically executed again, either immediately (for
251
+ reactive processes) or on-demand (for cached results).
252
+
253
+ Reactronic takes full care of tracking dependencies
254
+ between all the observable objects and reactive processes
255
+ or cached results. With Reactronic, you no longer need
256
+ to create data change events in one set of objects,
257
+ subscribe to these events in other objects, and manually
258
+ maintain switching from the previous object version to a
259
+ new one.
242
260
 
243
261
  ## Behavior Options
244
262
 
245
- There are multiple options to configure behavior of transactional reactivity.
263
+ There are multiple options to configure behavior of
264
+ transactional reactivity.
246
265
 
247
- **Order** options defines order of execution for reactions:
266
+ **Order** options defines order of execution for
267
+ reactive processes:
248
268
 
249
269
  - (TBD)
250
270
 
251
- **Throttling** option defines how often reaction is executed in case
252
- of recurring changes:
271
+ **Throttling** option defines how often reactive process
272
+ is executed in case of recurring changes:
253
273
 
254
274
  - `(ms)` - minimal delay in milliseconds between executions;
255
- - `-1` - execute immediately once transaction is applied (synchronously);
275
+ - `-1` - execute immediately once atomic action is applied (synchronously);
256
276
  - `0` - execute immediately via event loop (asynchronously with zero timeout);
257
277
  - `>= Number.MAX_SAFE_INTEGER` - never execute (suspended reaction).
258
278
 
259
- **Reentrance** option defines how to handle reentrant calls of applying
260
- and reaction functions:
279
+ **Reentrance** option defines how to handle reentrant calls of atomic
280
+ actions and reactive processes:
261
281
 
262
282
  - `preventWithError` - fail with error if there is an existing call in progress;
263
283
  - `waitAndRestart` - wait for previous call to finish and then restart current one;
@@ -267,8 +287,8 @@ and reaction functions:
267
287
 
268
288
  **Indicator** is an object that maintains status of running functions,
269
289
  which it is attached to. A single indicator object can be shared between
270
- multiple transactional, reactive, and cached functions, thus maintaining
271
- consolidated status for all of them (busy, workers, etc).
290
+ multiple atomic actions, reactive processes, and cached results, thus
291
+ maintaining consolidated status for all of them (busy, workers, etc).
272
292
 
273
293
  ## Notes
274
294
 
@@ -305,9 +325,9 @@ class ObservableObject { }
305
325
 
306
326
  function observable(proto, prop) // field only
307
327
  function unobservable(proto, prop) // field only
308
- function apply(proto, prop, pd) // method only
309
- function reaction(proto, prop, pd) // method only
310
- function cache(proto, prop, pd) // method only
328
+ function atomicAction(proto, prop, pd) // method only
329
+ function reactiveProcess(proto, prop, pd) // method only
330
+ function cachedResult(proto, prop, pd) // method only
311
331
  function options(value: Partial<MemberOptions>): F<any>
312
332
 
313
333
  function nonreactive<T>(func: F<T>, ...args: any[]): T
@@ -338,9 +358,9 @@ type MemberOptions = {
338
358
 
339
359
  enum Kind {
340
360
  plain = 0,
341
- transaction = 1,
342
- reaction = 2,
343
- cache = 3
361
+ atomicAction = 1,
362
+ reactiveProcess = 2,
363
+ cachedResult = 3
344
364
  }
345
365
 
346
366
  enum Reentrance {
@@ -8,7 +8,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { ObservableObject } from "./core/Mvcc.js";
11
- import { apply } from "./ReactiveSystem.js";
11
+ import { atomicAction } from "./ReactiveSystem.js";
12
12
  export class Clock extends ObservableObject {
13
13
  constructor(interval = 1000) {
14
14
  super();
@@ -40,13 +40,13 @@ export class Clock extends ObservableObject {
40
40
  }
41
41
  }
42
42
  __decorate([
43
- apply,
43
+ atomicAction,
44
44
  __metadata("design:type", Function),
45
45
  __metadata("design:paramtypes", [Boolean]),
46
46
  __metadata("design:returntype", void 0)
47
47
  ], Clock.prototype, "pause", null);
48
48
  __decorate([
49
- apply,
49
+ atomicAction,
50
50
  __metadata("design:type", Function),
51
51
  __metadata("design:paramtypes", []),
52
52
  __metadata("design:returntype", void 0)
@@ -25,9 +25,9 @@ export type MemberOptions = {
25
25
  };
26
26
  export declare enum Kind {
27
27
  plain = 0,
28
- apply = 1,
29
- reaction = 2,
30
- cache = 3
28
+ atomicAction = 1,
29
+ reactiveProcess = 2,
30
+ cachedResult = 3
31
31
  }
32
32
  export declare enum Reentrance {
33
33
  preventWithError = 1,
@@ -2,9 +2,9 @@ export { LoggingLevel } from "./Logging.js";
2
2
  export var Kind;
3
3
  (function (Kind) {
4
4
  Kind[Kind["plain"] = 0] = "plain";
5
- Kind[Kind["apply"] = 1] = "apply";
6
- Kind[Kind["reaction"] = 2] = "reaction";
7
- Kind[Kind["cache"] = 3] = "cache";
5
+ Kind[Kind["atomicAction"] = 1] = "atomicAction";
6
+ Kind[Kind["reactiveProcess"] = 2] = "reactiveProcess";
7
+ Kind[Kind["cachedResult"] = 3] = "cachedResult";
8
8
  })(Kind || (Kind = {}));
9
9
  export var Reentrance;
10
10
  (function (Reentrance) {
@@ -1,6 +1,6 @@
1
1
  import { F } from "./util/Utils.js";
2
2
  import { ObservableObject } from "./core/Mvcc.js";
3
- export declare class Reaction<T> extends ObservableObject {
3
+ export declare class ReactiveProcess<T> extends ObservableObject {
4
4
  protected action: F<T>;
5
5
  constructor(action: F<T>);
6
6
  protected launch(): T;
@@ -8,8 +8,8 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { ObservableObject } from "./core/Mvcc.js";
11
- import { reaction } from "./ReactiveSystem.js";
12
- export class Reaction extends ObservableObject {
11
+ import { reactiveProcess } from "./ReactiveSystem.js";
12
+ export class ReactiveProcess extends ObservableObject {
13
13
  constructor(action) {
14
14
  super();
15
15
  this.action = action;
@@ -19,8 +19,8 @@ export class Reaction extends ObservableObject {
19
19
  }
20
20
  }
21
21
  __decorate([
22
- reaction,
22
+ reactiveProcess,
23
23
  __metadata("design:type", Function),
24
24
  __metadata("design:paramtypes", []),
25
25
  __metadata("design:returntype", Object)
26
- ], Reaction.prototype, "launch", null);
26
+ ], ReactiveProcess.prototype, "launch", null);
@@ -18,13 +18,15 @@ export declare class ReactiveSystem {
18
18
  static setProfilingMode(isOn: boolean, options?: Partial<ProfilingOptions>): void;
19
19
  }
20
20
  export declare function nonreactive<T>(func: F<T>, ...args: any[]): T;
21
+ export declare function nonreactive2<T>(options: SnapshotOptions, func: F<T>, ...args: any[]): T;
22
+ export declare function nonreactive2<T>(func: F<T>, ...args: any[]): T;
21
23
  export declare function sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
22
24
  export declare function contextually<T>(p: Promise<T>): Promise<T>;
23
- export declare function apply<T>(func: F<T>, ...args: any[]): T;
24
- export declare function apply<T>(options: SnapshotOptions, func: F<T>, ...args: any[]): T;
25
- export declare function apply(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
25
+ export declare function atomicAction<T>(func: F<T>, ...args: any[]): T;
26
+ export declare function atomicAction<T>(options: SnapshotOptions, func: F<T>, ...args: any[]): T;
27
+ export declare function atomicAction(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
26
28
  export declare function unobservable(proto: object, prop: PropertyKey): any;
27
29
  export declare function observable(proto: object, prop: PropertyKey): any;
28
- export declare function reaction(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
29
- export declare function cache(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
30
+ export declare function reactiveProcess(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
31
+ export declare function cachedResult(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
30
32
  export declare function options(value: Partial<MemberOptions>): F<any>;
@@ -25,13 +25,31 @@ export class ReactiveSystem {
25
25
  export function nonreactive(func, ...args) {
26
26
  return OperationImpl.proceedWithinGivenLaunch(undefined, func, ...args);
27
27
  }
28
+ export function nonreactive2(p1, p2, p3) {
29
+ if (p1 instanceof Function) {
30
+ return OperationImpl.proceedWithinGivenLaunch(undefined, () => {
31
+ if (p2 !== undefined)
32
+ return Transaction.run(null, p1, ...p2);
33
+ else
34
+ return Transaction.run(null, p1);
35
+ });
36
+ }
37
+ else {
38
+ return OperationImpl.proceedWithinGivenLaunch(undefined, () => {
39
+ if (p3 !== undefined)
40
+ return Transaction.run(p1, p2, ...p3);
41
+ else
42
+ return Transaction.run(p1, p2);
43
+ });
44
+ }
45
+ }
28
46
  export function sensitive(sensitivity, func, ...args) {
29
47
  return Mvcc.sensitive(sensitivity, func, ...args);
30
48
  }
31
49
  export function contextually(p) {
32
50
  throw new Error("not implemented yet");
33
51
  }
34
- export function apply(p1, p2, p3) {
52
+ export function atomicAction(p1, p2, p3) {
35
53
  if (p1 instanceof Function) {
36
54
  if (p2 !== undefined)
37
55
  return Transaction.run(null, p1, ...p2);
@@ -46,10 +64,10 @@ export function apply(p1, p2, p3) {
46
64
  }
47
65
  else {
48
66
  const opts = {
49
- kind: Kind.apply,
67
+ kind: Kind.atomicAction,
50
68
  isolation: Isolation.joinToCurrentTransaction,
51
69
  };
52
- return Mvcc.decorateOperation(true, apply, opts, p1, p2, p3);
70
+ return Mvcc.decorateOperation(true, atomicAction, opts, p1, p2, p3);
53
71
  }
54
72
  }
55
73
  export function unobservable(proto, prop) {
@@ -58,21 +76,21 @@ export function unobservable(proto, prop) {
58
76
  export function observable(proto, prop) {
59
77
  return Mvcc.decorateData(true, proto, prop);
60
78
  }
61
- export function reaction(proto, prop, pd) {
79
+ export function reactiveProcess(proto, prop, pd) {
62
80
  const opts = {
63
- kind: Kind.reaction,
81
+ kind: Kind.reactiveProcess,
64
82
  isolation: Isolation.joinAsNestedTransaction,
65
83
  throttling: -1,
66
84
  };
67
- return Mvcc.decorateOperation(true, reaction, opts, proto, prop, pd);
85
+ return Mvcc.decorateOperation(true, reactiveProcess, opts, proto, prop, pd);
68
86
  }
69
- export function cache(proto, prop, pd) {
87
+ export function cachedResult(proto, prop, pd) {
70
88
  const opts = {
71
- kind: Kind.cache,
89
+ kind: Kind.cachedResult,
72
90
  isolation: Isolation.joinToCurrentTransaction,
73
91
  noSideEffects: true,
74
92
  };
75
- return Mvcc.decorateOperation(true, cache, opts, proto, prop, pd);
93
+ return Mvcc.decorateOperation(true, cachedResult, opts, proto, prop, pd);
76
94
  }
77
95
  export function options(value) {
78
96
  return Mvcc.decorateOperationParametrized(options, value);
@@ -1,4 +1,4 @@
1
- import { apply, nonreactive } from "./ReactiveSystem.js";
1
+ import { atomicAction, nonreactive } from "./ReactiveSystem.js";
2
2
  export function refs(owner) {
3
3
  return new Proxy(owner, RefGettingProxy);
4
4
  }
@@ -52,7 +52,7 @@ export class ToggleRef extends Ref {
52
52
  toggle() {
53
53
  const o = this.owner;
54
54
  const p = this.name;
55
- apply({ hint: `toggle ${o.constructor.name}.${p}` }, () => {
55
+ atomicAction({ hint: `toggle ${o.constructor.name}.${p}` }, () => {
56
56
  const v = o[p];
57
57
  const isOn = v === this.valueOn || (v instanceof Ref && this.valueOn instanceof Ref &&
58
58
  Ref.sameRefs(v, this.valueOn));
@@ -16,8 +16,8 @@ export { Changeset } from "./core/Changeset.js";
16
16
  export { Transaction } from "./core/Transaction.js";
17
17
  export { Indicator } from "./core/Indicator.js";
18
18
  export { Journal } from "./core/Journal.js";
19
- export { ReactiveSystem, observable, unobservable, apply, reaction, cache, nonreactive, sensitive, contextually, options } from "./ReactiveSystem.js";
20
- export { Reaction } from "./Reaction.js";
19
+ export { ReactiveSystem, observable, unobservable, atomicAction, reactiveProcess, cachedResult, nonreactive, sensitive, contextually, options } from "./ReactiveSystem.js";
20
+ export { ReactiveProcess } from "./Reaction.js";
21
21
  export { ReactiveNode, Mode, Priority, BaseDriver, ReactiveNodeVariable } from "./core/ReactiveNode.js";
22
22
  export type { Script, ScriptAsync, Handler, ReactiveNodeDecl, ReactiveNodeDriver, ReactiveNodeContext } from "./core/ReactiveNode.js";
23
23
  export { Clock } from "./Clock.js";
@@ -12,7 +12,7 @@ export { Changeset } from "./core/Changeset.js";
12
12
  export { Transaction } from "./core/Transaction.js";
13
13
  export { Indicator } from "./core/Indicator.js";
14
14
  export { Journal } from "./core/Journal.js";
15
- export { ReactiveSystem, observable, unobservable, apply, reaction, cache, nonreactive, sensitive, contextually, options } from "./ReactiveSystem.js";
16
- export { Reaction } from "./Reaction.js";
15
+ export { ReactiveSystem, observable, unobservable, atomicAction, reactiveProcess, cachedResult, nonreactive, sensitive, contextually, options } from "./ReactiveSystem.js";
16
+ export { ReactiveProcess } from "./Reaction.js";
17
17
  export { ReactiveNode, Mode, Priority, BaseDriver, ReactiveNodeVariable } from "./core/ReactiveNode.js";
18
18
  export { Clock } from "./Clock.js";
@@ -99,7 +99,7 @@ export class OperationImpl {
99
99
  const ov = ctx.lookupObjectVersion(this.ownerHandle, this.fieldKey, false);
100
100
  const launch = this.acquireFromObjectVersion(ov, args);
101
101
  const applied = this.ownerHandle.applied.data[this.fieldKey];
102
- const isReusable = launch.options.kind !== Kind.apply && launch.cause !== BOOT_CAUSE &&
102
+ const isReusable = launch.options.kind !== Kind.atomicAction && launch.cause !== BOOT_CAUSE &&
103
103
  (ctx === launch.changeset || ctx.timestamp < launch.obsoleteSince || applied.obsoleteDueTo === undefined) &&
104
104
  (!launch.options.triggeringArgs || args === undefined ||
105
105
  launch.args.length === args.length && launch.args.every((t, i) => t === args[i])) || ov.disposed;
@@ -175,7 +175,7 @@ export class OperationImpl {
175
175
  }
176
176
  else {
177
177
  ror = this.peek(argsx);
178
- if (ror.launch.options.kind === Kind.apply || !ror.isReusable) {
178
+ if (ror.launch.options.kind === Kind.atomicAction || !ror.isReusable) {
179
179
  ror = this.edit();
180
180
  if (Log.isOn && Log.opt.operation)
181
181
  Log.write("║", " o", `${ror.launch.why()}`);
@@ -251,7 +251,7 @@ class Launch extends FieldVersion {
251
251
  let cause;
252
252
  if (this.cause)
253
253
  cause = ` ◀◀ ${this.cause}`;
254
- else if (this.operation.options.kind === Kind.apply)
254
+ else if (this.operation.options.kind === Kind.atomicAction)
255
255
  cause = " ◀◀ operation";
256
256
  else
257
257
  cause = ` ◀◀ T${this.changeset.id}[${this.changeset.hint}]`;
@@ -294,7 +294,7 @@ class Launch extends FieldVersion {
294
294
  changeset.id === this.lastEditorChangesetId;
295
295
  if (!skip) {
296
296
  const why = `${Dump.snapshot2(h, changeset, fk, observable)} ◀◀ ${outer}`;
297
- const isReactive = this.options.kind === Kind.reaction;
297
+ const isReactive = this.options.kind === Kind.reactiveProcess;
298
298
  this.obsoleteDueTo = why;
299
299
  this.obsoleteSince = since;
300
300
  if (Log.isOn && (Log.opt.obsolete || ((_a = this.options.logging) === null || _a === void 0 ? void 0 : _a.obsolete)))
@@ -326,14 +326,14 @@ class Launch extends FieldVersion {
326
326
  const launch = this.operation.reuseOrRelaunch(false, undefined);
327
327
  if (launch.result instanceof Promise)
328
328
  launch.result.catch(error => {
329
- if (launch.options.kind === Kind.reaction)
329
+ if (launch.options.kind === Kind.reactiveProcess)
330
330
  misuse(`reactive function ${launch.hint()} failed and will not run anymore: ${error}`, error);
331
331
  });
332
332
  }
333
333
  catch (e) {
334
334
  if (!nothrow)
335
335
  throw e;
336
- else if (this.options.kind === Kind.reaction)
336
+ else if (this.options.kind === Kind.reactiveProcess)
337
337
  misuse(`reactive ${this.hint()} failed and will not run anymore: ${e}`, e);
338
338
  }
339
339
  }
@@ -346,7 +346,7 @@ class Launch extends FieldVersion {
346
346
  }
347
347
  }
348
348
  isNotUpToDate() {
349
- return !this.error && (this.options.kind === Kind.apply ||
349
+ return !this.error && (this.options.kind === Kind.atomicAction ||
350
350
  !this.successor || this.successor.transaction.isCanceled);
351
351
  }
352
352
  reenterOver(head) {
@@ -469,9 +469,9 @@ class Launch extends FieldVersion {
469
469
  x.relaunchIfNotUpToDate(true, true);
470
470
  }
471
471
  static markUsed(observable, ov, fk, h, kind, weak) {
472
- if (kind !== Kind.apply) {
472
+ if (kind !== Kind.atomicAction) {
473
473
  const launch = Launch.current;
474
- if (launch && launch.options.kind !== Kind.apply &&
474
+ if (launch && launch.options.kind !== Kind.atomicAction &&
475
475
  launch.transaction === Transaction.current && fk !== Meta.Handle) {
476
476
  const ctx = Changeset.current();
477
477
  if (ctx !== ov.changeset)
@@ -652,11 +652,11 @@ class Launch extends FieldVersion {
652
652
  const rx = launch ? launch.operation : new OperationImpl(EMPTY_HANDLE, fk);
653
653
  const opts = launch ? launch.options : OptionsImpl.INITIAL;
654
654
  initial[fk] = launch = new Launch(Transaction.current, rx, EMPTY_OBJECT_VERSION.changeset, new OptionsImpl(getter, setter, opts, options, implicit), false);
655
- if (launch.options.kind === Kind.reaction && launch.options.throttling < Number.MAX_SAFE_INTEGER) {
655
+ if (launch.options.kind === Kind.reactiveProcess && launch.options.throttling < Number.MAX_SAFE_INTEGER) {
656
656
  const reactive = Meta.acquire(proto, Meta.Reactive);
657
657
  reactive[fk] = launch;
658
658
  }
659
- else if (launch.options.kind === Kind.reaction && launch.options.throttling >= Number.MAX_SAFE_INTEGER) {
659
+ else if (launch.options.kind === Kind.reactiveProcess && launch.options.throttling >= Number.MAX_SAFE_INTEGER) {
660
660
  const reactive = Meta.getFrom(proto, Meta.Reactive);
661
661
  delete reactive[fk];
662
662
  }
@@ -744,8 +744,8 @@ function reactronicHookedThen(resolve, reject) {
744
744
  resolve = launch.wrap(resolve);
745
745
  reject = launch.wrap(reject);
746
746
  }
747
- resolve = tran.wrap(resolve, false);
748
- reject = tran.wrap(reject, true);
747
+ resolve = tran.wrapAsPending(resolve, false);
748
+ reject = tran.wrapAsPending(reject, true);
749
749
  }
750
750
  return ORIGINAL_PROMISE_THEN.call(this, resolve, reject);
751
751
  }
@@ -22,7 +22,7 @@ import { emitLetters, getCallerInfo, proceedSyncOrAsync } from "../util/Utils.js
22
22
  import { Isolation, Reentrance } from "../Options.js";
23
23
  import { ObservableObject } from "../core/Mvcc.js";
24
24
  import { Transaction } from "../core/Transaction.js";
25
- import { ReactiveSystem, options, unobservable, reaction, nonreactive, apply } from "../ReactiveSystem.js";
25
+ import { ReactiveSystem, options, unobservable, reactiveProcess, nonreactive, atomicAction } from "../ReactiveSystem.js";
26
26
  export var Mode;
27
27
  (function (Mode) {
28
28
  Mode[Mode["default"] = 0] = "default";
@@ -339,7 +339,7 @@ class ReactiveNodeImpl extends ReactiveNode {
339
339
  node.outer = owner;
340
340
  else
341
341
  node.outer = owner.outer;
342
- apply({ isolation: Isolation.joinAsNestedTransaction }, () => {
342
+ atomicAction({ isolation: Isolation.joinAsNestedTransaction }, () => {
343
343
  const ctx = node.context;
344
344
  if (ctx) {
345
345
  ctx.variable = variable;
@@ -359,7 +359,7 @@ ReactiveNodeImpl.logging = undefined;
359
359
  ReactiveNodeImpl.grandNodeCount = 0;
360
360
  ReactiveNodeImpl.disposableNodeCount = 0;
361
361
  __decorate([
362
- reaction,
362
+ reactiveProcess,
363
363
  options({
364
364
  reentrance: Reentrance.cancelAndWaitPrevious,
365
365
  allowObsoleteToFinish: true,
@@ -546,7 +546,7 @@ function triggerFinalization(slot, isLeader, individual) {
546
546
  else
547
547
  gFirstToDispose = gLastToDispose = slot;
548
548
  if (gFirstToDispose === slot)
549
- apply({ isolation: Isolation.disjoinForInternalDisposal, hint: `runDisposalLoop(initiator=${slot.instance.key})` }, () => {
549
+ atomicAction({ isolation: Isolation.disjoinForInternalDisposal, hint: `runDisposalLoop(initiator=${slot.instance.key})` }, () => {
550
550
  void runDisposalLoop().then(NOP, error => console.log(error));
551
551
  });
552
552
  }
@@ -17,7 +17,7 @@ export declare abstract class Transaction implements Worker {
17
17
  abstract inspect<T>(func: F<T>, ...args: any[]): T;
18
18
  abstract apply(): void;
19
19
  abstract seal(): this;
20
- abstract wrap<T>(func: F<T>, secondary: boolean): F<T>;
20
+ abstract wrapAsPending<T>(func: F<T>, secondary: boolean): F<T>;
21
21
  abstract cancel(error: Error, retryAfterOrIgnore?: Worker | null): this;
22
22
  abstract readonly isCanceled: boolean;
23
23
  abstract readonly isFinished: boolean;
@@ -33,7 +33,7 @@ export declare abstract class Transaction implements Worker {
33
33
  export declare class TransactionImpl extends Transaction {
34
34
  private static readonly none;
35
35
  private static curr;
36
- private static inspection;
36
+ private static isInspectionMode;
37
37
  private static frameStartTime;
38
38
  private static frameOverCounter;
39
39
  readonly margin: number;
@@ -57,9 +57,9 @@ export declare class TransactionImpl extends Transaction {
57
57
  inspect<T>(func: F<T>, ...args: any[]): T;
58
58
  apply(): void;
59
59
  seal(): this;
60
- wrap<T>(func: F<T>, error: boolean): F<T>;
61
- private static wrapperEnter;
62
- private static wrapperLeave;
60
+ wrapAsPending<T>(func: F<T>, secondary: boolean): F<T>;
61
+ private static preparePendingFunction;
62
+ private static runPendingFunction;
63
63
  cancel(error: Error, restartAfter?: Worker | null): this;
64
64
  get isCanceled(): boolean;
65
65
  get isFinished(): boolean;
@@ -50,15 +50,15 @@ export class TransactionImpl extends Transaction {
50
50
  return this.runImpl(undefined, func, ...args);
51
51
  }
52
52
  inspect(func, ...args) {
53
- const restore = TransactionImpl.inspection;
53
+ const outer = TransactionImpl.isInspectionMode;
54
54
  try {
55
- TransactionImpl.inspection = true;
55
+ TransactionImpl.isInspectionMode = true;
56
56
  if (Log.isOn && Log.opt.transaction)
57
57
  Log.write(" ", " ", `T${this.id}[${this.hint}] is being inspected by T${TransactionImpl.curr.id}[${TransactionImpl.curr.hint}]`);
58
58
  return this.runImpl(undefined, func, ...args);
59
59
  }
60
60
  finally {
61
- TransactionImpl.inspection = restore;
61
+ TransactionImpl.isInspectionMode = outer;
62
62
  }
63
63
  }
64
64
  apply() {
@@ -73,27 +73,27 @@ export class TransactionImpl extends Transaction {
73
73
  this.run(TransactionImpl.seal, this, undefined, undefined);
74
74
  return this;
75
75
  }
76
- wrap(func, error) {
76
+ wrapAsPending(func, secondary) {
77
77
  this.guard();
78
78
  const self = this;
79
- const inspect = TransactionImpl.inspection;
80
- if (!inspect)
81
- self.run(TransactionImpl.wrapperEnter, self, error);
79
+ const inspection = TransactionImpl.isInspectionMode;
80
+ if (!inspection)
81
+ self.run(TransactionImpl.preparePendingFunction, self, secondary);
82
82
  else
83
- self.inspect(TransactionImpl.wrapperEnter, self, error);
84
- const wrappedForTransaction = (...args) => {
85
- if (!inspect)
86
- return self.runImpl(undefined, TransactionImpl.wrapperLeave, self, error, func, ...args);
83
+ self.inspect(TransactionImpl.preparePendingFunction, self, secondary);
84
+ const wrappedAsPendingForTransaction = (...args) => {
85
+ if (!inspection)
86
+ return self.runImpl(undefined, TransactionImpl.runPendingFunction, self, secondary, func, ...args);
87
87
  else
88
- return self.inspect(TransactionImpl.wrapperLeave, self, error, func, ...args);
88
+ return self.inspect(TransactionImpl.runPendingFunction, self, secondary, func, ...args);
89
89
  };
90
- return wrappedForTransaction;
90
+ return wrappedAsPendingForTransaction;
91
91
  }
92
- static wrapperEnter(t, error) {
93
- if (!error)
92
+ static preparePendingFunction(t, secondary) {
93
+ if (!secondary)
94
94
  t.pending++;
95
95
  }
96
- static wrapperLeave(t, error, func, ...args) {
96
+ static runPendingFunction(t, secondary, func, ...args) {
97
97
  t.pending--;
98
98
  const result = func(...args);
99
99
  return result;
@@ -118,10 +118,10 @@ export class TransactionImpl extends Transaction {
118
118
  }
119
119
  static run(options, func, ...args) {
120
120
  const t = TransactionImpl.acquire(options);
121
- const root = t !== TransactionImpl.curr;
121
+ const isRoot = t !== TransactionImpl.curr;
122
122
  t.guard();
123
123
  let result = t.runImpl(options === null || options === void 0 ? void 0 : options.logging, func, ...args);
124
- if (root) {
124
+ if (isRoot) {
125
125
  if (result instanceof Promise) {
126
126
  result = TransactionImpl.outside(() => {
127
127
  return t.wrapToRetry(t.wrapToWaitUntilFinish(result), func, ...args);
@@ -231,7 +231,7 @@ export class TransactionImpl extends Transaction {
231
231
  }
232
232
  }
233
233
  catch (e) {
234
- if (!TransactionImpl.inspection)
234
+ if (!TransactionImpl.isInspectionMode)
235
235
  this.cancel(e);
236
236
  throw e;
237
237
  }
@@ -460,7 +460,7 @@ export class TransactionImpl extends Transaction {
460
460
  return TransactionImpl.curr.changeset;
461
461
  }
462
462
  static getEditableChangeset() {
463
- if (TransactionImpl.inspection)
463
+ if (TransactionImpl.isInspectionMode)
464
464
  throw misuse("cannot make changes during transaction inspection");
465
465
  return TransactionImpl.curr.changeset;
466
466
  }
@@ -474,7 +474,7 @@ export class TransactionImpl extends Transaction {
474
474
  }
475
475
  TransactionImpl.none = new TransactionImpl({ hint: "<none>" });
476
476
  TransactionImpl.curr = TransactionImpl.none;
477
- TransactionImpl.inspection = false;
477
+ TransactionImpl.isInspectionMode = false;
478
478
  TransactionImpl.frameStartTime = 0;
479
479
  TransactionImpl.frameOverCounter = 0;
480
480
  TransactionImpl.migrateFieldVersion = function (fv, target) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "reactronic",
3
- "version": "0.92.25004",
3
+ "version": "0.92.25006",
4
4
  "description": "Reactronic - Transactional Reactive State Management",
5
5
  "publisher": "Nezaboodka Software",
6
6
  "license": "Apache-2.0",