@legendapp/state 2.2.0-next.7 → 2.2.0-next.71
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.map +1 -1
- package/config/enableReactTracking.mjs.map +1 -1
- package/config/enableReactUse.d.ts +1 -1
- package/config/enableReactUse.js +1 -0
- package/config/enableReactUse.js.map +1 -1
- package/config/enableReactUse.mjs +1 -0
- 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 +30 -9
- package/index.js +877 -661
- package/index.js.map +1 -1
- package/index.mjs +874 -658
- package/index.mjs.map +1 -1
- package/package.json +22 -25
- package/persist-plugins/async-storage.d.ts +3 -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.js.map +1 -1
- package/persist-plugins/fetch.mjs.map +1 -1
- package/persist-plugins/firebase.d.ts +1 -1
- 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 +10 -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 +3 -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 +8 -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.js.map +1 -1
- package/persist-plugins/query.mjs.map +1 -1
- package/persist.d.ts +2 -14
- package/persist.js +1250 -268
- package/persist.js.map +1 -1
- package/persist.mjs +1250 -269
- 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 +5 -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 +61 -75
- package/react.js.map +1 -1
- package/react.mjs +61 -75
- package/react.mjs.map +1 -1
- package/src/ObservableObject.ts +1184 -0
- package/src/ObservablePrimitive.ts +62 -0
- package/src/babel/index.ts +70 -0
- package/src/batching.ts +372 -0
- package/src/computed.ts +16 -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 +60 -0
- package/src/config/enableReactUse.ts +23 -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 +224 -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 +221 -0
- package/src/history/trackHistory.ts +29 -0
- package/src/is.ts +56 -0
- package/src/linked.ts +6 -0
- package/src/observable.ts +32 -0
- package/src/observableInterfaces.ts +165 -0
- package/src/observableTypes.ts +221 -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 +1029 -0
- package/src/persist-plugins/async-storage.ts +102 -0
- package/src/persist-plugins/fetch.ts +33 -0
- package/src/persist-plugins/firebase.ts +1050 -0
- package/src/persist-plugins/indexeddb.ts +433 -0
- package/src/persist-plugins/local-storage.ts +90 -0
- package/src/persist-plugins/mmkv.ts +90 -0
- package/src/persist-plugins/query.ts +133 -0
- package/src/persistTypes.ts +226 -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 +24 -0
- package/src/retry.ts +69 -0
- package/src/setupTracking.ts +26 -0
- package/src/sync/activateSyncedNode.ts +146 -0
- package/src/sync/configureObservableSync.ts +7 -0
- package/src/sync/syncHelpers.ts +15 -0
- package/src/sync/syncObservable.ts +989 -0
- package/src/sync/syncObservableAdapter.ts +30 -0
- package/src/sync/synced.ts +20 -0
- package/src/sync-plugins/fetch.ts +42 -0
- package/src/syncTypes.ts +163 -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 +70 -0
- package/sync-plugins/fetch.d.ts +11 -0
- package/sync-plugins/fetch.js +24 -0
- package/sync-plugins/fetch.js.map +1 -0
- package/sync-plugins/fetch.mjs +22 -0
- package/sync-plugins/fetch.mjs.map +1 -0
- package/sync.d.ts +8 -0
- package/sync.js +919 -0
- package/sync.js.map +1 -0
- package/sync.mjs +912 -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 -456
- 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';
|
|
@@ -40,6 +43,9 @@ function isEmpty(obj) {
|
|
|
40
43
|
}
|
|
41
44
|
return true;
|
|
42
45
|
}
|
|
46
|
+
function isNullOrUndefined(value) {
|
|
47
|
+
return value === undefined || value === null;
|
|
48
|
+
}
|
|
43
49
|
const setPrimitives = new Set(['boolean', 'string', 'number']);
|
|
44
50
|
/** @internal */
|
|
45
51
|
function isActualPrimitive(arg) {
|
|
@@ -55,72 +61,110 @@ const symbolGetNode = Symbol('getNode');
|
|
|
55
61
|
const symbolDelete = /* @__PURE__ */ Symbol('delete');
|
|
56
62
|
const symbolOpaque = Symbol('opaque');
|
|
57
63
|
const optimized = Symbol('optimized');
|
|
58
|
-
|
|
59
|
-
const extraPrimitiveActivators = new Map();
|
|
60
|
-
const extraPrimitiveProps = new Map();
|
|
64
|
+
const symbolLinked = Symbol('linked');
|
|
61
65
|
const globalState = {
|
|
62
66
|
isLoadingLocal: false,
|
|
63
67
|
isMerging: false,
|
|
64
|
-
isLoadingRemote
|
|
65
|
-
|
|
68
|
+
isLoadingRemote: false,
|
|
69
|
+
activateSyncedNode: undefined,
|
|
70
|
+
pendingNodes: new Map(),
|
|
71
|
+
dirtyNodes: new Set(),
|
|
72
|
+
replacer: undefined,
|
|
73
|
+
reviver: undefined,
|
|
66
74
|
};
|
|
67
|
-
function
|
|
68
|
-
return
|
|
69
|
-
}
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
function getPathType(value) {
|
|
76
|
+
return isArray(value) ? 'array' : value instanceof Map ? 'map' : value instanceof Set ? 'set' : 'object';
|
|
77
|
+
}
|
|
78
|
+
function replacer(key, value) {
|
|
79
|
+
if (value instanceof Map) {
|
|
80
|
+
return {
|
|
81
|
+
__LSType: 'Map',
|
|
82
|
+
value: Array.from(value.entries()), // or with spread: value: [...value]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
else if (value instanceof Set) {
|
|
86
|
+
return {
|
|
87
|
+
__LSType: 'Set',
|
|
88
|
+
value: Array.from(value), // or with spread: value: [...value]
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
else if (globalState.replacer) {
|
|
92
|
+
value = globalState.replacer(key, value);
|
|
93
|
+
}
|
|
94
|
+
return value;
|
|
73
95
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
96
|
+
const ISO8601 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/;
|
|
97
|
+
function reviver(key, value) {
|
|
98
|
+
if (value) {
|
|
99
|
+
if (typeof value === 'string' && ISO8601.test(value)) {
|
|
100
|
+
return new Date(value);
|
|
101
|
+
}
|
|
102
|
+
if (typeof value === 'object') {
|
|
103
|
+
if (value.__LSType === 'Map') {
|
|
104
|
+
return new Map(value.value);
|
|
105
|
+
}
|
|
106
|
+
else if (value.__LSType === 'Set') {
|
|
107
|
+
return new Set(value.value);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (globalState.reviver) {
|
|
111
|
+
value = globalState.reviver(key, value);
|
|
112
|
+
}
|
|
81
113
|
}
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
function safeStringify(value) {
|
|
117
|
+
return JSON.stringify(value, replacer);
|
|
118
|
+
}
|
|
119
|
+
function safeParse(value) {
|
|
120
|
+
return JSON.parse(value, reviver);
|
|
121
|
+
}
|
|
122
|
+
function clone(value) {
|
|
123
|
+
return safeParse(safeStringify(value));
|
|
124
|
+
}
|
|
125
|
+
function isObservable(obs) {
|
|
126
|
+
return !!obs && !!obs[symbolGetNode];
|
|
82
127
|
}
|
|
83
128
|
function getNode(obs) {
|
|
84
129
|
return obs && obs[symbolGetNode];
|
|
85
130
|
}
|
|
86
|
-
function
|
|
131
|
+
function isEvent(obs) {
|
|
87
132
|
var _a;
|
|
133
|
+
return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isEvent);
|
|
134
|
+
}
|
|
135
|
+
function setNodeValue(node, newValue) {
|
|
136
|
+
var _a, _b, _c;
|
|
88
137
|
const parentNode = (_a = node.parent) !== null && _a !== void 0 ? _a : node;
|
|
89
138
|
const key = node.parent ? node.key : '_';
|
|
90
139
|
const isDelete = newValue === symbolDelete;
|
|
91
140
|
if (isDelete)
|
|
92
141
|
newValue = undefined;
|
|
93
142
|
// Get the value of the parent
|
|
94
|
-
// const parentValue = isRoot ? node.root : ensureNodeValue(node);
|
|
95
143
|
const parentValue = node.parent ? ensureNodeValue(parentNode) : parentNode.root;
|
|
96
144
|
// Save the previous value first
|
|
97
145
|
const prevValue = parentValue[key];
|
|
98
146
|
const isFunc = isFunction(newValue);
|
|
99
147
|
// 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
|
-
|
|
148
|
+
newValue = !parentNode.isAssigning && isFunc && !isFunction(prevValue) ? newValue(prevValue) : newValue;
|
|
149
|
+
if (!globalState.isMerging ||
|
|
150
|
+
prevValue === undefined ||
|
|
151
|
+
isFunction(prevValue) ||
|
|
152
|
+
!((_c = (_b = node.parent) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.get(key))) {
|
|
153
|
+
try {
|
|
154
|
+
parentNode.isSetting = (parentNode.isSetting || 0) + 1;
|
|
155
|
+
// Save the new value
|
|
156
|
+
if (isDelete) {
|
|
157
|
+
delete parentValue[key];
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
parentValue[key] = newValue;
|
|
161
|
+
}
|
|
112
162
|
}
|
|
113
|
-
|
|
114
|
-
|
|
163
|
+
finally {
|
|
164
|
+
parentNode.isSetting--;
|
|
115
165
|
}
|
|
116
166
|
}
|
|
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 };
|
|
167
|
+
return { prevValue, newValue };
|
|
124
168
|
}
|
|
125
169
|
const arrNodeKeys = [];
|
|
126
170
|
function getNodeValue(node) {
|
|
@@ -137,14 +181,8 @@ function getNodeValue(node) {
|
|
|
137
181
|
}
|
|
138
182
|
return child;
|
|
139
183
|
}
|
|
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
184
|
function getChildNode(node, key, asFunction) {
|
|
147
|
-
var _a;
|
|
185
|
+
var _a, _b;
|
|
148
186
|
// Get the child by key
|
|
149
187
|
let child = (_a = node.children) === null || _a === void 0 ? void 0 : _a.get(key);
|
|
150
188
|
// Create the child node if it doesn't already exist
|
|
@@ -155,11 +193,13 @@ function getChildNode(node, key, asFunction) {
|
|
|
155
193
|
key,
|
|
156
194
|
lazy: true,
|
|
157
195
|
};
|
|
158
|
-
|
|
159
|
-
|
|
196
|
+
// Lookup functions are bound with the child key
|
|
197
|
+
if (((_b = node.lazyFn) === null || _b === void 0 ? void 0 : _b.length) === 1) {
|
|
198
|
+
asFunction = node.lazyFn.bind(node, key);
|
|
160
199
|
}
|
|
161
|
-
|
|
162
|
-
child = Object.assign(
|
|
200
|
+
if (isFunction(asFunction)) {
|
|
201
|
+
child = Object.assign(() => { }, child);
|
|
202
|
+
child.lazyFn = asFunction;
|
|
163
203
|
}
|
|
164
204
|
if (!node.children) {
|
|
165
205
|
node.children = new Map();
|
|
@@ -170,7 +210,7 @@ function getChildNode(node, key, asFunction) {
|
|
|
170
210
|
}
|
|
171
211
|
function ensureNodeValue(node) {
|
|
172
212
|
let value = getNodeValue(node);
|
|
173
|
-
if (!value) {
|
|
213
|
+
if (!value || isFunction(value)) {
|
|
174
214
|
if (isChildNodeValue(node)) {
|
|
175
215
|
const parent = ensureNodeValue(node.parent);
|
|
176
216
|
value = parent[node.key] = {};
|
|
@@ -183,17 +223,19 @@ function ensureNodeValue(node) {
|
|
|
183
223
|
}
|
|
184
224
|
function findIDKey(obj, node) {
|
|
185
225
|
var _a, _b;
|
|
186
|
-
let idKey =
|
|
187
|
-
?
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
? '
|
|
191
|
-
: '
|
|
192
|
-
? '
|
|
193
|
-
: '
|
|
194
|
-
? '
|
|
195
|
-
:
|
|
196
|
-
|
|
226
|
+
let idKey = isObservable(obj)
|
|
227
|
+
? undefined
|
|
228
|
+
: isObject(obj)
|
|
229
|
+
? 'id' in obj
|
|
230
|
+
? 'id'
|
|
231
|
+
: 'key' in obj
|
|
232
|
+
? 'key'
|
|
233
|
+
: '_id' in obj
|
|
234
|
+
? '_id'
|
|
235
|
+
: '__id' in obj
|
|
236
|
+
? '__id'
|
|
237
|
+
: undefined
|
|
238
|
+
: undefined;
|
|
197
239
|
if (!idKey && node.parent) {
|
|
198
240
|
const k = node.key + '_keyExtractor';
|
|
199
241
|
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 +245,20 @@ function findIDKey(obj, node) {
|
|
|
203
245
|
}
|
|
204
246
|
return idKey;
|
|
205
247
|
}
|
|
206
|
-
function extractFunction(node, key, fnOrComputed
|
|
248
|
+
function extractFunction(node, key, fnOrComputed) {
|
|
207
249
|
if (!node.functions) {
|
|
208
250
|
node.functions = new Map();
|
|
209
251
|
}
|
|
210
252
|
node.functions.set(key, fnOrComputed);
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
node.root.toActivate = [];
|
|
215
|
-
}
|
|
216
|
-
node.root.toActivate.push(computedChildNode);
|
|
217
|
-
}
|
|
253
|
+
}
|
|
254
|
+
function equals(a, b) {
|
|
255
|
+
return a === b || (isDate(a) && isDate(b) && +a === +b);
|
|
218
256
|
}
|
|
219
257
|
|
|
220
258
|
let timeout;
|
|
221
259
|
let numInBatch = 0;
|
|
222
260
|
let isRunningBatch = false;
|
|
223
261
|
let didDelayEndBatch = false;
|
|
224
|
-
let _afterBatch = [];
|
|
225
|
-
let _queuedBatches = [];
|
|
226
262
|
let _batchMap = new Map();
|
|
227
263
|
function onActionTimeout() {
|
|
228
264
|
if (_batchMap.size > 0) {
|
|
@@ -241,23 +277,34 @@ function isArraySubset(mainArr, subsetArr) {
|
|
|
241
277
|
return true;
|
|
242
278
|
}
|
|
243
279
|
function createPreviousHandlerInner(value, changes) {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
280
|
+
try {
|
|
281
|
+
// Clones the current state and inject the previous data at the changed path
|
|
282
|
+
let cloned = value ? clone(value) : {};
|
|
283
|
+
for (let i = 0; i < changes.length; i++) {
|
|
284
|
+
const { path, prevAtPath } = changes[i];
|
|
285
|
+
let o = cloned;
|
|
286
|
+
if (path.length > 0) {
|
|
287
|
+
let i;
|
|
288
|
+
for (i = 0; i < path.length - 1; i++) {
|
|
289
|
+
o = o[path[i]];
|
|
290
|
+
}
|
|
291
|
+
const key = path[i];
|
|
292
|
+
if (o instanceof Map) {
|
|
293
|
+
o.set(key, prevAtPath);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
o[key] = prevAtPath;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
cloned = prevAtPath;
|
|
253
301
|
}
|
|
254
|
-
o[path[i]] = prevAtPath;
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
clone = prevAtPath;
|
|
258
302
|
}
|
|
303
|
+
return cloned;
|
|
304
|
+
}
|
|
305
|
+
catch (_a) {
|
|
306
|
+
return undefined;
|
|
259
307
|
}
|
|
260
|
-
return clone;
|
|
261
308
|
}
|
|
262
309
|
function createPreviousHandler(value, changes) {
|
|
263
310
|
// Create a function that generates the previous state
|
|
@@ -270,9 +317,13 @@ function createPreviousHandler(value, changes) {
|
|
|
270
317
|
function notify(node, value, prev, level, whenOptimizedOnlyIf) {
|
|
271
318
|
// Run immediate listeners if there are any
|
|
272
319
|
const changesInBatch = new Map();
|
|
273
|
-
computeChangesRecursive(changesInBatch, node,
|
|
320
|
+
computeChangesRecursive(changesInBatch, node,
|
|
321
|
+
/*loading*/ globalState.isLoadingLocal,
|
|
322
|
+
/*remote*/ globalState.isLoadingRemote, value, [], [], value, prev,
|
|
274
323
|
/*immediate*/ true, level, whenOptimizedOnlyIf);
|
|
275
|
-
|
|
324
|
+
if (changesInBatch.size) {
|
|
325
|
+
batchNotifyChanges(changesInBatch, /*immediate*/ true);
|
|
326
|
+
}
|
|
276
327
|
// Update the current batch
|
|
277
328
|
const existing = _batchMap.get(node);
|
|
278
329
|
if (existing) {
|
|
@@ -280,14 +331,21 @@ function notify(node, value, prev, level, whenOptimizedOnlyIf) {
|
|
|
280
331
|
// TODO: level, whenOptimizedOnlyIf
|
|
281
332
|
}
|
|
282
333
|
else {
|
|
283
|
-
_batchMap.set(node, {
|
|
334
|
+
_batchMap.set(node, {
|
|
335
|
+
value,
|
|
336
|
+
prev,
|
|
337
|
+
level,
|
|
338
|
+
whenOptimizedOnlyIf,
|
|
339
|
+
remote: globalState.isLoadingRemote,
|
|
340
|
+
loading: globalState.isLoadingLocal,
|
|
341
|
+
});
|
|
284
342
|
}
|
|
285
343
|
// If not in a batch run it immediately
|
|
286
344
|
if (numInBatch <= 0) {
|
|
287
345
|
runBatch();
|
|
288
346
|
}
|
|
289
347
|
}
|
|
290
|
-
function computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
348
|
+
function computeChangesAtNode(changesInBatch, node, loading, remote, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
291
349
|
// If there are listeners at this node compute the changes that need to be run
|
|
292
350
|
if (immediate ? node.listenersImmediate : node.listeners) {
|
|
293
351
|
const change = {
|
|
@@ -308,18 +366,21 @@ function computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valu
|
|
|
308
366
|
changesInBatch.set(node, {
|
|
309
367
|
level,
|
|
310
368
|
value,
|
|
369
|
+
remote,
|
|
370
|
+
loading,
|
|
311
371
|
whenOptimizedOnlyIf,
|
|
312
372
|
changes: [change],
|
|
313
373
|
});
|
|
314
374
|
}
|
|
315
375
|
}
|
|
316
376
|
}
|
|
317
|
-
function computeChangesRecursive(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
377
|
+
function computeChangesRecursive(changesInBatch, node, loading, remote, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf) {
|
|
318
378
|
// Do the compute at this node
|
|
319
|
-
computeChangesAtNode(changesInBatch, node, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf);
|
|
379
|
+
computeChangesAtNode(changesInBatch, node, loading, remote, value, path, pathTypes, valueAtPath, prevAtPath, immediate, level, whenOptimizedOnlyIf);
|
|
320
380
|
if (node.linkedFromNodes) {
|
|
321
381
|
for (const linkedFromNode of node.linkedFromNodes) {
|
|
322
|
-
|
|
382
|
+
const childNode = getNodeAtPath(linkedFromNode, path);
|
|
383
|
+
computeChangesRecursive(changesInBatch, childNode, loading, remote, valueAtPath, [], [], valueAtPath, prevAtPath, immediate, 0, whenOptimizedOnlyIf);
|
|
323
384
|
}
|
|
324
385
|
}
|
|
325
386
|
// If not root notify up through parents
|
|
@@ -327,14 +388,14 @@ function computeChangesRecursive(changesInBatch, node, value, path, pathTypes, v
|
|
|
327
388
|
const parent = node.parent;
|
|
328
389
|
if (parent) {
|
|
329
390
|
const parentValue = getNodeValue(parent);
|
|
330
|
-
computeChangesRecursive(changesInBatch, parent, parentValue, [node.key].concat(path), [(
|
|
391
|
+
computeChangesRecursive(changesInBatch, parent, loading, remote, parentValue, [node.key].concat(path), [getPathType(value)].concat(pathTypes), valueAtPath, prevAtPath, immediate, level + 1, whenOptimizedOnlyIf);
|
|
331
392
|
}
|
|
332
393
|
}
|
|
333
394
|
}
|
|
334
395
|
function batchNotifyChanges(changesInBatch, immediate) {
|
|
335
396
|
const listenersNotified = new Set();
|
|
336
397
|
// For each change in the batch, notify all of the listeners
|
|
337
|
-
changesInBatch.forEach(({ changes, level, value, whenOptimizedOnlyIf }, node) => {
|
|
398
|
+
changesInBatch.forEach(({ changes, level, value, loading, remote, whenOptimizedOnlyIf }, node) => {
|
|
338
399
|
const listeners = immediate ? node.listenersImmediate : node.listeners;
|
|
339
400
|
if (listeners) {
|
|
340
401
|
let listenerParams;
|
|
@@ -351,6 +412,8 @@ function batchNotifyChanges(changesInBatch, immediate) {
|
|
|
351
412
|
if (!noArgs && !listenerParams) {
|
|
352
413
|
listenerParams = {
|
|
353
414
|
value,
|
|
415
|
+
loading,
|
|
416
|
+
remote,
|
|
354
417
|
getPrevious: createPreviousHandler(value, changes),
|
|
355
418
|
changes,
|
|
356
419
|
};
|
|
@@ -366,32 +429,30 @@ function batchNotifyChanges(changesInBatch, immediate) {
|
|
|
366
429
|
});
|
|
367
430
|
}
|
|
368
431
|
function runBatch() {
|
|
432
|
+
const dirtyNodes = Array.from(globalState.dirtyNodes);
|
|
433
|
+
globalState.dirtyNodes.clear();
|
|
434
|
+
dirtyNodes.forEach((node) => {
|
|
435
|
+
var _a;
|
|
436
|
+
(_a = node.dirtyFn) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
437
|
+
node.dirtyFn = undefined;
|
|
438
|
+
});
|
|
369
439
|
// Save batch locally and reset _batchMap first because a new batch could begin while looping over callbacks.
|
|
370
|
-
// This can happen with
|
|
440
|
+
// This can happen with computeds for example.
|
|
371
441
|
const map = _batchMap;
|
|
372
442
|
_batchMap = new Map();
|
|
373
443
|
const changesInBatch = new Map();
|
|
374
444
|
// First compute all of the changes at each node. It's important to do this first before
|
|
375
445
|
// running all the notifications because createPreviousHandler depends on knowing
|
|
376
446
|
// 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);
|
|
447
|
+
map.forEach(({ value, prev, level, loading, remote, whenOptimizedOnlyIf }, node) => {
|
|
448
|
+
computeChangesRecursive(changesInBatch, node, loading, remote, value, [], [], value, prev, false, level, whenOptimizedOnlyIf);
|
|
379
449
|
});
|
|
380
450
|
// 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
|
-
}
|
|
451
|
+
if (changesInBatch.size) {
|
|
452
|
+
batchNotifyChanges(changesInBatch, false);
|
|
394
453
|
}
|
|
454
|
+
}
|
|
455
|
+
function batch(fn) {
|
|
395
456
|
beginBatch();
|
|
396
457
|
try {
|
|
397
458
|
fn();
|
|
@@ -420,45 +481,57 @@ function endBatch(force) {
|
|
|
420
481
|
timeout = undefined;
|
|
421
482
|
}
|
|
422
483
|
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
484
|
isRunningBatch = true;
|
|
430
485
|
runBatch();
|
|
431
486
|
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
487
|
// If an endBatch was delayed run it now
|
|
439
488
|
if (didDelayEndBatch) {
|
|
440
489
|
didDelayEndBatch = false;
|
|
441
490
|
endBatch(true);
|
|
442
491
|
}
|
|
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
492
|
}
|
|
452
493
|
}
|
|
453
494
|
}
|
|
495
|
+
function getNodeAtPath(obj, path) {
|
|
496
|
+
let o = obj;
|
|
497
|
+
for (let i = 0; i < path.length; i++) {
|
|
498
|
+
const p = path[i];
|
|
499
|
+
o = getChildNode(o, p);
|
|
500
|
+
}
|
|
501
|
+
return o;
|
|
502
|
+
}
|
|
454
503
|
|
|
455
|
-
function
|
|
456
|
-
|
|
457
|
-
|
|
504
|
+
function createObservable(value, makePrimitive, extractPromise, createObject, createPrimitive) {
|
|
505
|
+
if (isObservable(value)) {
|
|
506
|
+
return value;
|
|
507
|
+
}
|
|
508
|
+
const valueIsPromise = isPromise(value);
|
|
509
|
+
const valueIsFunction = isFunction(value);
|
|
510
|
+
const root = {
|
|
511
|
+
_: value,
|
|
512
|
+
};
|
|
513
|
+
let node = {
|
|
514
|
+
root,
|
|
515
|
+
lazy: true,
|
|
516
|
+
};
|
|
517
|
+
if (valueIsFunction) {
|
|
518
|
+
node = Object.assign(() => { }, node);
|
|
519
|
+
node.lazyFn = value;
|
|
520
|
+
}
|
|
521
|
+
const prim = makePrimitive || isActualPrimitive(value);
|
|
522
|
+
const obs = prim
|
|
523
|
+
? new createPrimitive(node)
|
|
524
|
+
: createObject(node);
|
|
525
|
+
if (valueIsPromise) {
|
|
526
|
+
setNodeValue(node, undefined);
|
|
527
|
+
extractPromise(node, value);
|
|
528
|
+
}
|
|
529
|
+
return obs;
|
|
458
530
|
}
|
|
531
|
+
|
|
459
532
|
function computeSelector(selector, e, retainObservable) {
|
|
460
533
|
let c = selector;
|
|
461
|
-
if (isFunction(c)) {
|
|
534
|
+
if (!isObservable(c) && isFunction(c)) {
|
|
462
535
|
c = e ? c(e) : c();
|
|
463
536
|
}
|
|
464
537
|
return isObservable(c) && !retainObservable ? c.get() : c;
|
|
@@ -474,45 +547,49 @@ function opaqueObject(value) {
|
|
|
474
547
|
}
|
|
475
548
|
return value;
|
|
476
549
|
}
|
|
477
|
-
function
|
|
478
|
-
var _a;
|
|
479
|
-
const root = (_a = getNode(obs)) === null || _a === void 0 ? void 0 : _a.root;
|
|
480
|
-
if (root) {
|
|
481
|
-
root.locked = value;
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
|
|
550
|
+
function setAtPath(obj, path, pathTypes, value, mode, fullObj, restore) {
|
|
485
551
|
let o = obj;
|
|
486
552
|
let oFull = fullObj;
|
|
553
|
+
let p = undefined;
|
|
487
554
|
if (path.length > 0) {
|
|
488
555
|
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) {
|
|
556
|
+
p = path[i];
|
|
557
|
+
if (o[p] === symbolDelete) {
|
|
498
558
|
// If this was previously deleted, restore it
|
|
499
559
|
if (oFull) {
|
|
500
560
|
o[p] = oFull[p];
|
|
501
561
|
restore === null || restore === void 0 ? void 0 : restore(path.slice(0, i + 1), o[p]);
|
|
502
562
|
}
|
|
503
|
-
|
|
563
|
+
return obj;
|
|
504
564
|
}
|
|
505
565
|
else if (o[p] === undefined || o[p] === null) {
|
|
506
|
-
o[p] = pathTypes[i]
|
|
566
|
+
o[p] = initializePathType(pathTypes[i]);
|
|
507
567
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
oFull
|
|
568
|
+
if (i < path.length - 1) {
|
|
569
|
+
o = o[p];
|
|
570
|
+
if (oFull) {
|
|
571
|
+
oFull = oFull[p];
|
|
572
|
+
}
|
|
511
573
|
}
|
|
512
574
|
}
|
|
513
575
|
}
|
|
576
|
+
// Don't set if the value is the same. This prevents creating a new key
|
|
577
|
+
// when setting undefined on an object without this key
|
|
578
|
+
if (p === undefined) {
|
|
579
|
+
if (mode === 'merge') {
|
|
580
|
+
obj = _mergeIntoObservable(obj, value);
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
obj = value;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
514
586
|
else {
|
|
515
|
-
|
|
587
|
+
if (mode === 'merge') {
|
|
588
|
+
o[p] = _mergeIntoObservable(o[p], value);
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
o[p] = value;
|
|
592
|
+
}
|
|
516
593
|
}
|
|
517
594
|
return obj;
|
|
518
595
|
}
|
|
@@ -521,8 +598,8 @@ function setInObservableAtPath(obs, path, pathTypes, value, mode) {
|
|
|
521
598
|
let v = value;
|
|
522
599
|
for (let i = 0; i < path.length; i++) {
|
|
523
600
|
const p = path[i];
|
|
524
|
-
if (!o.peek()[p]
|
|
525
|
-
o[p].set([]);
|
|
601
|
+
if (!o.peek()[p]) {
|
|
602
|
+
o[p].set(initializePathType(pathTypes[i]));
|
|
526
603
|
}
|
|
527
604
|
o = o[p];
|
|
528
605
|
v = v[p];
|
|
@@ -534,6 +611,9 @@ function setInObservableAtPath(obs, path, pathTypes, value, mode) {
|
|
|
534
611
|
else if (mode === 'assign' && o.assign && isObject(o.peek())) {
|
|
535
612
|
o.assign(v);
|
|
536
613
|
}
|
|
614
|
+
else if (mode === 'merge') {
|
|
615
|
+
mergeIntoObservable(o, v);
|
|
616
|
+
}
|
|
537
617
|
else {
|
|
538
618
|
o.set(v);
|
|
539
619
|
}
|
|
@@ -563,7 +643,9 @@ function _mergeIntoObservable(target, source) {
|
|
|
563
643
|
const key = keys[i];
|
|
564
644
|
const sourceValue = source[key];
|
|
565
645
|
if (sourceValue === symbolDelete) {
|
|
566
|
-
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete)
|
|
646
|
+
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete)
|
|
647
|
+
? target[key].delete()
|
|
648
|
+
: delete target[key];
|
|
567
649
|
}
|
|
568
650
|
else {
|
|
569
651
|
const isObj = isObject(sourceValue);
|
|
@@ -596,7 +678,7 @@ function constructObjectWithPath(path, pathTypes, value) {
|
|
|
596
678
|
let o = (out = {});
|
|
597
679
|
for (let i = 0; i < path.length; i++) {
|
|
598
680
|
const p = path[i];
|
|
599
|
-
o[p] = i === path.length - 1 ? value : pathTypes[i]
|
|
681
|
+
o[p] = i === path.length - 1 ? value : initializePathType(pathTypes[i]);
|
|
600
682
|
o = o[p];
|
|
601
683
|
}
|
|
602
684
|
}
|
|
@@ -609,7 +691,7 @@ function deconstructObjectWithPath(path, pathTypes, value) {
|
|
|
609
691
|
let o = value;
|
|
610
692
|
for (let i = 0; i < path.length; i++) {
|
|
611
693
|
const p = path[i];
|
|
612
|
-
o = o ? o[p] : pathTypes[i]
|
|
694
|
+
o = o ? o[p] : initializePathType(pathTypes[i]);
|
|
613
695
|
}
|
|
614
696
|
return o;
|
|
615
697
|
}
|
|
@@ -620,8 +702,21 @@ function setSilently(obs, newValue) {
|
|
|
620
702
|
const node = getNode(obs);
|
|
621
703
|
return setNodeValue(node, newValue).newValue;
|
|
622
704
|
}
|
|
705
|
+
function initializePathType(pathType) {
|
|
706
|
+
switch (pathType) {
|
|
707
|
+
case 'array':
|
|
708
|
+
return [];
|
|
709
|
+
case 'object':
|
|
710
|
+
return {};
|
|
711
|
+
case 'map':
|
|
712
|
+
return new Map();
|
|
713
|
+
case 'set':
|
|
714
|
+
return new Set();
|
|
715
|
+
}
|
|
716
|
+
}
|
|
623
717
|
|
|
624
|
-
function onChange(node, callback, options = {}) {
|
|
718
|
+
function onChange(node, callback, options = {}, fromLinks) {
|
|
719
|
+
var _a;
|
|
625
720
|
const { initial, immediate, noArgs } = options;
|
|
626
721
|
const { trackingType } = options;
|
|
627
722
|
let listeners = immediate ? node.listenersImmediate : node.listeners;
|
|
@@ -634,7 +729,6 @@ function onChange(node, callback, options = {}) {
|
|
|
634
729
|
node.listeners = listeners;
|
|
635
730
|
}
|
|
636
731
|
}
|
|
637
|
-
checkActivate(node);
|
|
638
732
|
const listener = {
|
|
639
733
|
listener: callback,
|
|
640
734
|
track: trackingType,
|
|
@@ -645,6 +739,8 @@ function onChange(node, callback, options = {}) {
|
|
|
645
739
|
const value = getNodeValue(node);
|
|
646
740
|
callback({
|
|
647
741
|
value,
|
|
742
|
+
loading: true,
|
|
743
|
+
remote: false,
|
|
648
744
|
changes: [
|
|
649
745
|
{
|
|
650
746
|
path: [],
|
|
@@ -656,7 +752,80 @@ function onChange(node, callback, options = {}) {
|
|
|
656
752
|
getPrevious: () => undefined,
|
|
657
753
|
});
|
|
658
754
|
}
|
|
659
|
-
|
|
755
|
+
let extraDisposes;
|
|
756
|
+
function addLinkedNodeListeners(childNode, cb = callback, from) {
|
|
757
|
+
// Don't add listeners for the same node more than once
|
|
758
|
+
if (!(fromLinks === null || fromLinks === void 0 ? void 0 : fromLinks.has(childNode))) {
|
|
759
|
+
fromLinks || (fromLinks = new Set());
|
|
760
|
+
fromLinks.add(from || node);
|
|
761
|
+
cb || (cb = callback);
|
|
762
|
+
const childOptions = {
|
|
763
|
+
trackingType: true,
|
|
764
|
+
...options,
|
|
765
|
+
};
|
|
766
|
+
// onChange for the linked node
|
|
767
|
+
extraDisposes = [...(extraDisposes || []), onChange(childNode, cb, childOptions, fromLinks)];
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
// Add listeners for linked to nodes
|
|
771
|
+
if (node.linkedToNode) {
|
|
772
|
+
addLinkedNodeListeners(node.linkedToNode);
|
|
773
|
+
}
|
|
774
|
+
// Add listeners for linked from nodes
|
|
775
|
+
(_a = node.linkedFromNodes) === null || _a === void 0 ? void 0 : _a.forEach((linkedFromNode) => addLinkedNodeListeners(linkedFromNode));
|
|
776
|
+
// Go up through the parents and add listeners for linked from nodes
|
|
777
|
+
let parent = node.parent;
|
|
778
|
+
let pathParent = [node.key];
|
|
779
|
+
while (parent) {
|
|
780
|
+
if (parent.linkedFromNodes) {
|
|
781
|
+
for (const linkedFromNode of parent.linkedFromNodes) {
|
|
782
|
+
if (!(fromLinks === null || fromLinks === void 0 ? void 0 : fromLinks.has(linkedFromNode))) {
|
|
783
|
+
const cb = createCb(linkedFromNode, pathParent, callback);
|
|
784
|
+
addLinkedNodeListeners(linkedFromNode, cb, parent);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
pathParent = [parent.key, ...pathParent];
|
|
789
|
+
parent = parent.parent;
|
|
790
|
+
}
|
|
791
|
+
return () => {
|
|
792
|
+
listeners.delete(listener);
|
|
793
|
+
extraDisposes === null || extraDisposes === void 0 ? void 0 : extraDisposes.forEach((fn) => fn());
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
function createCb(linkedFromNode, path, callback) {
|
|
797
|
+
// Create a callback for a path that calls it with the current value at the path
|
|
798
|
+
let { valueAtPath: prevAtPath } = getValueAtPath(getNodeValue(linkedFromNode), path);
|
|
799
|
+
return function ({ value: valueA, loading, remote }) {
|
|
800
|
+
const { valueAtPath, pathTypes } = getValueAtPath(valueA, path);
|
|
801
|
+
if (valueAtPath !== prevAtPath) {
|
|
802
|
+
callback({
|
|
803
|
+
value: valueAtPath,
|
|
804
|
+
loading,
|
|
805
|
+
remote,
|
|
806
|
+
changes: [
|
|
807
|
+
{
|
|
808
|
+
path,
|
|
809
|
+
pathTypes,
|
|
810
|
+
prevAtPath,
|
|
811
|
+
valueAtPath,
|
|
812
|
+
},
|
|
813
|
+
],
|
|
814
|
+
getPrevious: () => prevAtPath,
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
prevAtPath = valueAtPath;
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
function getValueAtPath(obj, path) {
|
|
821
|
+
let o = obj;
|
|
822
|
+
const pathTypes = [];
|
|
823
|
+
for (let i = 0; o && i < path.length; i++) {
|
|
824
|
+
pathTypes.push(isArray(o) ? 'array' : 'object');
|
|
825
|
+
const p = path[i];
|
|
826
|
+
o = o[p];
|
|
827
|
+
}
|
|
828
|
+
return { valueAtPath: o, pathTypes };
|
|
660
829
|
}
|
|
661
830
|
|
|
662
831
|
function setupTracking(nodes, update, noArgs, immediate) {
|
|
@@ -717,42 +886,39 @@ function updateTracking(node, track) {
|
|
|
717
886
|
|
|
718
887
|
function trackSelector(selector, update, observeEvent, observeOptions, createResubscribe) {
|
|
719
888
|
var _a;
|
|
720
|
-
let nodes;
|
|
721
|
-
let value;
|
|
722
889
|
let dispose;
|
|
723
|
-
let tracker;
|
|
724
890
|
let resubscribe;
|
|
725
891
|
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
|
-
}
|
|
892
|
+
beginTracking();
|
|
893
|
+
const value = selector ? computeSelector(selector, observeEvent, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.fromComputed) : selector;
|
|
894
|
+
const tracker = tracking.current;
|
|
895
|
+
const nodes = tracker.nodes;
|
|
896
|
+
endTracking();
|
|
897
|
+
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') && tracker && nodes) {
|
|
898
|
+
(_a = tracker.traceListeners) === null || _a === void 0 ? void 0 : _a.call(tracker, nodes);
|
|
899
|
+
if (tracker.traceUpdates) {
|
|
900
|
+
updateFn = tracker.traceUpdates(update);
|
|
901
|
+
}
|
|
902
|
+
// Clear tracing so it doesn't leak to other components
|
|
903
|
+
tracker.traceListeners = undefined;
|
|
904
|
+
tracker.traceUpdates = undefined;
|
|
747
905
|
}
|
|
748
906
|
if (!(observeEvent === null || observeEvent === void 0 ? void 0 : observeEvent.cancel)) {
|
|
749
907
|
// Do tracing if it was requested
|
|
750
908
|
// useSyncExternalStore doesn't subscribe until after the component mount.
|
|
751
909
|
// We want to subscribe immediately so we don't miss any updates
|
|
752
910
|
dispose = setupTracking(nodes, updateFn, false, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.immediate);
|
|
753
|
-
|
|
911
|
+
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
912
|
+
resubscribe = createResubscribe
|
|
913
|
+
? () => {
|
|
914
|
+
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
915
|
+
dispose = setupTracking(nodes, updateFn);
|
|
916
|
+
return dispose;
|
|
917
|
+
}
|
|
918
|
+
: undefined;
|
|
919
|
+
}
|
|
754
920
|
}
|
|
755
|
-
return { value, dispose, resubscribe };
|
|
921
|
+
return { nodes, value, dispose, resubscribe };
|
|
756
922
|
}
|
|
757
923
|
|
|
758
924
|
function observe(selectorOrRun, reactionOrOptions, options) {
|
|
@@ -777,9 +943,11 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
777
943
|
delete e.value;
|
|
778
944
|
// Dispose listeners from previous run
|
|
779
945
|
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
780
|
-
const { dispose: _dispose, value } = trackSelector(selectorOrRun, update, e, options);
|
|
946
|
+
const { dispose: _dispose, value, nodes } = trackSelector(selectorOrRun, update, e, options);
|
|
781
947
|
dispose = _dispose;
|
|
782
948
|
e.value = value;
|
|
949
|
+
e.nodes = nodes;
|
|
950
|
+
e.refresh = update;
|
|
783
951
|
if (e.onCleanupReaction) {
|
|
784
952
|
e.onCleanupReaction();
|
|
785
953
|
e.onCleanupReaction = undefined;
|
|
@@ -787,7 +955,9 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
787
955
|
endBatch();
|
|
788
956
|
// Call the reaction if there is one and the value changed
|
|
789
957
|
if (reaction &&
|
|
790
|
-
((options === null || options === void 0 ? void 0 : options.fromComputed) ||
|
|
958
|
+
((options === null || options === void 0 ? void 0 : options.fromComputed) ||
|
|
959
|
+
((e.num > 0 || !isEvent(selectorOrRun)) &&
|
|
960
|
+
(e.previous !== e.value || typeof e.value === 'object')))) {
|
|
791
961
|
reaction(e);
|
|
792
962
|
}
|
|
793
963
|
// Update the previous value
|
|
@@ -813,6 +983,7 @@ function _when(predicate, effect, checkReady) {
|
|
|
813
983
|
return effect ? predicate.then(effect) : predicate;
|
|
814
984
|
}
|
|
815
985
|
let value;
|
|
986
|
+
let effectValue;
|
|
816
987
|
// Create a wrapping fn that calls the effect if predicate returns true
|
|
817
988
|
function run(e) {
|
|
818
989
|
const ret = computeSelector(predicate);
|
|
@@ -825,7 +996,7 @@ function _when(predicate, effect, checkReady) {
|
|
|
825
996
|
}
|
|
826
997
|
function doEffect() {
|
|
827
998
|
// If value is truthy then run the effect
|
|
828
|
-
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
999
|
+
effectValue = effect === null || effect === void 0 ? void 0 : effect(value);
|
|
829
1000
|
}
|
|
830
1001
|
// Run in an observe
|
|
831
1002
|
observe(run, doEffect);
|
|
@@ -835,17 +1006,17 @@ function _when(predicate, effect, checkReady) {
|
|
|
835
1006
|
return effect ? value.then(effect) : value;
|
|
836
1007
|
}
|
|
837
1008
|
else if (value !== undefined) {
|
|
838
|
-
return Promise.resolve(value);
|
|
1009
|
+
return effect ? effectValue : Promise.resolve(value);
|
|
839
1010
|
}
|
|
840
1011
|
else {
|
|
841
1012
|
// Wrap it in a promise
|
|
842
1013
|
const promise = new Promise((resolve) => {
|
|
843
1014
|
if (effect) {
|
|
844
1015
|
const originalEffect = effect;
|
|
845
|
-
effect = (value) => {
|
|
1016
|
+
effect = ((value) => {
|
|
846
1017
|
const effectValue = originalEffect(value);
|
|
847
|
-
resolve(effectValue);
|
|
848
|
-
};
|
|
1018
|
+
resolve(isPromise(effectValue) ? effectValue.then((value) => value) : effectValue);
|
|
1019
|
+
});
|
|
849
1020
|
}
|
|
850
1021
|
else {
|
|
851
1022
|
effect = resolve;
|
|
@@ -861,64 +1032,6 @@ function whenReady(predicate, effect) {
|
|
|
861
1032
|
return _when(predicate, effect, true);
|
|
862
1033
|
}
|
|
863
1034
|
|
|
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
1035
|
const ArrayModifiers = new Set([
|
|
923
1036
|
'copyWithin',
|
|
924
1037
|
'fill',
|
|
@@ -937,9 +1050,9 @@ const ArrayLoopers = new Set([
|
|
|
937
1050
|
'find',
|
|
938
1051
|
'findIndex',
|
|
939
1052
|
'forEach',
|
|
940
|
-
'includes',
|
|
941
1053
|
'join',
|
|
942
1054
|
'map',
|
|
1055
|
+
'reduce',
|
|
943
1056
|
'some',
|
|
944
1057
|
]);
|
|
945
1058
|
const ArrayLoopersReturn = new Set(['filter', 'find']);
|
|
@@ -959,7 +1072,8 @@ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
|
959
1072
|
}
|
|
960
1073
|
function collectionSetter(node, target, prop, ...args) {
|
|
961
1074
|
var _a;
|
|
962
|
-
if (prop === 'push') {
|
|
1075
|
+
if (prop === 'push' && args.length === 1) {
|
|
1076
|
+
// Fast path for push to just append to the end
|
|
963
1077
|
setKey(node, target.length + '', args[0]);
|
|
964
1078
|
}
|
|
965
1079
|
else {
|
|
@@ -982,7 +1096,7 @@ function getKeys(obj, isArr, isMap) {
|
|
|
982
1096
|
return isArr ? undefined : obj ? (isMap ? Array.from(obj.keys()) : Object.keys(obj)) : [];
|
|
983
1097
|
}
|
|
984
1098
|
function updateNodes(parent, obj, prevValue) {
|
|
985
|
-
var _a, _b;
|
|
1099
|
+
var _a, _b, _c;
|
|
986
1100
|
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') &&
|
|
987
1101
|
typeof __devUpdateNodes !== 'undefined' &&
|
|
988
1102
|
isObject(obj)) {
|
|
@@ -1011,8 +1125,9 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1011
1125
|
let prevChildrenById;
|
|
1012
1126
|
let moved;
|
|
1013
1127
|
const isMap = obj instanceof Map;
|
|
1128
|
+
const isPrevMap = prevValue instanceof Map;
|
|
1014
1129
|
const keys = getKeys(obj, isArr, isMap);
|
|
1015
|
-
const keysPrev = getKeys(prevValue, isArr,
|
|
1130
|
+
const keysPrev = getKeys(prevValue, isArr, isPrevMap);
|
|
1016
1131
|
const length = ((_a = (keys || obj)) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
1017
1132
|
const lengthPrev = ((_b = (keysPrev || prevValue)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
1018
1133
|
let idField;
|
|
@@ -1029,15 +1144,22 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1029
1144
|
isIdFieldFunction = isFunction(idField);
|
|
1030
1145
|
prevChildrenById = new Map();
|
|
1031
1146
|
moved = [];
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1147
|
+
}
|
|
1148
|
+
const keysSeen = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test'
|
|
1149
|
+
? new Set()
|
|
1150
|
+
: undefined;
|
|
1151
|
+
if (parent.children) {
|
|
1152
|
+
for (let i = 0; i < prevValue.length; i++) {
|
|
1153
|
+
const p = prevValue[i];
|
|
1154
|
+
if (p) {
|
|
1155
|
+
const child = parent.children.get(i + '');
|
|
1156
|
+
if (child) {
|
|
1157
|
+
if (!obj[i]) {
|
|
1158
|
+
// If the previous value is not in the new array and it
|
|
1159
|
+
// is an activated, disable its listeners
|
|
1160
|
+
handleDeletedChild(child, p);
|
|
1161
|
+
}
|
|
1162
|
+
if (idField) {
|
|
1041
1163
|
const key = isIdFieldFunction
|
|
1042
1164
|
? idField(p)
|
|
1043
1165
|
: p[idField];
|
|
@@ -1064,14 +1186,9 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1064
1186
|
if (!keys.includes(key)) {
|
|
1065
1187
|
hasADiff = true;
|
|
1066
1188
|
const child = getChildNode(parent, key);
|
|
1067
|
-
const prev =
|
|
1189
|
+
const prev = isPrevMap ? prevValue.get(key) : prevValue[key];
|
|
1068
1190
|
if (prev !== undefined) {
|
|
1069
|
-
|
|
1070
|
-
updateNodes(child, undefined, prev);
|
|
1071
|
-
}
|
|
1072
|
-
if (child.listeners || child.listenersImmediate) {
|
|
1073
|
-
notify(child, undefined, prev, 0);
|
|
1074
|
-
}
|
|
1191
|
+
handleDeletedChild(child, prev);
|
|
1075
1192
|
}
|
|
1076
1193
|
}
|
|
1077
1194
|
}
|
|
@@ -1082,16 +1199,31 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1082
1199
|
let didMove = false;
|
|
1083
1200
|
for (let i = 0; i < length; i++) {
|
|
1084
1201
|
const key = isArr ? i + '' : keys[i];
|
|
1085
|
-
|
|
1086
|
-
const prev =
|
|
1087
|
-
let isDiff = value
|
|
1202
|
+
let value = isMap ? obj.get(key) : obj[key];
|
|
1203
|
+
const prev = isPrevMap ? prevValue === null || prevValue === void 0 ? void 0 : prevValue.get(key) : prevValue === null || prevValue === void 0 ? void 0 : prevValue[key];
|
|
1204
|
+
let isDiff = !equals(value, prev);
|
|
1088
1205
|
if (isDiff) {
|
|
1089
1206
|
const id = idField && value
|
|
1090
1207
|
? isIdFieldFunction
|
|
1091
1208
|
? idField(value)
|
|
1092
1209
|
: value[idField]
|
|
1093
1210
|
: undefined;
|
|
1094
|
-
|
|
1211
|
+
const existingChild = (_c = parent.children) === null || _c === void 0 ? void 0 : _c.get(key);
|
|
1212
|
+
if (isObservable(value)) {
|
|
1213
|
+
const valueNode = getNode(value);
|
|
1214
|
+
if ((existingChild === null || existingChild === void 0 ? void 0 : existingChild.linkedToNode) === valueNode) {
|
|
1215
|
+
const targetValue = getNodeValue(valueNode);
|
|
1216
|
+
isMap ? obj.set(key, targetValue) : (obj[key] = targetValue);
|
|
1217
|
+
continue;
|
|
1218
|
+
}
|
|
1219
|
+
const obs = value;
|
|
1220
|
+
value = () => obs;
|
|
1221
|
+
}
|
|
1222
|
+
let child = getChildNode(parent, key, value);
|
|
1223
|
+
if (!child.lazy && (isFunction(value) || isObservable(value))) {
|
|
1224
|
+
reactivateNode(child, value);
|
|
1225
|
+
peekInternal(child);
|
|
1226
|
+
}
|
|
1095
1227
|
// Detect moves within an array. Need to move the original proxy to the new position to keep
|
|
1096
1228
|
// the proxy stable, so that listeners to this node will be unaffected by the array shift.
|
|
1097
1229
|
if (isArr && id !== undefined) {
|
|
@@ -1121,7 +1253,10 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1121
1253
|
if (isDiff) {
|
|
1122
1254
|
// Array has a new / modified element
|
|
1123
1255
|
// If object iterate through its children
|
|
1124
|
-
if (
|
|
1256
|
+
if (isFunction(value) || isObservable(value)) {
|
|
1257
|
+
extractFunctionOrComputed(parent, key, value);
|
|
1258
|
+
}
|
|
1259
|
+
else if (isPrimitive(value)) {
|
|
1125
1260
|
hasADiff = true;
|
|
1126
1261
|
}
|
|
1127
1262
|
else {
|
|
@@ -1162,6 +1297,19 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1162
1297
|
}
|
|
1163
1298
|
return retValue !== null && retValue !== void 0 ? retValue : false;
|
|
1164
1299
|
}
|
|
1300
|
+
function handleDeletedChild(child, p) {
|
|
1301
|
+
var _a, _b;
|
|
1302
|
+
// If the previous value is not in the new array and it
|
|
1303
|
+
// is an activated, disable its listeners
|
|
1304
|
+
(_a = child.linkedToNodeDispose) === null || _a === void 0 ? void 0 : _a.call(child);
|
|
1305
|
+
(_b = child.activatedObserveDispose) === null || _b === void 0 ? void 0 : _b.call(child);
|
|
1306
|
+
if (!isPrimitive(p)) {
|
|
1307
|
+
updateNodes(child, undefined, p);
|
|
1308
|
+
}
|
|
1309
|
+
if (child.listeners || child.listenersImmediate) {
|
|
1310
|
+
notify(child, undefined, p, 0);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1165
1313
|
function getProxy(node, p, asFunction) {
|
|
1166
1314
|
// Get the child node if p prop
|
|
1167
1315
|
if (p !== undefined)
|
|
@@ -1169,6 +1317,15 @@ function getProxy(node, p, asFunction) {
|
|
|
1169
1317
|
// Create a proxy if not already cached and return it
|
|
1170
1318
|
return (node.proxy || (node.proxy = new Proxy(node, proxyHandler)));
|
|
1171
1319
|
}
|
|
1320
|
+
function flushPending() {
|
|
1321
|
+
// Need to short circuit the computed batching because the user called get() or peek()
|
|
1322
|
+
// in which case the set needs to run immediately so that the values are up to date.
|
|
1323
|
+
if (globalState.pendingNodes.size > 0) {
|
|
1324
|
+
const nodes = Array.from(globalState.pendingNodes.values());
|
|
1325
|
+
globalState.pendingNodes.clear();
|
|
1326
|
+
nodes.forEach((fn) => fn());
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1172
1329
|
const proxyHandler = {
|
|
1173
1330
|
get(node, p, receiver) {
|
|
1174
1331
|
var _a;
|
|
@@ -1180,12 +1337,19 @@ const proxyHandler = {
|
|
|
1180
1337
|
if (p === symbolGetNode) {
|
|
1181
1338
|
return node;
|
|
1182
1339
|
}
|
|
1183
|
-
|
|
1340
|
+
if (p === 'apply') {
|
|
1341
|
+
const nodeValue = getNodeValue(node);
|
|
1342
|
+
if (isFunction(nodeValue)) {
|
|
1343
|
+
return nodeValue.apply;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
let value = peekInternal(node, /*activateRecursive*/ p === 'get');
|
|
1184
1347
|
// If this node is linked to another observable then forward to the target's handler.
|
|
1185
1348
|
// The exception is onChange because it needs to listen to this node for changes.
|
|
1186
1349
|
// This needs to be below peek because it activates there.
|
|
1187
|
-
|
|
1188
|
-
|
|
1350
|
+
const targetNode = node.linkedToNode || (value === null || value === void 0 ? void 0 : value[symbolGetNode]);
|
|
1351
|
+
if (targetNode && p !== 'onChange') {
|
|
1352
|
+
return proxyHandler.get(targetNode, p, receiver);
|
|
1189
1353
|
}
|
|
1190
1354
|
if (value instanceof Map || value instanceof WeakMap || value instanceof Set || value instanceof WeakSet) {
|
|
1191
1355
|
const ret = handlerMapSet(node, p, value);
|
|
@@ -1196,6 +1360,9 @@ const proxyHandler = {
|
|
|
1196
1360
|
const fn = observableFns.get(p);
|
|
1197
1361
|
// If this is an observable function, call it
|
|
1198
1362
|
if (fn) {
|
|
1363
|
+
if (p === 'get' || p === 'peek') {
|
|
1364
|
+
flushPending();
|
|
1365
|
+
}
|
|
1199
1366
|
return function (a, b, c) {
|
|
1200
1367
|
const l = arguments.length;
|
|
1201
1368
|
// Array call and apply are slow so micro-optimize this hot path.
|
|
@@ -1213,33 +1380,11 @@ const proxyHandler = {
|
|
|
1213
1380
|
}
|
|
1214
1381
|
};
|
|
1215
1382
|
}
|
|
1216
|
-
if (node.isComputed) {
|
|
1217
|
-
if (node.proxyFn && !fn) {
|
|
1218
|
-
return node.proxyFn(p);
|
|
1219
|
-
}
|
|
1220
|
-
else {
|
|
1221
|
-
checkActivate(node);
|
|
1222
|
-
}
|
|
1223
|
-
}
|
|
1224
1383
|
const property = observableProperties.get(p);
|
|
1225
1384
|
if (property) {
|
|
1226
1385
|
return property.get(node);
|
|
1227
1386
|
}
|
|
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];
|
|
1387
|
+
let vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
1243
1388
|
if (isObject(value) && value[symbolOpaque]) {
|
|
1244
1389
|
return vProp;
|
|
1245
1390
|
}
|
|
@@ -1252,6 +1397,11 @@ const proxyHandler = {
|
|
|
1252
1397
|
return getProxy(node, p, fnOrComputed);
|
|
1253
1398
|
}
|
|
1254
1399
|
}
|
|
1400
|
+
if (isNullOrUndefined(value) && vProp === undefined && (ArrayModifiers.has(p) || ArrayLoopers.has(p))) {
|
|
1401
|
+
value = [];
|
|
1402
|
+
setNodeValue(node, value);
|
|
1403
|
+
vProp = value[p];
|
|
1404
|
+
}
|
|
1255
1405
|
// Handle function calls
|
|
1256
1406
|
if (isFunction(vProp)) {
|
|
1257
1407
|
if (isArray(value)) {
|
|
@@ -1263,30 +1413,29 @@ const proxyHandler = {
|
|
|
1263
1413
|
// Update that this node was accessed for observers
|
|
1264
1414
|
updateTracking(node);
|
|
1265
1415
|
return function (cbOrig, thisArg) {
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1416
|
+
const isReduce = p === 'reduce';
|
|
1417
|
+
const cbWrapped = isReduce
|
|
1418
|
+
? (previousValue, currentValue, currentIndex, array) => {
|
|
1419
|
+
return cbOrig(previousValue, getProxy(node, currentIndex + '', currentValue), currentIndex, array);
|
|
1420
|
+
}
|
|
1421
|
+
: (val, index, array) => {
|
|
1422
|
+
return cbOrig(getProxy(node, index + '', val), index, array);
|
|
1423
|
+
};
|
|
1424
|
+
if (isReduce || !ArrayLoopersReturn.has(p)) {
|
|
1425
|
+
return value[p](cbWrapped, thisArg);
|
|
1269
1426
|
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
if (
|
|
1276
|
-
|
|
1277
|
-
if (isFind) {
|
|
1278
|
-
return proxy;
|
|
1279
|
-
}
|
|
1280
|
-
else {
|
|
1281
|
-
out.push(proxy);
|
|
1282
|
-
}
|
|
1427
|
+
const isFind = p === 'find';
|
|
1428
|
+
const out = [];
|
|
1429
|
+
for (let i = 0; i < value.length; i++) {
|
|
1430
|
+
if (cbWrapped(value[i], i, value)) {
|
|
1431
|
+
const proxy = getProxy(node, i + '');
|
|
1432
|
+
if (isFind) {
|
|
1433
|
+
return proxy;
|
|
1283
1434
|
}
|
|
1435
|
+
out.push(proxy);
|
|
1284
1436
|
}
|
|
1285
|
-
return isFind ? undefined : out;
|
|
1286
|
-
}
|
|
1287
|
-
else {
|
|
1288
|
-
return value[p](cbWrapped, thisArg);
|
|
1289
1437
|
}
|
|
1438
|
+
return isFind ? undefined : out;
|
|
1290
1439
|
};
|
|
1291
1440
|
}
|
|
1292
1441
|
}
|
|
@@ -1301,10 +1450,6 @@ const proxyHandler = {
|
|
|
1301
1450
|
return vProp;
|
|
1302
1451
|
}
|
|
1303
1452
|
}
|
|
1304
|
-
// TODOV3: Remove "state"
|
|
1305
|
-
if (vProp === undefined && (p === 'state' || p === '_state') && node.state) {
|
|
1306
|
-
return node.state;
|
|
1307
|
-
}
|
|
1308
1453
|
// Return an observable proxy to the property
|
|
1309
1454
|
return getProxy(node, p);
|
|
1310
1455
|
},
|
|
@@ -1314,12 +1459,13 @@ const proxyHandler = {
|
|
|
1314
1459
|
return value !== null && typeof value === 'object' ? Reflect.getPrototypeOf(value) : null;
|
|
1315
1460
|
},
|
|
1316
1461
|
ownKeys(node) {
|
|
1317
|
-
|
|
1462
|
+
// TODO: Temporary workaround to fix a bug - the first peek may not return the correct value
|
|
1463
|
+
// if the value is a cached. This fixes the test "cache with initial ownKeys"
|
|
1464
|
+
peekInternal(node);
|
|
1465
|
+
const value = get(node, true);
|
|
1318
1466
|
if (isPrimitive(value))
|
|
1319
1467
|
return [];
|
|
1320
1468
|
const keys = value ? Reflect.ownKeys(value) : [];
|
|
1321
|
-
// Update that this node was accessed for observers
|
|
1322
|
-
updateTracking(node, true);
|
|
1323
1469
|
// This is required to fix this error:
|
|
1324
1470
|
// TypeError: 'getOwnPropertyDescriptor' on proxy: trap reported non-configurability for
|
|
1325
1471
|
// property 'length' which is either non-existent or configurable in the proxy node
|
|
@@ -1369,22 +1515,21 @@ const proxyHandler = {
|
|
|
1369
1515
|
},
|
|
1370
1516
|
apply(target, thisArg, argArray) {
|
|
1371
1517
|
// If it's a function call it as a function
|
|
1372
|
-
return Reflect.apply(target, thisArg, argArray);
|
|
1518
|
+
return Reflect.apply(target.lazyFn || target, thisArg, argArray);
|
|
1373
1519
|
},
|
|
1374
1520
|
};
|
|
1375
1521
|
function set(node, newValue) {
|
|
1376
1522
|
if (node.parent) {
|
|
1377
|
-
|
|
1523
|
+
setKey(node.parent, node.key, newValue);
|
|
1378
1524
|
}
|
|
1379
1525
|
else {
|
|
1380
|
-
|
|
1526
|
+
setKey(node, '_', newValue);
|
|
1381
1527
|
}
|
|
1382
1528
|
}
|
|
1383
1529
|
function toggle(node) {
|
|
1384
1530
|
const value = getNodeValue(node);
|
|
1385
|
-
if (value === undefined || isBoolean(value)) {
|
|
1531
|
+
if (value === undefined || value === null || isBoolean(value)) {
|
|
1386
1532
|
set(node, !value);
|
|
1387
|
-
return !value;
|
|
1388
1533
|
}
|
|
1389
1534
|
else if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
1390
1535
|
throw new Error('[legend-state] Cannot toggle a non-boolean value');
|
|
@@ -1396,31 +1541,27 @@ function setKey(node, key, newValue, level) {
|
|
|
1396
1541
|
console.warn(`[legend-state] Set an HTMLElement into state. You probably don't want to do that.`);
|
|
1397
1542
|
}
|
|
1398
1543
|
}
|
|
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
1544
|
const isRoot = !node.parent && key === '_';
|
|
1545
|
+
if (node.parent && !getNodeValue(node) && !isFunction(newValue)) {
|
|
1546
|
+
set(node, { [key]: newValue });
|
|
1547
|
+
}
|
|
1413
1548
|
// Get the child node for updating and notifying
|
|
1414
|
-
const childNode = isRoot ? node : getChildNode(node, key,
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1549
|
+
const childNode = isRoot ? node : getChildNode(node, key, newValue);
|
|
1550
|
+
if (isObservable(newValue)) {
|
|
1551
|
+
setToObservable(childNode, newValue);
|
|
1552
|
+
}
|
|
1553
|
+
else {
|
|
1554
|
+
// Set the raw value on the parent object
|
|
1555
|
+
const { newValue: savedValue, prevValue } = setNodeValue(childNode, newValue);
|
|
1556
|
+
const isPrim = isPrimitive(savedValue) || savedValue instanceof Date;
|
|
1557
|
+
if (!equals(savedValue, prevValue)) {
|
|
1558
|
+
updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level);
|
|
1559
|
+
}
|
|
1560
|
+
if (!isPrim) {
|
|
1561
|
+
childNode.needsExtract = true;
|
|
1562
|
+
}
|
|
1563
|
+
extractFunctionOrComputed(node, key, savedValue);
|
|
1421
1564
|
}
|
|
1422
|
-
extractFunctionOrComputed(node, parentValue, key, savedValue);
|
|
1423
|
-
return isFunc ? savedValue : isRoot ? getProxy(node) : getProxy(node, key);
|
|
1424
1565
|
}
|
|
1425
1566
|
function assign(node, value) {
|
|
1426
1567
|
const proxy = getProxy(node);
|
|
@@ -1445,7 +1586,13 @@ function deleteFn(node, key) {
|
|
|
1445
1586
|
key = node.key;
|
|
1446
1587
|
node = node.parent;
|
|
1447
1588
|
}
|
|
1448
|
-
|
|
1589
|
+
const value = getNodeValue(node);
|
|
1590
|
+
if (isArray(value)) {
|
|
1591
|
+
collectionSetter(node, value, 'splice', key, 1);
|
|
1592
|
+
}
|
|
1593
|
+
else {
|
|
1594
|
+
setKey(node, key !== null && key !== void 0 ? key : '_', symbolDelete, /*level*/ -1);
|
|
1595
|
+
}
|
|
1449
1596
|
}
|
|
1450
1597
|
function handlerMapSet(node, p, value) {
|
|
1451
1598
|
const vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
@@ -1525,8 +1672,11 @@ function handlerMapSet(node, p, value) {
|
|
|
1525
1672
|
function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRoot, level) {
|
|
1526
1673
|
if (!childNode)
|
|
1527
1674
|
childNode = node;
|
|
1528
|
-
// Make sure we don't call too many listeners for
|
|
1675
|
+
// Make sure we don't call too many listeners for every property set
|
|
1529
1676
|
beginBatch();
|
|
1677
|
+
if (isPrim === undefined) {
|
|
1678
|
+
isPrim = isPrimitive(newValue);
|
|
1679
|
+
}
|
|
1530
1680
|
let hasADiff = isPrim;
|
|
1531
1681
|
let whenOptimizedOnlyIf = false;
|
|
1532
1682
|
// If new value is an object or array update notify down the tree
|
|
@@ -1546,7 +1696,7 @@ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRo
|
|
|
1546
1696
|
}
|
|
1547
1697
|
endBatch();
|
|
1548
1698
|
}
|
|
1549
|
-
function extractPromise(node, value, setter
|
|
1699
|
+
function extractPromise(node, value, setter) {
|
|
1550
1700
|
if (!node.state) {
|
|
1551
1701
|
node.state = createObservable({
|
|
1552
1702
|
isLoaded: false,
|
|
@@ -1562,30 +1712,29 @@ function extractPromise(node, value, setter, handleError) {
|
|
|
1562
1712
|
})
|
|
1563
1713
|
.catch((error) => {
|
|
1564
1714
|
node.state.error.set(error);
|
|
1565
|
-
if (handleError) {
|
|
1566
|
-
handleError(error);
|
|
1567
|
-
}
|
|
1568
1715
|
});
|
|
1569
1716
|
}
|
|
1570
|
-
function extractFunctionOrComputed(node,
|
|
1717
|
+
function extractFunctionOrComputed(node, k, v, activateRecursive) {
|
|
1571
1718
|
if (isPromise(v)) {
|
|
1572
1719
|
const childNode = getChildNode(node, k);
|
|
1573
1720
|
extractPromise(childNode, v);
|
|
1574
1721
|
setNodeValue(childNode, undefined);
|
|
1575
1722
|
}
|
|
1723
|
+
else if (isObservable(v)) {
|
|
1724
|
+
const fn = () => v;
|
|
1725
|
+
extractFunction(node, k, fn);
|
|
1726
|
+
const childNode = getChildNode(node, k, fn);
|
|
1727
|
+
const targetNode = getNode(v);
|
|
1728
|
+
// Set node to target's value if activating or it's already activated
|
|
1729
|
+
const initialValue = activateRecursive || !targetNode.lazy ? peekInternal(targetNode) : undefined;
|
|
1730
|
+
setNodeValue(childNode, initialValue);
|
|
1731
|
+
}
|
|
1576
1732
|
else if (typeof v === 'function') {
|
|
1577
1733
|
extractFunction(node, k, v);
|
|
1578
|
-
delete obj[k];
|
|
1579
1734
|
}
|
|
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
|
-
}
|
|
1735
|
+
else if (activateRecursive && typeof v == 'object' && v !== null && v !== undefined) {
|
|
1736
|
+
const childNode = getChildNode(node, k);
|
|
1737
|
+
checkLazy(childNode, v, activateRecursive);
|
|
1589
1738
|
}
|
|
1590
1739
|
}
|
|
1591
1740
|
function get(node, options) {
|
|
@@ -1595,210 +1744,285 @@ function get(node, options) {
|
|
|
1595
1744
|
return peek(node);
|
|
1596
1745
|
}
|
|
1597
1746
|
function peek(node) {
|
|
1598
|
-
const value =
|
|
1747
|
+
const value = peekInternal(node, true);
|
|
1748
|
+
return value;
|
|
1749
|
+
}
|
|
1750
|
+
function peekInternal(node, activateRecursive) {
|
|
1751
|
+
if (node.dirtyFn) {
|
|
1752
|
+
node.dirtyFn();
|
|
1753
|
+
globalState.dirtyNodes.delete(node);
|
|
1754
|
+
node.dirtyFn = undefined;
|
|
1755
|
+
}
|
|
1756
|
+
let value = getNodeValue(node);
|
|
1757
|
+
value = checkLazy(node, value, !!activateRecursive);
|
|
1758
|
+
return value;
|
|
1759
|
+
}
|
|
1760
|
+
function checkLazy(node, value, activateRecursive) {
|
|
1599
1761
|
// If node is not yet lazily computed go do that
|
|
1600
1762
|
const lazy = node.lazy;
|
|
1601
1763
|
if (lazy) {
|
|
1764
|
+
const lazyFn = node.lazyFn;
|
|
1602
1765
|
delete node.lazy;
|
|
1603
|
-
if (isFunction(
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1766
|
+
if (isFunction(lazyFn)) {
|
|
1767
|
+
if (lazyFn.length === 1) {
|
|
1768
|
+
// This is a lookup function, so return a record object
|
|
1769
|
+
value = {};
|
|
1770
|
+
}
|
|
1771
|
+
else {
|
|
1772
|
+
if (node.parent) {
|
|
1773
|
+
const parentValue = getNodeValue(node.parent);
|
|
1774
|
+
if (parentValue) {
|
|
1775
|
+
delete parentValue[node.key];
|
|
1776
|
+
}
|
|
1777
|
+
else {
|
|
1778
|
+
node.root._ = undefined;
|
|
1779
|
+
}
|
|
1610
1780
|
}
|
|
1781
|
+
value = activateNodeFunction(node, lazyFn);
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
if (lazy || node.needsExtract || activateRecursive) {
|
|
1786
|
+
for (const key in value) {
|
|
1787
|
+
if (hasOwnProperty.call(value, key)) {
|
|
1788
|
+
extractFunctionOrComputed(node, key, value[key], activateRecursive);
|
|
1611
1789
|
}
|
|
1612
1790
|
}
|
|
1613
1791
|
}
|
|
1614
|
-
// Check if computed needs to activate
|
|
1615
|
-
checkActivate(node);
|
|
1616
1792
|
return value;
|
|
1617
1793
|
}
|
|
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
|
-
};
|
|
1794
|
+
function reactivateNode(node, lazyFn) {
|
|
1795
|
+
var _a, _b;
|
|
1796
|
+
(_a = node.activatedObserveDispose) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
1797
|
+
(_b = node.linkedToNodeDispose) === null || _b === void 0 ? void 0 : _b.call(node);
|
|
1798
|
+
node.activatedObserveDispose = node.linkedToNodeDispose = node.linkedToNode = undefined;
|
|
1799
|
+
node.lazyFn = lazyFn;
|
|
1800
|
+
node.lazy = true;
|
|
1679
1801
|
}
|
|
1680
1802
|
function activateNodeFunction(node, lazyFn) {
|
|
1681
|
-
let prevTarget
|
|
1682
|
-
let curTarget
|
|
1803
|
+
// let prevTarget$: Observable<any>;
|
|
1804
|
+
// let curTarget$: Observable<any>;
|
|
1683
1805
|
let update;
|
|
1684
1806
|
let wasPromise;
|
|
1685
|
-
let
|
|
1686
|
-
const
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1807
|
+
let ignoreThisUpdate;
|
|
1808
|
+
const activateFn = lazyFn;
|
|
1809
|
+
let activatedValue;
|
|
1810
|
+
let disposes = [];
|
|
1811
|
+
let refreshFn;
|
|
1812
|
+
function markDirty() {
|
|
1813
|
+
node.dirtyFn = refreshFn;
|
|
1814
|
+
globalState.dirtyNodes.add(node);
|
|
1815
|
+
}
|
|
1816
|
+
node.activatedObserveDispose = observe(() => {
|
|
1817
|
+
var _a, _b, _c, _d;
|
|
1691
1818
|
// 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
|
|
1819
|
+
let value = activateFn();
|
|
1820
|
+
// If target is an observable, make this node a link to it
|
|
1695
1821
|
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();
|
|
1822
|
+
value = setToObservable(node, value);
|
|
1714
1823
|
}
|
|
1715
|
-
|
|
1716
|
-
|
|
1824
|
+
if (isFunction(value)) {
|
|
1825
|
+
value = value();
|
|
1826
|
+
}
|
|
1827
|
+
const activated = !isObservable(value)
|
|
1828
|
+
? value === null || value === void 0 ? void 0 : value[symbolLinked]
|
|
1829
|
+
: undefined;
|
|
1830
|
+
if (activated) {
|
|
1831
|
+
node.activationState = activated;
|
|
1832
|
+
value = undefined;
|
|
1717
1833
|
}
|
|
1834
|
+
ignoreThisUpdate = false;
|
|
1835
|
+
wasPromise = isPromise(value);
|
|
1718
1836
|
// Activate this node if not activated already (may be called recursively)
|
|
1719
1837
|
// TODO: Is calling recursively bad? If so can it be fixed?
|
|
1720
1838
|
if (!node.activated) {
|
|
1721
1839
|
node.activated = true;
|
|
1722
|
-
|
|
1723
|
-
|
|
1840
|
+
let activateNodeFn = activateNodeBase;
|
|
1841
|
+
// If this is a Synced then run it through persistence instead of base
|
|
1842
|
+
if (activated === null || activated === void 0 ? void 0 : activated.synced) {
|
|
1843
|
+
activateNodeFn = globalState.activateSyncedNode;
|
|
1844
|
+
ignoreThisUpdate = true;
|
|
1845
|
+
}
|
|
1846
|
+
const { update: newUpdate, value: newValue } = activateNodeFn(node, value);
|
|
1847
|
+
update = newUpdate;
|
|
1848
|
+
value = newValue !== null && newValue !== void 0 ? newValue : activated === null || activated === void 0 ? void 0 : activated.initial;
|
|
1849
|
+
}
|
|
1850
|
+
else if (node.activationState) {
|
|
1851
|
+
const activated = node.activationState;
|
|
1852
|
+
if ((_b = (_a = node.state) === null || _a === void 0 ? void 0 : _a.peek()) === null || _b === void 0 ? void 0 : _b.sync) {
|
|
1853
|
+
node.state.sync();
|
|
1854
|
+
ignoreThisUpdate = true;
|
|
1855
|
+
}
|
|
1856
|
+
else {
|
|
1857
|
+
value = (_d = (_c = activated.get) === null || _c === void 0 ? void 0 : _c.call(activated)) !== null && _d !== void 0 ? _d : activated.initial;
|
|
1858
|
+
}
|
|
1724
1859
|
}
|
|
1725
|
-
|
|
1860
|
+
// value is undefined if it's in a persisted retry
|
|
1861
|
+
wasPromise = wasPromise || isPromise(value);
|
|
1726
1862
|
return value;
|
|
1727
|
-
}, (
|
|
1728
|
-
if (!
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
if (
|
|
1733
|
-
if (
|
|
1734
|
-
|
|
1863
|
+
}, (e) => {
|
|
1864
|
+
if (!ignoreThisUpdate) {
|
|
1865
|
+
const { value, nodes, refresh } = e;
|
|
1866
|
+
refreshFn = refresh;
|
|
1867
|
+
if (!wasPromise || !globalState.isLoadingRemote) {
|
|
1868
|
+
if (wasPromise) {
|
|
1869
|
+
if (node.activationState) {
|
|
1870
|
+
const { initial } = node.activationState;
|
|
1871
|
+
if (value && isPromise(value)) {
|
|
1872
|
+
// Extract the promise to make it set the value/error when it comes in
|
|
1873
|
+
extractPromise(node, value, update);
|
|
1874
|
+
}
|
|
1875
|
+
// Set this to undefined only if it's replacing the activation function,
|
|
1876
|
+
// so we don't overwrite it if it already has real data from either local
|
|
1877
|
+
// cache or a previous run
|
|
1878
|
+
if (isFunction(getNodeValue(node))) {
|
|
1879
|
+
setNodeValue(node, initial !== null && initial !== void 0 ? initial : undefined);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
else if (node.activated) {
|
|
1883
|
+
// Extract the promise to make it set the value/error when it comes in
|
|
1884
|
+
extractPromise(node, value, update);
|
|
1885
|
+
// Set this to undefined only if it's replacing the activation function,
|
|
1886
|
+
// so we don't overwrite it if it already has real data from either local
|
|
1887
|
+
// cache or a previous run
|
|
1888
|
+
if (isFunction(getNodeValue(node))) {
|
|
1889
|
+
setNodeValue(node, undefined);
|
|
1890
|
+
}
|
|
1735
1891
|
}
|
|
1736
|
-
const { handleError, timeout } = setupRetry(retryOptions, refresh, attemptNum);
|
|
1737
|
-
onError = handleError;
|
|
1738
|
-
timeoutRetry = timeout;
|
|
1739
1892
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1893
|
+
else {
|
|
1894
|
+
activatedValue = value;
|
|
1895
|
+
if (node.state.isLoaded.peek()) {
|
|
1896
|
+
node.isComputing = true;
|
|
1897
|
+
set(node, value);
|
|
1898
|
+
node.isComputing = false;
|
|
1899
|
+
}
|
|
1900
|
+
else {
|
|
1901
|
+
setNodeValue(node, value);
|
|
1902
|
+
node.state.assign({
|
|
1903
|
+
isLoaded: true,
|
|
1904
|
+
error: undefined,
|
|
1905
|
+
});
|
|
1906
|
+
}
|
|
1747
1907
|
}
|
|
1748
1908
|
}
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
});
|
|
1755
|
-
}
|
|
1909
|
+
disposes.forEach((fn) => fn());
|
|
1910
|
+
disposes = [];
|
|
1911
|
+
nodes === null || nodes === void 0 ? void 0 : nodes.forEach(({ node }) => {
|
|
1912
|
+
disposes.push(onChange(node, markDirty, { immediate: true }));
|
|
1913
|
+
});
|
|
1756
1914
|
}
|
|
1757
|
-
|
|
1915
|
+
e.cancel = true;
|
|
1916
|
+
}, { fromComputed: true });
|
|
1917
|
+
return activatedValue;
|
|
1758
1918
|
}
|
|
1759
|
-
|
|
1760
|
-
const { onSetFn, subscriber } = node.activationState;
|
|
1761
|
-
let isSetting = false;
|
|
1919
|
+
function activateNodeBase(node, value) {
|
|
1762
1920
|
if (!node.state) {
|
|
1763
1921
|
node.state = createObservable({
|
|
1764
1922
|
isLoaded: false,
|
|
1765
1923
|
}, false, extractPromise, getProxy);
|
|
1766
1924
|
}
|
|
1767
|
-
if (
|
|
1768
|
-
const
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1925
|
+
if (node.activationState) {
|
|
1926
|
+
const { set: setFn, get: getFn, initial } = node.activationState;
|
|
1927
|
+
value = getFn === null || getFn === void 0 ? void 0 : getFn();
|
|
1928
|
+
if (value == undefined || value === null) {
|
|
1929
|
+
value = initial;
|
|
1930
|
+
}
|
|
1931
|
+
if (setFn) {
|
|
1932
|
+
let allChanges = [];
|
|
1933
|
+
let latestValue = undefined;
|
|
1934
|
+
let runNumber = 0;
|
|
1935
|
+
const runChanges = (listenerParams) => {
|
|
1936
|
+
// Don't call the set if this is the first value coming in
|
|
1937
|
+
if (allChanges.length > 0) {
|
|
1938
|
+
let changes;
|
|
1939
|
+
let value;
|
|
1940
|
+
let loading = false;
|
|
1941
|
+
let remote = false;
|
|
1942
|
+
let getPrevious;
|
|
1943
|
+
if (listenerParams) {
|
|
1944
|
+
changes = listenerParams.changes;
|
|
1945
|
+
value = listenerParams.value;
|
|
1946
|
+
loading = listenerParams.loading;
|
|
1947
|
+
remote = listenerParams.remote;
|
|
1948
|
+
getPrevious = listenerParams.getPrevious;
|
|
1949
|
+
}
|
|
1950
|
+
else {
|
|
1951
|
+
// If this is called by flushPending then get the change array
|
|
1952
|
+
// that we've been building up.
|
|
1953
|
+
changes = allChanges;
|
|
1954
|
+
value = latestValue;
|
|
1955
|
+
getPrevious = createPreviousHandler(value, changes);
|
|
1956
|
+
}
|
|
1957
|
+
allChanges = [];
|
|
1958
|
+
latestValue = undefined;
|
|
1959
|
+
globalState.pendingNodes.delete(node);
|
|
1960
|
+
runNumber++;
|
|
1961
|
+
const thisRunNumber = runNumber;
|
|
1962
|
+
const run = () => {
|
|
1963
|
+
if (thisRunNumber !== runNumber) {
|
|
1964
|
+
// set may get called multiple times before it loads so ignore any previous runs
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
node.isComputing = true;
|
|
1968
|
+
setFn({
|
|
1969
|
+
value,
|
|
1970
|
+
changes,
|
|
1971
|
+
loading,
|
|
1972
|
+
remote,
|
|
1973
|
+
getPrevious,
|
|
1974
|
+
});
|
|
1975
|
+
node.isComputing = false;
|
|
1976
|
+
};
|
|
1977
|
+
whenReady(node.state.isLoaded, run);
|
|
1777
1978
|
}
|
|
1778
|
-
}
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1979
|
+
};
|
|
1980
|
+
const onChangeImmediate = ({ value, changes }) => {
|
|
1981
|
+
if (!node.isComputing) {
|
|
1982
|
+
if (changes.length > 1 || !isFunction(changes[0].prevAtPath)) {
|
|
1983
|
+
latestValue = value;
|
|
1984
|
+
if (allChanges.length > 0) {
|
|
1985
|
+
changes = changes.filter((change) => !isArraySubset(allChanges[0].path, change.path));
|
|
1986
|
+
}
|
|
1987
|
+
allChanges.push(...changes);
|
|
1988
|
+
globalState.pendingNodes.set(node, runChanges);
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
};
|
|
1992
|
+
// Create an immediate listener to mark this node as pending. Then actually run
|
|
1993
|
+
// the changes at the end of the batch so everything is properly batched.
|
|
1994
|
+
// However, this can be short circuited if the user calls get() or peek()
|
|
1995
|
+
// in which case the set needs to run immediately so that the values are up to date.
|
|
1996
|
+
onChange(node, onChangeImmediate, { immediate: true });
|
|
1997
|
+
onChange(node, runChanges);
|
|
1998
|
+
}
|
|
1789
1999
|
}
|
|
1790
2000
|
const update = ({ value }) => {
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
if (!isSetting) {
|
|
2001
|
+
if (!node.isComputing) {
|
|
2002
|
+
node.isComputing = true;
|
|
1794
2003
|
set(node, value);
|
|
2004
|
+
node.isComputing = false;
|
|
1795
2005
|
}
|
|
1796
2006
|
};
|
|
1797
|
-
|
|
1798
|
-
|
|
2007
|
+
return { update, value };
|
|
2008
|
+
}
|
|
2009
|
+
function setToObservable(node, value) {
|
|
2010
|
+
var _a;
|
|
2011
|
+
// If the computed is a proxy to another observable
|
|
2012
|
+
// link it to the target observable
|
|
2013
|
+
const linkedNode = getNode(value);
|
|
2014
|
+
if (linkedNode !== node && (linkedNode === null || linkedNode === void 0 ? void 0 : linkedNode.linkedToNode) !== node) {
|
|
2015
|
+
node.linkedToNode = linkedNode;
|
|
2016
|
+
linkedNode.linkedFromNodes || (linkedNode.linkedFromNodes = new Set());
|
|
2017
|
+
linkedNode.linkedFromNodes.add(node);
|
|
2018
|
+
(_a = node.linkedToNodeDispose) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
2019
|
+
node.linkedToNodeDispose = onChange(linkedNode, () => {
|
|
2020
|
+
value = peek(linkedNode);
|
|
2021
|
+
set(node, value);
|
|
2022
|
+
}, { initial: true }, new Set([node]));
|
|
1799
2023
|
}
|
|
1800
|
-
return
|
|
1801
|
-
}
|
|
2024
|
+
return value;
|
|
2025
|
+
}
|
|
1802
2026
|
|
|
1803
2027
|
const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
|
|
1804
2028
|
function ObservablePrimitiveClass(node) {
|
|
@@ -1815,8 +2039,14 @@ function proto(key, fn) {
|
|
|
1815
2039
|
return fn.call(this, this._node, ...args);
|
|
1816
2040
|
};
|
|
1817
2041
|
}
|
|
1818
|
-
proto('peek',
|
|
1819
|
-
|
|
2042
|
+
proto('peek', (node) => {
|
|
2043
|
+
flushPending();
|
|
2044
|
+
return peek(node);
|
|
2045
|
+
});
|
|
2046
|
+
proto('get', (node, options) => {
|
|
2047
|
+
flushPending();
|
|
2048
|
+
return get(node, options);
|
|
2049
|
+
});
|
|
1820
2050
|
proto('set', set);
|
|
1821
2051
|
proto('onChange', onChange);
|
|
1822
2052
|
// Getters
|
|
@@ -1828,13 +2058,12 @@ Object.defineProperty(ObservablePrimitiveClass.prototype, symbolGetNode, {
|
|
|
1828
2058
|
});
|
|
1829
2059
|
ObservablePrimitiveClass.prototype.toggle = function () {
|
|
1830
2060
|
const value = this.peek();
|
|
1831
|
-
if (value === undefined || isBoolean(value)) {
|
|
2061
|
+
if (value === undefined || value === null || isBoolean(value)) {
|
|
1832
2062
|
this.set(!value);
|
|
1833
2063
|
}
|
|
1834
2064
|
else if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
1835
2065
|
throw new Error('[legend-state] Cannot toggle a non-boolean value');
|
|
1836
2066
|
}
|
|
1837
|
-
return !value;
|
|
1838
2067
|
};
|
|
1839
2068
|
ObservablePrimitiveClass.prototype.delete = function () {
|
|
1840
2069
|
this.set(undefined);
|
|
@@ -1847,92 +2076,26 @@ function observable(value) {
|
|
|
1847
2076
|
function observablePrimitive(value) {
|
|
1848
2077
|
return createObservable(value, true, extractPromise, getProxy, ObservablePrimitiveClass);
|
|
1849
2078
|
}
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
function computed(compute, set$1) {
|
|
1853
|
-
// Create an observable for this computed variable
|
|
1854
|
-
const obs = observable();
|
|
1855
|
-
lockObservable(obs, true);
|
|
2079
|
+
function syncState(obs) {
|
|
1856
2080
|
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
|
-
};
|
|
2081
|
+
if (!node.state) {
|
|
2082
|
+
peekInternal(node);
|
|
1931
2083
|
}
|
|
1932
|
-
|
|
2084
|
+
if (!node.state) {
|
|
2085
|
+
node.state = observable({});
|
|
2086
|
+
}
|
|
2087
|
+
return node.state;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
function computed(get, set) {
|
|
2091
|
+
return observable(set ? () => ({ [symbolLinked]: { get, set: ({ value }) => set(value) } }) : get);
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
function linked(params) {
|
|
2095
|
+
return (() => ({ [symbolLinked]: params }));
|
|
1933
2096
|
}
|
|
1934
2097
|
|
|
1935
|
-
function configureLegendState({ observableFunctions, observableProperties: observableProperties$1, }) {
|
|
2098
|
+
function configureLegendState({ observableFunctions, observableProperties: observableProperties$1, jsonReplacer, jsonReviver, }) {
|
|
1936
2099
|
if (observableFunctions) {
|
|
1937
2100
|
for (const key in observableFunctions) {
|
|
1938
2101
|
const fn = observableFunctions[key];
|
|
@@ -1957,6 +2120,12 @@ function configureLegendState({ observableFunctions, observableProperties: obser
|
|
|
1957
2120
|
});
|
|
1958
2121
|
}
|
|
1959
2122
|
}
|
|
2123
|
+
if (jsonReplacer) {
|
|
2124
|
+
globalState.replacer = jsonReplacer;
|
|
2125
|
+
}
|
|
2126
|
+
if (jsonReviver) {
|
|
2127
|
+
globalState.reviver = jsonReviver;
|
|
2128
|
+
}
|
|
1960
2129
|
}
|
|
1961
2130
|
|
|
1962
2131
|
function event() {
|
|
@@ -1983,56 +2152,102 @@ function event() {
|
|
|
1983
2152
|
}
|
|
1984
2153
|
|
|
1985
2154
|
function proxy(get, set) {
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2155
|
+
return observable((key) => set
|
|
2156
|
+
? linked({
|
|
2157
|
+
get: () => get(key),
|
|
2158
|
+
set: ({ value }) => set(key, value),
|
|
2159
|
+
})
|
|
2160
|
+
: get(key));
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
function calculateRetryDelay(retryOptions, attemptNum) {
|
|
2164
|
+
const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
|
|
2165
|
+
if (infinite || attemptNum < times) {
|
|
2166
|
+
const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum), maxDelay);
|
|
2167
|
+
return delayTime;
|
|
2168
|
+
}
|
|
2169
|
+
return null;
|
|
2170
|
+
}
|
|
2171
|
+
function createRetryTimeout(retryOptions, attemptNum, fn) {
|
|
2172
|
+
const delayTime = calculateRetryDelay(retryOptions, attemptNum);
|
|
2173
|
+
if (delayTime) {
|
|
2174
|
+
return setTimeout(fn, delayTime);
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
function runWithRetry(node, state, fn) {
|
|
2178
|
+
const { retry, waitFor } = node.activationState;
|
|
2179
|
+
const e = { cancel: false };
|
|
2180
|
+
let value = undefined;
|
|
2181
|
+
if (waitFor) {
|
|
2182
|
+
value = whenReady(waitFor, () => {
|
|
2183
|
+
node.activationState.waitFor = undefined;
|
|
2184
|
+
return fn(e);
|
|
2185
|
+
});
|
|
2186
|
+
}
|
|
2187
|
+
else {
|
|
2188
|
+
value = fn(e);
|
|
2189
|
+
}
|
|
2190
|
+
if (isPromise(value) && retry) {
|
|
2191
|
+
let timeoutRetry;
|
|
2192
|
+
return new Promise((resolve) => {
|
|
2193
|
+
const run = () => {
|
|
2194
|
+
value
|
|
2195
|
+
.then((val) => {
|
|
2196
|
+
node.activationState.persistedRetry = false;
|
|
2197
|
+
resolve(val);
|
|
2198
|
+
})
|
|
2199
|
+
.catch(() => {
|
|
2200
|
+
state.attemptNum++;
|
|
2201
|
+
if (timeoutRetry) {
|
|
2202
|
+
clearTimeout(timeoutRetry);
|
|
2203
|
+
}
|
|
2204
|
+
if (!e.cancel) {
|
|
2205
|
+
timeoutRetry = createRetryTimeout(retry, state.attemptNum, () => {
|
|
2206
|
+
value = fn(e);
|
|
2207
|
+
run();
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2210
|
+
})
|
|
2211
|
+
.finally(() => {
|
|
2212
|
+
node.activationState.persistedRetry = false;
|
|
2006
2213
|
});
|
|
2007
|
-
}
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
}
|
|
2011
|
-
return
|
|
2214
|
+
};
|
|
2215
|
+
run();
|
|
2216
|
+
});
|
|
2217
|
+
}
|
|
2218
|
+
return value;
|
|
2012
2219
|
}
|
|
2013
2220
|
|
|
2014
2221
|
const internal = {
|
|
2222
|
+
createPreviousHandler,
|
|
2223
|
+
clone,
|
|
2015
2224
|
ensureNodeValue,
|
|
2016
2225
|
findIDKey,
|
|
2017
2226
|
get,
|
|
2018
2227
|
getNode,
|
|
2228
|
+
getNodeValue,
|
|
2229
|
+
getPathType,
|
|
2019
2230
|
getProxy,
|
|
2020
2231
|
globalState,
|
|
2232
|
+
initializePathType,
|
|
2021
2233
|
observableFns,
|
|
2022
2234
|
optimized,
|
|
2023
2235
|
peek,
|
|
2236
|
+
runWithRetry,
|
|
2237
|
+
safeParse,
|
|
2238
|
+
safeStringify,
|
|
2024
2239
|
set,
|
|
2025
2240
|
setAtPath,
|
|
2026
2241
|
setNodeValue,
|
|
2027
|
-
|
|
2242
|
+
symbolLinked,
|
|
2028
2243
|
symbolDelete,
|
|
2244
|
+
tracking,
|
|
2029
2245
|
};
|
|
2030
2246
|
|
|
2031
2247
|
exports.ObservablePrimitiveClass = ObservablePrimitiveClass;
|
|
2032
2248
|
exports.batch = batch;
|
|
2033
2249
|
exports.beginBatch = beginBatch;
|
|
2034
2250
|
exports.beginTracking = beginTracking;
|
|
2035
|
-
exports.checkActivate = checkActivate;
|
|
2036
2251
|
exports.computeSelector = computeSelector;
|
|
2037
2252
|
exports.computed = computed;
|
|
2038
2253
|
exports.configureLegendState = configureLegendState;
|
|
@@ -2041,8 +2256,6 @@ exports.deconstructObjectWithPath = deconstructObjectWithPath;
|
|
|
2041
2256
|
exports.endBatch = endBatch;
|
|
2042
2257
|
exports.endTracking = endTracking;
|
|
2043
2258
|
exports.event = event;
|
|
2044
|
-
exports.extraPrimitiveActivators = extraPrimitiveActivators;
|
|
2045
|
-
exports.extraPrimitiveProps = extraPrimitiveProps;
|
|
2046
2259
|
exports.findIDKey = findIDKey;
|
|
2047
2260
|
exports.getNode = getNode;
|
|
2048
2261
|
exports.getNodeValue = getNodeValue;
|
|
@@ -2051,8 +2264,10 @@ exports.hasOwnProperty = hasOwnProperty;
|
|
|
2051
2264
|
exports.internal = internal;
|
|
2052
2265
|
exports.isArray = isArray;
|
|
2053
2266
|
exports.isBoolean = isBoolean;
|
|
2267
|
+
exports.isDate = isDate;
|
|
2054
2268
|
exports.isEmpty = isEmpty;
|
|
2055
2269
|
exports.isFunction = isFunction;
|
|
2270
|
+
exports.isNullOrUndefined = isNullOrUndefined;
|
|
2056
2271
|
exports.isObject = isObject;
|
|
2057
2272
|
exports.isObservable = isObservable;
|
|
2058
2273
|
exports.isObservableValueReady = isObservableValueReady;
|
|
@@ -2060,7 +2275,7 @@ exports.isPrimitive = isPrimitive;
|
|
|
2060
2275
|
exports.isPromise = isPromise;
|
|
2061
2276
|
exports.isString = isString;
|
|
2062
2277
|
exports.isSymbol = isSymbol;
|
|
2063
|
-
exports.
|
|
2278
|
+
exports.linked = linked;
|
|
2064
2279
|
exports.mergeIntoObservable = mergeIntoObservable;
|
|
2065
2280
|
exports.observable = observable;
|
|
2066
2281
|
exports.observablePrimitive = observablePrimitive;
|
|
@@ -2073,6 +2288,7 @@ exports.setInObservableAtPath = setInObservableAtPath;
|
|
|
2073
2288
|
exports.setSilently = setSilently;
|
|
2074
2289
|
exports.setupTracking = setupTracking;
|
|
2075
2290
|
exports.symbolDelete = symbolDelete;
|
|
2291
|
+
exports.syncState = syncState;
|
|
2076
2292
|
exports.trackSelector = trackSelector;
|
|
2077
2293
|
exports.tracking = tracking;
|
|
2078
2294
|
exports.updateTracking = updateTracking;
|