@legendapp/state 2.2.0-next.8 → 2.2.0-next.80
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 +4 -2
- package/babel.js.map +1 -1
- package/config/enable$get.d.ts +8 -0
- package/config/enable$get.js +24 -0
- package/config/enable$get.js.map +1 -0
- package/config/enable$get.mjs +21 -0
- package/config/enable$get.mjs.map +1 -0
- package/config/enableReactComponents.js.map +1 -1
- package/config/enableReactComponents.mjs.map +1 -1
- package/config/enableReactNativeComponents.js.map +1 -1
- package/config/enableReactNativeComponents.mjs.map +1 -1
- package/config/enableReactTracking.d.ts +0 -9
- package/config/enableReactTracking.js +34 -32
- package/config/enableReactTracking.js.map +1 -1
- package/config/enableReactTracking.mjs +35 -33
- package/config/enableReactTracking.mjs.map +1 -1
- package/config/enableReactUse.d.ts +1 -1
- package/config/enableReactUse.js +9 -1
- package/config/enableReactUse.js.map +1 -1
- package/config/enableReactUse.mjs +9 -1
- package/config/enableReactUse.mjs.map +1 -1
- package/config/enable_peek.d.ts +8 -0
- package/config/{enableDirectPeek.js → enable_peek.js} +6 -3
- package/config/enable_peek.js.map +1 -0
- package/config/{enableDirectPeek.mjs → enable_peek.mjs} +5 -3
- package/config/enable_peek.mjs.map +1 -0
- package/helpers/fetch.d.ts +4 -3
- package/helpers/fetch.js.map +1 -1
- package/helpers/fetch.mjs.map +1 -1
- package/helpers/pageHash.js.map +1 -1
- package/helpers/pageHash.mjs.map +1 -1
- package/helpers/pageHashParams.js.map +1 -1
- package/helpers/pageHashParams.mjs.map +1 -1
- package/helpers/time.d.ts +2 -2
- package/helpers/time.js.map +1 -1
- package/helpers/time.mjs.map +1 -1
- package/history.js +2 -2
- package/history.js.map +1 -1
- package/history.mjs +3 -3
- package/history.mjs.map +1 -1
- package/index.d.ts +29 -9
- package/index.js +964 -671
- package/index.js.map +1 -1
- package/index.mjs +959 -668
- package/index.mjs.map +1 -1
- package/package.json +37 -25
- package/persist-plugins/async-storage.d.ts +4 -3
- package/persist-plugins/async-storage.js +8 -7
- package/persist-plugins/async-storage.js.map +1 -1
- package/persist-plugins/async-storage.mjs +9 -8
- package/persist-plugins/async-storage.mjs.map +1 -1
- package/persist-plugins/fetch.d.ts +1 -1
- package/persist-plugins/fetch.js.map +1 -1
- package/persist-plugins/fetch.mjs.map +1 -1
- package/persist-plugins/firebase.d.ts +2 -2
- package/persist-plugins/firebase.js +12 -11
- package/persist-plugins/firebase.js.map +1 -1
- package/persist-plugins/firebase.mjs +13 -12
- package/persist-plugins/firebase.mjs.map +1 -1
- package/persist-plugins/indexeddb.d.ts +11 -10
- package/persist-plugins/indexeddb.js +2 -2
- package/persist-plugins/indexeddb.js.map +1 -1
- package/persist-plugins/indexeddb.mjs +2 -2
- package/persist-plugins/indexeddb.mjs.map +1 -1
- package/persist-plugins/local-storage.d.ts +4 -4
- package/persist-plugins/local-storage.js +19 -7
- package/persist-plugins/local-storage.js.map +1 -1
- package/persist-plugins/local-storage.mjs +20 -9
- package/persist-plugins/local-storage.mjs.map +1 -1
- package/persist-plugins/mmkv.d.ts +9 -8
- package/persist-plugins/mmkv.js +5 -4
- package/persist-plugins/mmkv.js.map +1 -1
- package/persist-plugins/mmkv.mjs +6 -5
- package/persist-plugins/mmkv.mjs.map +1 -1
- package/persist-plugins/query.d.ts +1 -1
- package/persist-plugins/query.js.map +1 -1
- package/persist-plugins/query.mjs.map +1 -1
- package/persist.d.ts +2 -14
- package/persist.js +1270 -269
- package/persist.js.map +1 -1
- package/persist.mjs +1270 -270
- package/persist.mjs.map +1 -1
- package/react-hooks/createObservableHook.js +1 -1
- package/react-hooks/createObservableHook.js.map +1 -1
- package/react-hooks/createObservableHook.mjs +1 -1
- package/react-hooks/createObservableHook.mjs.map +1 -1
- package/react-hooks/useFetch.d.ts +4 -3
- package/react-hooks/useFetch.js.map +1 -1
- package/react-hooks/useFetch.mjs.map +1 -1
- package/react-hooks/useHover.js.map +1 -1
- package/react-hooks/useHover.mjs.map +1 -1
- package/react-hooks/useMeasure.js.map +1 -1
- package/react-hooks/useMeasure.mjs.map +1 -1
- package/react-hooks/useObservableNextRouter.js.map +1 -1
- package/react-hooks/useObservableNextRouter.mjs.map +1 -1
- package/react-hooks/useObservableQuery.js.map +1 -1
- package/react-hooks/useObservableQuery.mjs.map +1 -1
- package/react-hooks/usePersistedObservable.d.ts +6 -3
- package/react-hooks/usePersistedObservable.js +5 -2
- package/react-hooks/usePersistedObservable.js.map +1 -1
- package/react-hooks/usePersistedObservable.mjs +5 -2
- package/react-hooks/usePersistedObservable.mjs.map +1 -1
- package/react.js +73 -93
- package/react.js.map +1 -1
- package/react.mjs +73 -93
- package/react.mjs.map +1 -1
- package/src/ObservableObject.ts +1217 -0
- package/src/ObservablePrimitive.ts +62 -0
- package/src/babel/index.ts +70 -0
- package/src/batching.ts +378 -0
- package/src/computed.ts +18 -0
- package/src/config/enable$get.ts +30 -0
- package/src/config/enableReactComponents.ts +26 -0
- package/src/config/enableReactNativeComponents.ts +102 -0
- package/src/config/enableReactTracking.ts +62 -0
- package/src/config/enableReactUse.ts +32 -0
- package/src/config/enable_peek.ts +31 -0
- package/src/config.ts +47 -0
- package/src/createObservable.ts +46 -0
- package/src/event.ts +26 -0
- package/src/globals.ts +234 -0
- package/src/helpers/fetch.ts +26 -0
- package/src/helpers/pageHash.ts +41 -0
- package/src/helpers/pageHashParams.ts +55 -0
- package/src/helpers/time.ts +30 -0
- package/src/helpers.ts +224 -0
- package/src/history/trackHistory.ts +29 -0
- package/src/history/undoRedo.ts +111 -0
- package/src/is.ts +63 -0
- package/src/linked.ts +6 -0
- package/src/observable.ts +32 -0
- package/src/observableInterfaces.ts +148 -0
- package/src/observableTypes.ts +226 -0
- package/src/observe.ts +89 -0
- package/src/onChange.ts +136 -0
- package/src/persist/configureObservablePersistence.ts +7 -0
- package/src/persist/fieldTransformer.ts +149 -0
- package/src/persist/observablePersistRemoteFunctionsAdapter.ts +39 -0
- package/src/persist/persistObservable.ts +1031 -0
- package/src/persist-plugins/async-storage.ts +102 -0
- package/src/persist-plugins/fetch.ts +34 -0
- package/src/persist-plugins/firebase.ts +1052 -0
- package/src/persist-plugins/indexeddb.ts +432 -0
- package/src/persist-plugins/local-storage.ts +91 -0
- package/src/persist-plugins/mmkv.ts +91 -0
- package/src/persist-plugins/query.ts +129 -0
- package/src/proxy.ts +28 -0
- package/src/react/Computed.tsx +7 -0
- package/src/react/For.tsx +116 -0
- package/src/react/Memo.tsx +4 -0
- package/src/react/Reactive.tsx +53 -0
- package/src/react/Show.tsx +33 -0
- package/src/react/Switch.tsx +43 -0
- package/src/react/react-globals.ts +3 -0
- package/src/react/{reactInterfaces.d.ts → reactInterfaces.ts} +15 -7
- package/src/react/reactive-observer.tsx +210 -0
- package/src/react/useComputed.ts +36 -0
- package/src/react/useEffectOnce.ts +41 -0
- package/src/react/useIsMounted.ts +16 -0
- package/src/react/useMount.ts +15 -0
- package/src/react/useObservable.ts +24 -0
- package/src/react/useObservableReducer.ts +52 -0
- package/src/react/useObservableState.ts +30 -0
- package/src/react/useObserve.ts +54 -0
- package/src/react/useObserveEffect.ts +40 -0
- package/src/react/usePauseProvider.tsx +13 -0
- package/src/react/useSelector.ts +167 -0
- package/src/react/useUnmount.ts +8 -0
- package/src/react/useWhen.ts +9 -0
- package/src/react-hooks/createObservableHook.ts +53 -0
- package/src/react-hooks/useFetch.ts +16 -0
- package/src/react-hooks/useHover.ts +40 -0
- package/src/react-hooks/useMeasure.ts +48 -0
- package/src/react-hooks/useObservableNextRouter.ts +137 -0
- package/src/react-hooks/useObservableQuery.ts +205 -0
- package/src/react-hooks/usePersistedObservable.ts +25 -0
- package/src/retry.ts +71 -0
- package/src/setupTracking.ts +26 -0
- package/src/sync/activateSyncedNode.ts +128 -0
- package/src/sync/configureObservableSync.ts +7 -0
- package/src/sync/persistTypes.ts +226 -0
- package/src/sync/syncHelpers.ts +56 -0
- package/src/sync/syncObservable.ts +1040 -0
- package/src/sync/syncObservableAdapter.ts +31 -0
- package/src/sync/syncTypes.ts +188 -0
- package/src/sync/synced.ts +20 -0
- package/src/sync-plugins/crud.ts +404 -0
- package/src/sync-plugins/fetch.ts +72 -0
- package/src/sync-plugins/keel.ts +452 -0
- package/src/sync-plugins/supabase.ts +261 -0
- package/src/trace/traceHelpers.ts +11 -0
- package/src/trace/useTraceListeners.ts +34 -0
- package/src/trace/useTraceUpdates.ts +24 -0
- package/src/trace/useVerifyNotTracking.ts +33 -0
- package/src/trace/useVerifyOneRender.ts +10 -0
- package/src/trackSelector.ts +52 -0
- package/src/tracking.ts +43 -0
- package/src/types/babel.d.ts +12 -0
- package/src/when.ts +75 -0
- package/sync-plugins/crud.d.ts +41 -0
- package/sync-plugins/crud.js +290 -0
- package/sync-plugins/crud.js.map +1 -0
- package/sync-plugins/crud.mjs +286 -0
- package/sync-plugins/crud.mjs.map +1 -0
- package/sync-plugins/fetch.d.ts +13 -0
- package/sync-plugins/fetch.js +46 -0
- package/sync-plugins/fetch.js.map +1 -0
- package/sync-plugins/fetch.mjs +44 -0
- package/sync-plugins/fetch.mjs.map +1 -0
- package/sync-plugins/keel.d.ts +91 -0
- package/sync-plugins/keel.js +277 -0
- package/sync-plugins/keel.js.map +1 -0
- package/sync-plugins/keel.mjs +273 -0
- package/sync-plugins/keel.mjs.map +1 -0
- package/sync-plugins/supabase.d.ts +36 -0
- package/sync-plugins/supabase.js +152 -0
- package/sync-plugins/supabase.js.map +1 -0
- package/sync-plugins/supabase.mjs +149 -0
- package/sync-plugins/supabase.mjs.map +1 -0
- package/sync.d.ts +11 -0
- package/sync.js +976 -0
- package/sync.js.map +1 -0
- package/sync.mjs +966 -0
- package/sync.mjs.map +1 -0
- package/trace.js +13 -10
- package/trace.js.map +1 -1
- package/trace.mjs +11 -8
- package/trace.mjs.map +1 -1
- package/types/babel.d.ts +3 -3
- package/config/enableDirectAccess.d.ts +0 -7
- package/config/enableDirectAccess.js +0 -25
- package/config/enableDirectAccess.js.map +0 -1
- package/config/enableDirectAccess.mjs +0 -23
- package/config/enableDirectAccess.mjs.map +0 -1
- package/config/enableDirectPeek.d.ts +0 -7
- package/config/enableDirectPeek.js.map +0 -1
- package/config/enableDirectPeek.mjs.map +0 -1
- package/config/enableReactDirectRender.d.ts +0 -2
- package/config/enableReactDirectRender.js +0 -78
- package/config/enableReactDirectRender.js.map +0 -1
- package/config/enableReactDirectRender.mjs +0 -75
- package/config/enableReactDirectRender.mjs.map +0 -1
- package/src/ObservableObject.d.ts +0 -14
- package/src/ObservablePrimitive.d.ts +0 -7
- package/src/babel/index.d.ts +0 -17
- package/src/batching.d.ts +0 -6
- package/src/computed.d.ts +0 -4
- package/src/config/enableDirectAccess.d.ts +0 -7
- package/src/config/enableDirectPeek.d.ts +0 -7
- package/src/config/enableReactComponents.d.ts +0 -7
- package/src/config/enableReactDirectRender.d.ts +0 -2
- package/src/config/enableReactNativeComponents.d.ts +0 -20
- package/src/config/enableReactTracking.d.ts +0 -15
- package/src/config/enableReactUse.d.ts +0 -7
- package/src/config.d.ts +0 -8
- package/src/createObservable.d.ts +0 -2
- package/src/event.d.ts +0 -2
- package/src/globals.d.ts +0 -32
- package/src/helpers/fetch.d.ts +0 -6
- package/src/helpers/pageHash.d.ts +0 -7
- package/src/helpers/pageHashParams.d.ts +0 -7
- package/src/helpers/time.d.ts +0 -3
- package/src/helpers.d.ts +0 -13
- package/src/history/trackHistory.d.ts +0 -4
- package/src/is.d.ts +0 -10
- package/src/observable.d.ts +0 -16
- package/src/observableInterfaces.d.ts +0 -458
- package/src/observe.d.ts +0 -6
- package/src/onChange.d.ts +0 -7
- package/src/persist/configureObservablePersistence.d.ts +0 -3
- package/src/persist/fieldTransformer.d.ts +0 -8
- package/src/persist/observablePersistRemoteFunctionsAdapter.d.ts +0 -2
- package/src/persist/persistActivateNode.d.ts +0 -1
- package/src/persist/persistHelpers.d.ts +0 -1
- package/src/persist/persistObservable.d.ts +0 -25
- package/src/persist-plugins/async-storage.d.ts +0 -14
- package/src/persist-plugins/fetch.d.ts +0 -10
- package/src/persist-plugins/firebase.d.ts +0 -51
- package/src/persist-plugins/indexeddb.d.ts +0 -25
- package/src/persist-plugins/local-storage.d.ts +0 -21
- package/src/persist-plugins/mmkv.d.ts +0 -14
- package/src/persist-plugins/query.d.ts +0 -18
- package/src/proxy.d.ts +0 -5
- package/src/react/Computed.d.ts +0 -5
- package/src/react/For.d.ts +0 -15
- package/src/react/Memo.d.ts +0 -3
- package/src/react/Reactive.d.ts +0 -9
- package/src/react/Show.d.ts +0 -18
- package/src/react/Switch.d.ts +0 -14
- package/src/react/react-globals.d.ts +0 -3
- package/src/react/reactive-observer.d.ts +0 -14
- package/src/react/useComputed.d.ts +0 -5
- package/src/react/useEffectOnce.d.ts +0 -1
- package/src/react/useIsMounted.d.ts +0 -2
- package/src/react/useMount.d.ts +0 -2
- package/src/react/useObservable.d.ts +0 -9
- package/src/react/useObservableReducer.d.ts +0 -7
- package/src/react/useObservableState.d.ts +0 -2
- package/src/react/useObserve.d.ts +0 -4
- package/src/react/useObserveEffect.d.ts +0 -4
- package/src/react/usePauseProvider.d.ts +0 -8
- package/src/react/useSelector.d.ts +0 -3
- package/src/react/useUnmount.d.ts +0 -2
- package/src/react/useWhen.d.ts +0 -3
- package/src/react-hooks/createObservableHook.d.ts +0 -2
- package/src/react-hooks/useFetch.d.ts +0 -6
- package/src/react-hooks/useHover.d.ts +0 -3
- package/src/react-hooks/useMeasure.d.ts +0 -6
- package/src/react-hooks/useObservableNextRouter.d.ts +0 -33
- package/src/react-hooks/useObservableQuery.d.ts +0 -6
- package/src/react-hooks/usePersistedObservable.d.ts +0 -11
- package/src/retry.d.ts +0 -9
- package/src/setupTracking.d.ts +0 -2
- package/src/trace/traceHelpers.d.ts +0 -2
- package/src/trace/useTraceListeners.d.ts +0 -1
- package/src/trace/useTraceUpdates.d.ts +0 -1
- package/src/trace/useVerifyNotTracking.d.ts +0 -1
- package/src/trace/useVerifyOneRender.d.ts +0 -1
- package/src/trackSelector.d.ts +0 -7
- package/src/tracking.d.ts +0 -13
- package/src/when.d.ts +0 -3
package/index.mjs
CHANGED
|
@@ -6,14 +6,17 @@ function isString(obj) {
|
|
|
6
6
|
return typeof obj === 'string';
|
|
7
7
|
}
|
|
8
8
|
function isObject(obj) {
|
|
9
|
-
return !!obj && typeof obj === 'object' && !isArray(obj);
|
|
9
|
+
return !!obj && typeof obj === 'object' && !(obj instanceof Date) && !isArray(obj);
|
|
10
10
|
}
|
|
11
11
|
function isFunction(obj) {
|
|
12
12
|
return typeof obj === 'function';
|
|
13
13
|
}
|
|
14
14
|
function isPrimitive(arg) {
|
|
15
15
|
const type = typeof arg;
|
|
16
|
-
return arg !== undefined && type !== 'object' && type !== 'function';
|
|
16
|
+
return arg !== undefined && (isDate(arg) || (type !== 'object' && type !== 'function'));
|
|
17
|
+
}
|
|
18
|
+
function isDate(obj) {
|
|
19
|
+
return obj instanceof Date;
|
|
17
20
|
}
|
|
18
21
|
function isSymbol(obj) {
|
|
19
22
|
return typeof obj === 'symbol';
|
|
@@ -24,6 +27,13 @@ function isBoolean(obj) {
|
|
|
24
27
|
function isPromise(obj) {
|
|
25
28
|
return obj instanceof Promise;
|
|
26
29
|
}
|
|
30
|
+
function isMap(obj) {
|
|
31
|
+
return obj instanceof Map;
|
|
32
|
+
}
|
|
33
|
+
function isNumber(obj) {
|
|
34
|
+
const n = obj;
|
|
35
|
+
return n - n < 1;
|
|
36
|
+
}
|
|
27
37
|
function isEmpty(obj) {
|
|
28
38
|
// Looping and returning false on the first property is faster than Object.keys(obj).length === 0
|
|
29
39
|
// https://jsbench.me/qfkqv692c8
|
|
@@ -38,6 +48,9 @@ function isEmpty(obj) {
|
|
|
38
48
|
}
|
|
39
49
|
return true;
|
|
40
50
|
}
|
|
51
|
+
function isNullOrUndefined(value) {
|
|
52
|
+
return value === undefined || value === null;
|
|
53
|
+
}
|
|
41
54
|
const setPrimitives = new Set(['boolean', 'string', 'number']);
|
|
42
55
|
/** @internal */
|
|
43
56
|
function isActualPrimitive(arg) {
|
|
@@ -53,72 +66,122 @@ const symbolGetNode = Symbol('getNode');
|
|
|
53
66
|
const symbolDelete = /* @__PURE__ */ Symbol('delete');
|
|
54
67
|
const symbolOpaque = Symbol('opaque');
|
|
55
68
|
const optimized = Symbol('optimized');
|
|
56
|
-
|
|
57
|
-
const extraPrimitiveActivators = new Map();
|
|
58
|
-
const extraPrimitiveProps = new Map();
|
|
69
|
+
const symbolLinked = Symbol('linked');
|
|
59
70
|
const globalState = {
|
|
60
71
|
isLoadingLocal: false,
|
|
61
72
|
isMerging: false,
|
|
62
|
-
isLoadingRemote
|
|
63
|
-
|
|
73
|
+
isLoadingRemote: false,
|
|
74
|
+
activateSyncedNode: undefined,
|
|
75
|
+
pendingNodes: new Map(),
|
|
76
|
+
dirtyNodes: new Set(),
|
|
77
|
+
replacer: undefined,
|
|
78
|
+
reviver: undefined,
|
|
64
79
|
};
|
|
65
|
-
function
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
function getPathType(value) {
|
|
81
|
+
return isArray(value) ? 'array' : isMap(value) ? 'map' : value instanceof Set ? 'set' : 'object';
|
|
82
|
+
}
|
|
83
|
+
function replacer(key, value) {
|
|
84
|
+
if (isMap(value)) {
|
|
85
|
+
return {
|
|
86
|
+
__LSType: 'Map',
|
|
87
|
+
value: Array.from(value.entries()), // or with spread: value: [...value]
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
else if (value instanceof Set) {
|
|
91
|
+
return {
|
|
92
|
+
__LSType: 'Set',
|
|
93
|
+
value: Array.from(value), // or with spread: value: [...value]
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
else if (globalState.replacer) {
|
|
97
|
+
value = globalState.replacer(key, value);
|
|
98
|
+
}
|
|
99
|
+
return value;
|
|
71
100
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
101
|
+
const ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
|
|
102
|
+
function reviver(key, value) {
|
|
103
|
+
if (value) {
|
|
104
|
+
if (typeof value === 'string' && ISO8601.test(value)) {
|
|
105
|
+
return new Date(value);
|
|
106
|
+
}
|
|
107
|
+
if (typeof value === 'object') {
|
|
108
|
+
if (value.__LSType === 'Map') {
|
|
109
|
+
return new Map(value.value);
|
|
110
|
+
}
|
|
111
|
+
else if (value.__LSType === 'Set') {
|
|
112
|
+
return new Set(value.value);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (globalState.reviver) {
|
|
116
|
+
value = globalState.reviver(key, value);
|
|
117
|
+
}
|
|
79
118
|
}
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
function safeStringify(value) {
|
|
122
|
+
return JSON.stringify(value, replacer);
|
|
123
|
+
}
|
|
124
|
+
function safeParse(value) {
|
|
125
|
+
return JSON.parse(value, reviver);
|
|
126
|
+
}
|
|
127
|
+
function clone(value) {
|
|
128
|
+
return safeParse(safeStringify(value));
|
|
129
|
+
}
|
|
130
|
+
function isObservable(obs) {
|
|
131
|
+
return !!obs && !!obs[symbolGetNode];
|
|
80
132
|
}
|
|
81
133
|
function getNode(obs) {
|
|
82
134
|
return obs && obs[symbolGetNode];
|
|
83
135
|
}
|
|
84
|
-
function
|
|
136
|
+
function isEvent(obs) {
|
|
85
137
|
var _a;
|
|
138
|
+
return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isEvent);
|
|
139
|
+
}
|
|
140
|
+
function setNodeValue(node, newValue) {
|
|
141
|
+
var _a, _b, _c;
|
|
86
142
|
const parentNode = (_a = node.parent) !== null && _a !== void 0 ? _a : node;
|
|
87
143
|
const key = node.parent ? node.key : '_';
|
|
88
144
|
const isDelete = newValue === symbolDelete;
|
|
89
145
|
if (isDelete)
|
|
90
146
|
newValue = undefined;
|
|
91
147
|
// Get the value of the parent
|
|
92
|
-
// const parentValue = isRoot ? node.root : ensureNodeValue(node);
|
|
93
148
|
const parentValue = node.parent ? ensureNodeValue(parentNode) : parentNode.root;
|
|
94
149
|
// Save the previous value first
|
|
95
150
|
const prevValue = parentValue[key];
|
|
96
151
|
const isFunc = isFunction(newValue);
|
|
97
152
|
// Compute newValue if newValue is a function or an observable
|
|
98
|
-
newValue = !parentNode.isAssigning && isFunc ? newValue(prevValue) : newValue;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
node.
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
153
|
+
newValue = !parentNode.isAssigning && isFunc && !isFunction(prevValue) ? newValue(prevValue) : newValue;
|
|
154
|
+
if (!globalState.isMerging ||
|
|
155
|
+
isNullOrUndefined(prevValue) ||
|
|
156
|
+
isFunction(prevValue) ||
|
|
157
|
+
!((_c = (_b = node.parent) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.get(key))) {
|
|
158
|
+
try {
|
|
159
|
+
parentNode.isSetting = (parentNode.isSetting || 0) + 1;
|
|
160
|
+
const useMapFn = isMap(parentValue);
|
|
161
|
+
// Save the new value
|
|
162
|
+
if (isDelete) {
|
|
163
|
+
if (useMapFn) {
|
|
164
|
+
parentValue.delete(key);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
delete parentValue[key];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
const useMapFn = isMap(parentValue);
|
|
172
|
+
if (useMapFn) {
|
|
173
|
+
parentValue.set(key, newValue);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
parentValue[key] = newValue;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
110
179
|
}
|
|
111
|
-
|
|
112
|
-
|
|
180
|
+
finally {
|
|
181
|
+
parentNode.isSetting--;
|
|
113
182
|
}
|
|
114
183
|
}
|
|
115
|
-
|
|
116
|
-
parentNode.isSetting--;
|
|
117
|
-
}
|
|
118
|
-
if (parentNode.root.locked && parentNode.root.set) {
|
|
119
|
-
parentNode.root.set(parentNode.root._);
|
|
120
|
-
}
|
|
121
|
-
return { prevValue, newValue, parentValue };
|
|
184
|
+
return { prevValue, newValue };
|
|
122
185
|
}
|
|
123
186
|
const arrNodeKeys = [];
|
|
124
187
|
function getNodeValue(node) {
|
|
@@ -131,18 +194,12 @@ function getNodeValue(node) {
|
|
|
131
194
|
let child = node.root._;
|
|
132
195
|
for (let i = count - 1; child && i >= 0; i--) {
|
|
133
196
|
const key = arrNodeKeys[i];
|
|
134
|
-
child = key !== 'size' && (child
|
|
197
|
+
child = key !== 'size' && (isMap(child) || child instanceof WeakMap) ? child.get(key) : child[key];
|
|
135
198
|
}
|
|
136
199
|
return child;
|
|
137
200
|
}
|
|
138
|
-
const cloneFunction = (originalFunction) => {
|
|
139
|
-
const length = originalFunction.length;
|
|
140
|
-
return length > 1
|
|
141
|
-
? (arg1, arg2) => originalFunction(arg1, arg2)
|
|
142
|
-
: (...args) => originalFunction(...args);
|
|
143
|
-
};
|
|
144
201
|
function getChildNode(node, key, asFunction) {
|
|
145
|
-
var _a;
|
|
202
|
+
var _a, _b;
|
|
146
203
|
// Get the child by key
|
|
147
204
|
let child = (_a = node.children) === null || _a === void 0 ? void 0 : _a.get(key);
|
|
148
205
|
// Create the child node if it doesn't already exist
|
|
@@ -153,11 +210,13 @@ function getChildNode(node, key, asFunction) {
|
|
|
153
210
|
key,
|
|
154
211
|
lazy: true,
|
|
155
212
|
};
|
|
156
|
-
|
|
157
|
-
|
|
213
|
+
// Lookup functions are bound with the child key
|
|
214
|
+
if (((_b = node.lazyFn) === null || _b === void 0 ? void 0 : _b.length) === 1) {
|
|
215
|
+
asFunction = node.lazyFn.bind(node, key);
|
|
158
216
|
}
|
|
159
|
-
|
|
160
|
-
child = Object.assign(
|
|
217
|
+
if (isFunction(asFunction)) {
|
|
218
|
+
child = Object.assign(() => { }, child);
|
|
219
|
+
child.lazyFn = asFunction;
|
|
161
220
|
}
|
|
162
221
|
if (!node.children) {
|
|
163
222
|
node.children = new Map();
|
|
@@ -168,7 +227,7 @@ function getChildNode(node, key, asFunction) {
|
|
|
168
227
|
}
|
|
169
228
|
function ensureNodeValue(node) {
|
|
170
229
|
let value = getNodeValue(node);
|
|
171
|
-
if (!value) {
|
|
230
|
+
if (!value || isFunction(value)) {
|
|
172
231
|
if (isChildNodeValue(node)) {
|
|
173
232
|
const parent = ensureNodeValue(node.parent);
|
|
174
233
|
value = parent[node.key] = {};
|
|
@@ -181,17 +240,19 @@ function ensureNodeValue(node) {
|
|
|
181
240
|
}
|
|
182
241
|
function findIDKey(obj, node) {
|
|
183
242
|
var _a, _b;
|
|
184
|
-
let idKey =
|
|
185
|
-
?
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
? '
|
|
189
|
-
: '
|
|
190
|
-
? '
|
|
191
|
-
: '
|
|
192
|
-
? '
|
|
193
|
-
:
|
|
194
|
-
|
|
243
|
+
let idKey = isObservable(obj)
|
|
244
|
+
? undefined
|
|
245
|
+
: isObject(obj)
|
|
246
|
+
? 'id' in obj
|
|
247
|
+
? 'id'
|
|
248
|
+
: 'key' in obj
|
|
249
|
+
? 'key'
|
|
250
|
+
: '_id' in obj
|
|
251
|
+
? '_id'
|
|
252
|
+
: '__id' in obj
|
|
253
|
+
? '__id'
|
|
254
|
+
: undefined
|
|
255
|
+
: undefined;
|
|
195
256
|
if (!idKey && node.parent) {
|
|
196
257
|
const k = node.key + '_keyExtractor';
|
|
197
258
|
const keyExtractor = (_b = (_a = node.functions) === null || _a === void 0 ? void 0 : _a.get(k)) !== null && _b !== void 0 ? _b : getNodeValue(node.parent)[node.key + '_keyExtractor'];
|
|
@@ -201,26 +262,20 @@ function findIDKey(obj, node) {
|
|
|
201
262
|
}
|
|
202
263
|
return idKey;
|
|
203
264
|
}
|
|
204
|
-
function extractFunction(node, key, fnOrComputed
|
|
265
|
+
function extractFunction(node, key, fnOrComputed) {
|
|
205
266
|
if (!node.functions) {
|
|
206
267
|
node.functions = new Map();
|
|
207
268
|
}
|
|
208
269
|
node.functions.set(key, fnOrComputed);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
node.root.toActivate = [];
|
|
213
|
-
}
|
|
214
|
-
node.root.toActivate.push(computedChildNode);
|
|
215
|
-
}
|
|
270
|
+
}
|
|
271
|
+
function equals(a, b) {
|
|
272
|
+
return a === b || (isDate(a) && isDate(b) && +a === +b);
|
|
216
273
|
}
|
|
217
274
|
|
|
218
275
|
let timeout;
|
|
219
276
|
let numInBatch = 0;
|
|
220
277
|
let isRunningBatch = false;
|
|
221
278
|
let didDelayEndBatch = false;
|
|
222
|
-
let _afterBatch = [];
|
|
223
|
-
let _queuedBatches = [];
|
|
224
279
|
let _batchMap = new Map();
|
|
225
280
|
function onActionTimeout() {
|
|
226
281
|
if (_batchMap.size > 0) {
|
|
@@ -239,23 +294,36 @@ function isArraySubset(mainArr, subsetArr) {
|
|
|
239
294
|
return true;
|
|
240
295
|
}
|
|
241
296
|
function createPreviousHandlerInner(value, changes) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
let
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
297
|
+
try {
|
|
298
|
+
// Clones the current state and inject the previous data at the changed path
|
|
299
|
+
// TODO: Is this behavior similar to setAtPath or mergeIntoObservable so one
|
|
300
|
+
// of those could be used here?
|
|
301
|
+
let cloned = value ? clone(value) : {};
|
|
302
|
+
for (let i = 0; i < changes.length; i++) {
|
|
303
|
+
const { path, prevAtPath } = changes[i];
|
|
304
|
+
let o = cloned;
|
|
305
|
+
if (path.length > 0) {
|
|
306
|
+
let i;
|
|
307
|
+
for (i = 0; i < path.length - 1; i++) {
|
|
308
|
+
o = o[path[i]];
|
|
309
|
+
}
|
|
310
|
+
const key = path[i];
|
|
311
|
+
if (isMap(o)) {
|
|
312
|
+
o.set(key, prevAtPath);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
o[key] = prevAtPath;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
cloned = prevAtPath;
|
|
251
320
|
}
|
|
252
|
-
o[path[i]] = prevAtPath;
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
clone = prevAtPath;
|
|
256
321
|
}
|
|
322
|
+
return cloned;
|
|
323
|
+
}
|
|
324
|
+
catch (_a) {
|
|
325
|
+
return undefined;
|
|
257
326
|
}
|
|
258
|
-
return clone;
|
|
259
327
|
}
|
|
260
328
|
function createPreviousHandler(value, changes) {
|
|
261
329
|
// Create a function that generates the previous state
|
|
@@ -268,9 +336,13 @@ function createPreviousHandler(value, changes) {
|
|
|
268
336
|
function notify(node, value, prev, level, whenOptimizedOnlyIf) {
|
|
269
337
|
// Run immediate listeners if there are any
|
|
270
338
|
const changesInBatch = new Map();
|
|
271
|
-
computeChangesRecursive(changesInBatch, node,
|
|
339
|
+
computeChangesRecursive(changesInBatch, node,
|
|
340
|
+
/*loading*/ globalState.isLoadingLocal,
|
|
341
|
+
/*remote*/ globalState.isLoadingRemote, value, [], [], value, prev,
|
|
272
342
|
/*immediate*/ true, level, whenOptimizedOnlyIf);
|
|
273
|
-
|
|
343
|
+
if (changesInBatch.size) {
|
|
344
|
+
batchNotifyChanges(changesInBatch, /*immediate*/ true);
|
|
345
|
+
}
|
|
274
346
|
// Update the current batch
|
|
275
347
|
const existing = _batchMap.get(node);
|
|
276
348
|
if (existing) {
|
|
@@ -278,14 +350,21 @@ function notify(node, value, prev, level, whenOptimizedOnlyIf) {
|
|
|
278
350
|
// TODO: level, whenOptimizedOnlyIf
|
|
279
351
|
}
|
|
280
352
|
else {
|
|
281
|
-
_batchMap.set(node, {
|
|
353
|
+
_batchMap.set(node, {
|
|
354
|
+
value,
|
|
355
|
+
prev,
|
|
356
|
+
level,
|
|
357
|
+
whenOptimizedOnlyIf,
|
|
358
|
+
remote: globalState.isLoadingRemote,
|
|
359
|
+
loading: globalState.isLoadingLocal,
|
|
360
|
+
});
|
|
282
361
|
}
|
|
283
362
|
// If not in a batch run it immediately
|
|
284
363
|
if (numInBatch <= 0) {
|
|
285
364
|
runBatch();
|
|
286
365
|
}
|
|
287
366
|
}
|
|
288
|
-
function computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
367
|
+
function computeChangesAtNode(changesInBatch, node, loading, remote, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
289
368
|
// If there are listeners at this node compute the changes that need to be run
|
|
290
369
|
if (immediate ? node.listenersImmediate : node.listeners) {
|
|
291
370
|
const change = {
|
|
@@ -306,18 +385,21 @@ function computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valu
|
|
|
306
385
|
changesInBatch.set(node, {
|
|
307
386
|
level,
|
|
308
387
|
value,
|
|
388
|
+
remote,
|
|
389
|
+
loading,
|
|
309
390
|
whenOptimizedOnlyIf,
|
|
310
391
|
changes: [change],
|
|
311
392
|
});
|
|
312
393
|
}
|
|
313
394
|
}
|
|
314
395
|
}
|
|
315
|
-
function computeChangesRecursive(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
396
|
+
function computeChangesRecursive(changesInBatch, node, loading, remote, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
316
397
|
// Do the compute at this node
|
|
317
|
-
computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf);
|
|
398
|
+
computeChangesAtNode(changesInBatch, node, loading, remote, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf);
|
|
318
399
|
if (node.linkedFromNodes) {
|
|
319
400
|
for (const linkedFromNode of node.linkedFromNodes) {
|
|
320
|
-
|
|
401
|
+
const childNode = getNodeAtPath(linkedFromNode, path);
|
|
402
|
+
computeChangesRecursive(changesInBatch, childNode, loading, remote, valueAtPath, [], [], valueAtPath, prevAtPath, immediate, 0, whenOptimizedOnlyIf);
|
|
321
403
|
}
|
|
322
404
|
}
|
|
323
405
|
// If not root notify up through parents
|
|
@@ -325,14 +407,14 @@ function computeChangesRecursive(changesInBatch, node, value, path, pathTypes, v
|
|
|
325
407
|
const parent = node.parent;
|
|
326
408
|
if (parent) {
|
|
327
409
|
const parentValue = getNodeValue(parent);
|
|
328
|
-
computeChangesRecursive(changesInBatch, parent, parentValue, [node.key].concat(path), [(
|
|
410
|
+
computeChangesRecursive(changesInBatch, parent, loading, remote, parentValue, [node.key].concat(path), [getPathType(value)].concat(pathTypes), valueAtPath, prevAtPath, immediate, level + 1, whenOptimizedOnlyIf);
|
|
329
411
|
}
|
|
330
412
|
}
|
|
331
413
|
}
|
|
332
414
|
function batchNotifyChanges(changesInBatch, immediate) {
|
|
333
415
|
const listenersNotified = new Set();
|
|
334
416
|
// For each change in the batch, notify all of the listeners
|
|
335
|
-
changesInBatch.forEach(({ changes, level, value, whenOptimizedOnlyIf }, node) => {
|
|
417
|
+
changesInBatch.forEach(({ changes, level, value, loading, remote, whenOptimizedOnlyIf }, node) => {
|
|
336
418
|
const listeners = immediate ? node.listenersImmediate : node.listeners;
|
|
337
419
|
if (listeners) {
|
|
338
420
|
let listenerParams;
|
|
@@ -349,6 +431,8 @@ function batchNotifyChanges(changesInBatch, immediate) {
|
|
|
349
431
|
if (!noArgs && !listenerParams) {
|
|
350
432
|
listenerParams = {
|
|
351
433
|
value,
|
|
434
|
+
loading,
|
|
435
|
+
remote,
|
|
352
436
|
getPrevious: createPreviousHandler(value, changes),
|
|
353
437
|
changes,
|
|
354
438
|
};
|
|
@@ -364,32 +448,32 @@ function batchNotifyChanges(changesInBatch, immediate) {
|
|
|
364
448
|
});
|
|
365
449
|
}
|
|
366
450
|
function runBatch() {
|
|
451
|
+
const dirtyNodes = Array.from(globalState.dirtyNodes);
|
|
452
|
+
globalState.dirtyNodes.clear();
|
|
453
|
+
dirtyNodes.forEach((node) => {
|
|
454
|
+
const dirtyFn = node.dirtyFn;
|
|
455
|
+
if (dirtyFn) {
|
|
456
|
+
node.dirtyFn = undefined;
|
|
457
|
+
dirtyFn();
|
|
458
|
+
}
|
|
459
|
+
});
|
|
367
460
|
// Save batch locally and reset _batchMap first because a new batch could begin while looping over callbacks.
|
|
368
|
-
// This can happen with
|
|
461
|
+
// This can happen with computeds for example.
|
|
369
462
|
const map = _batchMap;
|
|
370
463
|
_batchMap = new Map();
|
|
371
464
|
const changesInBatch = new Map();
|
|
372
465
|
// First compute all of the changes at each node. It's important to do this first before
|
|
373
466
|
// running all the notifications because createPreviousHandler depends on knowing
|
|
374
467
|
// all of the changes happening at the node.
|
|
375
|
-
map.forEach(({ value, prev, level, whenOptimizedOnlyIf }, node) => {
|
|
376
|
-
computeChangesRecursive(changesInBatch, node, value, [], [], value, prev, false, level, whenOptimizedOnlyIf);
|
|
468
|
+
map.forEach(({ value, prev, level, loading, remote, whenOptimizedOnlyIf }, node) => {
|
|
469
|
+
computeChangesRecursive(changesInBatch, node, loading, remote, value, [], [], value, prev, false, level, whenOptimizedOnlyIf);
|
|
377
470
|
});
|
|
378
471
|
// Once all changes are computed, notify all listeners for each node with the computed changes.
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
function batch(fn, onComplete) {
|
|
382
|
-
if (onComplete) {
|
|
383
|
-
// If there's an onComplete we need a batch that's fully isolated from others to ensure it wraps only the given changes.
|
|
384
|
-
// So if already batching, push this batch onto a queue and run it after the current batch is fully done.
|
|
385
|
-
if (isRunningBatch) {
|
|
386
|
-
_queuedBatches.push([fn, onComplete]);
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
_afterBatch.push(onComplete);
|
|
391
|
-
}
|
|
472
|
+
if (changesInBatch.size) {
|
|
473
|
+
batchNotifyChanges(changesInBatch, false);
|
|
392
474
|
}
|
|
475
|
+
}
|
|
476
|
+
function batch(fn) {
|
|
393
477
|
beginBatch();
|
|
394
478
|
try {
|
|
395
479
|
fn();
|
|
@@ -418,45 +502,61 @@ function endBatch(force) {
|
|
|
418
502
|
timeout = undefined;
|
|
419
503
|
}
|
|
420
504
|
numInBatch = 0;
|
|
421
|
-
// Save batch locally and reset _batch first because a new batch could begin while looping over callbacks.
|
|
422
|
-
// This can happen with observableComputed for example.
|
|
423
|
-
const after = _afterBatch;
|
|
424
|
-
if (after.length) {
|
|
425
|
-
_afterBatch = [];
|
|
426
|
-
}
|
|
427
505
|
isRunningBatch = true;
|
|
428
506
|
runBatch();
|
|
429
507
|
isRunningBatch = false;
|
|
430
|
-
// Run after functions at the end of this batch before running the next batch.
|
|
431
|
-
// This needs to run before the delayed endBatch because the after functions need
|
|
432
|
-
// to run before any side effects of the batch
|
|
433
|
-
for (let i = 0; i < after.length; i++) {
|
|
434
|
-
after[i]();
|
|
435
|
-
}
|
|
436
508
|
// If an endBatch was delayed run it now
|
|
437
509
|
if (didDelayEndBatch) {
|
|
438
510
|
didDelayEndBatch = false;
|
|
439
511
|
endBatch(true);
|
|
440
512
|
}
|
|
441
|
-
const queued = _queuedBatches;
|
|
442
|
-
if (queued.length) {
|
|
443
|
-
_queuedBatches = [];
|
|
444
|
-
for (let i = 0; i < queued.length; i++) {
|
|
445
|
-
const [fn, onComplete] = queued[i];
|
|
446
|
-
batch(fn, onComplete);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
513
|
}
|
|
450
514
|
}
|
|
451
515
|
}
|
|
516
|
+
function getNodeAtPath(obj, path) {
|
|
517
|
+
let o = obj;
|
|
518
|
+
for (let i = 0; i < path.length; i++) {
|
|
519
|
+
const p = path[i];
|
|
520
|
+
o = getChildNode(o, p);
|
|
521
|
+
}
|
|
522
|
+
return o;
|
|
523
|
+
}
|
|
452
524
|
|
|
453
|
-
function
|
|
454
|
-
|
|
455
|
-
|
|
525
|
+
function linked(params) {
|
|
526
|
+
return (() => ({ [symbolLinked]: params }));
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function createObservable(value, makePrimitive, extractPromise, createObject, createPrimitive) {
|
|
530
|
+
if (isObservable(value)) {
|
|
531
|
+
return value;
|
|
532
|
+
}
|
|
533
|
+
const valueIsPromise = isPromise(value);
|
|
534
|
+
const valueIsFunction = isFunction(value);
|
|
535
|
+
const root = {
|
|
536
|
+
_: value,
|
|
537
|
+
};
|
|
538
|
+
let node = {
|
|
539
|
+
root,
|
|
540
|
+
lazy: true,
|
|
541
|
+
};
|
|
542
|
+
if (valueIsFunction) {
|
|
543
|
+
node = Object.assign(() => { }, node);
|
|
544
|
+
node.lazyFn = value;
|
|
545
|
+
}
|
|
546
|
+
const prim = makePrimitive || isActualPrimitive(value);
|
|
547
|
+
const obs = prim
|
|
548
|
+
? new createPrimitive(node)
|
|
549
|
+
: createObject(node);
|
|
550
|
+
if (valueIsPromise) {
|
|
551
|
+
setNodeValue(node, undefined);
|
|
552
|
+
extractPromise(node, value);
|
|
553
|
+
}
|
|
554
|
+
return obs;
|
|
456
555
|
}
|
|
556
|
+
|
|
457
557
|
function computeSelector(selector, e, retainObservable) {
|
|
458
558
|
let c = selector;
|
|
459
|
-
if (isFunction(c)) {
|
|
559
|
+
if (!isObservable(c) && isFunction(c)) {
|
|
460
560
|
c = e ? c(e) : c();
|
|
461
561
|
}
|
|
462
562
|
return isObservable(c) && !retainObservable ? c.get() : c;
|
|
@@ -464,7 +564,7 @@ function computeSelector(selector, e, retainObservable) {
|
|
|
464
564
|
function getObservableIndex(obs) {
|
|
465
565
|
const node = getNode(obs);
|
|
466
566
|
const n = +node.key;
|
|
467
|
-
return n
|
|
567
|
+
return isNumber(n) ? n : -1;
|
|
468
568
|
}
|
|
469
569
|
function opaqueObject(value) {
|
|
470
570
|
if (value) {
|
|
@@ -472,45 +572,61 @@ function opaqueObject(value) {
|
|
|
472
572
|
}
|
|
473
573
|
return value;
|
|
474
574
|
}
|
|
475
|
-
function
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
575
|
+
function getValueAtPath$1(obj, path) {
|
|
576
|
+
let o = obj;
|
|
577
|
+
for (let i = 0; o && i < path.length; i++) {
|
|
578
|
+
const p = path[i];
|
|
579
|
+
o = o[p];
|
|
480
580
|
}
|
|
581
|
+
return o;
|
|
481
582
|
}
|
|
482
|
-
function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
|
|
583
|
+
function setAtPath(obj, path, pathTypes, value, mode, fullObj, restore) {
|
|
483
584
|
let o = obj;
|
|
484
585
|
let oFull = fullObj;
|
|
586
|
+
let p = undefined;
|
|
485
587
|
if (path.length > 0) {
|
|
486
588
|
for (let i = 0; i < path.length; i++) {
|
|
487
|
-
|
|
488
|
-
if (
|
|
489
|
-
// Don't set if the value is the same. This prevents creating a new key
|
|
490
|
-
// when setting undefined on an object without this key
|
|
491
|
-
if (o[p] !== value) {
|
|
492
|
-
o[p] = value;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
else if (o[p] === symbolDelete) {
|
|
589
|
+
p = path[i];
|
|
590
|
+
if (o[p] === symbolDelete) {
|
|
496
591
|
// If this was previously deleted, restore it
|
|
497
592
|
if (oFull) {
|
|
498
593
|
o[p] = oFull[p];
|
|
499
594
|
restore === null || restore === void 0 ? void 0 : restore(path.slice(0, i + 1), o[p]);
|
|
500
595
|
}
|
|
501
|
-
|
|
596
|
+
return obj;
|
|
597
|
+
}
|
|
598
|
+
else if (o[p] === undefined && value === undefined && i === path.length - 1) {
|
|
599
|
+
// If setting undefined and the key is undefined, no need to initialize or set it
|
|
600
|
+
return obj;
|
|
502
601
|
}
|
|
503
602
|
else if (o[p] === undefined || o[p] === null) {
|
|
504
|
-
o[p] = pathTypes[i]
|
|
603
|
+
o[p] = initializePathType(pathTypes[i]);
|
|
505
604
|
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
oFull
|
|
605
|
+
if (i < path.length - 1) {
|
|
606
|
+
o = o[p];
|
|
607
|
+
if (oFull) {
|
|
608
|
+
oFull = oFull[p];
|
|
609
|
+
}
|
|
509
610
|
}
|
|
510
611
|
}
|
|
511
612
|
}
|
|
613
|
+
// Don't set if the value is the same. This prevents creating a new key
|
|
614
|
+
// when setting undefined on an object without this key
|
|
615
|
+
if (p === undefined) {
|
|
616
|
+
if (mode === 'merge') {
|
|
617
|
+
obj = _mergeIntoObservable(obj, value);
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
obj = value;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
512
623
|
else {
|
|
513
|
-
|
|
624
|
+
if (mode === 'merge') {
|
|
625
|
+
o[p] = _mergeIntoObservable(o[p], value);
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
o[p] = value;
|
|
629
|
+
}
|
|
514
630
|
}
|
|
515
631
|
return obj;
|
|
516
632
|
}
|
|
@@ -519,8 +635,8 @@ function setInObservableAtPath(obs, path, pathTypes, value, mode) {
|
|
|
519
635
|
let v = value;
|
|
520
636
|
for (let i = 0; i < path.length; i++) {
|
|
521
637
|
const p = path[i];
|
|
522
|
-
if (!o.peek()[p]
|
|
523
|
-
o[p].set([]);
|
|
638
|
+
if (!o.peek()[p]) {
|
|
639
|
+
o[p].set(initializePathType(pathTypes[i]));
|
|
524
640
|
}
|
|
525
641
|
o = o[p];
|
|
526
642
|
v = v[p];
|
|
@@ -532,6 +648,9 @@ function setInObservableAtPath(obs, path, pathTypes, value, mode) {
|
|
|
532
648
|
else if (mode === 'assign' && o.assign && isObject(o.peek())) {
|
|
533
649
|
o.assign(v);
|
|
534
650
|
}
|
|
651
|
+
else if (mode === 'merge') {
|
|
652
|
+
mergeIntoObservable(o, v);
|
|
653
|
+
}
|
|
535
654
|
else {
|
|
536
655
|
o.set(v);
|
|
537
656
|
}
|
|
@@ -561,7 +680,9 @@ function _mergeIntoObservable(target, source) {
|
|
|
561
680
|
const key = keys[i];
|
|
562
681
|
const sourceValue = source[key];
|
|
563
682
|
if (sourceValue === symbolDelete) {
|
|
564
|
-
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete)
|
|
683
|
+
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete)
|
|
684
|
+
? target[key].delete()
|
|
685
|
+
: delete target[key];
|
|
565
686
|
}
|
|
566
687
|
else {
|
|
567
688
|
const isObj = isObject(sourceValue);
|
|
@@ -594,7 +715,7 @@ function constructObjectWithPath(path, pathTypes, value) {
|
|
|
594
715
|
let o = (out = {});
|
|
595
716
|
for (let i = 0; i < path.length; i++) {
|
|
596
717
|
const p = path[i];
|
|
597
|
-
o[p] = i === path.length - 1 ? value : pathTypes[i]
|
|
718
|
+
o[p] = i === path.length - 1 ? value : initializePathType(pathTypes[i]);
|
|
598
719
|
o = o[p];
|
|
599
720
|
}
|
|
600
721
|
}
|
|
@@ -607,7 +728,7 @@ function deconstructObjectWithPath(path, pathTypes, value) {
|
|
|
607
728
|
let o = value;
|
|
608
729
|
for (let i = 0; i < path.length; i++) {
|
|
609
730
|
const p = path[i];
|
|
610
|
-
o = o ? o[p] : pathTypes[i]
|
|
731
|
+
o = o ? o[p] : initializePathType(pathTypes[i]);
|
|
611
732
|
}
|
|
612
733
|
return o;
|
|
613
734
|
}
|
|
@@ -618,8 +739,21 @@ function setSilently(obs, newValue) {
|
|
|
618
739
|
const node = getNode(obs);
|
|
619
740
|
return setNodeValue(node, newValue).newValue;
|
|
620
741
|
}
|
|
742
|
+
function initializePathType(pathType) {
|
|
743
|
+
switch (pathType) {
|
|
744
|
+
case 'array':
|
|
745
|
+
return [];
|
|
746
|
+
case 'object':
|
|
747
|
+
return {};
|
|
748
|
+
case 'map':
|
|
749
|
+
return new Map();
|
|
750
|
+
case 'set':
|
|
751
|
+
return new Set();
|
|
752
|
+
}
|
|
753
|
+
}
|
|
621
754
|
|
|
622
|
-
function onChange(node, callback, options = {}) {
|
|
755
|
+
function onChange(node, callback, options = {}, fromLinks) {
|
|
756
|
+
var _a;
|
|
623
757
|
const { initial, immediate, noArgs } = options;
|
|
624
758
|
const { trackingType } = options;
|
|
625
759
|
let listeners = immediate ? node.listenersImmediate : node.listeners;
|
|
@@ -632,7 +766,6 @@ function onChange(node, callback, options = {}) {
|
|
|
632
766
|
node.listeners = listeners;
|
|
633
767
|
}
|
|
634
768
|
}
|
|
635
|
-
checkActivate(node);
|
|
636
769
|
const listener = {
|
|
637
770
|
listener: callback,
|
|
638
771
|
track: trackingType,
|
|
@@ -643,6 +776,8 @@ function onChange(node, callback, options = {}) {
|
|
|
643
776
|
const value = getNodeValue(node);
|
|
644
777
|
callback({
|
|
645
778
|
value,
|
|
779
|
+
loading: true,
|
|
780
|
+
remote: false,
|
|
646
781
|
changes: [
|
|
647
782
|
{
|
|
648
783
|
path: [],
|
|
@@ -654,7 +789,80 @@ function onChange(node, callback, options = {}) {
|
|
|
654
789
|
getPrevious: () => undefined,
|
|
655
790
|
});
|
|
656
791
|
}
|
|
657
|
-
|
|
792
|
+
let extraDisposes;
|
|
793
|
+
function addLinkedNodeListeners(childNode, cb = callback, from) {
|
|
794
|
+
// Don't add listeners for the same node more than once
|
|
795
|
+
if (!(fromLinks === null || fromLinks === void 0 ? void 0 : fromLinks.has(childNode))) {
|
|
796
|
+
fromLinks || (fromLinks = new Set());
|
|
797
|
+
fromLinks.add(from || node);
|
|
798
|
+
cb || (cb = callback);
|
|
799
|
+
const childOptions = {
|
|
800
|
+
trackingType: true,
|
|
801
|
+
...options,
|
|
802
|
+
};
|
|
803
|
+
// onChange for the linked node
|
|
804
|
+
extraDisposes = [...(extraDisposes || []), onChange(childNode, cb, childOptions, fromLinks)];
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
// Add listeners for linked to nodes
|
|
808
|
+
if (node.linkedToNode) {
|
|
809
|
+
addLinkedNodeListeners(node.linkedToNode);
|
|
810
|
+
}
|
|
811
|
+
// Add listeners for linked from nodes
|
|
812
|
+
(_a = node.linkedFromNodes) === null || _a === void 0 ? void 0 : _a.forEach((linkedFromNode) => addLinkedNodeListeners(linkedFromNode));
|
|
813
|
+
// Go up through the parents and add listeners for linked from nodes
|
|
814
|
+
let parent = node.parent;
|
|
815
|
+
let pathParent = [node.key];
|
|
816
|
+
while (parent) {
|
|
817
|
+
if (parent.linkedFromNodes) {
|
|
818
|
+
for (const linkedFromNode of parent.linkedFromNodes) {
|
|
819
|
+
if (!(fromLinks === null || fromLinks === void 0 ? void 0 : fromLinks.has(linkedFromNode))) {
|
|
820
|
+
const cb = createCb(linkedFromNode, pathParent, callback);
|
|
821
|
+
addLinkedNodeListeners(linkedFromNode, cb, parent);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
pathParent = [parent.key, ...pathParent];
|
|
826
|
+
parent = parent.parent;
|
|
827
|
+
}
|
|
828
|
+
return () => {
|
|
829
|
+
listeners.delete(listener);
|
|
830
|
+
extraDisposes === null || extraDisposes === void 0 ? void 0 : extraDisposes.forEach((fn) => fn());
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
function createCb(linkedFromNode, path, callback) {
|
|
834
|
+
// Create a callback for a path that calls it with the current value at the path
|
|
835
|
+
let { valueAtPath: prevAtPath } = getValueAtPath(getNodeValue(linkedFromNode), path);
|
|
836
|
+
return function ({ value: valueA, loading, remote }) {
|
|
837
|
+
const { valueAtPath, pathTypes } = getValueAtPath(valueA, path);
|
|
838
|
+
if (valueAtPath !== prevAtPath) {
|
|
839
|
+
callback({
|
|
840
|
+
value: valueAtPath,
|
|
841
|
+
loading,
|
|
842
|
+
remote,
|
|
843
|
+
changes: [
|
|
844
|
+
{
|
|
845
|
+
path,
|
|
846
|
+
pathTypes,
|
|
847
|
+
prevAtPath,
|
|
848
|
+
valueAtPath,
|
|
849
|
+
},
|
|
850
|
+
],
|
|
851
|
+
getPrevious: () => prevAtPath,
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
prevAtPath = valueAtPath;
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
function getValueAtPath(obj, path) {
|
|
858
|
+
let o = obj;
|
|
859
|
+
const pathTypes = [];
|
|
860
|
+
for (let i = 0; o && i < path.length; i++) {
|
|
861
|
+
pathTypes.push(isArray(o) ? 'array' : 'object');
|
|
862
|
+
const p = path[i];
|
|
863
|
+
o = o[p];
|
|
864
|
+
}
|
|
865
|
+
return { valueAtPath: o, pathTypes };
|
|
658
866
|
}
|
|
659
867
|
|
|
660
868
|
function setupTracking(nodes, update, noArgs, immediate) {
|
|
@@ -715,42 +923,39 @@ function updateTracking(node, track) {
|
|
|
715
923
|
|
|
716
924
|
function trackSelector(selector, update, observeEvent, observeOptions, createResubscribe) {
|
|
717
925
|
var _a;
|
|
718
|
-
let nodes;
|
|
719
|
-
let value;
|
|
720
926
|
let dispose;
|
|
721
|
-
let tracker;
|
|
722
927
|
let resubscribe;
|
|
723
928
|
let updateFn = update;
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
(_a = tracker.traceListeners) === null || _a === void 0 ? void 0 : _a.call(tracker, nodes);
|
|
738
|
-
if (tracker.traceUpdates) {
|
|
739
|
-
updateFn = tracker.traceUpdates(update);
|
|
740
|
-
}
|
|
741
|
-
// Clear tracing so it doesn't leak to other components
|
|
742
|
-
tracker.traceListeners = undefined;
|
|
743
|
-
tracker.traceUpdates = undefined;
|
|
744
|
-
}
|
|
929
|
+
beginTracking();
|
|
930
|
+
const value = selector ? computeSelector(selector, observeEvent, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.fromComputed) : selector;
|
|
931
|
+
const tracker = tracking.current;
|
|
932
|
+
const nodes = tracker.nodes;
|
|
933
|
+
endTracking();
|
|
934
|
+
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') && tracker && nodes) {
|
|
935
|
+
(_a = tracker.traceListeners) === null || _a === void 0 ? void 0 : _a.call(tracker, nodes);
|
|
936
|
+
if (tracker.traceUpdates) {
|
|
937
|
+
updateFn = tracker.traceUpdates(update);
|
|
938
|
+
}
|
|
939
|
+
// Clear tracing so it doesn't leak to other components
|
|
940
|
+
tracker.traceListeners = undefined;
|
|
941
|
+
tracker.traceUpdates = undefined;
|
|
745
942
|
}
|
|
746
943
|
if (!(observeEvent === null || observeEvent === void 0 ? void 0 : observeEvent.cancel)) {
|
|
747
944
|
// Do tracing if it was requested
|
|
748
945
|
// useSyncExternalStore doesn't subscribe until after the component mount.
|
|
749
946
|
// We want to subscribe immediately so we don't miss any updates
|
|
750
947
|
dispose = setupTracking(nodes, updateFn, false, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.immediate);
|
|
751
|
-
|
|
948
|
+
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
949
|
+
resubscribe = createResubscribe
|
|
950
|
+
? () => {
|
|
951
|
+
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
952
|
+
dispose = setupTracking(nodes, updateFn);
|
|
953
|
+
return dispose;
|
|
954
|
+
}
|
|
955
|
+
: undefined;
|
|
956
|
+
}
|
|
752
957
|
}
|
|
753
|
-
return { value, dispose, resubscribe };
|
|
958
|
+
return { nodes, value, dispose, resubscribe };
|
|
754
959
|
}
|
|
755
960
|
|
|
756
961
|
function observe(selectorOrRun, reactionOrOptions, options) {
|
|
@@ -775,9 +980,11 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
775
980
|
delete e.value;
|
|
776
981
|
// Dispose listeners from previous run
|
|
777
982
|
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
778
|
-
const { dispose: _dispose, value } = trackSelector(selectorOrRun, update, e, options);
|
|
983
|
+
const { dispose: _dispose, value, nodes } = trackSelector(selectorOrRun, update, e, options);
|
|
779
984
|
dispose = _dispose;
|
|
780
985
|
e.value = value;
|
|
986
|
+
e.nodes = nodes;
|
|
987
|
+
e.refresh = update;
|
|
781
988
|
if (e.onCleanupReaction) {
|
|
782
989
|
e.onCleanupReaction();
|
|
783
990
|
e.onCleanupReaction = undefined;
|
|
@@ -785,7 +992,9 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
785
992
|
endBatch();
|
|
786
993
|
// Call the reaction if there is one and the value changed
|
|
787
994
|
if (reaction &&
|
|
788
|
-
((options === null || options === void 0 ? void 0 : options.fromComputed) ||
|
|
995
|
+
((options === null || options === void 0 ? void 0 : options.fromComputed) ||
|
|
996
|
+
((e.num > 0 || !isEvent(selectorOrRun)) &&
|
|
997
|
+
(e.previous !== e.value || typeof e.value === 'object')))) {
|
|
789
998
|
reaction(e);
|
|
790
999
|
}
|
|
791
1000
|
// Update the previous value
|
|
@@ -811,10 +1020,17 @@ function _when(predicate, effect, checkReady) {
|
|
|
811
1020
|
return effect ? predicate.then(effect) : predicate;
|
|
812
1021
|
}
|
|
813
1022
|
let value;
|
|
1023
|
+
let effectValue;
|
|
814
1024
|
// Create a wrapping fn that calls the effect if predicate returns true
|
|
815
1025
|
function run(e) {
|
|
816
1026
|
const ret = computeSelector(predicate);
|
|
817
|
-
if (
|
|
1027
|
+
if (isPromise(ret)) {
|
|
1028
|
+
value = ret;
|
|
1029
|
+
// We want value to be the Promise but return undefined
|
|
1030
|
+
// so it doesn't run the effect with the Promise as the value
|
|
1031
|
+
return undefined;
|
|
1032
|
+
}
|
|
1033
|
+
else if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
818
1034
|
value = ret;
|
|
819
1035
|
// Set cancel so that observe does not track anymore
|
|
820
1036
|
e.cancel = true;
|
|
@@ -823,7 +1039,7 @@ function _when(predicate, effect, checkReady) {
|
|
|
823
1039
|
}
|
|
824
1040
|
function doEffect() {
|
|
825
1041
|
// If value is truthy then run the effect
|
|
826
|
-
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
1042
|
+
effectValue = effect === null || effect === void 0 ? void 0 : effect(value);
|
|
827
1043
|
}
|
|
828
1044
|
// Run in an observe
|
|
829
1045
|
observe(run, doEffect);
|
|
@@ -833,17 +1049,17 @@ function _when(predicate, effect, checkReady) {
|
|
|
833
1049
|
return effect ? value.then(effect) : value;
|
|
834
1050
|
}
|
|
835
1051
|
else if (value !== undefined) {
|
|
836
|
-
return Promise.resolve(value);
|
|
1052
|
+
return effect ? effectValue : Promise.resolve(value);
|
|
837
1053
|
}
|
|
838
1054
|
else {
|
|
839
1055
|
// Wrap it in a promise
|
|
840
1056
|
const promise = new Promise((resolve) => {
|
|
841
1057
|
if (effect) {
|
|
842
1058
|
const originalEffect = effect;
|
|
843
|
-
effect = (value) => {
|
|
1059
|
+
effect = ((value) => {
|
|
844
1060
|
const effectValue = originalEffect(value);
|
|
845
|
-
resolve(effectValue);
|
|
846
|
-
};
|
|
1061
|
+
resolve(isPromise(effectValue) ? effectValue.then((value) => value) : effectValue);
|
|
1062
|
+
});
|
|
847
1063
|
}
|
|
848
1064
|
else {
|
|
849
1065
|
effect = resolve;
|
|
@@ -859,64 +1075,6 @@ function whenReady(predicate, effect) {
|
|
|
859
1075
|
return _when(predicate, effect, true);
|
|
860
1076
|
}
|
|
861
1077
|
|
|
862
|
-
function createObservable(value, makePrimitive, extractPromise, createObject, createPrimitive) {
|
|
863
|
-
const valueIsPromise = isPromise(value);
|
|
864
|
-
const valueIsFunction = isFunction(value);
|
|
865
|
-
const root = {
|
|
866
|
-
_: value,
|
|
867
|
-
};
|
|
868
|
-
let node = {
|
|
869
|
-
root,
|
|
870
|
-
lazy: true,
|
|
871
|
-
};
|
|
872
|
-
if (valueIsFunction) {
|
|
873
|
-
node = Object.assign(cloneFunction(value), node);
|
|
874
|
-
}
|
|
875
|
-
const prim = makePrimitive || isActualPrimitive(value);
|
|
876
|
-
const obs = prim
|
|
877
|
-
? new createPrimitive(node)
|
|
878
|
-
: createObject(node);
|
|
879
|
-
if (valueIsPromise) {
|
|
880
|
-
setNodeValue(node, undefined);
|
|
881
|
-
extractPromise(node, value);
|
|
882
|
-
}
|
|
883
|
-
return obs;
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
function setupRetry(retryOptions, refresh, attemptNum) {
|
|
887
|
-
const timeout = {};
|
|
888
|
-
let didGiveUp = false;
|
|
889
|
-
const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
|
|
890
|
-
let handleError;
|
|
891
|
-
attemptNum.current++;
|
|
892
|
-
if (infinite || attemptNum.current < times) {
|
|
893
|
-
const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum.current), maxDelay);
|
|
894
|
-
handleError = () => {
|
|
895
|
-
timeout.current = setTimeout(refresh, delayTime);
|
|
896
|
-
};
|
|
897
|
-
}
|
|
898
|
-
else {
|
|
899
|
-
handleError = () => {
|
|
900
|
-
didGiveUp = true;
|
|
901
|
-
};
|
|
902
|
-
}
|
|
903
|
-
if (typeof window !== 'undefined') {
|
|
904
|
-
window.addEventListener('online', () => {
|
|
905
|
-
if (didGiveUp || timeout) {
|
|
906
|
-
if (timeout) {
|
|
907
|
-
clearTimeout(timeout.current);
|
|
908
|
-
timeout.current = undefined;
|
|
909
|
-
}
|
|
910
|
-
// Restart the backoff when coming back online
|
|
911
|
-
attemptNum.current = 0;
|
|
912
|
-
didGiveUp = false;
|
|
913
|
-
refresh();
|
|
914
|
-
}
|
|
915
|
-
});
|
|
916
|
-
}
|
|
917
|
-
return { handleError, timeout };
|
|
918
|
-
}
|
|
919
|
-
|
|
920
1078
|
const ArrayModifiers = new Set([
|
|
921
1079
|
'copyWithin',
|
|
922
1080
|
'fill',
|
|
@@ -935,9 +1093,9 @@ const ArrayLoopers = new Set([
|
|
|
935
1093
|
'find',
|
|
936
1094
|
'findIndex',
|
|
937
1095
|
'forEach',
|
|
938
|
-
'includes',
|
|
939
1096
|
'join',
|
|
940
1097
|
'map',
|
|
1098
|
+
'reduce',
|
|
941
1099
|
'some',
|
|
942
1100
|
]);
|
|
943
1101
|
const ArrayLoopersReturn = new Set(['filter', 'find']);
|
|
@@ -957,7 +1115,8 @@ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
|
957
1115
|
}
|
|
958
1116
|
function collectionSetter(node, target, prop, ...args) {
|
|
959
1117
|
var _a;
|
|
960
|
-
if (prop === 'push') {
|
|
1118
|
+
if (prop === 'push' && args.length === 1) {
|
|
1119
|
+
// Fast path for push to just append to the end
|
|
961
1120
|
setKey(node, target.length + '', args[0]);
|
|
962
1121
|
}
|
|
963
1122
|
else {
|
|
@@ -980,7 +1139,7 @@ function getKeys(obj, isArr, isMap) {
|
|
|
980
1139
|
return isArr ? undefined : obj ? (isMap ? Array.from(obj.keys()) : Object.keys(obj)) : [];
|
|
981
1140
|
}
|
|
982
1141
|
function updateNodes(parent, obj, prevValue) {
|
|
983
|
-
var _a, _b;
|
|
1142
|
+
var _a, _b, _c;
|
|
984
1143
|
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') &&
|
|
985
1144
|
typeof __devUpdateNodes !== 'undefined' &&
|
|
986
1145
|
isObject(obj)) {
|
|
@@ -1008,9 +1167,10 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1008
1167
|
const isArr = isArray(obj);
|
|
1009
1168
|
let prevChildrenById;
|
|
1010
1169
|
let moved;
|
|
1011
|
-
const
|
|
1012
|
-
const
|
|
1013
|
-
const
|
|
1170
|
+
const isCurMap = isMap(obj);
|
|
1171
|
+
const isPrevMap = isMap(prevValue);
|
|
1172
|
+
const keys = getKeys(obj, isArr, isCurMap);
|
|
1173
|
+
const keysPrev = getKeys(prevValue, isArr, isPrevMap);
|
|
1014
1174
|
const length = ((_a = (keys || obj)) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
1015
1175
|
const lengthPrev = ((_b = (keysPrev || prevValue)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
1016
1176
|
let idField;
|
|
@@ -1027,15 +1187,22 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1027
1187
|
isIdFieldFunction = isFunction(idField);
|
|
1028
1188
|
prevChildrenById = new Map();
|
|
1029
1189
|
moved = [];
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1190
|
+
}
|
|
1191
|
+
const keysSeen = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test'
|
|
1192
|
+
? new Set()
|
|
1193
|
+
: undefined;
|
|
1194
|
+
if (parent.children) {
|
|
1195
|
+
for (let i = 0; i < prevValue.length; i++) {
|
|
1196
|
+
const p = prevValue[i];
|
|
1197
|
+
if (p) {
|
|
1198
|
+
const child = parent.children.get(i + '');
|
|
1199
|
+
if (child) {
|
|
1200
|
+
if (!obj[i]) {
|
|
1201
|
+
// If the previous value is not in the new array and it
|
|
1202
|
+
// is an activated, disable its listeners
|
|
1203
|
+
handleDeletedChild(child, p);
|
|
1204
|
+
}
|
|
1205
|
+
if (idField) {
|
|
1039
1206
|
const key = isIdFieldFunction
|
|
1040
1207
|
? idField(p)
|
|
1041
1208
|
: p[idField];
|
|
@@ -1062,14 +1229,9 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1062
1229
|
if (!keys.includes(key)) {
|
|
1063
1230
|
hasADiff = true;
|
|
1064
1231
|
const child = getChildNode(parent, key);
|
|
1065
|
-
const prev =
|
|
1232
|
+
const prev = isPrevMap ? prevValue.get(key) : prevValue[key];
|
|
1066
1233
|
if (prev !== undefined) {
|
|
1067
|
-
|
|
1068
|
-
updateNodes(child, undefined, prev);
|
|
1069
|
-
}
|
|
1070
|
-
if (child.listeners || child.listenersImmediate) {
|
|
1071
|
-
notify(child, undefined, prev, 0);
|
|
1072
|
-
}
|
|
1234
|
+
handleDeletedChild(child, prev);
|
|
1073
1235
|
}
|
|
1074
1236
|
}
|
|
1075
1237
|
}
|
|
@@ -1080,16 +1242,31 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1080
1242
|
let didMove = false;
|
|
1081
1243
|
for (let i = 0; i < length; i++) {
|
|
1082
1244
|
const key = isArr ? i + '' : keys[i];
|
|
1083
|
-
|
|
1084
|
-
const prev =
|
|
1085
|
-
let isDiff = value
|
|
1245
|
+
let value = isCurMap ? obj.get(key) : obj[key];
|
|
1246
|
+
const prev = isPrevMap ? prevValue === null || prevValue === void 0 ? void 0 : prevValue.get(key) : prevValue === null || prevValue === void 0 ? void 0 : prevValue[key];
|
|
1247
|
+
let isDiff = !equals(value, prev);
|
|
1086
1248
|
if (isDiff) {
|
|
1087
1249
|
const id = idField && value
|
|
1088
1250
|
? isIdFieldFunction
|
|
1089
1251
|
? idField(value)
|
|
1090
1252
|
: value[idField]
|
|
1091
1253
|
: undefined;
|
|
1092
|
-
|
|
1254
|
+
const existingChild = (_c = parent.children) === null || _c === void 0 ? void 0 : _c.get(key);
|
|
1255
|
+
if (isObservable(value)) {
|
|
1256
|
+
const valueNode = getNode(value);
|
|
1257
|
+
if ((existingChild === null || existingChild === void 0 ? void 0 : existingChild.linkedToNode) === valueNode) {
|
|
1258
|
+
const targetValue = getNodeValue(valueNode);
|
|
1259
|
+
isCurMap ? obj.set(key, targetValue) : (obj[key] = targetValue);
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1262
|
+
const obs = value;
|
|
1263
|
+
value = () => obs;
|
|
1264
|
+
}
|
|
1265
|
+
let child = getChildNode(parent, key, value);
|
|
1266
|
+
if (!child.lazy && (isFunction(value) || isObservable(value))) {
|
|
1267
|
+
reactivateNode(child, value);
|
|
1268
|
+
peekInternal(child);
|
|
1269
|
+
}
|
|
1093
1270
|
// Detect moves within an array. Need to move the original proxy to the new position to keep
|
|
1094
1271
|
// the proxy stable, so that listeners to this node will be unaffected by the array shift.
|
|
1095
1272
|
if (isArr && id !== undefined) {
|
|
@@ -1097,7 +1274,7 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1097
1274
|
const prevChild = id !== undefined ? prevChildrenById === null || prevChildrenById === void 0 ? void 0 : prevChildrenById.get(id) : undefined;
|
|
1098
1275
|
if (!prevChild) {
|
|
1099
1276
|
// This id was not in the array before so it does not need to notify children
|
|
1100
|
-
isDiff
|
|
1277
|
+
// It does need to notify itself so isDiff should remain.
|
|
1101
1278
|
hasADiff = true;
|
|
1102
1279
|
}
|
|
1103
1280
|
else if (prevChild !== undefined && prevChild.key !== key) {
|
|
@@ -1119,7 +1296,10 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1119
1296
|
if (isDiff) {
|
|
1120
1297
|
// Array has a new / modified element
|
|
1121
1298
|
// If object iterate through its children
|
|
1122
|
-
if (
|
|
1299
|
+
if (isFunction(value) || isObservable(value)) {
|
|
1300
|
+
extractFunctionOrComputed(parent, key, value);
|
|
1301
|
+
}
|
|
1302
|
+
else if (isPrimitive(value)) {
|
|
1123
1303
|
hasADiff = true;
|
|
1124
1304
|
}
|
|
1125
1305
|
else {
|
|
@@ -1160,6 +1340,19 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1160
1340
|
}
|
|
1161
1341
|
return retValue !== null && retValue !== void 0 ? retValue : false;
|
|
1162
1342
|
}
|
|
1343
|
+
function handleDeletedChild(child, p) {
|
|
1344
|
+
var _a, _b;
|
|
1345
|
+
// If the previous value is not in the new array and it
|
|
1346
|
+
// is an activated, disable its listeners
|
|
1347
|
+
(_a = child.linkedToNodeDispose) === null || _a === void 0 ? void 0 : _a.call(child);
|
|
1348
|
+
(_b = child.activatedObserveDispose) === null || _b === void 0 ? void 0 : _b.call(child);
|
|
1349
|
+
if (!isPrimitive(p)) {
|
|
1350
|
+
updateNodes(child, undefined, p);
|
|
1351
|
+
}
|
|
1352
|
+
if (child.listeners || child.listenersImmediate) {
|
|
1353
|
+
notify(child, undefined, p, 0);
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1163
1356
|
function getProxy(node, p, asFunction) {
|
|
1164
1357
|
// Get the child node if p prop
|
|
1165
1358
|
if (p !== undefined)
|
|
@@ -1167,6 +1360,15 @@ function getProxy(node, p, asFunction) {
|
|
|
1167
1360
|
// Create a proxy if not already cached and return it
|
|
1168
1361
|
return (node.proxy || (node.proxy = new Proxy(node, proxyHandler)));
|
|
1169
1362
|
}
|
|
1363
|
+
function flushPending() {
|
|
1364
|
+
// Need to short circuit the computed batching because the user called get() or peek()
|
|
1365
|
+
// in which case the set needs to run immediately so that the values are up to date.
|
|
1366
|
+
if (globalState.pendingNodes.size > 0) {
|
|
1367
|
+
const nodes = Array.from(globalState.pendingNodes.values());
|
|
1368
|
+
globalState.pendingNodes.clear();
|
|
1369
|
+
nodes.forEach((fn) => fn());
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1170
1372
|
const proxyHandler = {
|
|
1171
1373
|
get(node, p, receiver) {
|
|
1172
1374
|
var _a;
|
|
@@ -1178,14 +1380,21 @@ const proxyHandler = {
|
|
|
1178
1380
|
if (p === symbolGetNode) {
|
|
1179
1381
|
return node;
|
|
1180
1382
|
}
|
|
1181
|
-
|
|
1383
|
+
if (p === 'apply') {
|
|
1384
|
+
const nodeValue = getNodeValue(node);
|
|
1385
|
+
if (isFunction(nodeValue)) {
|
|
1386
|
+
return nodeValue.apply;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
let value = peekInternal(node, /*activateRecursive*/ p === 'get');
|
|
1182
1390
|
// If this node is linked to another observable then forward to the target's handler.
|
|
1183
1391
|
// The exception is onChange because it needs to listen to this node for changes.
|
|
1184
1392
|
// This needs to be below peek because it activates there.
|
|
1185
|
-
|
|
1186
|
-
|
|
1393
|
+
const targetNode = node.linkedToNode || (value === null || value === void 0 ? void 0 : value[symbolGetNode]);
|
|
1394
|
+
if (targetNode && p !== 'onChange') {
|
|
1395
|
+
return proxyHandler.get(targetNode, p, receiver);
|
|
1187
1396
|
}
|
|
1188
|
-
if (value
|
|
1397
|
+
if (isMap(value) || value instanceof WeakMap || value instanceof Set || value instanceof WeakSet) {
|
|
1189
1398
|
const ret = handlerMapSet(node, p, value);
|
|
1190
1399
|
if (ret !== undefined) {
|
|
1191
1400
|
return ret;
|
|
@@ -1194,6 +1403,9 @@ const proxyHandler = {
|
|
|
1194
1403
|
const fn = observableFns.get(p);
|
|
1195
1404
|
// If this is an observable function, call it
|
|
1196
1405
|
if (fn) {
|
|
1406
|
+
if (p === 'get' || p === 'peek') {
|
|
1407
|
+
flushPending();
|
|
1408
|
+
}
|
|
1197
1409
|
return function (a, b, c) {
|
|
1198
1410
|
const l = arguments.length;
|
|
1199
1411
|
// Array call and apply are slow so micro-optimize this hot path.
|
|
@@ -1211,33 +1423,11 @@ const proxyHandler = {
|
|
|
1211
1423
|
}
|
|
1212
1424
|
};
|
|
1213
1425
|
}
|
|
1214
|
-
if (node.isComputed) {
|
|
1215
|
-
if (node.proxyFn && !fn) {
|
|
1216
|
-
return node.proxyFn(p);
|
|
1217
|
-
}
|
|
1218
|
-
else {
|
|
1219
|
-
checkActivate(node);
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
1426
|
const property = observableProperties.get(p);
|
|
1223
1427
|
if (property) {
|
|
1224
1428
|
return property.get(node);
|
|
1225
1429
|
}
|
|
1226
|
-
|
|
1227
|
-
const isValuePrimitive = isPrimitive(value);
|
|
1228
|
-
// If accessing a key that doesn't already exist, and this node has been activated with extra keys
|
|
1229
|
-
// then return the values that were set. This is used by enableLegendStateReact for example.
|
|
1230
|
-
if (value === undefined || value === null || isValuePrimitive) {
|
|
1231
|
-
if (extraPrimitiveProps.size && (node.isActivatedPrimitive || extraPrimitiveActivators.has(p))) {
|
|
1232
|
-
node.isActivatedPrimitive = true;
|
|
1233
|
-
const vPrim = extraPrimitiveProps.get(p);
|
|
1234
|
-
if (vPrim !== undefined) {
|
|
1235
|
-
return isFunction(vPrim) ? vPrim(getProxy(node)) : vPrim;
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
// /TODOV3 Remove this
|
|
1240
|
-
const vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
1430
|
+
let vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
1241
1431
|
if (isObject(value) && value[symbolOpaque]) {
|
|
1242
1432
|
return vProp;
|
|
1243
1433
|
}
|
|
@@ -1250,6 +1440,11 @@ const proxyHandler = {
|
|
|
1250
1440
|
return getProxy(node, p, fnOrComputed);
|
|
1251
1441
|
}
|
|
1252
1442
|
}
|
|
1443
|
+
if (isNullOrUndefined(value) && vProp === undefined && (ArrayModifiers.has(p) || ArrayLoopers.has(p))) {
|
|
1444
|
+
value = [];
|
|
1445
|
+
setNodeValue(node, value);
|
|
1446
|
+
vProp = value[p];
|
|
1447
|
+
}
|
|
1253
1448
|
// Handle function calls
|
|
1254
1449
|
if (isFunction(vProp)) {
|
|
1255
1450
|
if (isArray(value)) {
|
|
@@ -1261,30 +1456,31 @@ const proxyHandler = {
|
|
|
1261
1456
|
// Update that this node was accessed for observers
|
|
1262
1457
|
updateTracking(node);
|
|
1263
1458
|
return function (cbOrig, thisArg) {
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1459
|
+
const isReduce = p === 'reduce';
|
|
1460
|
+
// Callbacks are given the Proxy rather than the underlying data
|
|
1461
|
+
const cbWrapped = isReduce
|
|
1462
|
+
? (previousValue, currentValue, currentIndex, array) => {
|
|
1463
|
+
return cbOrig(previousValue, getProxy(node, currentIndex + '', currentValue), currentIndex, array);
|
|
1464
|
+
}
|
|
1465
|
+
: (val, index, array) => {
|
|
1466
|
+
return cbOrig(getProxy(node, index + '', val), index, array);
|
|
1467
|
+
};
|
|
1468
|
+
if (isReduce || !ArrayLoopersReturn.has(p)) {
|
|
1469
|
+
return value[p](cbWrapped, thisArg);
|
|
1267
1470
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
return proxy;
|
|
1277
|
-
}
|
|
1278
|
-
else {
|
|
1279
|
-
out.push(proxy);
|
|
1280
|
-
}
|
|
1471
|
+
const isFind = p === 'find';
|
|
1472
|
+
const out = [];
|
|
1473
|
+
for (let i = 0; i < value.length; i++) {
|
|
1474
|
+
if (cbWrapped(value[i], i, value)) {
|
|
1475
|
+
const proxy = getProxy(node, i + '');
|
|
1476
|
+
// find returns the first match, otherwise it returns an array
|
|
1477
|
+
if (isFind) {
|
|
1478
|
+
return proxy;
|
|
1281
1479
|
}
|
|
1480
|
+
out.push(proxy);
|
|
1282
1481
|
}
|
|
1283
|
-
return isFind ? undefined : out;
|
|
1284
|
-
}
|
|
1285
|
-
else {
|
|
1286
|
-
return value[p](cbWrapped, thisArg);
|
|
1287
1482
|
}
|
|
1483
|
+
return isFind ? undefined : out;
|
|
1288
1484
|
};
|
|
1289
1485
|
}
|
|
1290
1486
|
}
|
|
@@ -1299,10 +1495,6 @@ const proxyHandler = {
|
|
|
1299
1495
|
return vProp;
|
|
1300
1496
|
}
|
|
1301
1497
|
}
|
|
1302
|
-
// TODOV3: Remove "state"
|
|
1303
|
-
if (vProp === undefined && (p === 'state' || p === '_state') && node.state) {
|
|
1304
|
-
return node.state;
|
|
1305
|
-
}
|
|
1306
1498
|
// Return an observable proxy to the property
|
|
1307
1499
|
return getProxy(node, p);
|
|
1308
1500
|
},
|
|
@@ -1312,12 +1504,13 @@ const proxyHandler = {
|
|
|
1312
1504
|
return value !== null && typeof value === 'object' ? Reflect.getPrototypeOf(value) : null;
|
|
1313
1505
|
},
|
|
1314
1506
|
ownKeys(node) {
|
|
1315
|
-
|
|
1507
|
+
// TODO: Temporary workaround to fix a bug - the first peek may not return the correct value
|
|
1508
|
+
// if the value is a cached. This fixes the test "cache with initial ownKeys"
|
|
1509
|
+
peekInternal(node);
|
|
1510
|
+
const value = get(node, true);
|
|
1316
1511
|
if (isPrimitive(value))
|
|
1317
1512
|
return [];
|
|
1318
1513
|
const keys = value ? Reflect.ownKeys(value) : [];
|
|
1319
|
-
// Update that this node was accessed for observers
|
|
1320
|
-
updateTracking(node, true);
|
|
1321
1514
|
// This is required to fix this error:
|
|
1322
1515
|
// TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for
|
|
1323
1516
|
// property 'length' which is either non-existent or configurable in the proxy node
|
|
@@ -1367,22 +1560,21 @@ const proxyHandler = {
|
|
|
1367
1560
|
},
|
|
1368
1561
|
apply(target, thisArg, argArray) {
|
|
1369
1562
|
// If it's a function call it as a function
|
|
1370
|
-
return Reflect.apply(target, thisArg, argArray);
|
|
1563
|
+
return Reflect.apply(target.lazyFn || target, thisArg, argArray);
|
|
1371
1564
|
},
|
|
1372
1565
|
};
|
|
1373
1566
|
function set(node, newValue) {
|
|
1374
1567
|
if (node.parent) {
|
|
1375
|
-
|
|
1568
|
+
setKey(node.parent, node.key, newValue);
|
|
1376
1569
|
}
|
|
1377
1570
|
else {
|
|
1378
|
-
|
|
1571
|
+
setKey(node, '_', newValue);
|
|
1379
1572
|
}
|
|
1380
1573
|
}
|
|
1381
1574
|
function toggle(node) {
|
|
1382
1575
|
const value = getNodeValue(node);
|
|
1383
|
-
if (value === undefined || isBoolean(value)) {
|
|
1576
|
+
if (value === undefined || value === null || isBoolean(value)) {
|
|
1384
1577
|
set(node, !value);
|
|
1385
|
-
return !value;
|
|
1386
1578
|
}
|
|
1387
1579
|
else if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
1388
1580
|
throw new Error('[legend-state] Cannot toggle a non-boolean value');
|
|
@@ -1394,31 +1586,27 @@ function setKey(node, key, newValue, level) {
|
|
|
1394
1586
|
console.warn(`[legend-state] Set an HTMLElement into state. You probably don't want to do that.`);
|
|
1395
1587
|
}
|
|
1396
1588
|
}
|
|
1397
|
-
if (node.root.locked && !node.root.set) {
|
|
1398
|
-
// This happens when modifying a locked observable such as a computed.
|
|
1399
|
-
// If merging this could be happening deep in a hierarchy so we don't want to throw errors so we'll just do nothing.
|
|
1400
|
-
// This could happen during persistence local load for example.
|
|
1401
|
-
if (globalState.isMerging) {
|
|
1402
|
-
return;
|
|
1403
|
-
}
|
|
1404
|
-
else {
|
|
1405
|
-
throw new Error(process.env.NODE_ENV === 'development'
|
|
1406
|
-
? '[legend-state] Cannot modify an observable while it is locked. Please make sure that you unlock the observable before making changes.'
|
|
1407
|
-
: '[legend-state] Modified locked observable');
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
1589
|
const isRoot = !node.parent && key === '_';
|
|
1590
|
+
if (node.parent && !getNodeValue(node) && !isFunction(newValue)) {
|
|
1591
|
+
set(node, { [key]: newValue });
|
|
1592
|
+
}
|
|
1411
1593
|
// Get the child node for updating and notifying
|
|
1412
|
-
const childNode = isRoot ? node : getChildNode(node, key,
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1594
|
+
const childNode = isRoot ? node : getChildNode(node, key, newValue);
|
|
1595
|
+
if (isObservable(newValue)) {
|
|
1596
|
+
setToObservable(childNode, newValue);
|
|
1597
|
+
}
|
|
1598
|
+
else {
|
|
1599
|
+
// Set the raw value on the parent object
|
|
1600
|
+
const { newValue: savedValue, prevValue } = setNodeValue(childNode, newValue);
|
|
1601
|
+
const isPrim = isPrimitive(savedValue) || savedValue instanceof Date;
|
|
1602
|
+
if (!equals(savedValue, prevValue)) {
|
|
1603
|
+
updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level);
|
|
1604
|
+
}
|
|
1605
|
+
if (!isPrim) {
|
|
1606
|
+
childNode.needsExtract = true;
|
|
1607
|
+
}
|
|
1608
|
+
extractFunctionOrComputed(node, key, savedValue);
|
|
1419
1609
|
}
|
|
1420
|
-
extractFunctionOrComputed(node, parentValue, key, savedValue);
|
|
1421
|
-
return isFunc ? savedValue : isRoot ? getProxy(node) : getProxy(node, key);
|
|
1422
1610
|
}
|
|
1423
1611
|
function assign(node, value) {
|
|
1424
1612
|
const proxy = getProxy(node);
|
|
@@ -1426,13 +1614,22 @@ function assign(node, value) {
|
|
|
1426
1614
|
if (isPrimitive(node.root._)) {
|
|
1427
1615
|
node.root._ = {};
|
|
1428
1616
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1617
|
+
if (isMap(value)) {
|
|
1618
|
+
const currentValue = getNodeValue(node);
|
|
1619
|
+
if (isMap(currentValue)) {
|
|
1620
|
+
value.forEach((value, key) => currentValue.set(key, value));
|
|
1621
|
+
}
|
|
1433
1622
|
}
|
|
1434
|
-
|
|
1435
|
-
|
|
1623
|
+
else {
|
|
1624
|
+
// Set inAssign to allow setting on safe observables
|
|
1625
|
+
node.isAssigning = (node.isAssigning || 0) + 1;
|
|
1626
|
+
try {
|
|
1627
|
+
// TODO: If current value is a Map how to assign into the Map?
|
|
1628
|
+
Object.assign(proxy, value);
|
|
1629
|
+
}
|
|
1630
|
+
finally {
|
|
1631
|
+
node.isAssigning--;
|
|
1632
|
+
}
|
|
1436
1633
|
}
|
|
1437
1634
|
endBatch();
|
|
1438
1635
|
return proxy;
|
|
@@ -1443,7 +1640,13 @@ function deleteFn(node, key) {
|
|
|
1443
1640
|
key = node.key;
|
|
1444
1641
|
node = node.parent;
|
|
1445
1642
|
}
|
|
1446
|
-
|
|
1643
|
+
const value = getNodeValue(node);
|
|
1644
|
+
if (isArray(value)) {
|
|
1645
|
+
collectionSetter(node, value, 'splice', key, 1);
|
|
1646
|
+
}
|
|
1647
|
+
else {
|
|
1648
|
+
setKey(node, key !== null && key !== void 0 ? key : '_', symbolDelete, /*level*/ -1);
|
|
1649
|
+
}
|
|
1447
1650
|
}
|
|
1448
1651
|
function handlerMapSet(node, p, value) {
|
|
1449
1652
|
const vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
@@ -1468,6 +1671,9 @@ function handlerMapSet(node, p, value) {
|
|
|
1468
1671
|
}
|
|
1469
1672
|
return ret;
|
|
1470
1673
|
}
|
|
1674
|
+
else if (l === 1 && isMap(value)) {
|
|
1675
|
+
set(node, a);
|
|
1676
|
+
}
|
|
1471
1677
|
}
|
|
1472
1678
|
else if (p === 'delete') {
|
|
1473
1679
|
if (l > 0) {
|
|
@@ -1523,8 +1729,11 @@ function handlerMapSet(node, p, value) {
|
|
|
1523
1729
|
function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRoot, level) {
|
|
1524
1730
|
if (!childNode)
|
|
1525
1731
|
childNode = node;
|
|
1526
|
-
// Make sure we don't call too many listeners for
|
|
1732
|
+
// Make sure we don't call too many listeners for every property set
|
|
1527
1733
|
beginBatch();
|
|
1734
|
+
if (isPrim === undefined) {
|
|
1735
|
+
isPrim = isPrimitive(newValue);
|
|
1736
|
+
}
|
|
1528
1737
|
let hasADiff = isPrim;
|
|
1529
1738
|
let whenOptimizedOnlyIf = false;
|
|
1530
1739
|
// If new value is an object or array update notify down the tree
|
|
@@ -1544,7 +1753,7 @@ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRo
|
|
|
1544
1753
|
}
|
|
1545
1754
|
endBatch();
|
|
1546
1755
|
}
|
|
1547
|
-
function extractPromise(node, value, setter
|
|
1756
|
+
function extractPromise(node, value, setter) {
|
|
1548
1757
|
if (!node.state) {
|
|
1549
1758
|
node.state = createObservable({
|
|
1550
1759
|
isLoaded: false,
|
|
@@ -1560,30 +1769,29 @@ function extractPromise(node, value, setter, handleError) {
|
|
|
1560
1769
|
})
|
|
1561
1770
|
.catch((error) => {
|
|
1562
1771
|
node.state.error.set(error);
|
|
1563
|
-
if (handleError) {
|
|
1564
|
-
handleError(error);
|
|
1565
|
-
}
|
|
1566
1772
|
});
|
|
1567
1773
|
}
|
|
1568
|
-
function extractFunctionOrComputed(node,
|
|
1774
|
+
function extractFunctionOrComputed(node, k, v, activateRecursive) {
|
|
1569
1775
|
if (isPromise(v)) {
|
|
1570
1776
|
const childNode = getChildNode(node, k);
|
|
1571
1777
|
extractPromise(childNode, v);
|
|
1572
1778
|
setNodeValue(childNode, undefined);
|
|
1573
1779
|
}
|
|
1780
|
+
else if (isObservable(v)) {
|
|
1781
|
+
const fn = () => v;
|
|
1782
|
+
extractFunction(node, k, fn);
|
|
1783
|
+
const childNode = getChildNode(node, k, fn);
|
|
1784
|
+
const targetNode = getNode(v);
|
|
1785
|
+
// Set node to target's value if activating or it's already activated
|
|
1786
|
+
const initialValue = activateRecursive || !targetNode.lazy ? peekInternal(targetNode) : undefined;
|
|
1787
|
+
setNodeValue(childNode, initialValue);
|
|
1788
|
+
}
|
|
1574
1789
|
else if (typeof v === 'function') {
|
|
1575
1790
|
extractFunction(node, k, v);
|
|
1576
|
-
delete obj[k];
|
|
1577
1791
|
}
|
|
1578
|
-
else if (typeof v == 'object' && v !== null && v !== undefined) {
|
|
1579
|
-
const childNode =
|
|
1580
|
-
|
|
1581
|
-
extractFunction(node, k, v, childNode);
|
|
1582
|
-
delete obj[k];
|
|
1583
|
-
}
|
|
1584
|
-
else {
|
|
1585
|
-
return true;
|
|
1586
|
-
}
|
|
1792
|
+
else if (activateRecursive && typeof v == 'object' && v !== null && v !== undefined) {
|
|
1793
|
+
const childNode = getChildNode(node, k);
|
|
1794
|
+
checkLazy(childNode, v, activateRecursive);
|
|
1587
1795
|
}
|
|
1588
1796
|
}
|
|
1589
1797
|
function get(node, options) {
|
|
@@ -1593,210 +1801,303 @@ function get(node, options) {
|
|
|
1593
1801
|
return peek(node);
|
|
1594
1802
|
}
|
|
1595
1803
|
function peek(node) {
|
|
1596
|
-
const value =
|
|
1804
|
+
const value = peekInternal(node, true);
|
|
1805
|
+
return value;
|
|
1806
|
+
}
|
|
1807
|
+
function peekInternal(node, activateRecursive) {
|
|
1808
|
+
if (node.dirtyFn) {
|
|
1809
|
+
const dirtyFn = node.dirtyFn;
|
|
1810
|
+
node.dirtyFn = undefined;
|
|
1811
|
+
globalState.dirtyNodes.delete(node);
|
|
1812
|
+
dirtyFn();
|
|
1813
|
+
}
|
|
1814
|
+
let value = getNodeValue(node);
|
|
1815
|
+
value = checkLazy(node, value, !!activateRecursive);
|
|
1816
|
+
return value;
|
|
1817
|
+
}
|
|
1818
|
+
function checkLazy(node, value, activateRecursive) {
|
|
1597
1819
|
// If node is not yet lazily computed go do that
|
|
1598
1820
|
const lazy = node.lazy;
|
|
1599
1821
|
if (lazy) {
|
|
1822
|
+
const lazyFn = node.lazyFn;
|
|
1600
1823
|
delete node.lazy;
|
|
1601
|
-
if (isFunction(
|
|
1602
|
-
|
|
1824
|
+
if (isFunction(lazyFn)) {
|
|
1825
|
+
if (lazyFn.length === 1) {
|
|
1826
|
+
// This is a lookup function, so return a record object
|
|
1827
|
+
value = {};
|
|
1828
|
+
}
|
|
1829
|
+
else {
|
|
1830
|
+
if (node.parent) {
|
|
1831
|
+
const parentValue = getNodeValue(node.parent);
|
|
1832
|
+
if (parentValue) {
|
|
1833
|
+
delete parentValue[node.key];
|
|
1834
|
+
}
|
|
1835
|
+
else {
|
|
1836
|
+
node.root._ = undefined;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
value = activateNodeFunction(node, lazyFn);
|
|
1840
|
+
}
|
|
1603
1841
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1842
|
+
}
|
|
1843
|
+
if (lazy || node.needsExtract || activateRecursive) {
|
|
1844
|
+
for (const key in value) {
|
|
1845
|
+
if (hasOwnProperty.call(value, key)) {
|
|
1846
|
+
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
1847
|
+
if (property === null || property === void 0 ? void 0 : property.get) {
|
|
1848
|
+
delete value[key];
|
|
1849
|
+
value[key] = property.set
|
|
1850
|
+
? linked({
|
|
1851
|
+
get: property.get,
|
|
1852
|
+
set: ({ value }) => property.set(value),
|
|
1853
|
+
})
|
|
1854
|
+
: property.get;
|
|
1608
1855
|
}
|
|
1856
|
+
extractFunctionOrComputed(node, key, value[key], activateRecursive);
|
|
1609
1857
|
}
|
|
1610
1858
|
}
|
|
1611
1859
|
}
|
|
1612
|
-
// Check if computed needs to activate
|
|
1613
|
-
checkActivate(node);
|
|
1614
1860
|
return value;
|
|
1615
1861
|
}
|
|
1616
|
-
function
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
const onSet = (onSetFnParam) => {
|
|
1624
|
-
state.onSetFn = onSetFnParam;
|
|
1625
|
-
};
|
|
1626
|
-
// The onSet function handles the observable being set
|
|
1627
|
-
// and forwards the set elsewhere
|
|
1628
|
-
const updateLastSync = (fn) => {
|
|
1629
|
-
state.lastSync.value = fn;
|
|
1630
|
-
};
|
|
1631
|
-
// The subscribe function runs a function that listens to
|
|
1632
|
-
// a data source and sends updates into the observable
|
|
1633
|
-
const subscribe = (fn) => {
|
|
1634
|
-
if (!state.subscriber) {
|
|
1635
|
-
state.subscriber = fn;
|
|
1636
|
-
}
|
|
1637
|
-
};
|
|
1638
|
-
const cache = (fn) => {
|
|
1639
|
-
if (!state.cacheOptions) {
|
|
1640
|
-
state.cacheOptions = isFunction(fn) ? fn() : fn;
|
|
1641
|
-
}
|
|
1642
|
-
return new Promise((resolve) => {
|
|
1643
|
-
const wait = () => {
|
|
1644
|
-
if (node.state) {
|
|
1645
|
-
when(node.state.isLoadedLocal, () => {
|
|
1646
|
-
const dateModified = node.state.dateModified.get();
|
|
1647
|
-
resolve({ dateModified, value: peek(node) });
|
|
1648
|
-
});
|
|
1649
|
-
}
|
|
1650
|
-
else {
|
|
1651
|
-
queueMicrotask(wait);
|
|
1652
|
-
}
|
|
1653
|
-
};
|
|
1654
|
-
wait();
|
|
1655
|
-
});
|
|
1656
|
-
};
|
|
1657
|
-
const retry = (params) => {
|
|
1658
|
-
if (!state.retryOptions) {
|
|
1659
|
-
state.retryOptions = params || {};
|
|
1660
|
-
}
|
|
1661
|
-
};
|
|
1662
|
-
// The proxy function simply marks the node as a proxy with this function
|
|
1663
|
-
// so that child nodes will be created with this function, and then simply
|
|
1664
|
-
// activated as a function
|
|
1665
|
-
const proxy = (fn) => {
|
|
1666
|
-
node.proxyFn2 = fn;
|
|
1667
|
-
};
|
|
1668
|
-
return {
|
|
1669
|
-
onSet,
|
|
1670
|
-
proxy,
|
|
1671
|
-
cache,
|
|
1672
|
-
retry,
|
|
1673
|
-
subscribe,
|
|
1674
|
-
updateLastSync,
|
|
1675
|
-
obs$: getProxy(node),
|
|
1676
|
-
};
|
|
1862
|
+
function reactivateNode(node, lazyFn) {
|
|
1863
|
+
var _a, _b;
|
|
1864
|
+
(_a = node.activatedObserveDispose) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
1865
|
+
(_b = node.linkedToNodeDispose) === null || _b === void 0 ? void 0 : _b.call(node);
|
|
1866
|
+
node.activatedObserveDispose = node.linkedToNodeDispose = node.linkedToNode = undefined;
|
|
1867
|
+
node.lazyFn = lazyFn;
|
|
1868
|
+
node.lazy = true;
|
|
1677
1869
|
}
|
|
1678
1870
|
function activateNodeFunction(node, lazyFn) {
|
|
1679
|
-
let prevTarget
|
|
1680
|
-
let curTarget
|
|
1871
|
+
// let prevTarget$: Observable<any>;
|
|
1872
|
+
// let curTarget$: Observable<any>;
|
|
1681
1873
|
let update;
|
|
1682
1874
|
let wasPromise;
|
|
1683
|
-
let
|
|
1684
|
-
|
|
1685
|
-
const
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1875
|
+
let ignoreThisUpdate;
|
|
1876
|
+
let isFirst = true;
|
|
1877
|
+
const activateFn = lazyFn;
|
|
1878
|
+
let activatedValue;
|
|
1879
|
+
let disposes = [];
|
|
1880
|
+
let refreshFn;
|
|
1881
|
+
function markDirty() {
|
|
1882
|
+
node.dirtyFn = refreshFn;
|
|
1883
|
+
globalState.dirtyNodes.add(node);
|
|
1884
|
+
}
|
|
1885
|
+
node.activatedObserveDispose = observe(() => {
|
|
1886
|
+
var _a, _b, _c, _d;
|
|
1887
|
+
// Set it to undefined so that the activation function gets undefined
|
|
1888
|
+
// if it peeks itself
|
|
1889
|
+
if (isFirst) {
|
|
1890
|
+
isFirst = false;
|
|
1891
|
+
setNodeValue(node, undefined);
|
|
1892
|
+
}
|
|
1689
1893
|
// Run the function at this node
|
|
1690
|
-
let value =
|
|
1691
|
-
// If target is an observable,
|
|
1692
|
-
// and set up an onSet to write changes back to it
|
|
1894
|
+
let value = activateFn();
|
|
1895
|
+
// If target is an observable, make this node a link to it
|
|
1693
1896
|
if (isObservable(value)) {
|
|
1694
|
-
|
|
1695
|
-
curTarget$ = value;
|
|
1696
|
-
params.onSet(({ value: newValue, getPrevious }) => {
|
|
1697
|
-
// Don't set the target observable if the target has changed since the last run
|
|
1698
|
-
if (!prevTarget$ || curTarget$ === prevTarget$) {
|
|
1699
|
-
// Set the node value back to what it was before before setting it.
|
|
1700
|
-
// This is a workaround for linked objects because it might not notify
|
|
1701
|
-
// if setting a property of an object
|
|
1702
|
-
// TODO: Is there a way to not do this? Or at least only do it in a
|
|
1703
|
-
// small subset of cases?
|
|
1704
|
-
setNodeValue(getNode(curTarget$), getPrevious());
|
|
1705
|
-
// Set the value on the curTarget
|
|
1706
|
-
curTarget$.set(newValue);
|
|
1707
|
-
}
|
|
1708
|
-
});
|
|
1709
|
-
// Get the value from the observable because we still want the raw value
|
|
1710
|
-
// for the effect.
|
|
1711
|
-
value = value.get();
|
|
1897
|
+
value = setToObservable(node, value);
|
|
1712
1898
|
}
|
|
1713
|
-
|
|
1714
|
-
|
|
1899
|
+
if (isFunction(value)) {
|
|
1900
|
+
value = value();
|
|
1901
|
+
}
|
|
1902
|
+
const activated = !isObservable(value)
|
|
1903
|
+
? value === null || value === void 0 ? void 0 : value[symbolLinked]
|
|
1904
|
+
: undefined;
|
|
1905
|
+
if (activated) {
|
|
1906
|
+
node.activationState = activated;
|
|
1907
|
+
value = undefined;
|
|
1715
1908
|
}
|
|
1909
|
+
ignoreThisUpdate = false;
|
|
1910
|
+
wasPromise = isPromise(value);
|
|
1716
1911
|
// Activate this node if not activated already (may be called recursively)
|
|
1717
1912
|
// TODO: Is calling recursively bad? If so can it be fixed?
|
|
1718
1913
|
if (!node.activated) {
|
|
1719
1914
|
node.activated = true;
|
|
1720
|
-
|
|
1721
|
-
|
|
1915
|
+
let activateNodeFn = activateNodeBase;
|
|
1916
|
+
// If this is a Synced then run it through persistence instead of base
|
|
1917
|
+
if (activated === null || activated === void 0 ? void 0 : activated.synced) {
|
|
1918
|
+
activateNodeFn = globalState.activateSyncedNode;
|
|
1919
|
+
ignoreThisUpdate = true;
|
|
1920
|
+
}
|
|
1921
|
+
const { update: newUpdate, value: newValue } = activateNodeFn(node, value);
|
|
1922
|
+
update = newUpdate;
|
|
1923
|
+
value = newValue !== null && newValue !== void 0 ? newValue : activated === null || activated === void 0 ? void 0 : activated.initial;
|
|
1924
|
+
}
|
|
1925
|
+
else if (node.activationState) {
|
|
1926
|
+
const activated = node.activationState;
|
|
1927
|
+
if ((_b = (_a = node.state) === null || _a === void 0 ? void 0 : _a.peek()) === null || _b === void 0 ? void 0 : _b.sync) {
|
|
1928
|
+
node.state.sync();
|
|
1929
|
+
ignoreThisUpdate = true;
|
|
1930
|
+
}
|
|
1931
|
+
else {
|
|
1932
|
+
value = (_d = (_c = activated.get) === null || _c === void 0 ? void 0 : _c.call(activated)) !== null && _d !== void 0 ? _d : activated.initial;
|
|
1933
|
+
}
|
|
1722
1934
|
}
|
|
1723
|
-
|
|
1935
|
+
// value is undefined if it's in a persisted retry
|
|
1936
|
+
wasPromise = wasPromise || isPromise(value);
|
|
1724
1937
|
return value;
|
|
1725
|
-
}, (
|
|
1726
|
-
if (!
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
if (
|
|
1731
|
-
if (
|
|
1732
|
-
|
|
1938
|
+
}, (e) => {
|
|
1939
|
+
if (!ignoreThisUpdate) {
|
|
1940
|
+
const { value, nodes, refresh } = e;
|
|
1941
|
+
refreshFn = refresh;
|
|
1942
|
+
if (!wasPromise || !globalState.isLoadingRemote) {
|
|
1943
|
+
if (wasPromise) {
|
|
1944
|
+
if (node.activationState) {
|
|
1945
|
+
const { initial } = node.activationState;
|
|
1946
|
+
if (value && isPromise(value)) {
|
|
1947
|
+
// Extract the promise to make it set the value/error when it comes in
|
|
1948
|
+
extractPromise(node, value, update);
|
|
1949
|
+
}
|
|
1950
|
+
// Set this to undefined only if it's replacing the activation function,
|
|
1951
|
+
// so we don't overwrite it if it already has real data from either local
|
|
1952
|
+
// cache or a previous run
|
|
1953
|
+
if (isFunction(getNodeValue(node))) {
|
|
1954
|
+
setNodeValue(node, initial !== null && initial !== void 0 ? initial : undefined);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
else if (node.activated) {
|
|
1958
|
+
// Extract the promise to make it set the value/error when it comes in
|
|
1959
|
+
extractPromise(node, value, update);
|
|
1960
|
+
// Set this to undefined only if it's replacing the activation function,
|
|
1961
|
+
// so we don't overwrite it if it already has real data from either local
|
|
1962
|
+
// cache or a previous run
|
|
1963
|
+
if (isFunction(getNodeValue(node))) {
|
|
1964
|
+
setNodeValue(node, undefined);
|
|
1965
|
+
}
|
|
1733
1966
|
}
|
|
1734
|
-
const { handleError, timeout } = setupRetry(retryOptions, refresh, attemptNum);
|
|
1735
|
-
onError = handleError;
|
|
1736
|
-
timeoutRetry = timeout;
|
|
1737
1967
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1968
|
+
else {
|
|
1969
|
+
activatedValue = value;
|
|
1970
|
+
if (node.state.isLoaded.peek()) {
|
|
1971
|
+
node.isComputing = true;
|
|
1972
|
+
set(node, value);
|
|
1973
|
+
node.isComputing = false;
|
|
1974
|
+
}
|
|
1975
|
+
else {
|
|
1976
|
+
setNodeValue(node, value);
|
|
1977
|
+
node.state.assign({
|
|
1978
|
+
isLoaded: true,
|
|
1979
|
+
error: undefined,
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1745
1982
|
}
|
|
1746
1983
|
}
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
});
|
|
1753
|
-
}
|
|
1984
|
+
disposes.forEach((fn) => fn());
|
|
1985
|
+
disposes = [];
|
|
1986
|
+
nodes === null || nodes === void 0 ? void 0 : nodes.forEach(({ node }) => {
|
|
1987
|
+
disposes.push(onChange(node, markDirty, { immediate: true }));
|
|
1988
|
+
});
|
|
1754
1989
|
}
|
|
1755
|
-
|
|
1990
|
+
e.cancel = true;
|
|
1991
|
+
}, { fromComputed: true });
|
|
1992
|
+
return activatedValue;
|
|
1756
1993
|
}
|
|
1757
|
-
|
|
1758
|
-
const { onSetFn, subscriber } = node.activationState;
|
|
1759
|
-
let isSetting = false;
|
|
1994
|
+
function activateNodeBase(node, value) {
|
|
1760
1995
|
if (!node.state) {
|
|
1761
1996
|
node.state = createObservable({
|
|
1762
1997
|
isLoaded: false,
|
|
1763
1998
|
}, false, extractPromise, getProxy);
|
|
1764
1999
|
}
|
|
1765
|
-
if (
|
|
1766
|
-
const
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
2000
|
+
if (node.activationState) {
|
|
2001
|
+
const { set: setFn, get: getFn, initial } = node.activationState;
|
|
2002
|
+
value = getFn === null || getFn === void 0 ? void 0 : getFn();
|
|
2003
|
+
if (value == undefined || value === null) {
|
|
2004
|
+
value = initial;
|
|
2005
|
+
}
|
|
2006
|
+
if (setFn) {
|
|
2007
|
+
let allChanges = [];
|
|
2008
|
+
let latestValue = undefined;
|
|
2009
|
+
let runNumber = 0;
|
|
2010
|
+
const runChanges = (listenerParams) => {
|
|
2011
|
+
// Don't call the set if this is the first value coming in
|
|
2012
|
+
if (allChanges.length > 0) {
|
|
2013
|
+
let changes;
|
|
2014
|
+
let value;
|
|
2015
|
+
let loading = false;
|
|
2016
|
+
let remote = false;
|
|
2017
|
+
let getPrevious;
|
|
2018
|
+
if (listenerParams) {
|
|
2019
|
+
changes = listenerParams.changes;
|
|
2020
|
+
value = listenerParams.value;
|
|
2021
|
+
loading = listenerParams.loading;
|
|
2022
|
+
remote = listenerParams.remote;
|
|
2023
|
+
getPrevious = listenerParams.getPrevious;
|
|
2024
|
+
}
|
|
2025
|
+
else {
|
|
2026
|
+
// If this is called by flushPending then get the change array
|
|
2027
|
+
// that we've been building up.
|
|
2028
|
+
changes = allChanges;
|
|
2029
|
+
value = latestValue;
|
|
2030
|
+
getPrevious = createPreviousHandler(value, changes);
|
|
2031
|
+
}
|
|
2032
|
+
allChanges = [];
|
|
2033
|
+
latestValue = undefined;
|
|
2034
|
+
globalState.pendingNodes.delete(node);
|
|
2035
|
+
runNumber++;
|
|
2036
|
+
const thisRunNumber = runNumber;
|
|
2037
|
+
const run = () => {
|
|
2038
|
+
if (thisRunNumber !== runNumber) {
|
|
2039
|
+
// set may get called multiple times before it loads so ignore any previous runs
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
2042
|
+
node.isComputing = true;
|
|
2043
|
+
setFn({
|
|
2044
|
+
value,
|
|
2045
|
+
changes,
|
|
2046
|
+
loading,
|
|
2047
|
+
remote,
|
|
2048
|
+
getPrevious,
|
|
2049
|
+
});
|
|
2050
|
+
node.isComputing = false;
|
|
2051
|
+
};
|
|
2052
|
+
whenReady(node.state.isLoaded, run);
|
|
1775
2053
|
}
|
|
1776
|
-
}
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
2054
|
+
};
|
|
2055
|
+
const onChangeImmediate = ({ value, changes }) => {
|
|
2056
|
+
if (!node.isComputing) {
|
|
2057
|
+
if (changes.length > 1 || !isFunction(changes[0].prevAtPath)) {
|
|
2058
|
+
latestValue = value;
|
|
2059
|
+
if (allChanges.length > 0) {
|
|
2060
|
+
changes = changes.filter((change) => !isArraySubset(allChanges[0].path, change.path));
|
|
2061
|
+
}
|
|
2062
|
+
allChanges.push(...changes);
|
|
2063
|
+
globalState.pendingNodes.set(node, runChanges);
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
};
|
|
2067
|
+
// Create an immediate listener to mark this node as pending. Then actually run
|
|
2068
|
+
// the changes at the end of the batch so everything is properly batched.
|
|
2069
|
+
// However, this can be short circuited if the user calls get() or peek()
|
|
2070
|
+
// in which case the set needs to run immediately so that the values are up to date.
|
|
2071
|
+
onChange(node, onChangeImmediate, { immediate: true });
|
|
2072
|
+
onChange(node, runChanges);
|
|
2073
|
+
}
|
|
1787
2074
|
}
|
|
1788
2075
|
const update = ({ value }) => {
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
if (!isSetting) {
|
|
2076
|
+
if (!node.isComputing) {
|
|
2077
|
+
node.isComputing = true;
|
|
1792
2078
|
set(node, value);
|
|
2079
|
+
node.isComputing = false;
|
|
1793
2080
|
}
|
|
1794
2081
|
};
|
|
1795
|
-
|
|
1796
|
-
|
|
2082
|
+
return { update, value };
|
|
2083
|
+
}
|
|
2084
|
+
function setToObservable(node, value) {
|
|
2085
|
+
var _a;
|
|
2086
|
+
// If the computed is a proxy to another observable
|
|
2087
|
+
// link it to the target observable
|
|
2088
|
+
const linkedNode = getNode(value);
|
|
2089
|
+
if (linkedNode !== node && (linkedNode === null || linkedNode === void 0 ? void 0 : linkedNode.linkedToNode) !== node) {
|
|
2090
|
+
node.linkedToNode = linkedNode;
|
|
2091
|
+
linkedNode.linkedFromNodes || (linkedNode.linkedFromNodes = new Set());
|
|
2092
|
+
linkedNode.linkedFromNodes.add(node);
|
|
2093
|
+
(_a = node.linkedToNodeDispose) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
2094
|
+
node.linkedToNodeDispose = onChange(linkedNode, () => {
|
|
2095
|
+
value = peek(linkedNode);
|
|
2096
|
+
set(node, value);
|
|
2097
|
+
}, { initial: true }, new Set([node]));
|
|
1797
2098
|
}
|
|
1798
|
-
return
|
|
1799
|
-
}
|
|
2099
|
+
return value;
|
|
2100
|
+
}
|
|
1800
2101
|
|
|
1801
2102
|
const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
|
|
1802
2103
|
function ObservablePrimitiveClass(node) {
|
|
@@ -1813,8 +2114,14 @@ function proto(key, fn) {
|
|
|
1813
2114
|
return fn.call(this, this._node, ...args);
|
|
1814
2115
|
};
|
|
1815
2116
|
}
|
|
1816
|
-
proto('peek',
|
|
1817
|
-
|
|
2117
|
+
proto('peek', (node) => {
|
|
2118
|
+
flushPending();
|
|
2119
|
+
return peek(node);
|
|
2120
|
+
});
|
|
2121
|
+
proto('get', (node, options) => {
|
|
2122
|
+
flushPending();
|
|
2123
|
+
return get(node, options);
|
|
2124
|
+
});
|
|
1818
2125
|
proto('set', set);
|
|
1819
2126
|
proto('onChange', onChange);
|
|
1820
2127
|
// Getters
|
|
@@ -1826,13 +2133,12 @@ Object.defineProperty(ObservablePrimitiveClass.prototype, symbolGetNode, {
|
|
|
1826
2133
|
});
|
|
1827
2134
|
ObservablePrimitiveClass.prototype.toggle = function () {
|
|
1828
2135
|
const value = this.peek();
|
|
1829
|
-
if (value === undefined || isBoolean(value)) {
|
|
2136
|
+
if (value === undefined || value === null || isBoolean(value)) {
|
|
1830
2137
|
this.set(!value);
|
|
1831
2138
|
}
|
|
1832
2139
|
else if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
1833
2140
|
throw new Error('[legend-state] Cannot toggle a non-boolean value');
|
|
1834
2141
|
}
|
|
1835
|
-
return !value;
|
|
1836
2142
|
};
|
|
1837
2143
|
ObservablePrimitiveClass.prototype.delete = function () {
|
|
1838
2144
|
this.set(undefined);
|
|
@@ -1845,92 +2151,22 @@ function observable(value) {
|
|
|
1845
2151
|
function observablePrimitive(value) {
|
|
1846
2152
|
return createObservable(value, true, extractPromise, getProxy, ObservablePrimitiveClass);
|
|
1847
2153
|
}
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
function computed(compute, set$1) {
|
|
1851
|
-
// Create an observable for this computed variable
|
|
1852
|
-
const obs = observable();
|
|
1853
|
-
lockObservable(obs, true);
|
|
2154
|
+
function syncState(obs) {
|
|
1854
2155
|
const node = getNode(obs);
|
|
1855
|
-
node.
|
|
1856
|
-
|
|
1857
|
-
const setInner = function (val) {
|
|
1858
|
-
const prevNode = node.linkedToNode;
|
|
1859
|
-
// If it was previously linked to a node remove self
|
|
1860
|
-
// from its linkedFromNodes
|
|
1861
|
-
if (prevNode) {
|
|
1862
|
-
prevNode.linkedFromNodes.delete(node);
|
|
1863
|
-
node.linkedToNode = undefined;
|
|
1864
|
-
}
|
|
1865
|
-
const { parentOther } = node;
|
|
1866
|
-
if (isObservable(val)) {
|
|
1867
|
-
// If the computed is a proxy to another observable
|
|
1868
|
-
// link it to the target observable
|
|
1869
|
-
const linkedNode = getNode(val);
|
|
1870
|
-
node.linkedToNode = linkedNode;
|
|
1871
|
-
if (!linkedNode.linkedFromNodes) {
|
|
1872
|
-
linkedNode.linkedFromNodes = new Set();
|
|
1873
|
-
}
|
|
1874
|
-
linkedNode.linkedFromNodes.add(node);
|
|
1875
|
-
if (node.parentOther) {
|
|
1876
|
-
onChange(linkedNode, ({ value }) => {
|
|
1877
|
-
setNodeValue(node.parentOther, value);
|
|
1878
|
-
}, { initial: true });
|
|
1879
|
-
}
|
|
1880
|
-
// If the target observable is different then notify for the change
|
|
1881
|
-
if (prevNode) {
|
|
1882
|
-
const value = getNodeValue(linkedNode);
|
|
1883
|
-
const prevValue = getNodeValue(prevNode);
|
|
1884
|
-
notify(node, value, prevValue, 0);
|
|
1885
|
-
}
|
|
1886
|
-
}
|
|
1887
|
-
else if (val !== obs.peek()) {
|
|
1888
|
-
// Unlock computed node before setting the value
|
|
1889
|
-
lockObservable(obs, false);
|
|
1890
|
-
const setter = isSetAfterActivated ? set : setNodeValue;
|
|
1891
|
-
// Update the computed value
|
|
1892
|
-
setter(node, val);
|
|
1893
|
-
// If the computed is a child of an observable set the value on it
|
|
1894
|
-
if (parentOther) {
|
|
1895
|
-
let didUnlock = false;
|
|
1896
|
-
if (parentOther.root.locked) {
|
|
1897
|
-
parentOther.root.locked = false;
|
|
1898
|
-
didUnlock = true;
|
|
1899
|
-
}
|
|
1900
|
-
setter(parentOther, val);
|
|
1901
|
-
if (didUnlock) {
|
|
1902
|
-
parentOther.root.locked = true;
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
// Re-lock the computed node
|
|
1906
|
-
lockObservable(obs, true);
|
|
1907
|
-
}
|
|
1908
|
-
else if (parentOther) {
|
|
1909
|
-
setNodeValue(parentOther, val);
|
|
1910
|
-
}
|
|
1911
|
-
isSetAfterActivated = true;
|
|
1912
|
-
};
|
|
1913
|
-
// Lazily activate the observable when get is called
|
|
1914
|
-
node.root.activate = () => {
|
|
1915
|
-
node.root.activate = undefined;
|
|
1916
|
-
observe(compute, ({ value }) => {
|
|
1917
|
-
if (isPromise(value)) {
|
|
1918
|
-
value.then((v) => setInner(v));
|
|
1919
|
-
}
|
|
1920
|
-
else {
|
|
1921
|
-
setInner(value);
|
|
1922
|
-
}
|
|
1923
|
-
}, { immediate: true, fromComputed: true });
|
|
1924
|
-
};
|
|
1925
|
-
if (set$1) {
|
|
1926
|
-
node.root.set = (value) => {
|
|
1927
|
-
batch(() => set$1(value));
|
|
1928
|
-
};
|
|
2156
|
+
if (!node.state) {
|
|
2157
|
+
peekInternal(node);
|
|
1929
2158
|
}
|
|
1930
|
-
|
|
2159
|
+
if (!node.state) {
|
|
2160
|
+
node.state = observable({});
|
|
2161
|
+
}
|
|
2162
|
+
return node.state;
|
|
1931
2163
|
}
|
|
1932
2164
|
|
|
1933
|
-
function
|
|
2165
|
+
function computed(get, set) {
|
|
2166
|
+
return observable(set ? linked({ get: get, set: ({ value }) => set(value) }) : get);
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
function configureLegendState({ observableFunctions, observableProperties: observableProperties$1, jsonReplacer, jsonReviver, }) {
|
|
1934
2170
|
if (observableFunctions) {
|
|
1935
2171
|
for (const key in observableFunctions) {
|
|
1936
2172
|
const fn = observableFunctions[key];
|
|
@@ -1955,6 +2191,12 @@ function configureLegendState({ observableFunctions, observableProperties: obser
|
|
|
1955
2191
|
});
|
|
1956
2192
|
}
|
|
1957
2193
|
}
|
|
2194
|
+
if (jsonReplacer) {
|
|
2195
|
+
globalState.replacer = jsonReplacer;
|
|
2196
|
+
}
|
|
2197
|
+
if (jsonReviver) {
|
|
2198
|
+
globalState.reviver = jsonReviver;
|
|
2199
|
+
}
|
|
1958
2200
|
}
|
|
1959
2201
|
|
|
1960
2202
|
function event() {
|
|
@@ -1981,50 +2223,99 @@ function event() {
|
|
|
1981
2223
|
}
|
|
1982
2224
|
|
|
1983
2225
|
function proxy(get, set) {
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2226
|
+
return observable((key) => set
|
|
2227
|
+
? linked({
|
|
2228
|
+
get: () => get(key),
|
|
2229
|
+
set: ({ value }) => set(key, value),
|
|
2230
|
+
})
|
|
2231
|
+
: get(key));
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2234
|
+
function calculateRetryDelay(retryOptions, attemptNum) {
|
|
2235
|
+
const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
|
|
2236
|
+
if (infinite || attemptNum < times) {
|
|
2237
|
+
const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum), maxDelay);
|
|
2238
|
+
return delayTime;
|
|
2239
|
+
}
|
|
2240
|
+
return null;
|
|
2241
|
+
}
|
|
2242
|
+
function createRetryTimeout(retryOptions, attemptNum, fn) {
|
|
2243
|
+
const delayTime = calculateRetryDelay(retryOptions, attemptNum);
|
|
2244
|
+
if (delayTime) {
|
|
2245
|
+
return setTimeout(fn, delayTime);
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
function runWithRetry(node, state, fn) {
|
|
2249
|
+
const { waitFor } = node.activationState;
|
|
2250
|
+
const { retry } = state;
|
|
2251
|
+
const e = { cancel: false };
|
|
2252
|
+
let value = undefined;
|
|
2253
|
+
if (waitFor) {
|
|
2254
|
+
value = whenReady(waitFor, () => {
|
|
2255
|
+
node.activationState.waitFor = undefined;
|
|
2256
|
+
return fn(e);
|
|
2257
|
+
});
|
|
2258
|
+
}
|
|
2259
|
+
else {
|
|
2260
|
+
value = fn(e);
|
|
2261
|
+
}
|
|
2262
|
+
if (isPromise(value) && retry) {
|
|
2263
|
+
let timeoutRetry;
|
|
2264
|
+
return new Promise((resolve) => {
|
|
2265
|
+
const run = () => {
|
|
2266
|
+
value
|
|
2267
|
+
.then((val) => {
|
|
2268
|
+
node.activationState.persistedRetry = false;
|
|
2269
|
+
resolve(val);
|
|
2270
|
+
})
|
|
2271
|
+
.catch(() => {
|
|
2272
|
+
state.attemptNum++;
|
|
2273
|
+
if (timeoutRetry) {
|
|
2274
|
+
clearTimeout(timeoutRetry);
|
|
2275
|
+
}
|
|
2276
|
+
if (!e.cancel) {
|
|
2277
|
+
timeoutRetry = createRetryTimeout(retry, state.attemptNum, () => {
|
|
2278
|
+
value = fn(e);
|
|
2279
|
+
run();
|
|
2280
|
+
});
|
|
2281
|
+
}
|
|
2282
|
+
})
|
|
2283
|
+
.finally(() => {
|
|
2284
|
+
node.activationState.persistedRetry = false;
|
|
2004
2285
|
});
|
|
2005
|
-
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
}
|
|
2009
|
-
return
|
|
2286
|
+
};
|
|
2287
|
+
run();
|
|
2288
|
+
});
|
|
2289
|
+
}
|
|
2290
|
+
return value;
|
|
2010
2291
|
}
|
|
2011
2292
|
|
|
2012
2293
|
const internal = {
|
|
2294
|
+
createPreviousHandler,
|
|
2295
|
+
clone,
|
|
2013
2296
|
ensureNodeValue,
|
|
2014
2297
|
findIDKey,
|
|
2015
2298
|
get,
|
|
2016
2299
|
getNode,
|
|
2300
|
+
getNodeValue,
|
|
2301
|
+
getPathType,
|
|
2017
2302
|
getProxy,
|
|
2303
|
+
getValueAtPath: getValueAtPath$1,
|
|
2018
2304
|
globalState,
|
|
2305
|
+
initializePathType,
|
|
2019
2306
|
observableFns,
|
|
2020
2307
|
optimized,
|
|
2021
2308
|
peek,
|
|
2309
|
+
runWithRetry,
|
|
2310
|
+
safeParse,
|
|
2311
|
+
safeStringify,
|
|
2022
2312
|
set,
|
|
2023
2313
|
setAtPath,
|
|
2024
2314
|
setNodeValue,
|
|
2025
|
-
|
|
2315
|
+
symbolLinked,
|
|
2026
2316
|
symbolDelete,
|
|
2317
|
+
tracking,
|
|
2027
2318
|
};
|
|
2028
2319
|
|
|
2029
|
-
export { ObservablePrimitiveClass, batch, beginBatch, beginTracking,
|
|
2320
|
+
export { ObservablePrimitiveClass, batch, beginBatch, beginTracking, computeSelector, computed, configureLegendState, constructObjectWithPath, deconstructObjectWithPath, endBatch, endTracking, event, findIDKey, getNode, getNodeValue, getObservableIndex, hasOwnProperty, internal, isArray, isBoolean, isDate, isEmpty, isFunction, isMap, isNullOrUndefined, isNumber, isObject, isObservable, isObservableValueReady, isPrimitive, isPromise, isString, isSymbol, linked, mergeIntoObservable, observable, observablePrimitive, observe, opaqueObject, optimized, proxy, setAtPath, setInObservableAtPath, setSilently, setupTracking, symbolDelete, syncState, trackSelector, tracking, updateTracking, when, whenReady };
|
|
2030
2321
|
//# sourceMappingURL=index.mjs.map
|