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