reactronic 0.22.210 → 0.22.300
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 +22 -22
- package/build/dist/source/Buffer.d.ts +2 -2
- package/build/dist/source/Buffer.js +1 -1
- package/build/dist/source/Ref.d.ts +1 -1
- package/build/dist/source/Ref.js +2 -2
- package/build/dist/source/Rx.d.ts +2 -2
- package/build/dist/source/Rx.js +6 -6
- package/build/dist/source/api.d.ts +2 -2
- package/build/dist/source/api.js +4 -4
- package/build/dist/source/impl/Data.d.ts +20 -20
- package/build/dist/source/impl/Data.js +12 -12
- package/build/dist/source/impl/Hooks.d.ts +13 -13
- package/build/dist/source/impl/Hooks.js +34 -34
- package/build/dist/source/impl/Journal.d.ts +15 -15
- package/build/dist/source/impl/Journal.js +11 -11
- package/build/dist/source/impl/Meta.d.ts +1 -1
- package/build/dist/source/impl/Meta.js +1 -1
- package/build/dist/source/impl/Monitor.d.ts +2 -2
- package/build/dist/source/impl/Monitor.js +1 -1
- package/build/dist/source/impl/Operation.d.ts +9 -9
- package/build/dist/source/impl/Operation.js +40 -40
- package/build/dist/source/impl/Snapshot.d.ts +23 -23
- package/build/dist/source/impl/Snapshot.js +22 -22
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,13 +19,13 @@ isolated data snapshot and then, once atomically applied, are
|
|
|
19
19
|
**consistently propagated** to corresponding visual components for
|
|
20
20
|
(re)rendering. All that is done in automatic, seamless, and fine-grained
|
|
21
21
|
way, because reactronic **takes full care of tracking dependencies**
|
|
22
|
-
between visual components (
|
|
22
|
+
between visual components (subscribers) and state (subscribing objects).
|
|
23
23
|
|
|
24
24
|
Transactional reactivity is based on four fundamental concepts:
|
|
25
25
|
|
|
26
|
-
- **
|
|
27
|
-
application (state);
|
|
28
|
-
- **Transaction** - a function that makes changes in
|
|
26
|
+
- **Subscribing Objects** - a set of objects that store data of an
|
|
27
|
+
application (state) and maintain subscription lists;
|
|
28
|
+
- **Transaction** - a function that makes changes in subscribing
|
|
29
29
|
objects in transactional (atomic) way;
|
|
30
30
|
- **Reaction** - a function that is executed automatically in
|
|
31
31
|
response to changes made by a transaction;
|
|
@@ -39,11 +39,11 @@ Quick introduction and detailed description is below.
|
|
|
39
39
|
|
|
40
40
|
## Quick Introduction
|
|
41
41
|
|
|
42
|
-
Here is an example of transactional reactive code with
|
|
43
|
-
object, transaction and reaction:
|
|
42
|
+
Here is an example of transactional reactive code with
|
|
43
|
+
subscribing object, transaction and reaction:
|
|
44
44
|
|
|
45
45
|
``` typescript
|
|
46
|
-
class Demo extends
|
|
46
|
+
class Demo extends SubscribingObject {
|
|
47
47
|
name: string = 'Nezaboodka Software'
|
|
48
48
|
email: string = 'contact@nezaboodka.com'
|
|
49
49
|
|
|
@@ -70,7 +70,7 @@ to changes of these fields made by `saveContact` transaction.
|
|
|
70
70
|
Here is an example of if cached value computed on-demand:
|
|
71
71
|
|
|
72
72
|
``` typescript
|
|
73
|
-
class Demo extends
|
|
73
|
+
class Demo extends SubscribingObject {
|
|
74
74
|
name: string = 'Nezaboodka Software'
|
|
75
75
|
email: string = 'contact@nezaboodka.com'
|
|
76
76
|
|
|
@@ -95,14 +95,14 @@ invalidated, thus causing execution of depending reaction
|
|
|
95
95
|
`printContact`. Then `printContact` reaction causes `contact`
|
|
96
96
|
re-computation on the first use.
|
|
97
97
|
|
|
98
|
-
##
|
|
98
|
+
## Subscribing Objects
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
Subscribing objects store data of an application. All such objects
|
|
101
101
|
are transparently hooked to track access to their properties,
|
|
102
102
|
both on reads and writes.
|
|
103
103
|
|
|
104
104
|
``` typescript
|
|
105
|
-
class MyModel extends
|
|
105
|
+
class MyModel extends SubscribingObject {
|
|
106
106
|
url: string = "https://github.com/nezaboodka/reactronic"
|
|
107
107
|
content: string = "transactional reactive state management"
|
|
108
108
|
timestamp: Date = Date.now()
|
|
@@ -110,18 +110,18 @@ class MyModel extends ObservableObject {
|
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
In the example above, the class `MyModel` is based on Reactronic's
|
|
113
|
-
`
|
|
113
|
+
`SubscribingObject` class and all its properties `url`, `content`,
|
|
114
114
|
and `timestamp` are hooked.
|
|
115
115
|
|
|
116
116
|
## Transaction
|
|
117
117
|
|
|
118
|
-
Transaction is a function that makes changes in
|
|
118
|
+
Transaction is a function that makes changes in subscribing objects
|
|
119
119
|
in transactional (atomic) way. Such a function is instrumented with hooks
|
|
120
120
|
to provide transparent atomicity (by implicit context switching
|
|
121
121
|
and isolation).
|
|
122
122
|
|
|
123
123
|
``` typescript
|
|
124
|
-
class MyModel extends
|
|
124
|
+
class MyModel extends SubscribingObject {
|
|
125
125
|
// ...
|
|
126
126
|
@transaction
|
|
127
127
|
async load(url: string): Promise<void> {
|
|
@@ -164,12 +164,12 @@ of asynchronous operations is fully completed.
|
|
|
164
164
|
## Reaction & Cache
|
|
165
165
|
|
|
166
166
|
Reaction is an code block that is immediately called in response to
|
|
167
|
-
changes made by a transaction in
|
|
167
|
+
changes made by a transaction in subscribing objects. Cache is a
|
|
168
168
|
computed value having an associated function that is called
|
|
169
169
|
on-demand to renew the value if it was marked as obsolete due to changes
|
|
170
170
|
made by a transaction. Reactive and cached functions are
|
|
171
171
|
instrumented with hooks to seamlessly subscribe to those
|
|
172
|
-
|
|
172
|
+
subscribing objects and other cached functions (dependencies),
|
|
173
173
|
which are used during their execution.
|
|
174
174
|
|
|
175
175
|
``` tsx
|
|
@@ -223,15 +223,15 @@ function enqueues re-rendering request to React, which calls
|
|
|
223
223
|
`render` function causing it to renew its cached value.
|
|
224
224
|
|
|
225
225
|
In general case, all reactions and caches are automatically and
|
|
226
|
-
immediately marked as obsolete when changes are made in those
|
|
226
|
+
immediately marked as obsolete when changes are made in those subscribing
|
|
227
227
|
objects and cached functions that were used during their execution.
|
|
228
228
|
And once marked, the functions are automatically executed again,
|
|
229
229
|
either immediately (for @reactive functions) or on-demand
|
|
230
230
|
(for @cached functions).
|
|
231
231
|
|
|
232
232
|
Reactronic takes full care of tracking dependencies between
|
|
233
|
-
all the
|
|
234
|
-
With Reactronic, you no longer need to create data change events
|
|
233
|
+
all the subscribing objects and reactions/caches (subscribing objects
|
|
234
|
+
and subscribers). With Reactronic, you no longer need to create data change events
|
|
235
235
|
in one set of objects, subscribe to these events in other objects,
|
|
236
236
|
and manually maintain switching from the previous object version
|
|
237
237
|
to a new one.
|
|
@@ -292,17 +292,17 @@ NPM: `npm install reactronic`
|
|
|
292
292
|
|
|
293
293
|
// Classes
|
|
294
294
|
|
|
295
|
-
class
|
|
295
|
+
class SubscribingObject { }
|
|
296
296
|
|
|
297
297
|
// Decorators & Operators
|
|
298
298
|
|
|
299
|
-
function
|
|
299
|
+
function subscribeless(proto, prop) // field only
|
|
300
300
|
function transaction(proto, prop, pd) // method only
|
|
301
301
|
function reaction(proto, prop, pd) // method only
|
|
302
302
|
function cached(proto, prop, pd) // method only
|
|
303
303
|
function options(value: Partial<MemberOptions>): F<any>
|
|
304
304
|
|
|
305
|
-
function
|
|
305
|
+
function nonsubscribing<T>(func: F<T>, ...args: any[]): T
|
|
306
306
|
function sensitive<T>(sensitivity: Sensitivity, func: F<T>, ...args: any[]): T
|
|
307
307
|
|
|
308
308
|
// SnapshotOptions, MemberOptions, Kind, Reentrance, Monitor, LoggingOptions, ProfilingOptions
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare abstract class Buffer<T> extends
|
|
1
|
+
import { SubscribingObject } from './impl/Hooks';
|
|
2
|
+
export declare abstract class Buffer<T> extends SubscribingObject {
|
|
3
3
|
abstract readonly capacity: number;
|
|
4
4
|
abstract readonly count: number;
|
|
5
5
|
abstract put(...items: T[]): void;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Buffer = void 0;
|
|
4
4
|
const Hooks_1 = require("./impl/Hooks");
|
|
5
|
-
class Buffer extends Hooks_1.
|
|
5
|
+
class Buffer extends Hooks_1.SubscribingObject {
|
|
6
6
|
static create(hint, capacity) { throw new Error('not implemented'); }
|
|
7
7
|
}
|
|
8
8
|
exports.Buffer = Buffer;
|
|
@@ -11,7 +11,7 @@ export declare class Ref<T = any> {
|
|
|
11
11
|
constructor(owner: any, name: string, index?: number);
|
|
12
12
|
get value(): T;
|
|
13
13
|
set value(value: T);
|
|
14
|
-
|
|
14
|
+
nonsubscribing(): T;
|
|
15
15
|
observe(): T;
|
|
16
16
|
unobserve(): T;
|
|
17
17
|
static to<O extends object = object>(owner: O): {
|
package/build/dist/source/Ref.js
CHANGED
|
@@ -21,8 +21,8 @@ class Ref {
|
|
|
21
21
|
else
|
|
22
22
|
this.owner[this.name][this.index] = value;
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
return (0, Rx_1.
|
|
24
|
+
nonsubscribing() {
|
|
25
|
+
return (0, Rx_1.nonsubscribing)(() => this.value);
|
|
26
26
|
}
|
|
27
27
|
observe() {
|
|
28
28
|
return this.value;
|
|
@@ -17,9 +17,9 @@ export declare class Rx {
|
|
|
17
17
|
static getLoggingHint<T extends object>(obj: T, full?: boolean): string | undefined;
|
|
18
18
|
static setProfilingMode(isOn: boolean, options?: Partial<ProfilingOptions>): void;
|
|
19
19
|
}
|
|
20
|
-
export declare function
|
|
20
|
+
export declare function nonsubscribing<T>(func: F<T>, ...args: any[]): T;
|
|
21
21
|
export declare function sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function subscribeless(proto: object, prop: PropertyKey): any;
|
|
23
23
|
export declare function transaction(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
|
|
24
24
|
export declare function reaction(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
|
|
25
25
|
export declare function cached(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
|
package/build/dist/source/Rx.js
CHANGED
|
@@ -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.
|
|
3
|
+
exports.options = exports.cached = exports.reaction = exports.transaction = exports.subscribeless = exports.sensitive = exports.nonsubscribing = 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");
|
|
@@ -20,22 +20,22 @@ class Rx {
|
|
|
20
20
|
static get loggingOptions() { return Dbg_1.Log.opt; }
|
|
21
21
|
static setLoggingMode(isOn, options) { Dbg_1.Log.setMode(isOn, options); }
|
|
22
22
|
static setLoggingHint(obj, name) { Hooks_1.Hooks.setHint(obj, name); }
|
|
23
|
-
static getLoggingHint(obj, full = false) { return Data_1.
|
|
23
|
+
static getLoggingHint(obj, full = false) { return Data_1.DataHolder.getHint(obj, full); }
|
|
24
24
|
static setProfilingMode(isOn, options) { Hooks_1.Hooks.setProfilingMode(isOn, options); }
|
|
25
25
|
}
|
|
26
26
|
exports.Rx = Rx;
|
|
27
|
-
function
|
|
27
|
+
function nonsubscribing(func, ...args) {
|
|
28
28
|
return Operation_1.OperationController.runWithin(undefined, func, ...args);
|
|
29
29
|
}
|
|
30
|
-
exports.
|
|
30
|
+
exports.nonsubscribing = nonsubscribing;
|
|
31
31
|
function sensitive(sensitivity, func, ...args) {
|
|
32
32
|
return Hooks_1.Hooks.sensitive(sensitivity, func, ...args);
|
|
33
33
|
}
|
|
34
34
|
exports.sensitive = sensitive;
|
|
35
|
-
function
|
|
35
|
+
function subscribeless(proto, prop) {
|
|
36
36
|
return Hooks_1.Hooks.decorateData(false, proto, prop);
|
|
37
37
|
}
|
|
38
|
-
exports.
|
|
38
|
+
exports.subscribeless = subscribeless;
|
|
39
39
|
function transaction(proto, prop, pd) {
|
|
40
40
|
const opts = { kind: Options_1.Kind.Transaction };
|
|
41
41
|
return Hooks_1.Hooks.decorateOperation(true, transaction, opts, proto, prop, pd);
|
|
@@ -6,9 +6,9 @@ export { MemberOptions, SnapshotOptions, Kind, Reentrance, LoggingOptions, Profi
|
|
|
6
6
|
export { Worker } from './Worker';
|
|
7
7
|
export { Controller } from './Controller';
|
|
8
8
|
export { Ref, ToggleRef, BoolOnly, GivenTypeOnly } from './Ref';
|
|
9
|
-
export {
|
|
9
|
+
export { SubscribingObject } from './impl/Hooks';
|
|
10
10
|
export { Snapshot } from './impl/Snapshot';
|
|
11
11
|
export { Transaction } from './impl/Transaction';
|
|
12
12
|
export { Monitor } from './impl/Monitor';
|
|
13
13
|
export { Journal } from './impl/Journal';
|
|
14
|
-
export { Rx,
|
|
14
|
+
export { Rx, nonsubscribing, sensitive, subscribeless, transaction, reaction, cached, options } from './Rx';
|
package/build/dist/source/api.js
CHANGED
|
@@ -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.
|
|
3
|
+
exports.options = exports.cached = exports.reaction = exports.transaction = exports.subscribeless = exports.sensitive = exports.nonsubscribing = exports.Rx = exports.Journal = exports.Monitor = exports.Transaction = exports.Snapshot = exports.SubscribingObject = exports.ToggleRef = exports.Ref = exports.Controller = exports.LoggingLevel = 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; } });
|
|
@@ -20,7 +20,7 @@ var Ref_1 = require("./Ref");
|
|
|
20
20
|
Object.defineProperty(exports, "Ref", { enumerable: true, get: function () { return Ref_1.Ref; } });
|
|
21
21
|
Object.defineProperty(exports, "ToggleRef", { enumerable: true, get: function () { return Ref_1.ToggleRef; } });
|
|
22
22
|
var Hooks_1 = require("./impl/Hooks");
|
|
23
|
-
Object.defineProperty(exports, "
|
|
23
|
+
Object.defineProperty(exports, "SubscribingObject", { enumerable: true, get: function () { return Hooks_1.SubscribingObject; } });
|
|
24
24
|
var Snapshot_1 = require("./impl/Snapshot");
|
|
25
25
|
Object.defineProperty(exports, "Snapshot", { enumerable: true, get: function () { return Snapshot_1.Snapshot; } });
|
|
26
26
|
var Transaction_1 = require("./impl/Transaction");
|
|
@@ -31,9 +31,9 @@ var Journal_1 = require("./impl/Journal");
|
|
|
31
31
|
Object.defineProperty(exports, "Journal", { enumerable: true, get: function () { return Journal_1.Journal; } });
|
|
32
32
|
var Rx_1 = require("./Rx");
|
|
33
33
|
Object.defineProperty(exports, "Rx", { enumerable: true, get: function () { return Rx_1.Rx; } });
|
|
34
|
-
Object.defineProperty(exports, "
|
|
34
|
+
Object.defineProperty(exports, "nonsubscribing", { enumerable: true, get: function () { return Rx_1.nonsubscribing; } });
|
|
35
35
|
Object.defineProperty(exports, "sensitive", { enumerable: true, get: function () { return Rx_1.sensitive; } });
|
|
36
|
-
Object.defineProperty(exports, "
|
|
36
|
+
Object.defineProperty(exports, "subscribeless", { enumerable: true, get: function () { return Rx_1.subscribeless; } });
|
|
37
37
|
Object.defineProperty(exports, "transaction", { enumerable: true, get: function () { return Rx_1.transaction; } });
|
|
38
38
|
Object.defineProperty(exports, "reaction", { enumerable: true, get: function () { return Rx_1.reaction; } });
|
|
39
39
|
Object.defineProperty(exports, "cached", { enumerable: true, get: function () { return Rx_1.cached; } });
|
|
@@ -5,54 +5,54 @@ export interface AbstractSnapshot {
|
|
|
5
5
|
readonly timestamp: number;
|
|
6
6
|
readonly sealed: boolean;
|
|
7
7
|
}
|
|
8
|
-
export declare class
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export declare class Subscription {
|
|
9
|
+
content: any;
|
|
10
|
+
subscribers?: Set<Subscriber>;
|
|
11
11
|
get isOperation(): boolean;
|
|
12
12
|
get originSnapshotId(): number | undefined;
|
|
13
|
-
constructor(
|
|
13
|
+
constructor(content: any);
|
|
14
14
|
}
|
|
15
15
|
export declare type StandaloneMode = boolean | 'isolated' | 'disposal';
|
|
16
|
-
export interface
|
|
16
|
+
export interface Subscriber {
|
|
17
17
|
readonly order: number;
|
|
18
|
-
readonly
|
|
18
|
+
readonly subscriptions: Map<Subscription, SubscriptionInfo> | undefined;
|
|
19
19
|
readonly obsoleteSince: number;
|
|
20
20
|
hint(nop?: boolean): string;
|
|
21
|
-
markObsoleteDueTo(
|
|
21
|
+
markObsoleteDueTo(subscription: Subscription, memberName: MemberName, snapshot: AbstractSnapshot, holder: DataHolder, outer: string, since: number, reactions: Array<Subscriber>): void;
|
|
22
22
|
runIfNotUpToDate(now: boolean, nothrow: boolean): void;
|
|
23
23
|
}
|
|
24
24
|
export declare type MemberName = PropertyKey;
|
|
25
|
-
export interface
|
|
25
|
+
export interface SubscriptionInfo {
|
|
26
26
|
readonly memberHint: string;
|
|
27
27
|
readonly usageCount: number;
|
|
28
28
|
}
|
|
29
|
-
export declare class
|
|
29
|
+
export declare class DataRevision {
|
|
30
30
|
readonly snapshot: AbstractSnapshot;
|
|
31
31
|
readonly former: {
|
|
32
|
-
revision:
|
|
32
|
+
revision: DataRevision;
|
|
33
33
|
};
|
|
34
34
|
readonly data: any;
|
|
35
35
|
readonly changes: Set<MemberName>;
|
|
36
|
-
readonly conflicts: Map<MemberName,
|
|
37
|
-
constructor(snapshot: AbstractSnapshot, former:
|
|
36
|
+
readonly conflicts: Map<MemberName, DataRevision>;
|
|
37
|
+
constructor(snapshot: AbstractSnapshot, former: DataRevision | undefined, data: object);
|
|
38
38
|
}
|
|
39
|
-
export declare class
|
|
39
|
+
export declare class DataHolder {
|
|
40
40
|
private static generator;
|
|
41
41
|
readonly id: number;
|
|
42
|
-
readonly
|
|
42
|
+
readonly data: any;
|
|
43
43
|
readonly proxy: any;
|
|
44
|
-
head:
|
|
45
|
-
editing?:
|
|
44
|
+
head: DataRevision;
|
|
45
|
+
editing?: DataRevision;
|
|
46
46
|
editors: number;
|
|
47
47
|
hint: string;
|
|
48
|
-
constructor(
|
|
48
|
+
constructor(data: any, proxy: any, handler: ProxyHandler<DataHolder>, head: DataRevision, hint: string);
|
|
49
49
|
static getHint(obj: object, full: boolean): string | undefined;
|
|
50
50
|
}
|
|
51
|
-
export interface
|
|
51
|
+
export interface PatchSet {
|
|
52
52
|
hint: string;
|
|
53
|
-
objects: Map<object,
|
|
53
|
+
objects: Map<object, DataPatch>;
|
|
54
54
|
}
|
|
55
|
-
export interface
|
|
55
|
+
export interface DataPatch {
|
|
56
56
|
data: any;
|
|
57
57
|
former: any;
|
|
58
58
|
}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.DataHolder = exports.DataRevision = exports.Subscription = exports.Meta = void 0;
|
|
4
4
|
const Dbg_1 = require("../util/Dbg");
|
|
5
5
|
const Meta_1 = require("./Meta");
|
|
6
6
|
var Meta_2 = require("./Meta");
|
|
7
7
|
Object.defineProperty(exports, "Meta", { enumerable: true, get: function () { return Meta_2.Meta; } });
|
|
8
|
-
class
|
|
9
|
-
constructor(
|
|
8
|
+
class Subscription {
|
|
9
|
+
constructor(content) { this.content = content; }
|
|
10
10
|
get isOperation() { return false; }
|
|
11
11
|
get originSnapshotId() { return 0; }
|
|
12
12
|
}
|
|
13
|
-
exports.
|
|
14
|
-
class
|
|
13
|
+
exports.Subscription = Subscription;
|
|
14
|
+
class DataRevision {
|
|
15
15
|
constructor(snapshot, former, data) {
|
|
16
16
|
this.snapshot = snapshot;
|
|
17
17
|
this.former = { revision: former || this };
|
|
@@ -22,11 +22,11 @@ class ObjectRevision {
|
|
|
22
22
|
Object.freeze(this);
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
exports.
|
|
26
|
-
class
|
|
27
|
-
constructor(
|
|
28
|
-
this.id = ++
|
|
29
|
-
this.
|
|
25
|
+
exports.DataRevision = DataRevision;
|
|
26
|
+
class DataHolder {
|
|
27
|
+
constructor(data, proxy, handler, head, hint) {
|
|
28
|
+
this.id = ++DataHolder.generator;
|
|
29
|
+
this.data = data;
|
|
30
30
|
this.proxy = proxy || new Proxy(this, handler);
|
|
31
31
|
this.head = head;
|
|
32
32
|
this.editing = undefined;
|
|
@@ -38,5 +38,5 @@ class ObjectHolder {
|
|
|
38
38
|
return h !== undefined ? (full ? `${h.hint}#${h.id}` : h.hint) : undefined;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
|
-
exports.
|
|
42
|
-
|
|
41
|
+
exports.DataHolder = DataHolder;
|
|
42
|
+
DataHolder.generator = 19;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { F } from '../util/Utils';
|
|
2
2
|
import { MemberOptions, Kind, Reentrance } from '../Options';
|
|
3
3
|
import { LoggingOptions, ProfilingOptions } from '../Logging';
|
|
4
|
-
import { MemberName,
|
|
4
|
+
import { MemberName, DataHolder, StandaloneMode } from './Data';
|
|
5
5
|
import { Journal } from './Journal';
|
|
6
6
|
import { Monitor } from './Monitor';
|
|
7
|
-
export declare abstract class
|
|
7
|
+
export declare abstract class SubscribingObject {
|
|
8
8
|
constructor();
|
|
9
9
|
[Symbol.toStringTag](): string;
|
|
10
10
|
}
|
|
@@ -24,27 +24,27 @@ export declare class OptionsImpl implements MemberOptions {
|
|
|
24
24
|
static readonly INITIAL: Readonly<OptionsImpl>;
|
|
25
25
|
constructor(getter: Function | undefined, setter: Function | undefined, existing: OptionsImpl, patch: Partial<OptionsImpl>, implicit: boolean);
|
|
26
26
|
}
|
|
27
|
-
export declare class Hooks implements ProxyHandler<
|
|
27
|
+
export declare class Hooks implements ProxyHandler<DataHolder> {
|
|
28
28
|
static reactionsAutoStartDisabled: boolean;
|
|
29
29
|
static repetitiveUsageWarningThreshold: number;
|
|
30
30
|
static mainThreadBlockingWarningThreshold: number;
|
|
31
31
|
static asyncActionDurationWarningThreshold: number;
|
|
32
32
|
static sensitivity: boolean;
|
|
33
33
|
static readonly proxy: Hooks;
|
|
34
|
-
getPrototypeOf(h:
|
|
35
|
-
get(h:
|
|
36
|
-
set(h:
|
|
37
|
-
has(h:
|
|
38
|
-
getOwnPropertyDescriptor(h:
|
|
39
|
-
ownKeys(h:
|
|
40
|
-
static decorateData(
|
|
34
|
+
getPrototypeOf(h: DataHolder): object | null;
|
|
35
|
+
get(h: DataHolder, m: MemberName, receiver: any): any;
|
|
36
|
+
set(h: DataHolder, m: MemberName, value: any, receiver: any): boolean;
|
|
37
|
+
has(h: DataHolder, m: MemberName): boolean;
|
|
38
|
+
getOwnPropertyDescriptor(h: DataHolder, m: MemberName): PropertyDescriptor | undefined;
|
|
39
|
+
ownKeys(h: DataHolder): Array<string | symbol>;
|
|
40
|
+
static decorateData(subscribing: boolean, proto: any, m: MemberName): any;
|
|
41
41
|
static decorateOperation(implicit: boolean, decorator: Function, options: Partial<MemberOptions>, proto: any, member: MemberName, pd: PropertyDescriptor | undefined): any;
|
|
42
42
|
static decorateOperationParametrized(decorator: Function, options: Partial<MemberOptions>): F<any>;
|
|
43
|
-
static
|
|
44
|
-
static
|
|
43
|
+
static acquireDataHolder(obj: any): DataHolder;
|
|
44
|
+
static createDataHolderForSubscribingObject(proto: any, data: any, blank: any, hint: string): DataHolder;
|
|
45
45
|
static setProfilingMode(isOn: boolean, options?: Partial<ProfilingOptions>): void;
|
|
46
46
|
static sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
47
47
|
static setHint<T>(obj: T, hint: string | undefined): T;
|
|
48
|
-
static createOperation: (h:
|
|
48
|
+
static createOperation: (h: DataHolder, m: MemberName, options: OptionsImpl) => F<any>;
|
|
49
49
|
static rememberOperationOptions: (proto: any, m: MemberName, getter: Function | undefined, setter: Function | undefined, enumerable: boolean, configurable: boolean, options: Partial<MemberOptions>, implicit: boolean) => OptionsImpl;
|
|
50
50
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Hooks = exports.OptionsImpl = exports.
|
|
3
|
+
exports.Hooks = exports.OptionsImpl = exports.SubscribingObject = void 0;
|
|
4
4
|
const Utils_1 = require("../util/Utils");
|
|
5
5
|
const Dbg_1 = require("../util/Dbg");
|
|
6
6
|
const Options_1 = require("../Options");
|
|
7
7
|
const Data_1 = require("./Data");
|
|
8
8
|
const Snapshot_1 = require("./Snapshot");
|
|
9
|
-
class
|
|
9
|
+
class SubscribingObject {
|
|
10
10
|
constructor() {
|
|
11
11
|
const proto = new.target.prototype;
|
|
12
12
|
const initial = Data_1.Meta.getFrom(proto, Data_1.Meta.Initial);
|
|
13
|
-
const h = Hooks.
|
|
13
|
+
const h = Hooks.createDataHolderForSubscribingObject(proto, this, initial, new.target.name);
|
|
14
14
|
return h.proxy;
|
|
15
15
|
}
|
|
16
16
|
[Symbol.toStringTag]() {
|
|
@@ -18,7 +18,7 @@ class ObservableObject {
|
|
|
18
18
|
return Snapshot_1.Dump.obj(h);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
exports.
|
|
21
|
+
exports.SubscribingObject = SubscribingObject;
|
|
22
22
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
23
23
|
kind: Options_1.Kind.Plain,
|
|
24
24
|
standalone: false,
|
|
@@ -56,49 +56,49 @@ function merge(def, existing, patch, implicit) {
|
|
|
56
56
|
}
|
|
57
57
|
class Hooks {
|
|
58
58
|
getPrototypeOf(h) {
|
|
59
|
-
return Reflect.getPrototypeOf(h.
|
|
59
|
+
return Reflect.getPrototypeOf(h.data);
|
|
60
60
|
}
|
|
61
61
|
get(h, m, receiver) {
|
|
62
62
|
let result;
|
|
63
63
|
const r = Snapshot_1.Snapshot.current().getCurrentRevision(h, m);
|
|
64
64
|
result = r.data[m];
|
|
65
|
-
if (result instanceof Data_1.
|
|
65
|
+
if (result instanceof Data_1.Subscription && !result.isOperation) {
|
|
66
66
|
Snapshot_1.Snapshot.markUsed(result, r, m, h, Options_1.Kind.Plain, false);
|
|
67
|
-
result = result.
|
|
67
|
+
result = result.content;
|
|
68
68
|
}
|
|
69
69
|
else if (m === Data_1.Meta.Holder) {
|
|
70
70
|
}
|
|
71
71
|
else
|
|
72
|
-
result = Reflect.get(h.
|
|
72
|
+
result = Reflect.get(h.data, m, receiver);
|
|
73
73
|
return result;
|
|
74
74
|
}
|
|
75
75
|
set(h, m, value, receiver) {
|
|
76
76
|
const r = Snapshot_1.Snapshot.edit().getEditableRevision(h, m, value);
|
|
77
77
|
if (r !== Snapshot_1.ROOT_REV) {
|
|
78
78
|
let curr = r.data[m];
|
|
79
|
-
if (curr !== undefined || (r.former.revision.snapshot === Snapshot_1.ROOT_REV.snapshot && (m in h.
|
|
80
|
-
if (curr === undefined || curr.
|
|
81
|
-
const
|
|
79
|
+
if (curr !== undefined || (r.former.revision.snapshot === Snapshot_1.ROOT_REV.snapshot && (m in h.data) === false)) {
|
|
80
|
+
if (curr === undefined || curr.content !== value || Hooks.sensitivity) {
|
|
81
|
+
const existing = curr === null || curr === void 0 ? void 0 : curr.content;
|
|
82
82
|
if (r.former.revision.data[m] === curr) {
|
|
83
|
-
curr = r.data[m] = new Data_1.
|
|
84
|
-
Snapshot_1.Snapshot.markEdited(
|
|
83
|
+
curr = r.data[m] = new Data_1.Subscription(value);
|
|
84
|
+
Snapshot_1.Snapshot.markEdited(existing, value, true, r, m, h);
|
|
85
85
|
}
|
|
86
86
|
else {
|
|
87
|
-
curr.
|
|
88
|
-
Snapshot_1.Snapshot.markEdited(
|
|
87
|
+
curr.content = value;
|
|
88
|
+
Snapshot_1.Snapshot.markEdited(existing, value, true, r, m, h);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
else
|
|
93
|
-
Reflect.set(h.
|
|
93
|
+
Reflect.set(h.data, m, value, receiver);
|
|
94
94
|
}
|
|
95
95
|
else
|
|
96
|
-
h.
|
|
96
|
+
h.data[m] = value;
|
|
97
97
|
return true;
|
|
98
98
|
}
|
|
99
99
|
has(h, m) {
|
|
100
100
|
const r = Snapshot_1.Snapshot.current().getCurrentRevision(h, m);
|
|
101
|
-
return m in r.data || m in h.
|
|
101
|
+
return m in r.data || m in h.data;
|
|
102
102
|
}
|
|
103
103
|
getOwnPropertyDescriptor(h, m) {
|
|
104
104
|
const r = Snapshot_1.Snapshot.current().getCurrentRevision(h, m);
|
|
@@ -112,19 +112,19 @@ class Hooks {
|
|
|
112
112
|
const result = [];
|
|
113
113
|
for (const m of Object.getOwnPropertyNames(r.data)) {
|
|
114
114
|
const value = r.data[m];
|
|
115
|
-
if (!(value instanceof Data_1.
|
|
115
|
+
if (!(value instanceof Data_1.Subscription) || !value.isOperation)
|
|
116
116
|
result.push(m);
|
|
117
117
|
}
|
|
118
118
|
return result;
|
|
119
119
|
}
|
|
120
|
-
static decorateData(
|
|
121
|
-
if (
|
|
120
|
+
static decorateData(subscribing, proto, m) {
|
|
121
|
+
if (subscribing) {
|
|
122
122
|
const get = function () {
|
|
123
|
-
const h = Hooks.
|
|
123
|
+
const h = Hooks.acquireDataHolder(this);
|
|
124
124
|
return Hooks.proxy.get(h, m, this);
|
|
125
125
|
};
|
|
126
126
|
const set = function (value) {
|
|
127
|
-
const h = Hooks.
|
|
127
|
+
const h = Hooks.acquireDataHolder(this);
|
|
128
128
|
return Hooks.proxy.set(h, m, value, this);
|
|
129
129
|
};
|
|
130
130
|
const enumerable = true;
|
|
@@ -132,7 +132,7 @@ class Hooks {
|
|
|
132
132
|
return Object.defineProperty(proto, m, { get, set, enumerable, configurable });
|
|
133
133
|
}
|
|
134
134
|
else
|
|
135
|
-
Data_1.Meta.acquire(proto, Data_1.Meta.Initial)[m] = Data_1.Meta.
|
|
135
|
+
Data_1.Meta.acquire(proto, Data_1.Meta.Initial)[m] = Data_1.Meta.Nonsubscribing;
|
|
136
136
|
}
|
|
137
137
|
static decorateOperation(implicit, decorator, options, proto, member, pd) {
|
|
138
138
|
var _a, _b, _c, _d;
|
|
@@ -143,18 +143,18 @@ class Hooks {
|
|
|
143
143
|
const opts = Hooks.rememberOperationOptions(proto, member, (_c = pd.value) !== null && _c !== void 0 ? _c : pd.get, (_d = pd.value) !== null && _d !== void 0 ? _d : pd.set, true, configurable, options, implicit);
|
|
144
144
|
if (opts.getter === opts.setter) {
|
|
145
145
|
const bootstrap = function () {
|
|
146
|
-
const h = Hooks.
|
|
146
|
+
const h = Hooks.acquireDataHolder(this);
|
|
147
147
|
const operation = Hooks.createOperation(h, member, opts);
|
|
148
|
-
Object.defineProperty(h.
|
|
148
|
+
Object.defineProperty(h.data, member, { value: operation, enumerable, configurable });
|
|
149
149
|
return operation;
|
|
150
150
|
};
|
|
151
151
|
return Object.defineProperty(proto, member, { get: bootstrap, enumerable, configurable: true });
|
|
152
152
|
}
|
|
153
153
|
else if (opts.setter === Utils_1.UNDEF) {
|
|
154
154
|
const bootstrap = function () {
|
|
155
|
-
const h = Hooks.
|
|
155
|
+
const h = Hooks.acquireDataHolder(this);
|
|
156
156
|
const operation = Hooks.createOperation(h, member, opts);
|
|
157
|
-
Object.defineProperty(h.
|
|
157
|
+
Object.defineProperty(h.data, member, { get: operation, enumerable, configurable });
|
|
158
158
|
return operation.call(this);
|
|
159
159
|
};
|
|
160
160
|
return Object.defineProperty(proto, member, { get: bootstrap, enumerable, configurable: true });
|
|
@@ -167,22 +167,22 @@ class Hooks {
|
|
|
167
167
|
return Hooks.decorateOperation(false, decorator, options, proto, prop, pd);
|
|
168
168
|
};
|
|
169
169
|
}
|
|
170
|
-
static
|
|
170
|
+
static acquireDataHolder(obj) {
|
|
171
171
|
let h = obj[Data_1.Meta.Holder];
|
|
172
172
|
if (!h) {
|
|
173
173
|
if (obj !== Object(obj) || Array.isArray(obj))
|
|
174
174
|
throw (0, Dbg_1.misuse)('only objects can be reactive');
|
|
175
175
|
const initial = Data_1.Meta.getFrom(Object.getPrototypeOf(obj), Data_1.Meta.Initial);
|
|
176
|
-
const rev = new Data_1.
|
|
176
|
+
const rev = new Data_1.DataRevision(Snapshot_1.ROOT_REV.snapshot, Snapshot_1.ROOT_REV, Object.assign({}, initial));
|
|
177
177
|
Data_1.Meta.set(rev.data, Data_1.Meta.Holder, h);
|
|
178
|
-
h = new Data_1.
|
|
178
|
+
h = new Data_1.DataHolder(obj, obj, Hooks.proxy, rev, obj.constructor.name);
|
|
179
179
|
Data_1.Meta.set(obj, Data_1.Meta.Holder, h);
|
|
180
180
|
}
|
|
181
181
|
return h;
|
|
182
182
|
}
|
|
183
|
-
static
|
|
183
|
+
static createDataHolderForSubscribingObject(proto, data, blank, hint) {
|
|
184
184
|
const ctx = Snapshot_1.Snapshot.edit();
|
|
185
|
-
const h = new Data_1.
|
|
185
|
+
const h = new Data_1.DataHolder(data, undefined, Hooks.proxy, Snapshot_1.ROOT_REV, hint);
|
|
186
186
|
ctx.getEditableRevision(h, Data_1.Meta.Holder, blank);
|
|
187
187
|
if (!Hooks.reactionsAutoStartDisabled)
|
|
188
188
|
for (const m in Data_1.Meta.getFrom(proto, Data_1.Meta.Reactions))
|
|
@@ -215,7 +215,7 @@ class Hooks {
|
|
|
215
215
|
}
|
|
216
216
|
static setHint(obj, hint) {
|
|
217
217
|
if (hint) {
|
|
218
|
-
const h = Hooks.
|
|
218
|
+
const h = Hooks.acquireDataHolder(obj);
|
|
219
219
|
h.hint = hint;
|
|
220
220
|
}
|
|
221
221
|
return obj;
|