reactronic 0.22.314 → 0.22.317
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 +23 -23
- package/build/dist/source/Buffer.d.ts +2 -2
- package/build/dist/source/Buffer.js +2 -2
- package/build/dist/source/Options.d.ts +3 -3
- package/build/dist/source/Rx.d.ts +2 -2
- package/build/dist/source/Rx.js +14 -14
- package/build/dist/source/api.d.ts +5 -5
- package/build/dist/source/api.js +4 -4
- package/build/dist/source/impl/Changeset.js +8 -8
- package/build/dist/source/impl/Data.d.ts +1 -1
- package/build/dist/source/impl/Journal.d.ts +2 -2
- package/build/dist/source/impl/Journal.js +5 -5
- 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 +5 -5
- package/build/dist/source/impl/{Hooks.d.ts → Mvcc.d.ts} +15 -12
- package/build/dist/source/impl/{Hooks.js → Mvcc.js} +57 -52
- package/build/dist/source/impl/MvccArray.d.ts +60 -0
- package/build/dist/source/impl/MvccArray.js +58 -0
- package/build/dist/source/impl/MvccCollection.d.ts +25 -0
- package/build/dist/source/impl/MvccCollection.js +23 -0
- package/build/dist/source/impl/MvccMap.d.ts +25 -0
- package/build/dist/source/impl/MvccMap.js +35 -0
- package/build/dist/source/impl/Operation.d.ts +3 -3
- package/build/dist/source/impl/Operation.js +20 -20
- package/build/dist/source/impl/Transaction.d.ts +2 -2
- package/build/dist/source/impl/Transaction.js +9 -9
- package/build/dist/source/util/Collection.d.ts +3 -1
- package/build/dist/source/util/Collection.js +16 -8
- package/package.json +1 -1
- package/build/dist/source/impl/ReactiveArray.d.ts +0 -33
- package/build/dist/source/impl/ReactiveArray.js +0 -42
- package/build/dist/source/impl/ReactiveMap.d.ts +0 -15
- package/build/dist/source/impl/ReactiveMap.js +0 -24
package/README.md
CHANGED
|
@@ -18,13 +18,13 @@ isolated data snapshot and then, once atomically applied, are
|
|
|
18
18
|
**consistently propagated** to corresponding visual components for
|
|
19
19
|
(re)rendering. All that is done in automatic, seamless, and fine-grained
|
|
20
20
|
way, because reactronic **takes full care of tracking dependencies**
|
|
21
|
-
between visual components (
|
|
21
|
+
between visual components (observers) and state (observable objects).
|
|
22
22
|
|
|
23
23
|
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) and maintain subscription lists;
|
|
27
|
-
- **Transaction** - a function that makes changes in
|
|
27
|
+
- **Transaction** - a function that makes changes in observable
|
|
28
28
|
objects in transactional (atomic) way;
|
|
29
29
|
- **Reaction** - a function that is executed automatically in
|
|
30
30
|
response to changes made by a transaction;
|
|
@@ -39,10 +39,10 @@ Quick introduction and detailed description is below.
|
|
|
39
39
|
## Quick Introduction
|
|
40
40
|
|
|
41
41
|
Here is an example of transactional reactive code with
|
|
42
|
-
|
|
42
|
+
observable object, transaction and reaction:
|
|
43
43
|
|
|
44
44
|
``` typescript
|
|
45
|
-
class Demo extends
|
|
45
|
+
class Demo extends ObservableObject {
|
|
46
46
|
name: string = 'Nezaboodka Software'
|
|
47
47
|
email: string = 'contact@nezaboodka.com'
|
|
48
48
|
|
|
@@ -69,7 +69,7 @@ to changes of these fields made by `saveContact` transaction.
|
|
|
69
69
|
Here is an example of if cached value computed on-demand:
|
|
70
70
|
|
|
71
71
|
``` typescript
|
|
72
|
-
class Demo extends
|
|
72
|
+
class Demo extends ObservableObject {
|
|
73
73
|
name: string = 'Nezaboodka Software'
|
|
74
74
|
email: string = 'contact@nezaboodka.com'
|
|
75
75
|
|
|
@@ -94,14 +94,14 @@ invalidated, thus causing execution of depending reaction
|
|
|
94
94
|
`printContact`. Then `printContact` reaction causes `contact`
|
|
95
95
|
re-computation on the first use.
|
|
96
96
|
|
|
97
|
-
##
|
|
97
|
+
## Observable Objects
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
Observable objects store data of an application. All such objects
|
|
100
100
|
are transparently hooked to track access to their properties,
|
|
101
101
|
both on reads and writes.
|
|
102
102
|
|
|
103
103
|
``` typescript
|
|
104
|
-
class MyModel extends
|
|
104
|
+
class MyModel extends ObservableObject {
|
|
105
105
|
url: string = "https://github.com/nezaboodka/reactronic"
|
|
106
106
|
content: string = "transactional reactive state management"
|
|
107
107
|
timestamp: Date = Date.now()
|
|
@@ -109,18 +109,18 @@ class MyModel extends ReactiveObject {
|
|
|
109
109
|
```
|
|
110
110
|
|
|
111
111
|
In the example above, the class `MyModel` is based on Reactronic's
|
|
112
|
-
`
|
|
112
|
+
`ObservableObject` class and all its properties `url`, `content`,
|
|
113
113
|
and `timestamp` are hooked.
|
|
114
114
|
|
|
115
115
|
## Transaction
|
|
116
116
|
|
|
117
|
-
Transaction is a function that makes changes in
|
|
117
|
+
Transaction is a function that makes changes in observable objects
|
|
118
118
|
in transactional (atomic) way. Such a function is instrumented with hooks
|
|
119
119
|
to provide transparent atomicity (by implicit context switching
|
|
120
120
|
and isolation).
|
|
121
121
|
|
|
122
122
|
``` typescript
|
|
123
|
-
class MyModel extends
|
|
123
|
+
class MyModel extends ObservableObject {
|
|
124
124
|
// ...
|
|
125
125
|
@transaction
|
|
126
126
|
async load(url: string): Promise<void> {
|
|
@@ -163,12 +163,12 @@ of asynchronous operations is fully completed.
|
|
|
163
163
|
## Reaction & Cache
|
|
164
164
|
|
|
165
165
|
Reaction is an code block that is immediately called in response to
|
|
166
|
-
changes made by a transaction in
|
|
166
|
+
changes made by a transaction in observable objects. Cache is a
|
|
167
167
|
computed value having an associated function that is called
|
|
168
168
|
on-demand to renew the value if it was marked as obsolete due to changes
|
|
169
169
|
made by a transaction. Reactive and cached functions are
|
|
170
170
|
instrumented with hooks to seamlessly subscribe to those
|
|
171
|
-
|
|
171
|
+
observable objects and other cached functions (dependencies),
|
|
172
172
|
which are used during their execution.
|
|
173
173
|
|
|
174
174
|
``` tsx
|
|
@@ -195,7 +195,7 @@ class Component<P> extends React.Component<P> {
|
|
|
195
195
|
@reaction // called immediately in response to changes
|
|
196
196
|
ensureUpToDate(): void {
|
|
197
197
|
if (this.shouldComponentUpdate())
|
|
198
|
-
Transaction.
|
|
198
|
+
Transaction.outside(() => this.setState({})) // ask React to re-render
|
|
199
199
|
} // ensureUpToDate is subscribed to render
|
|
200
200
|
|
|
201
201
|
shouldComponentUpdate(): boolean {
|
|
@@ -222,14 +222,14 @@ function enqueues re-rendering request to React, which calls
|
|
|
222
222
|
`render` function causing it to renew its cached value.
|
|
223
223
|
|
|
224
224
|
In general case, all reactions and caches are automatically and
|
|
225
|
-
immediately marked as obsolete when changes are made in those
|
|
225
|
+
immediately marked as obsolete when changes are made in those observable
|
|
226
226
|
objects and cached functions that were used during their execution.
|
|
227
227
|
And once marked, the functions are automatically executed again,
|
|
228
228
|
either immediately (for @reactive functions) or on-demand
|
|
229
229
|
(for @cached functions).
|
|
230
230
|
|
|
231
231
|
Reactronic takes full care of tracking dependencies between
|
|
232
|
-
all the
|
|
232
|
+
all the observable objects and reactions/caches.
|
|
233
233
|
With Reactronic, you no longer need to create data change events
|
|
234
234
|
in one set of objects, subscribe to these events in other objects,
|
|
235
235
|
and manually maintain switching from the previous object version
|
|
@@ -291,11 +291,12 @@ NPM: `npm install reactronic`
|
|
|
291
291
|
|
|
292
292
|
// Classes
|
|
293
293
|
|
|
294
|
-
class
|
|
294
|
+
class TransactionalObject { }
|
|
295
|
+
class ObservableObject { }
|
|
295
296
|
|
|
296
297
|
// Decorators & Operators
|
|
297
298
|
|
|
298
|
-
function
|
|
299
|
+
function raw(proto, prop) // field only
|
|
299
300
|
function transaction(proto, prop, pd) // method only
|
|
300
301
|
function reaction(proto, prop, pd) // method only
|
|
301
302
|
function cached(proto, prop, pd) // method only
|
|
@@ -308,7 +309,7 @@ function sensitive<T>(sensitivity: Sensitivity, func: F<T>, ...args: any[]): T
|
|
|
308
309
|
|
|
309
310
|
export interface SnapshotOptions {
|
|
310
311
|
readonly hint?: string
|
|
311
|
-
readonly
|
|
312
|
+
readonly separation?: SeparationMode
|
|
312
313
|
readonly journal?: Journal
|
|
313
314
|
readonly logging?: Partial<LoggingOptions>
|
|
314
315
|
readonly token?: any
|
|
@@ -316,7 +317,7 @@ export interface SnapshotOptions {
|
|
|
316
317
|
|
|
317
318
|
interface MemberOptions {
|
|
318
319
|
readonly kind: Kind
|
|
319
|
-
readonly
|
|
320
|
+
readonly separation: SeparationMode
|
|
320
321
|
readonly order: number
|
|
321
322
|
readonly noSideEffects: boolean
|
|
322
323
|
readonly triggeringArgs: boolean
|
|
@@ -436,8 +437,7 @@ class Reactronic {
|
|
|
436
437
|
static why(short: boolean = false): string
|
|
437
438
|
static getMethodCache<T>(method: F<T>): Cache<T>
|
|
438
439
|
static configureCurrentOperation(options: Partial<Options>): Options
|
|
439
|
-
|
|
440
|
-
// static assign<T, P extends keyof T>(obj: T, prop: P, value: T[P], sensitivity: Sensitivity)
|
|
440
|
+
static getRevisionOf(obj: any): number
|
|
441
441
|
static takeSnapshot<T>(obj: T): T
|
|
442
442
|
static dispose(obj: any): void
|
|
443
443
|
static reactionsAutoStartDisabled: boolean
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare abstract class Buffer<T> extends
|
|
1
|
+
import { ObservableObject } from './impl/Mvcc';
|
|
2
|
+
export declare abstract class Buffer<T> extends ObservableObject {
|
|
3
3
|
abstract readonly capacity: number;
|
|
4
4
|
abstract readonly count: number;
|
|
5
5
|
abstract put(...items: T[]): void;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { LoggingOptions } from './Logging';
|
|
2
|
-
import {
|
|
2
|
+
import { SeparationMode } from './impl/Data';
|
|
3
3
|
export { LoggingOptions, ProfilingOptions, LoggingLevel } from './Logging';
|
|
4
4
|
import { Journal } from './impl/Journal';
|
|
5
5
|
import { Monitor } from './impl/Monitor';
|
|
6
6
|
export interface SnapshotOptions {
|
|
7
7
|
readonly hint?: string;
|
|
8
|
-
readonly
|
|
8
|
+
readonly separation?: SeparationMode;
|
|
9
9
|
readonly journal?: Journal;
|
|
10
10
|
readonly logging?: Partial<LoggingOptions>;
|
|
11
11
|
readonly token?: any;
|
|
12
12
|
}
|
|
13
13
|
export interface MemberOptions {
|
|
14
14
|
readonly kind: Kind;
|
|
15
|
-
readonly
|
|
15
|
+
readonly separation: SeparationMode;
|
|
16
16
|
readonly order: number;
|
|
17
17
|
readonly noSideEffects: boolean;
|
|
18
18
|
readonly triggeringArgs: boolean;
|
|
@@ -2,11 +2,11 @@ import { F } from './util/Utils';
|
|
|
2
2
|
import { Controller } from './Controller';
|
|
3
3
|
import { MemberOptions, LoggingOptions, ProfilingOptions } from './Options';
|
|
4
4
|
export declare class Rx {
|
|
5
|
-
static getRevisionOf(obj: any): number;
|
|
6
5
|
static why(brief?: boolean): string;
|
|
7
6
|
static getController<T>(method: F<T>): Controller<T>;
|
|
8
7
|
static pullLastResult<T>(method: F<Promise<T>>, args?: any[]): T | undefined;
|
|
9
8
|
static configureCurrentOperation(options: Partial<MemberOptions>): MemberOptions;
|
|
9
|
+
static getRevisionOf(obj: any): number;
|
|
10
10
|
static takeSnapshot<T>(obj: T): T;
|
|
11
11
|
static dispose(obj: any): void;
|
|
12
12
|
static get reactionsAutoStartDisabled(): boolean;
|
|
@@ -20,7 +20,7 @@ export declare class Rx {
|
|
|
20
20
|
}
|
|
21
21
|
export declare function nonreactive<T>(func: F<T>, ...args: any[]): T;
|
|
22
22
|
export declare function sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
23
|
-
export declare function
|
|
23
|
+
export declare function raw(proto: object, prop: PropertyKey): any;
|
|
24
24
|
export declare function transaction(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
|
|
25
25
|
export declare function reaction(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
|
|
26
26
|
export declare function cached(proto: object, prop: PropertyKey, pd: PropertyDescriptor): any;
|
package/build/dist/source/Rx.js
CHANGED
|
@@ -2,46 +2,46 @@ import { Log } from './util/Dbg';
|
|
|
2
2
|
import { Kind } from './Options';
|
|
3
3
|
import { Meta, ObjectHandle } from './impl/Data';
|
|
4
4
|
import { Changeset } from './impl/Changeset';
|
|
5
|
-
import {
|
|
5
|
+
import { Mvcc } from './impl/Mvcc';
|
|
6
6
|
import { OperationController } from './impl/Operation';
|
|
7
7
|
export class Rx {
|
|
8
|
-
static getRevisionOf(obj) { return obj[Meta.Revision]; }
|
|
9
8
|
static why(brief = false) { return brief ? OperationController.briefWhy() : OperationController.why(); }
|
|
10
|
-
static getController(method) { return OperationController.
|
|
9
|
+
static getController(method) { return OperationController.getControllerOf(method); }
|
|
11
10
|
static pullLastResult(method, args) { return Rx.getController(method).pullLastResult(args); }
|
|
12
11
|
static configureCurrentOperation(options) { return OperationController.configureImpl(undefined, options); }
|
|
12
|
+
static getRevisionOf(obj) { return obj[Meta.Revision]; }
|
|
13
13
|
static takeSnapshot(obj) { return Changeset.takeSnapshot(obj); }
|
|
14
14
|
static dispose(obj) { Changeset.dispose(obj); }
|
|
15
|
-
static get reactionsAutoStartDisabled() { return
|
|
16
|
-
static set reactionsAutoStartDisabled(value) {
|
|
15
|
+
static get reactionsAutoStartDisabled() { return Mvcc.reactionsAutoStartDisabled; }
|
|
16
|
+
static set reactionsAutoStartDisabled(value) { Mvcc.reactionsAutoStartDisabled = value; }
|
|
17
17
|
static get isLogging() { return Log.isOn; }
|
|
18
18
|
static get loggingOptions() { return Log.opt; }
|
|
19
19
|
static setLoggingMode(isOn, options) { Log.setMode(isOn, options); }
|
|
20
|
-
static setLoggingHint(obj, name) {
|
|
20
|
+
static setLoggingHint(obj, name) { Mvcc.setHint(obj, name); }
|
|
21
21
|
static getLoggingHint(obj, full = false) { return ObjectHandle.getHint(obj, full); }
|
|
22
|
-
static setProfilingMode(isOn, options) {
|
|
22
|
+
static setProfilingMode(isOn, options) { Mvcc.setProfilingMode(isOn, options); }
|
|
23
23
|
}
|
|
24
24
|
export function nonreactive(func, ...args) {
|
|
25
25
|
return OperationController.runWithin(undefined, func, ...args);
|
|
26
26
|
}
|
|
27
27
|
export function sensitive(sensitivity, func, ...args) {
|
|
28
|
-
return
|
|
28
|
+
return Mvcc.sensitive(sensitivity, func, ...args);
|
|
29
29
|
}
|
|
30
|
-
export function
|
|
31
|
-
return
|
|
30
|
+
export function raw(proto, prop) {
|
|
31
|
+
return Mvcc.decorateData(false, proto, prop);
|
|
32
32
|
}
|
|
33
33
|
export function transaction(proto, prop, pd) {
|
|
34
34
|
const opts = { kind: Kind.Transaction };
|
|
35
|
-
return
|
|
35
|
+
return Mvcc.decorateOperation(true, transaction, opts, proto, prop, pd);
|
|
36
36
|
}
|
|
37
37
|
export function reaction(proto, prop, pd) {
|
|
38
38
|
const opts = { kind: Kind.Reaction, throttling: -1 };
|
|
39
|
-
return
|
|
39
|
+
return Mvcc.decorateOperation(true, reaction, opts, proto, prop, pd);
|
|
40
40
|
}
|
|
41
41
|
export function cached(proto, prop, pd) {
|
|
42
42
|
const opts = { kind: Kind.Cache, noSideEffects: true };
|
|
43
|
-
return
|
|
43
|
+
return Mvcc.decorateOperation(true, cached, opts, proto, prop, pd);
|
|
44
44
|
}
|
|
45
45
|
export function options(value) {
|
|
46
|
-
return
|
|
46
|
+
return Mvcc.decorateOperationParametrized(options, value);
|
|
47
47
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { all, pause } from './util/Utils';
|
|
2
|
-
export { Collection } from './util/Collection';
|
|
2
|
+
export { Collection, Item, CollectionReader } from './util/Collection';
|
|
3
3
|
export { SealedArray } from './util/SealedArray';
|
|
4
4
|
export { SealedMap } from './util/SealedMap';
|
|
5
5
|
export { SealedSet } from './util/SealedSet';
|
|
@@ -7,11 +7,11 @@ export { MemberOptions, SnapshotOptions, Kind, Reentrance, LoggingOptions, Profi
|
|
|
7
7
|
export { Worker } from './Worker';
|
|
8
8
|
export { Controller } from './Controller';
|
|
9
9
|
export { Ref, ToggleRef, BoolOnly, GivenTypeOnly } from './Ref';
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
10
|
+
export { TransactionalObject, ObservableObject } from './impl/Mvcc';
|
|
11
|
+
export { TransactionalArray, ObservableArray } from './impl/MvccArray';
|
|
12
|
+
export { TransactionalMap, ObservableMap } from './impl/MvccMap';
|
|
13
13
|
export { Changeset } from './impl/Changeset';
|
|
14
14
|
export { Transaction } from './impl/Transaction';
|
|
15
15
|
export { Monitor } from './impl/Monitor';
|
|
16
16
|
export { Journal } from './impl/Journal';
|
|
17
|
-
export { Rx, nonreactive, sensitive,
|
|
17
|
+
export { Rx, nonreactive, sensitive, raw, transaction, reaction, cached, options } from './Rx';
|
package/build/dist/source/api.js
CHANGED
|
@@ -6,11 +6,11 @@ export { SealedSet } from './util/SealedSet';
|
|
|
6
6
|
export { Kind, Reentrance, LoggingLevel } from './Options';
|
|
7
7
|
export { Controller } from './Controller';
|
|
8
8
|
export { Ref, ToggleRef } from './Ref';
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
9
|
+
export { TransactionalObject, ObservableObject } from './impl/Mvcc';
|
|
10
|
+
export { TransactionalArray, ObservableArray } from './impl/MvccArray';
|
|
11
|
+
export { TransactionalMap, ObservableMap } from './impl/MvccMap';
|
|
12
12
|
export { Changeset } from './impl/Changeset';
|
|
13
13
|
export { Transaction } from './impl/Transaction';
|
|
14
14
|
export { Monitor } from './impl/Monitor';
|
|
15
15
|
export { Journal } from './impl/Journal';
|
|
16
|
-
export { Rx, nonreactive, sensitive,
|
|
16
|
+
export { Rx, nonreactive, sensitive, raw, transaction, reaction, cached, options } from './Rx';
|
|
@@ -7,16 +7,16 @@ import { SealedSet } from '../util/SealedSet';
|
|
|
7
7
|
import { ObjectSnapshot, ObjectHandle, Subscription, Meta } from './Data';
|
|
8
8
|
export const MAX_REVISION = Number.MAX_SAFE_INTEGER;
|
|
9
9
|
export const UNDEFINED_REVISION = MAX_REVISION - 1;
|
|
10
|
-
Object.defineProperty(ObjectHandle.prototype, '#this', {
|
|
10
|
+
Object.defineProperty(ObjectHandle.prototype, '#this#', {
|
|
11
11
|
configurable: false, enumerable: false,
|
|
12
12
|
get() {
|
|
13
13
|
const result = {};
|
|
14
|
-
const data = Changeset.current().getObjectSnapshot(this, '#this').data;
|
|
14
|
+
const data = Changeset.current().getObjectSnapshot(this, '#this#').data;
|
|
15
15
|
for (const m in data) {
|
|
16
16
|
const v = data[m];
|
|
17
17
|
if (v instanceof Subscription)
|
|
18
18
|
result[m] = v.content;
|
|
19
|
-
else if (v === Meta.
|
|
19
|
+
else if (v === Meta.Raw)
|
|
20
20
|
result[m] = this.data[m];
|
|
21
21
|
else
|
|
22
22
|
result[m] = v;
|
|
@@ -61,7 +61,7 @@ export class Changeset {
|
|
|
61
61
|
getEditableObjectSnapshot(h, m, value, token) {
|
|
62
62
|
let os = this.lookupObjectSnapshot(h, m);
|
|
63
63
|
const existing = os.data[m];
|
|
64
|
-
if (existing !== Meta.
|
|
64
|
+
if (existing !== Meta.Raw) {
|
|
65
65
|
if (this.isNewSnapshotRequired(h, os, m, existing, value, token)) {
|
|
66
66
|
this.bumpBy(os.changeset.timestamp);
|
|
67
67
|
const revision = m === Meta.Handle ? 1 : os.revision + 1;
|
|
@@ -81,7 +81,7 @@ export class Changeset {
|
|
|
81
81
|
return os;
|
|
82
82
|
}
|
|
83
83
|
static takeSnapshot(obj) {
|
|
84
|
-
return obj[Meta.Handle]['#this'];
|
|
84
|
+
return obj[Meta.Handle]['#this#'];
|
|
85
85
|
}
|
|
86
86
|
static dispose(obj) {
|
|
87
87
|
const ctx = Changeset.edit();
|
|
@@ -97,7 +97,7 @@ export class Changeset {
|
|
|
97
97
|
}
|
|
98
98
|
isNewSnapshotRequired(h, os, m, existing, value, token) {
|
|
99
99
|
if (this.sealed && os.changeset !== EMPTY_SNAPSHOT.changeset)
|
|
100
|
-
throw misuse(`
|
|
100
|
+
throw misuse(`observable property ${Dump.obj(h, m)} can only be modified inside transaction`);
|
|
101
101
|
if (m !== Meta.Handle) {
|
|
102
102
|
if (value !== Meta.Handle) {
|
|
103
103
|
if (os.changeset !== this || os.former.snapshot !== EMPTY_SNAPSHOT) {
|
|
@@ -165,7 +165,7 @@ export class Changeset {
|
|
|
165
165
|
merged[m] = ours.data[m];
|
|
166
166
|
if (headDisposed || oursDisposed) {
|
|
167
167
|
if (headDisposed !== oursDisposed) {
|
|
168
|
-
if (headDisposed || this.options.
|
|
168
|
+
if (headDisposed || this.options.separation !== 'disposal') {
|
|
169
169
|
if (Log.isOn && Log.opt.change)
|
|
170
170
|
Log.write('║╠', '', `${Dump.snapshot2(h, ours.changeset, m)} <> ${Dump.snapshot2(h, head.changeset, m)}`, 0, ' *** CONFLICT ***');
|
|
171
171
|
ours.conflicts.set(m, head);
|
|
@@ -351,7 +351,7 @@ Dump.valueHint = (value, m) => '???';
|
|
|
351
351
|
export const EMPTY_SNAPSHOT = new ObjectSnapshot(new Changeset({ hint: '<empty>' }), undefined, {});
|
|
352
352
|
export const DefaultSnapshotOptions = Object.freeze({
|
|
353
353
|
hint: 'noname',
|
|
354
|
-
|
|
354
|
+
separation: false,
|
|
355
355
|
journal: undefined,
|
|
356
356
|
logging: undefined,
|
|
357
357
|
token: undefined,
|
|
@@ -12,7 +12,7 @@ export declare class Subscription {
|
|
|
12
12
|
get originSnapshotId(): number | undefined;
|
|
13
13
|
constructor(content: any);
|
|
14
14
|
}
|
|
15
|
-
export declare type
|
|
15
|
+
export declare type SeparationMode = boolean | 'isolated' | 'disposal';
|
|
16
16
|
export interface Subscriber {
|
|
17
17
|
readonly order: number;
|
|
18
18
|
readonly subscriptions: Map<Subscription, SubscriptionInfo> | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObservableObject } from './Mvcc';
|
|
2
2
|
import { ObjectHandle, ObjectSnapshot, PatchSet } from './Data';
|
|
3
3
|
export declare type Saver = (patch: PatchSet) => Promise<void>;
|
|
4
|
-
export declare abstract class Journal extends
|
|
4
|
+
export declare abstract class Journal extends ObservableObject {
|
|
5
5
|
abstract capacity: number;
|
|
6
6
|
abstract readonly edits: ReadonlyArray<PatchSet>;
|
|
7
7
|
abstract readonly unsaved: PatchSet;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObservableObject } from './Mvcc';
|
|
2
2
|
import { Meta, Subscription } from './Data';
|
|
3
3
|
import { Changeset, EMPTY_SNAPSHOT } from './Changeset';
|
|
4
4
|
import { Transaction } from './Transaction';
|
|
5
5
|
import { Sealant } from '../util/Sealant';
|
|
6
|
-
export class Journal extends
|
|
6
|
+
export class Journal extends ObservableObject {
|
|
7
7
|
static create() { return new JournalImpl(); }
|
|
8
8
|
}
|
|
9
9
|
export class JournalImpl extends Journal {
|
|
@@ -22,7 +22,7 @@ export class JournalImpl extends Journal {
|
|
|
22
22
|
get canUndo() { return this._edits.length > 0 && this._position > 0; }
|
|
23
23
|
get canRedo() { return this._position < this._edits.length; }
|
|
24
24
|
edited(p) {
|
|
25
|
-
Transaction.run({ hint: 'EditJournal.edited',
|
|
25
|
+
Transaction.run({ hint: 'EditJournal.edited', separation: 'isolated' }, () => {
|
|
26
26
|
const items = this._edits = this._edits.toMutable();
|
|
27
27
|
if (items.length >= this._capacity)
|
|
28
28
|
items.shift();
|
|
@@ -40,7 +40,7 @@ export class JournalImpl extends Journal {
|
|
|
40
40
|
throw new Error('not implemented');
|
|
41
41
|
}
|
|
42
42
|
undo(count = 1) {
|
|
43
|
-
Transaction.run({ hint: 'Journal.undo',
|
|
43
|
+
Transaction.run({ hint: 'Journal.undo', separation: 'isolated' }, () => {
|
|
44
44
|
let i = this._position - 1;
|
|
45
45
|
while (i >= 0 && count > 0) {
|
|
46
46
|
const patch = this._edits[i];
|
|
@@ -52,7 +52,7 @@ export class JournalImpl extends Journal {
|
|
|
52
52
|
});
|
|
53
53
|
}
|
|
54
54
|
redo(count = 1) {
|
|
55
|
-
Transaction.run({ hint: 'Journal.redo',
|
|
55
|
+
Transaction.run({ hint: 'Journal.redo', separation: 'isolated' }, () => {
|
|
56
56
|
let i = this._position;
|
|
57
57
|
while (i < this._edits.length && count > 0) {
|
|
58
58
|
const patch = this._edits[i];
|
|
@@ -4,7 +4,7 @@ export declare abstract class Meta {
|
|
|
4
4
|
static readonly Controller: unique symbol;
|
|
5
5
|
static readonly Initial: unique symbol;
|
|
6
6
|
static readonly Reactions: unique symbol;
|
|
7
|
-
static readonly
|
|
7
|
+
static readonly Raw: unique symbol;
|
|
8
8
|
static readonly Undefined: unique symbol;
|
|
9
9
|
static get<T>(obj: any, sym: symbol): T;
|
|
10
10
|
static set(obj: any, sym: symbol, value: any): any;
|
|
@@ -25,5 +25,5 @@ Meta.Revision = Symbol('rx-revision');
|
|
|
25
25
|
Meta.Controller = Symbol('rx-controller');
|
|
26
26
|
Meta.Initial = Symbol('rx-initial');
|
|
27
27
|
Meta.Reactions = Symbol('rx-reactions');
|
|
28
|
-
Meta.
|
|
28
|
+
Meta.Raw = Symbol('rx-raw');
|
|
29
29
|
Meta.Undefined = Symbol('rx-undefined');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Worker } from '../Worker';
|
|
2
|
-
import {
|
|
3
|
-
export declare abstract class Monitor extends
|
|
2
|
+
import { ObservableObject } from './Mvcc';
|
|
3
|
+
export declare abstract class Monitor extends ObservableObject {
|
|
4
4
|
abstract readonly isActive: boolean;
|
|
5
5
|
abstract readonly counter: number;
|
|
6
6
|
abstract readonly workers: ReadonlySet<Worker>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ObservableObject, Mvcc } from './Mvcc';
|
|
2
2
|
import { Transaction } from './Transaction';
|
|
3
|
-
export class Monitor extends
|
|
3
|
+
export class Monitor extends ObservableObject {
|
|
4
4
|
static create(hint, activationDelay, deactivationDelay, durationResolution) {
|
|
5
5
|
return MonitorImpl.create(hint, activationDelay, deactivationDelay, durationResolution);
|
|
6
6
|
}
|
|
@@ -44,7 +44,7 @@ export class MonitorImpl extends Monitor {
|
|
|
44
44
|
}
|
|
45
45
|
static doCreate(hint, activationDelay, deactivationDelay, durationResolution) {
|
|
46
46
|
const m = new MonitorImpl();
|
|
47
|
-
|
|
47
|
+
Mvcc.setHint(m, hint);
|
|
48
48
|
m.internals.activationDelay = activationDelay;
|
|
49
49
|
m.internals.deactivationDelay = deactivationDelay;
|
|
50
50
|
m.internals.durationResolution = durationResolution;
|
|
@@ -59,7 +59,7 @@ export class MonitorImpl extends Monitor {
|
|
|
59
59
|
}
|
|
60
60
|
if (delay >= 0) {
|
|
61
61
|
if (mon.internals.activationTimeout === undefined)
|
|
62
|
-
mon.internals.activationTimeout = setTimeout(() => Transaction.run({ hint: 'Monitor.activate',
|
|
62
|
+
mon.internals.activationTimeout = setTimeout(() => Transaction.run({ hint: 'Monitor.activate', separation: 'isolated' }, MonitorImpl.activate, mon, -1), delay);
|
|
63
63
|
}
|
|
64
64
|
else if (active)
|
|
65
65
|
mon.isActive = true;
|
|
@@ -67,7 +67,7 @@ export class MonitorImpl extends Monitor {
|
|
|
67
67
|
static deactivate(mon, delay) {
|
|
68
68
|
if (delay >= 0) {
|
|
69
69
|
clearTimeout(mon.internals.deactivationTimeout);
|
|
70
|
-
mon.internals.deactivationTimeout = setTimeout(() => Transaction.run({ hint: 'Monitor.deactivate',
|
|
70
|
+
mon.internals.deactivationTimeout = setTimeout(() => Transaction.run({ hint: 'Monitor.deactivate', separation: 'isolated' }, MonitorImpl.deactivate, mon, -1), delay);
|
|
71
71
|
}
|
|
72
72
|
else if (mon.counter <= 0) {
|
|
73
73
|
mon.isActive = false;
|
|
@@ -1,21 +1,24 @@
|
|
|
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, ObjectHandle,
|
|
4
|
+
import { MemberName, ObjectHandle, SeparationMode } from './Data';
|
|
5
5
|
import { Journal } from './Journal';
|
|
6
6
|
import { Monitor } from './Monitor';
|
|
7
|
-
export declare abstract class
|
|
8
|
-
protected constructor(
|
|
7
|
+
export declare abstract class MvccObject {
|
|
8
|
+
protected constructor(observable: boolean);
|
|
9
9
|
[Symbol.toStringTag](): string;
|
|
10
10
|
}
|
|
11
|
-
export declare abstract class
|
|
11
|
+
export declare abstract class TransactionalObject extends MvccObject {
|
|
12
|
+
constructor();
|
|
13
|
+
}
|
|
14
|
+
export declare abstract class ObservableObject extends MvccObject {
|
|
12
15
|
constructor();
|
|
13
16
|
}
|
|
14
17
|
export declare class OptionsImpl implements MemberOptions {
|
|
15
18
|
readonly getter: Function;
|
|
16
19
|
readonly setter: Function;
|
|
17
20
|
readonly kind: Kind;
|
|
18
|
-
readonly
|
|
21
|
+
readonly separation: SeparationMode;
|
|
19
22
|
readonly order: number;
|
|
20
23
|
readonly noSideEffects: boolean;
|
|
21
24
|
readonly triggeringArgs: boolean;
|
|
@@ -27,27 +30,27 @@ export declare class OptionsImpl implements MemberOptions {
|
|
|
27
30
|
static readonly INITIAL: Readonly<OptionsImpl>;
|
|
28
31
|
constructor(getter: Function | undefined, setter: Function | undefined, existing: OptionsImpl, patch: Partial<OptionsImpl>, implicit: boolean);
|
|
29
32
|
}
|
|
30
|
-
export declare class
|
|
33
|
+
export declare class Mvcc implements ProxyHandler<ObjectHandle> {
|
|
31
34
|
static reactionsAutoStartDisabled: boolean;
|
|
32
35
|
static repetitiveUsageWarningThreshold: number;
|
|
33
36
|
static mainThreadBlockingWarningThreshold: number;
|
|
34
37
|
static asyncActionDurationWarningThreshold: number;
|
|
35
38
|
static sensitivity: boolean;
|
|
36
|
-
static readonly transactional:
|
|
37
|
-
static readonly
|
|
38
|
-
readonly
|
|
39
|
-
constructor(
|
|
39
|
+
static readonly transactional: Mvcc;
|
|
40
|
+
static readonly observable: Mvcc;
|
|
41
|
+
readonly isObservable: boolean;
|
|
42
|
+
constructor(isObservable: boolean);
|
|
40
43
|
getPrototypeOf(h: ObjectHandle): object | null;
|
|
41
44
|
get(h: ObjectHandle, m: MemberName, receiver: any): any;
|
|
42
45
|
set(h: ObjectHandle, m: MemberName, value: any, receiver: any): boolean;
|
|
43
46
|
has(h: ObjectHandle, m: MemberName): boolean;
|
|
44
47
|
getOwnPropertyDescriptor(h: ObjectHandle, m: MemberName): PropertyDescriptor | undefined;
|
|
45
48
|
ownKeys(h: ObjectHandle): Array<string | symbol>;
|
|
46
|
-
static decorateData(
|
|
49
|
+
static decorateData(isObservable: boolean, proto: any, m: MemberName): any;
|
|
47
50
|
static decorateOperation(implicit: boolean, decorator: Function, options: Partial<MemberOptions>, proto: any, member: MemberName, pd: PropertyDescriptor | undefined): any;
|
|
48
51
|
static decorateOperationParametrized(decorator: Function, options: Partial<MemberOptions>): F<any>;
|
|
49
52
|
static acquireHandle(obj: any): ObjectHandle;
|
|
50
|
-
static
|
|
53
|
+
static createHandleForMvccObject(proto: any, data: any, blank: any, hint: string, isObservable: boolean): ObjectHandle;
|
|
51
54
|
static setProfilingMode(isOn: boolean, options?: Partial<ProfilingOptions>): void;
|
|
52
55
|
static sensitive<T>(sensitivity: boolean, func: F<T>, ...args: any[]): T;
|
|
53
56
|
static setHint<T>(obj: T, hint: string | undefined): T;
|