reactronic 0.22.315 → 0.22.316
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 +6 -6
- package/build/dist/source/Buffer.d.ts +1 -1
- package/build/dist/source/Buffer.js +1 -1
- 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 +4 -4
- package/build/dist/source/api.js +4 -4
- package/build/dist/source/impl/Changeset.js +5 -5
- package/build/dist/source/impl/Data.d.ts +1 -1
- package/build/dist/source/impl/Journal.d.ts +1 -1
- package/build/dist/source/impl/Journal.js +4 -4
- package/build/dist/source/impl/Monitor.d.ts +1 -1
- package/build/dist/source/impl/Monitor.js +4 -4
- package/build/dist/source/impl/{Hooks.d.ts → Mvcc.d.ts} +11 -8
- package/build/dist/source/impl/{Hooks.js → Mvcc.js} +49 -44
- 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
|
@@ -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 {
|
|
@@ -291,11 +291,12 @@ NPM: `npm install reactronic`
|
|
|
291
291
|
|
|
292
292
|
// Classes
|
|
293
293
|
|
|
294
|
+
class TransactionalObject { }
|
|
294
295
|
class ReactiveObject { }
|
|
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,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
|
}
|
|
@@ -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 { ReactiveObject } from './impl/
|
|
11
|
-
export { ReactiveArray } from './impl/
|
|
12
|
-
export { ReactiveMap } from './impl/
|
|
10
|
+
export { TransactionalObject, ReactiveObject } from './impl/Mvcc';
|
|
11
|
+
export { TransactionalArray, ReactiveArray } from './impl/MvccArray';
|
|
12
|
+
export { TransactionalMap, ReactiveMap } 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 { ReactiveObject } from './impl/
|
|
10
|
-
export { ReactiveArray } from './impl/
|
|
11
|
-
export { ReactiveMap } from './impl/
|
|
9
|
+
export { TransactionalObject, ReactiveObject } from './impl/Mvcc';
|
|
10
|
+
export { TransactionalArray, ReactiveArray } from './impl/MvccArray';
|
|
11
|
+
export { TransactionalMap, ReactiveMap } 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,11 +7,11 @@ 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)
|
|
@@ -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();
|
|
@@ -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,4 +1,4 @@
|
|
|
1
|
-
import { ReactiveObject } from './
|
|
1
|
+
import { ReactiveObject } from './Mvcc';
|
|
2
2
|
import { ObjectHandle, ObjectSnapshot, PatchSet } from './Data';
|
|
3
3
|
export declare type Saver = (patch: PatchSet) => Promise<void>;
|
|
4
4
|
export declare abstract class Journal extends ReactiveObject {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactiveObject } from './
|
|
1
|
+
import { ReactiveObject } from './Mvcc';
|
|
2
2
|
import { Meta, Subscription } from './Data';
|
|
3
3
|
import { Changeset, EMPTY_SNAPSHOT } from './Changeset';
|
|
4
4
|
import { Transaction } from './Transaction';
|
|
@@ -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];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactiveObject,
|
|
1
|
+
import { ReactiveObject, Mvcc } from './Mvcc';
|
|
2
2
|
import { Transaction } from './Transaction';
|
|
3
3
|
export class Monitor extends ReactiveObject {
|
|
4
4
|
static create(hint, activationDelay, deactivationDelay, durationResolution) {
|
|
@@ -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
|
|
7
|
+
export declare abstract class MvccObject {
|
|
8
8
|
protected constructor(reactive: 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 ReactiveObject 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,14 +30,14 @@ 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 reactive:
|
|
39
|
+
static readonly transactional: Mvcc;
|
|
40
|
+
static readonly reactive: Mvcc;
|
|
38
41
|
readonly isReactive: boolean;
|
|
39
42
|
constructor(isReactive: boolean);
|
|
40
43
|
getPrototypeOf(h: ObjectHandle): object | null;
|
|
@@ -47,7 +50,7 @@ export declare class Hooks implements ProxyHandler<ObjectHandle> {
|
|
|
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, reactive: 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;
|
|
@@ -3,11 +3,11 @@ import { Log, misuse } from '../util/Dbg';
|
|
|
3
3
|
import { Kind, Reentrance } from '../Options';
|
|
4
4
|
import { ObjectSnapshot, ObjectHandle, Subscription, Meta } from './Data';
|
|
5
5
|
import { Changeset, Dump, EMPTY_SNAPSHOT } from './Changeset';
|
|
6
|
-
export class
|
|
6
|
+
export class MvccObject {
|
|
7
7
|
constructor(reactive) {
|
|
8
8
|
const proto = new.target.prototype;
|
|
9
9
|
const initial = Meta.getFrom(proto, Meta.Initial);
|
|
10
|
-
const h =
|
|
10
|
+
const h = Mvcc.createHandleForMvccObject(proto, this, initial, new.target.name, reactive);
|
|
11
11
|
return h.proxy;
|
|
12
12
|
}
|
|
13
13
|
[Symbol.toStringTag]() {
|
|
@@ -15,14 +15,19 @@ export class HookedObject {
|
|
|
15
15
|
return Dump.obj(h);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
export class
|
|
18
|
+
export class TransactionalObject extends MvccObject {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(false);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export class ReactiveObject extends MvccObject {
|
|
19
24
|
constructor() {
|
|
20
25
|
super(true);
|
|
21
26
|
}
|
|
22
27
|
}
|
|
23
28
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
24
29
|
kind: Kind.Plain,
|
|
25
|
-
|
|
30
|
+
separation: false,
|
|
26
31
|
order: 0,
|
|
27
32
|
noSideEffects: false,
|
|
28
33
|
triggeringArgs: false,
|
|
@@ -37,7 +42,7 @@ export class OptionsImpl {
|
|
|
37
42
|
this.getter = getter !== undefined ? getter : existing.getter;
|
|
38
43
|
this.setter = setter !== undefined ? setter : existing.setter;
|
|
39
44
|
this.kind = merge(DEFAULT_OPTIONS.kind, existing.kind, patch.kind, implicit);
|
|
40
|
-
this.
|
|
45
|
+
this.separation = merge(DEFAULT_OPTIONS.separation, existing.separation, patch.separation, implicit);
|
|
41
46
|
this.order = merge(DEFAULT_OPTIONS.order, existing.order, patch.order, implicit);
|
|
42
47
|
this.noSideEffects = merge(DEFAULT_OPTIONS.noSideEffects, existing.noSideEffects, patch.noSideEffects, implicit);
|
|
43
48
|
this.triggeringArgs = merge(DEFAULT_OPTIONS.triggeringArgs, existing.triggeringArgs, patch.triggeringArgs, implicit);
|
|
@@ -54,7 +59,7 @@ OptionsImpl.INITIAL = Object.freeze(new OptionsImpl(UNDEF, UNDEF, Object.assign(
|
|
|
54
59
|
function merge(def, existing, patch, implicit) {
|
|
55
60
|
return patch !== undefined && (existing === def || !implicit) ? patch : existing;
|
|
56
61
|
}
|
|
57
|
-
export class
|
|
62
|
+
export class Mvcc {
|
|
58
63
|
constructor(isReactive) {
|
|
59
64
|
this.isReactive = isReactive;
|
|
60
65
|
}
|
|
@@ -84,7 +89,7 @@ export class Hooks {
|
|
|
84
89
|
if (os !== EMPTY_SNAPSHOT) {
|
|
85
90
|
let curr = os.data[m];
|
|
86
91
|
if (curr !== undefined || (os.former.snapshot.changeset === EMPTY_SNAPSHOT.changeset && (m in h.data) === false)) {
|
|
87
|
-
if (curr === undefined || curr.content !== value ||
|
|
92
|
+
if (curr === undefined || curr.content !== value || Mvcc.sensitivity) {
|
|
88
93
|
const existing = curr === null || curr === void 0 ? void 0 : curr.content;
|
|
89
94
|
if (os.former.snapshot.data[m] === curr) {
|
|
90
95
|
curr = os.data[m] = new Subscription(value);
|
|
@@ -127,12 +132,12 @@ export class Hooks {
|
|
|
127
132
|
static decorateData(reactive, proto, m) {
|
|
128
133
|
if (reactive) {
|
|
129
134
|
const get = function () {
|
|
130
|
-
const h =
|
|
131
|
-
return
|
|
135
|
+
const h = Mvcc.acquireHandle(this);
|
|
136
|
+
return Mvcc.reactive.get(h, m, this);
|
|
132
137
|
};
|
|
133
138
|
const set = function (value) {
|
|
134
|
-
const h =
|
|
135
|
-
return
|
|
139
|
+
const h = Mvcc.acquireHandle(this);
|
|
140
|
+
return Mvcc.reactive.set(h, m, value, this);
|
|
136
141
|
};
|
|
137
142
|
const enumerable = true;
|
|
138
143
|
const configurable = false;
|
|
@@ -147,11 +152,11 @@ export class Hooks {
|
|
|
147
152
|
pd = EMPTY_PROP_DESCRIPTOR;
|
|
148
153
|
const enumerable = (_a = pd.enumerable) !== null && _a !== void 0 ? _a : true;
|
|
149
154
|
const configurable = (_b = pd.configurable) !== null && _b !== void 0 ? _b : true;
|
|
150
|
-
const opts =
|
|
155
|
+
const opts = Mvcc.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);
|
|
151
156
|
if (opts.getter === opts.setter) {
|
|
152
157
|
const bootstrap = function () {
|
|
153
|
-
const h =
|
|
154
|
-
const operation =
|
|
158
|
+
const h = Mvcc.acquireHandle(this);
|
|
159
|
+
const operation = Mvcc.createOperation(h, member, opts);
|
|
155
160
|
Object.defineProperty(h.data, member, { value: operation, enumerable, configurable });
|
|
156
161
|
return operation;
|
|
157
162
|
};
|
|
@@ -159,8 +164,8 @@ export class Hooks {
|
|
|
159
164
|
}
|
|
160
165
|
else if (opts.setter === UNDEF) {
|
|
161
166
|
const bootstrap = function () {
|
|
162
|
-
const h =
|
|
163
|
-
const operation =
|
|
167
|
+
const h = Mvcc.acquireHandle(this);
|
|
168
|
+
const operation = Mvcc.createOperation(h, member, opts);
|
|
164
169
|
Object.defineProperty(h.data, member, { get: operation, enumerable, configurable });
|
|
165
170
|
return operation.call(this);
|
|
166
171
|
};
|
|
@@ -171,7 +176,7 @@ export class Hooks {
|
|
|
171
176
|
}
|
|
172
177
|
static decorateOperationParametrized(decorator, options) {
|
|
173
178
|
return function (proto, prop, pd) {
|
|
174
|
-
return
|
|
179
|
+
return Mvcc.decorateOperation(false, decorator, options, proto, prop, pd);
|
|
175
180
|
};
|
|
176
181
|
}
|
|
177
182
|
static acquireHandle(obj) {
|
|
@@ -181,71 +186,71 @@ export class Hooks {
|
|
|
181
186
|
throw misuse('only objects can be reactive');
|
|
182
187
|
const initial = Meta.getFrom(Object.getPrototypeOf(obj), Meta.Initial);
|
|
183
188
|
const os = new ObjectSnapshot(EMPTY_SNAPSHOT.changeset, EMPTY_SNAPSHOT, Object.assign({}, initial));
|
|
184
|
-
h = new ObjectHandle(obj, obj,
|
|
189
|
+
h = new ObjectHandle(obj, obj, Mvcc.reactive, os, obj.constructor.name);
|
|
185
190
|
Meta.set(os.data, Meta.Handle, h);
|
|
186
191
|
Meta.set(obj, Meta.Handle, h);
|
|
187
192
|
Meta.set(os.data, Meta.Revision, new Subscription(1));
|
|
188
193
|
}
|
|
189
194
|
return h;
|
|
190
195
|
}
|
|
191
|
-
static
|
|
196
|
+
static createHandleForMvccObject(proto, data, blank, hint, reactive) {
|
|
192
197
|
const ctx = Changeset.edit();
|
|
193
|
-
const
|
|
194
|
-
const h = new ObjectHandle(data, undefined,
|
|
198
|
+
const mvcc = reactive ? Mvcc.reactive : Mvcc.transactional;
|
|
199
|
+
const h = new ObjectHandle(data, undefined, mvcc, EMPTY_SNAPSHOT, hint);
|
|
195
200
|
ctx.getEditableObjectSnapshot(h, Meta.Handle, blank);
|
|
196
|
-
if (!
|
|
201
|
+
if (!Mvcc.reactionsAutoStartDisabled)
|
|
197
202
|
for (const m in Meta.getFrom(proto, Meta.Reactions))
|
|
198
203
|
h.proxy[m][Meta.Controller].markObsolete();
|
|
199
204
|
return h;
|
|
200
205
|
}
|
|
201
206
|
static setProfilingMode(isOn, options) {
|
|
202
207
|
if (isOn) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
208
|
+
Mvcc.repetitiveUsageWarningThreshold = options && options.repetitiveUsageWarningThreshold !== undefined ? options.repetitiveUsageWarningThreshold : 10;
|
|
209
|
+
Mvcc.mainThreadBlockingWarningThreshold = options && options.mainThreadBlockingWarningThreshold !== undefined ? options.mainThreadBlockingWarningThreshold : 14;
|
|
210
|
+
Mvcc.asyncActionDurationWarningThreshold = options && options.asyncActionDurationWarningThreshold !== undefined ? options.asyncActionDurationWarningThreshold : 300;
|
|
206
211
|
Changeset.garbageCollectionSummaryInterval = options && options.garbageCollectionSummaryInterval !== undefined ? options.garbageCollectionSummaryInterval : 100;
|
|
207
212
|
}
|
|
208
213
|
else {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
214
|
+
Mvcc.repetitiveUsageWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
215
|
+
Mvcc.mainThreadBlockingWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
216
|
+
Mvcc.asyncActionDurationWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
212
217
|
Changeset.garbageCollectionSummaryInterval = Number.MAX_SAFE_INTEGER;
|
|
213
218
|
}
|
|
214
219
|
}
|
|
215
220
|
static sensitive(sensitivity, func, ...args) {
|
|
216
|
-
const restore =
|
|
217
|
-
|
|
221
|
+
const restore = Mvcc.sensitivity;
|
|
222
|
+
Mvcc.sensitivity = sensitivity;
|
|
218
223
|
try {
|
|
219
224
|
return func(...args);
|
|
220
225
|
}
|
|
221
226
|
finally {
|
|
222
|
-
|
|
227
|
+
Mvcc.sensitivity = restore;
|
|
223
228
|
}
|
|
224
229
|
}
|
|
225
230
|
static setHint(obj, hint) {
|
|
226
231
|
if (hint) {
|
|
227
|
-
const h =
|
|
232
|
+
const h = Mvcc.acquireHandle(obj);
|
|
228
233
|
h.hint = hint;
|
|
229
234
|
}
|
|
230
235
|
return obj;
|
|
231
236
|
}
|
|
232
237
|
static getHint(obj) {
|
|
233
|
-
const h =
|
|
238
|
+
const h = Mvcc.acquireHandle(obj);
|
|
234
239
|
return h.hint;
|
|
235
240
|
}
|
|
236
241
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
throw misuse('createOperation should never be called');
|
|
242
|
+
Mvcc.reactionsAutoStartDisabled = false;
|
|
243
|
+
Mvcc.repetitiveUsageWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
244
|
+
Mvcc.mainThreadBlockingWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
245
|
+
Mvcc.asyncActionDurationWarningThreshold = Number.MAX_SAFE_INTEGER;
|
|
246
|
+
Mvcc.sensitivity = false;
|
|
247
|
+
Mvcc.transactional = new Mvcc(false);
|
|
248
|
+
Mvcc.reactive = new Mvcc(true);
|
|
249
|
+
Mvcc.createOperation = function (h, m, options) {
|
|
250
|
+
throw misuse('this implementation of createOperation should never be called');
|
|
246
251
|
};
|
|
247
|
-
|
|
248
|
-
throw misuse('rememberOperationOptions should never be called');
|
|
252
|
+
Mvcc.rememberOperationOptions = function (proto, m, getter, setter, enumerable, configurable, options, implicit) {
|
|
253
|
+
throw misuse('this implementation of rememberOperationOptions should never be called');
|
|
249
254
|
};
|
|
250
255
|
const EMPTY_PROP_DESCRIPTOR = {
|
|
251
256
|
configurable: true,
|