@legendapp/state 2.2.0-next.4 → 2.2.0-next.41
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/babel.js.map +1 -1
- package/config/enableDirectAccess.d.ts +1 -1
- package/config/enableDirectPeek.d.ts +1 -1
- package/config/enableReactDirectRender.js.map +1 -1
- package/config/enableReactDirectRender.mjs.map +1 -1
- package/config/enableReactTracking.d.ts +4 -3
- package/config/enableReactTracking.js.map +1 -1
- package/config/enableReactTracking.mjs.map +1 -1
- package/config/enableReactUse.d.ts +1 -1
- 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.map +1 -1
- package/history.mjs.map +1 -1
- package/index.d.ts +13 -4
- package/index.js +655 -448
- package/index.js.map +1 -1
- package/index.mjs +652 -447
- package/index.mjs.map +1 -1
- package/package.json +1 -12
- package/persist-plugins/async-storage.js.map +1 -1
- 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.js.map +1 -1
- package/persist-plugins/firebase.mjs.map +1 -1
- package/persist-plugins/indexeddb.js.map +1 -1
- package/persist-plugins/indexeddb.mjs.map +1 -1
- package/persist-plugins/local-storage.js +10 -2
- package/persist-plugins/local-storage.js.map +1 -1
- package/persist-plugins/local-storage.mjs +10 -2
- package/persist-plugins/local-storage.mjs.map +1 -1
- package/persist-plugins/mmkv.js.map +1 -1
- 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 +15 -1
- package/persist.js +412 -180
- package/persist.js.map +1 -1
- package/persist.mjs +413 -181
- 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 +2 -2
- package/react-hooks/usePersistedObservable.js +4 -3
- package/react-hooks/usePersistedObservable.js.map +1 -1
- package/react-hooks/usePersistedObservable.mjs +4 -3
- package/react-hooks/usePersistedObservable.mjs.map +1 -1
- package/react.js +13 -8
- package/react.js.map +1 -1
- package/react.mjs +14 -9
- package/react.mjs.map +1 -1
- package/src/ObservableObject.d.ts +6 -4
- package/src/ObservablePrimitive.d.ts +2 -1
- package/src/activated.d.ts +3 -0
- package/src/batching.d.ts +3 -1
- package/src/computed.d.ts +3 -3
- package/src/config/enableDirectAccess.d.ts +1 -1
- package/src/config/enableDirectPeek.d.ts +1 -1
- package/src/config/enableReactTracking.d.ts +4 -3
- package/src/config/enableReactUse.d.ts +1 -1
- package/src/createObservable.d.ts +2 -2
- package/src/globals.d.ts +10 -8
- package/src/helpers/fetch.d.ts +4 -3
- package/src/helpers/time.d.ts +2 -2
- package/src/helpers.d.ts +3 -3
- package/src/history/trackHistory.d.ts +1 -1
- package/src/is.d.ts +2 -0
- package/src/observable.d.ts +7 -15
- package/src/observableInterfaces.d.ts +56 -348
- package/src/observableTypes.d.ts +85 -0
- package/src/persist/observablePersistRemoteFunctionsAdapter.d.ts +1 -1
- package/src/persist/persistActivateNode.d.ts +0 -17
- package/src/persist/persistHelpers.d.ts +1 -1
- package/src/persist/persistObservable.d.ts +2 -3
- package/src/persistTypes.d.ts +196 -0
- package/src/proxy.d.ts +5 -5
- package/src/react/Computed.d.ts +1 -1
- package/src/react/Switch.d.ts +3 -3
- package/src/react/reactInterfaces.d.ts +2 -1
- package/src/react/useComputed.d.ts +5 -5
- package/src/react/usePauseProvider.d.ts +3 -3
- package/src/react/useWhen.d.ts +2 -2
- package/src/react-hooks/useFetch.d.ts +4 -3
- package/src/react-hooks/usePersistedObservable.d.ts +2 -2
- package/src/retry.d.ts +6 -0
- package/src/trackSelector.d.ts +3 -2
- package/src/when.d.ts +6 -2
- package/trace.js.map +1 -1
- package/trace.mjs.map +1 -1
package/index.mjs
CHANGED
|
@@ -6,14 +6,17 @@ function isString(obj) {
|
|
|
6
6
|
return typeof obj === 'string';
|
|
7
7
|
}
|
|
8
8
|
function isObject(obj) {
|
|
9
|
-
return !!obj && typeof obj === 'object' && !isArray(obj);
|
|
9
|
+
return !!obj && typeof obj === 'object' && !(obj instanceof Date) && !isArray(obj);
|
|
10
10
|
}
|
|
11
11
|
function isFunction(obj) {
|
|
12
12
|
return typeof obj === 'function';
|
|
13
13
|
}
|
|
14
14
|
function isPrimitive(arg) {
|
|
15
15
|
const type = typeof arg;
|
|
16
|
-
return arg !== undefined && type !== 'object' && type !== 'function';
|
|
16
|
+
return arg !== undefined && (isDate(arg) || (type !== 'object' && type !== 'function'));
|
|
17
|
+
}
|
|
18
|
+
function isDate(obj) {
|
|
19
|
+
return obj instanceof Date;
|
|
17
20
|
}
|
|
18
21
|
function isSymbol(obj) {
|
|
19
22
|
return typeof obj === 'symbol';
|
|
@@ -38,6 +41,9 @@ function isEmpty(obj) {
|
|
|
38
41
|
}
|
|
39
42
|
return true;
|
|
40
43
|
}
|
|
44
|
+
function isNullOrUndefined(value) {
|
|
45
|
+
return value === undefined || value === null;
|
|
46
|
+
}
|
|
41
47
|
const setPrimitives = new Set(['boolean', 'string', 'number']);
|
|
42
48
|
/** @internal */
|
|
43
49
|
function isActualPrimitive(arg) {
|
|
@@ -53,6 +59,7 @@ const symbolGetNode = Symbol('getNode');
|
|
|
53
59
|
const symbolDelete = /* @__PURE__ */ Symbol('delete');
|
|
54
60
|
const symbolOpaque = Symbol('opaque');
|
|
55
61
|
const optimized = Symbol('optimized');
|
|
62
|
+
const symbolActivated = Symbol('activated');
|
|
56
63
|
// TODOV3 Remove these
|
|
57
64
|
const extraPrimitiveActivators = new Map();
|
|
58
65
|
const extraPrimitiveProps = new Map();
|
|
@@ -61,28 +68,17 @@ const globalState = {
|
|
|
61
68
|
isMerging: false,
|
|
62
69
|
isLoadingRemote$: undefined,
|
|
63
70
|
activateNode: undefined,
|
|
71
|
+
pendingNodes: new Map(),
|
|
72
|
+
dirtyNodes: new Set(),
|
|
64
73
|
};
|
|
65
74
|
function isObservable(obs) {
|
|
66
75
|
return !!obs && !!obs[symbolGetNode];
|
|
67
76
|
}
|
|
68
|
-
function isComputed(obs) {
|
|
69
|
-
var _a;
|
|
70
|
-
return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isComputed);
|
|
71
|
-
}
|
|
72
|
-
function checkActivate(node) {
|
|
73
|
-
var _a;
|
|
74
|
-
const root = node.root;
|
|
75
|
-
(_a = root.activate) === null || _a === void 0 ? void 0 : _a.call(root);
|
|
76
|
-
if (root.toActivate) {
|
|
77
|
-
root.toActivate.forEach(checkActivate);
|
|
78
|
-
delete root.toActivate;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
77
|
function getNode(obs) {
|
|
82
78
|
return obs && obs[symbolGetNode];
|
|
83
79
|
}
|
|
84
80
|
function setNodeValue(node, newValue) {
|
|
85
|
-
var _a;
|
|
81
|
+
var _a, _b, _c;
|
|
86
82
|
const parentNode = (_a = node.parent) !== null && _a !== void 0 ? _a : node;
|
|
87
83
|
const key = node.parent ? node.key : '_';
|
|
88
84
|
const isDelete = newValue === symbolDelete;
|
|
@@ -97,27 +93,30 @@ function setNodeValue(node, newValue) {
|
|
|
97
93
|
// Compute newValue if newValue is a function or an observable
|
|
98
94
|
newValue = !parentNode.isAssigning && isFunc ? newValue(prevValue) : newValue;
|
|
99
95
|
// If setting an observable, set a link to the observable instead
|
|
100
|
-
if (isObservable(newValue)
|
|
96
|
+
if (isObservable(newValue)) {
|
|
101
97
|
const val = newValue;
|
|
102
|
-
node.lazy =
|
|
98
|
+
node.lazy = true;
|
|
99
|
+
node.lazyFn = () => val;
|
|
103
100
|
newValue = undefined;
|
|
104
101
|
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
if (!globalState.isMerging ||
|
|
103
|
+
prevValue === undefined ||
|
|
104
|
+
isFunction(prevValue) ||
|
|
105
|
+
!((_c = (_b = node.parent) === null || _b === void 0 ? void 0 : _b.functions) === null || _c === void 0 ? void 0 : _c.get(key))) {
|
|
106
|
+
try {
|
|
107
|
+
parentNode.isSetting = (parentNode.isSetting || 0) + 1;
|
|
108
|
+
// Save the new value
|
|
109
|
+
if (isDelete) {
|
|
110
|
+
delete parentValue[key];
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
parentValue[key] = newValue;
|
|
114
|
+
}
|
|
110
115
|
}
|
|
111
|
-
|
|
112
|
-
|
|
116
|
+
finally {
|
|
117
|
+
parentNode.isSetting--;
|
|
113
118
|
}
|
|
114
119
|
}
|
|
115
|
-
finally {
|
|
116
|
-
parentNode.isSetting--;
|
|
117
|
-
}
|
|
118
|
-
if (parentNode.root.locked && parentNode.root.set) {
|
|
119
|
-
parentNode.root.set(parentNode.root._);
|
|
120
|
-
}
|
|
121
120
|
return { prevValue, newValue, parentValue };
|
|
122
121
|
}
|
|
123
122
|
const arrNodeKeys = [];
|
|
@@ -135,12 +134,6 @@ function getNodeValue(node) {
|
|
|
135
134
|
}
|
|
136
135
|
return child;
|
|
137
136
|
}
|
|
138
|
-
const cloneFunction = (originalFunction) => {
|
|
139
|
-
const length = originalFunction.length;
|
|
140
|
-
return length > 1
|
|
141
|
-
? (arg1, arg2) => originalFunction(arg1, arg2)
|
|
142
|
-
: (...args) => originalFunction(...args);
|
|
143
|
-
};
|
|
144
137
|
function getChildNode(node, key, asFunction) {
|
|
145
138
|
var _a;
|
|
146
139
|
// Get the child by key
|
|
@@ -153,11 +146,15 @@ function getChildNode(node, key, asFunction) {
|
|
|
153
146
|
key,
|
|
154
147
|
lazy: true,
|
|
155
148
|
};
|
|
156
|
-
if (
|
|
157
|
-
|
|
149
|
+
if (node.activationState) {
|
|
150
|
+
const { lookup } = node.activationState;
|
|
151
|
+
if (lookup) {
|
|
152
|
+
asFunction = lookup.bind(node, key);
|
|
153
|
+
}
|
|
158
154
|
}
|
|
159
|
-
|
|
160
|
-
child = Object.assign(
|
|
155
|
+
if (asFunction) {
|
|
156
|
+
child = Object.assign(() => { }, child);
|
|
157
|
+
child.lazyFn = asFunction;
|
|
161
158
|
}
|
|
162
159
|
if (!node.children) {
|
|
163
160
|
node.children = new Map();
|
|
@@ -181,17 +178,19 @@ function ensureNodeValue(node) {
|
|
|
181
178
|
}
|
|
182
179
|
function findIDKey(obj, node) {
|
|
183
180
|
var _a, _b;
|
|
184
|
-
let idKey =
|
|
185
|
-
?
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
? '
|
|
189
|
-
: '
|
|
190
|
-
? '
|
|
191
|
-
: '
|
|
192
|
-
? '
|
|
193
|
-
:
|
|
194
|
-
|
|
181
|
+
let idKey = isObservable(obj)
|
|
182
|
+
? undefined
|
|
183
|
+
: isObject(obj)
|
|
184
|
+
? 'id' in obj
|
|
185
|
+
? 'id'
|
|
186
|
+
: 'key' in obj
|
|
187
|
+
? 'key'
|
|
188
|
+
: '_id' in obj
|
|
189
|
+
? '_id'
|
|
190
|
+
: '__id' in obj
|
|
191
|
+
? '__id'
|
|
192
|
+
: undefined
|
|
193
|
+
: undefined;
|
|
195
194
|
if (!idKey && node.parent) {
|
|
196
195
|
const k = node.key + '_keyExtractor';
|
|
197
196
|
const keyExtractor = (_b = (_a = node.functions) === null || _a === void 0 ? void 0 : _a.get(k)) !== null && _b !== void 0 ? _b : getNodeValue(node.parent)[node.key + '_keyExtractor'];
|
|
@@ -201,18 +200,17 @@ function findIDKey(obj, node) {
|
|
|
201
200
|
}
|
|
202
201
|
return idKey;
|
|
203
202
|
}
|
|
204
|
-
function extractFunction(node, key, fnOrComputed
|
|
203
|
+
function extractFunction(node, key, fnOrComputed) {
|
|
205
204
|
if (!node.functions) {
|
|
206
205
|
node.functions = new Map();
|
|
207
206
|
}
|
|
208
207
|
node.functions.set(key, fnOrComputed);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function activated(params) {
|
|
211
|
+
return (() => ({
|
|
212
|
+
[symbolActivated]: params,
|
|
213
|
+
}));
|
|
216
214
|
}
|
|
217
215
|
|
|
218
216
|
let timeout;
|
|
@@ -239,23 +237,28 @@ function isArraySubset(mainArr, subsetArr) {
|
|
|
239
237
|
return true;
|
|
240
238
|
}
|
|
241
239
|
function createPreviousHandlerInner(value, changes) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
240
|
+
try {
|
|
241
|
+
// Clones the current state and inject the previous data at the changed path
|
|
242
|
+
let clone = value ? JSON.parse(JSON.stringify(value)) : {};
|
|
243
|
+
for (let i = 0; i < changes.length; i++) {
|
|
244
|
+
const { path, prevAtPath } = changes[i];
|
|
245
|
+
let o = clone;
|
|
246
|
+
if (path.length > 0) {
|
|
247
|
+
let i;
|
|
248
|
+
for (i = 0; i < path.length - 1; i++) {
|
|
249
|
+
o = o[path[i]];
|
|
250
|
+
}
|
|
251
|
+
o[path[i]] = prevAtPath;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
clone = prevAtPath;
|
|
251
255
|
}
|
|
252
|
-
o[path[i]] = prevAtPath;
|
|
253
|
-
}
|
|
254
|
-
else {
|
|
255
|
-
clone = prevAtPath;
|
|
256
256
|
}
|
|
257
|
+
return clone;
|
|
258
|
+
}
|
|
259
|
+
catch (_a) {
|
|
260
|
+
return undefined;
|
|
257
261
|
}
|
|
258
|
-
return clone;
|
|
259
262
|
}
|
|
260
263
|
function createPreviousHandler(value, changes) {
|
|
261
264
|
// Create a function that generates the previous state
|
|
@@ -364,8 +367,15 @@ function batchNotifyChanges(changesInBatch, immediate) {
|
|
|
364
367
|
});
|
|
365
368
|
}
|
|
366
369
|
function runBatch() {
|
|
370
|
+
const dirtyNodes = Array.from(globalState.dirtyNodes);
|
|
371
|
+
globalState.dirtyNodes.clear();
|
|
372
|
+
dirtyNodes.forEach((node) => {
|
|
373
|
+
var _a;
|
|
374
|
+
(_a = node.dirtyFn) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
375
|
+
node.dirtyFn = undefined;
|
|
376
|
+
});
|
|
367
377
|
// Save batch locally and reset _batchMap first because a new batch could begin while looping over callbacks.
|
|
368
|
-
// This can happen with
|
|
378
|
+
// This can happen with computeds for example.
|
|
369
379
|
const map = _batchMap;
|
|
370
380
|
_batchMap = new Map();
|
|
371
381
|
const changesInBatch = new Map();
|
|
@@ -419,7 +429,7 @@ function endBatch(force) {
|
|
|
419
429
|
}
|
|
420
430
|
numInBatch = 0;
|
|
421
431
|
// Save batch locally and reset _batch first because a new batch could begin while looping over callbacks.
|
|
422
|
-
// This can happen with
|
|
432
|
+
// This can happen with computeds for example.
|
|
423
433
|
const after = _afterBatch;
|
|
424
434
|
if (after.length) {
|
|
425
435
|
_afterBatch = [];
|
|
@@ -461,7 +471,8 @@ function createObservable(value, makePrimitive, extractPromise, createObject, cr
|
|
|
461
471
|
lazy: true,
|
|
462
472
|
};
|
|
463
473
|
if (valueIsFunction) {
|
|
464
|
-
node = Object.assign(
|
|
474
|
+
node = Object.assign(() => { }, node);
|
|
475
|
+
node.lazyFn = value;
|
|
465
476
|
}
|
|
466
477
|
const prim = makePrimitive || isActualPrimitive(value);
|
|
467
478
|
const obs = prim
|
|
@@ -480,7 +491,7 @@ function isEvent(obs) {
|
|
|
480
491
|
}
|
|
481
492
|
function computeSelector(selector, e, retainObservable) {
|
|
482
493
|
let c = selector;
|
|
483
|
-
if (isFunction(c)) {
|
|
494
|
+
if (!isObservable(c) && isFunction(c)) {
|
|
484
495
|
c = e ? c(e) : c();
|
|
485
496
|
}
|
|
486
497
|
return isObservable(c) && !retainObservable ? c.get() : c;
|
|
@@ -496,13 +507,6 @@ function opaqueObject(value) {
|
|
|
496
507
|
}
|
|
497
508
|
return value;
|
|
498
509
|
}
|
|
499
|
-
function lockObservable(obs, value) {
|
|
500
|
-
var _a;
|
|
501
|
-
const root = (_a = getNode(obs)) === null || _a === void 0 ? void 0 : _a.root;
|
|
502
|
-
if (root) {
|
|
503
|
-
root.locked = value;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
510
|
function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
|
|
507
511
|
let o = obj;
|
|
508
512
|
let oFull = fullObj;
|
|
@@ -579,14 +583,15 @@ function _mergeIntoObservable(target, source) {
|
|
|
579
583
|
const targetValue = needsSet ? target.peek() : target;
|
|
580
584
|
const isTargetArr = isArray(targetValue);
|
|
581
585
|
const isTargetObj = !isTargetArr && isObject(targetValue);
|
|
582
|
-
if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) ||
|
|
583
|
-
(isTargetArr && isArray(source) && targetValue.length > 0)) {
|
|
586
|
+
if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) || (isTargetArr && targetValue.length > 0)) {
|
|
584
587
|
const keys = Object.keys(source);
|
|
585
588
|
for (let i = 0; i < keys.length; i++) {
|
|
586
589
|
const key = keys[i];
|
|
587
590
|
const sourceValue = source[key];
|
|
588
591
|
if (sourceValue === symbolDelete) {
|
|
589
|
-
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete)
|
|
592
|
+
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete)
|
|
593
|
+
? target[key].delete()
|
|
594
|
+
: delete target[key];
|
|
590
595
|
}
|
|
591
596
|
else {
|
|
592
597
|
const isObj = isObject(sourceValue);
|
|
@@ -657,7 +662,6 @@ function onChange(node, callback, options = {}) {
|
|
|
657
662
|
node.listeners = listeners;
|
|
658
663
|
}
|
|
659
664
|
}
|
|
660
|
-
checkActivate(node);
|
|
661
665
|
const listener = {
|
|
662
666
|
listener: callback,
|
|
663
667
|
track: trackingType,
|
|
@@ -679,7 +683,14 @@ function onChange(node, callback, options = {}) {
|
|
|
679
683
|
getPrevious: () => undefined,
|
|
680
684
|
});
|
|
681
685
|
}
|
|
682
|
-
|
|
686
|
+
let extraDispose;
|
|
687
|
+
if (node.linkedToNode) {
|
|
688
|
+
extraDispose = onChange(node.linkedToNode, callback, options);
|
|
689
|
+
}
|
|
690
|
+
return () => {
|
|
691
|
+
listeners.delete(listener);
|
|
692
|
+
extraDispose === null || extraDispose === void 0 ? void 0 : extraDispose();
|
|
693
|
+
};
|
|
683
694
|
}
|
|
684
695
|
|
|
685
696
|
function setupTracking(nodes, update, noArgs, immediate) {
|
|
@@ -775,7 +786,7 @@ function trackSelector(selector, update, observeEvent, observeOptions, createRes
|
|
|
775
786
|
dispose = setupTracking(nodes, updateFn, false, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.immediate);
|
|
776
787
|
resubscribe = createResubscribe ? () => setupTracking(nodes, updateFn) : undefined;
|
|
777
788
|
}
|
|
778
|
-
return { value, dispose, resubscribe };
|
|
789
|
+
return { value, nodes, dispose, resubscribe };
|
|
779
790
|
}
|
|
780
791
|
|
|
781
792
|
function observe(selectorOrRun, reactionOrOptions, options) {
|
|
@@ -800,9 +811,11 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
800
811
|
delete e.value;
|
|
801
812
|
// Dispose listeners from previous run
|
|
802
813
|
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
803
|
-
const { dispose: _dispose, value } = trackSelector(selectorOrRun, update, e, options);
|
|
814
|
+
const { dispose: _dispose, value, nodes } = trackSelector(selectorOrRun, update, e, options);
|
|
804
815
|
dispose = _dispose;
|
|
805
816
|
e.value = value;
|
|
817
|
+
e.nodes = nodes;
|
|
818
|
+
e.refresh = update;
|
|
806
819
|
if (e.onCleanupReaction) {
|
|
807
820
|
e.onCleanupReaction();
|
|
808
821
|
e.onCleanupReaction = undefined;
|
|
@@ -810,7 +823,9 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
810
823
|
endBatch();
|
|
811
824
|
// Call the reaction if there is one and the value changed
|
|
812
825
|
if (reaction &&
|
|
813
|
-
((options === null || options === void 0 ? void 0 : options.fromComputed) ||
|
|
826
|
+
((options === null || options === void 0 ? void 0 : options.fromComputed) ||
|
|
827
|
+
((e.num > 0 || !isEvent(selectorOrRun)) &&
|
|
828
|
+
(e.previous !== e.value || typeof e.value === 'object')))) {
|
|
814
829
|
reaction(e);
|
|
815
830
|
}
|
|
816
831
|
// Update the previous value
|
|
@@ -830,6 +845,120 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
830
845
|
};
|
|
831
846
|
}
|
|
832
847
|
|
|
848
|
+
function _when(predicate, effect, checkReady) {
|
|
849
|
+
// If predicate is a regular Promise skip all the observable stuff
|
|
850
|
+
if (isPromise(predicate)) {
|
|
851
|
+
return effect ? predicate.then(effect) : predicate;
|
|
852
|
+
}
|
|
853
|
+
let value;
|
|
854
|
+
let effectValue;
|
|
855
|
+
// Create a wrapping fn that calls the effect if predicate returns true
|
|
856
|
+
function run(e) {
|
|
857
|
+
const ret = computeSelector(predicate);
|
|
858
|
+
if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
859
|
+
value = ret;
|
|
860
|
+
// Set cancel so that observe does not track anymore
|
|
861
|
+
e.cancel = true;
|
|
862
|
+
}
|
|
863
|
+
return value;
|
|
864
|
+
}
|
|
865
|
+
function doEffect() {
|
|
866
|
+
// If value is truthy then run the effect
|
|
867
|
+
effectValue = effect === null || effect === void 0 ? void 0 : effect(value);
|
|
868
|
+
}
|
|
869
|
+
// Run in an observe
|
|
870
|
+
observe(run, doEffect);
|
|
871
|
+
// If first run resulted in a truthy value just return it.
|
|
872
|
+
// It will have set e.cancel so no need to dispose
|
|
873
|
+
if (isPromise(value)) {
|
|
874
|
+
return effect ? value.then(effect) : value;
|
|
875
|
+
}
|
|
876
|
+
else if (value !== undefined) {
|
|
877
|
+
return effect ? effectValue : Promise.resolve(value);
|
|
878
|
+
}
|
|
879
|
+
else {
|
|
880
|
+
// Wrap it in a promise
|
|
881
|
+
const promise = new Promise((resolve) => {
|
|
882
|
+
if (effect) {
|
|
883
|
+
const originalEffect = effect;
|
|
884
|
+
effect = ((value) => {
|
|
885
|
+
const effectValue = originalEffect(value);
|
|
886
|
+
resolve(isPromise(effectValue) ? effectValue.then((value) => value) : effectValue);
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
else {
|
|
890
|
+
effect = resolve;
|
|
891
|
+
}
|
|
892
|
+
});
|
|
893
|
+
return promise;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
function when(predicate, effect) {
|
|
897
|
+
return _when(predicate, effect, false);
|
|
898
|
+
}
|
|
899
|
+
function whenReady(predicate, effect) {
|
|
900
|
+
return _when(predicate, effect, true);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
function calculateRetryDelay(retryOptions, attemptNum) {
|
|
904
|
+
const { backoff, delay = 1000, infinite, times = 3, maxDelay = 30000 } = retryOptions;
|
|
905
|
+
if (infinite || attemptNum < times) {
|
|
906
|
+
const delayTime = Math.min(delay * (backoff === 'constant' ? 1 : 2 ** attemptNum), maxDelay);
|
|
907
|
+
return delayTime;
|
|
908
|
+
}
|
|
909
|
+
return null;
|
|
910
|
+
}
|
|
911
|
+
function createRetryTimeout(retryOptions, attemptNum, fn) {
|
|
912
|
+
const delayTime = calculateRetryDelay(retryOptions, attemptNum);
|
|
913
|
+
if (delayTime) {
|
|
914
|
+
return setTimeout(fn, delayTime);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
function runWithRetry(node, state, fn) {
|
|
918
|
+
const { retry, waitFor } = node.activationState;
|
|
919
|
+
const e = { cancel: false };
|
|
920
|
+
let value = undefined;
|
|
921
|
+
if (waitFor) {
|
|
922
|
+
value = whenReady(waitFor, () => {
|
|
923
|
+
node.activationState.waitFor = undefined;
|
|
924
|
+
return fn(e);
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
else {
|
|
928
|
+
value = fn(e);
|
|
929
|
+
}
|
|
930
|
+
if (isPromise(value) && retry) {
|
|
931
|
+
let timeoutRetry;
|
|
932
|
+
return new Promise((resolve) => {
|
|
933
|
+
const run = () => {
|
|
934
|
+
value
|
|
935
|
+
.then((val) => {
|
|
936
|
+
node.activationState.persistedRetry = false;
|
|
937
|
+
resolve(val);
|
|
938
|
+
})
|
|
939
|
+
.catch(() => {
|
|
940
|
+
state.attemptNum++;
|
|
941
|
+
if (timeoutRetry) {
|
|
942
|
+
clearTimeout(timeoutRetry);
|
|
943
|
+
}
|
|
944
|
+
if (!e.cancel) {
|
|
945
|
+
timeoutRetry = createRetryTimeout(retry, state.attemptNum, () => {
|
|
946
|
+
value = fn(e);
|
|
947
|
+
run();
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
})
|
|
951
|
+
.finally(() => {
|
|
952
|
+
node.activationState.persistedRetry = false;
|
|
953
|
+
});
|
|
954
|
+
};
|
|
955
|
+
run();
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
return value;
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
const noop = () => { };
|
|
833
962
|
const ArrayModifiers = new Set([
|
|
834
963
|
'copyWithin',
|
|
835
964
|
'fill',
|
|
@@ -870,7 +999,8 @@ if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
|
870
999
|
}
|
|
871
1000
|
function collectionSetter(node, target, prop, ...args) {
|
|
872
1001
|
var _a;
|
|
873
|
-
if (prop === 'push') {
|
|
1002
|
+
if (prop === 'push' && args.length === 1) {
|
|
1003
|
+
// Fast path for push to just append to the end
|
|
874
1004
|
setKey(node, target.length + '', args[0]);
|
|
875
1005
|
}
|
|
876
1006
|
else {
|
|
@@ -922,8 +1052,9 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
922
1052
|
let prevChildrenById;
|
|
923
1053
|
let moved;
|
|
924
1054
|
const isMap = obj instanceof Map;
|
|
1055
|
+
const isPrevMap = prevValue instanceof Map;
|
|
925
1056
|
const keys = getKeys(obj, isArr, isMap);
|
|
926
|
-
const keysPrev = getKeys(prevValue, isArr,
|
|
1057
|
+
const keysPrev = getKeys(prevValue, isArr, isPrevMap);
|
|
927
1058
|
const length = ((_a = (keys || obj)) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
928
1059
|
const lengthPrev = ((_b = (keysPrev || prevValue)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
929
1060
|
let idField;
|
|
@@ -975,7 +1106,7 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
975
1106
|
if (!keys.includes(key)) {
|
|
976
1107
|
hasADiff = true;
|
|
977
1108
|
const child = getChildNode(parent, key);
|
|
978
|
-
const prev =
|
|
1109
|
+
const prev = isPrevMap ? prevValue.get(key) : prevValue[key];
|
|
979
1110
|
if (prev !== undefined) {
|
|
980
1111
|
if (!isPrimitive(prev)) {
|
|
981
1112
|
updateNodes(child, undefined, prev);
|
|
@@ -993,16 +1124,24 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
993
1124
|
let didMove = false;
|
|
994
1125
|
for (let i = 0; i < length; i++) {
|
|
995
1126
|
const key = isArr ? i + '' : keys[i];
|
|
996
|
-
|
|
997
|
-
const prev =
|
|
998
|
-
let isDiff = value !== prev;
|
|
1127
|
+
let value = isMap ? obj.get(key) : obj[key];
|
|
1128
|
+
const prev = isPrevMap ? prevValue === null || prevValue === void 0 ? void 0 : prevValue.get(key) : prevValue === null || prevValue === void 0 ? void 0 : prevValue[key];
|
|
1129
|
+
let isDiff = isDate(value) ? +value !== +prev : value !== prev;
|
|
999
1130
|
if (isDiff) {
|
|
1000
1131
|
const id = idField && value
|
|
1001
1132
|
? isIdFieldFunction
|
|
1002
1133
|
? idField(value)
|
|
1003
1134
|
: value[idField]
|
|
1004
1135
|
: undefined;
|
|
1005
|
-
|
|
1136
|
+
if (isObservable(value)) {
|
|
1137
|
+
const obs = value;
|
|
1138
|
+
value = () => obs;
|
|
1139
|
+
}
|
|
1140
|
+
let child = getChildNode(parent, key, isFunction(value) ? value : undefined);
|
|
1141
|
+
if (!child.lazy && (isFunction(value) || isObservable(value))) {
|
|
1142
|
+
reactivateNode(child, value);
|
|
1143
|
+
peek(child);
|
|
1144
|
+
}
|
|
1006
1145
|
// Detect moves within an array. Need to move the original proxy to the new position to keep
|
|
1007
1146
|
// the proxy stable, so that listeners to this node will be unaffected by the array shift.
|
|
1008
1147
|
if (isArr && id !== undefined) {
|
|
@@ -1032,7 +1171,10 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
1032
1171
|
if (isDiff) {
|
|
1033
1172
|
// Array has a new / modified element
|
|
1034
1173
|
// If object iterate through its children
|
|
1035
|
-
if (
|
|
1174
|
+
if (isFunction(value) || isObservable(value)) {
|
|
1175
|
+
extractFunctionOrComputed(parent, obj, key, value);
|
|
1176
|
+
}
|
|
1177
|
+
else if (isPrimitive(value)) {
|
|
1036
1178
|
hasADiff = true;
|
|
1037
1179
|
}
|
|
1038
1180
|
else {
|
|
@@ -1080,6 +1222,15 @@ function getProxy(node, p, asFunction) {
|
|
|
1080
1222
|
// Create a proxy if not already cached and return it
|
|
1081
1223
|
return (node.proxy || (node.proxy = new Proxy(node, proxyHandler)));
|
|
1082
1224
|
}
|
|
1225
|
+
function flushPending() {
|
|
1226
|
+
// Need to short circuit the computed batching because the user called get() or peek()
|
|
1227
|
+
// in which case the set needs to run immediately so that the values are up to date.
|
|
1228
|
+
if (globalState.pendingNodes.size > 0) {
|
|
1229
|
+
const nodes = Array.from(globalState.pendingNodes.values());
|
|
1230
|
+
globalState.pendingNodes.clear();
|
|
1231
|
+
nodes.forEach((fn) => fn());
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1083
1234
|
const proxyHandler = {
|
|
1084
1235
|
get(node, p, receiver) {
|
|
1085
1236
|
var _a;
|
|
@@ -1091,11 +1242,12 @@ const proxyHandler = {
|
|
|
1091
1242
|
if (p === symbolGetNode) {
|
|
1092
1243
|
return node;
|
|
1093
1244
|
}
|
|
1094
|
-
|
|
1245
|
+
let value = peek(node);
|
|
1095
1246
|
// If this node is linked to another observable then forward to the target's handler.
|
|
1096
1247
|
// The exception is onChange because it needs to listen to this node for changes.
|
|
1097
1248
|
// This needs to be below peek because it activates there.
|
|
1098
1249
|
if (node.linkedToNode && p !== 'onChange') {
|
|
1250
|
+
updateTracking(node);
|
|
1099
1251
|
return proxyHandler.get(node.linkedToNode, p, receiver);
|
|
1100
1252
|
}
|
|
1101
1253
|
if (value instanceof Map || value instanceof WeakMap || value instanceof Set || value instanceof WeakSet) {
|
|
@@ -1107,6 +1259,9 @@ const proxyHandler = {
|
|
|
1107
1259
|
const fn = observableFns.get(p);
|
|
1108
1260
|
// If this is an observable function, call it
|
|
1109
1261
|
if (fn) {
|
|
1262
|
+
if (p === 'get' || p === 'peek') {
|
|
1263
|
+
flushPending();
|
|
1264
|
+
}
|
|
1110
1265
|
return function (a, b, c) {
|
|
1111
1266
|
const l = arguments.length;
|
|
1112
1267
|
// Array call and apply are slow so micro-optimize this hot path.
|
|
@@ -1124,14 +1279,6 @@ const proxyHandler = {
|
|
|
1124
1279
|
}
|
|
1125
1280
|
};
|
|
1126
1281
|
}
|
|
1127
|
-
if (node.isComputed) {
|
|
1128
|
-
if (node.proxyFn && !fn) {
|
|
1129
|
-
return node.proxyFn(p);
|
|
1130
|
-
}
|
|
1131
|
-
else {
|
|
1132
|
-
checkActivate(node);
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
1282
|
const property = observableProperties.get(p);
|
|
1136
1283
|
if (property) {
|
|
1137
1284
|
return property.get(node);
|
|
@@ -1150,7 +1297,7 @@ const proxyHandler = {
|
|
|
1150
1297
|
}
|
|
1151
1298
|
}
|
|
1152
1299
|
// /TODOV3 Remove this
|
|
1153
|
-
|
|
1300
|
+
let vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
1154
1301
|
if (isObject(value) && value[symbolOpaque]) {
|
|
1155
1302
|
return vProp;
|
|
1156
1303
|
}
|
|
@@ -1163,6 +1310,11 @@ const proxyHandler = {
|
|
|
1163
1310
|
return getProxy(node, p, fnOrComputed);
|
|
1164
1311
|
}
|
|
1165
1312
|
}
|
|
1313
|
+
if (isNullOrUndefined(value) && vProp === undefined && (ArrayModifiers.has(p) || ArrayLoopers.has(p))) {
|
|
1314
|
+
value = [];
|
|
1315
|
+
setNodeValue(node, value);
|
|
1316
|
+
vProp = value[p];
|
|
1317
|
+
}
|
|
1166
1318
|
// Handle function calls
|
|
1167
1319
|
if (isFunction(vProp)) {
|
|
1168
1320
|
if (isArray(value)) {
|
|
@@ -1212,10 +1364,6 @@ const proxyHandler = {
|
|
|
1212
1364
|
return vProp;
|
|
1213
1365
|
}
|
|
1214
1366
|
}
|
|
1215
|
-
// TODOV3: Remove "state"
|
|
1216
|
-
if (vProp === undefined && (p === 'state' || p === '_state') && node.state) {
|
|
1217
|
-
return node.state;
|
|
1218
|
-
}
|
|
1219
1367
|
// Return an observable proxy to the property
|
|
1220
1368
|
return getProxy(node, p);
|
|
1221
1369
|
},
|
|
@@ -1280,7 +1428,7 @@ const proxyHandler = {
|
|
|
1280
1428
|
},
|
|
1281
1429
|
apply(target, thisArg, argArray) {
|
|
1282
1430
|
// If it's a function call it as a function
|
|
1283
|
-
return Reflect.apply(target, thisArg, argArray);
|
|
1431
|
+
return Reflect.apply(target.lazyFn || target, thisArg, argArray);
|
|
1284
1432
|
},
|
|
1285
1433
|
};
|
|
1286
1434
|
function set(node, newValue) {
|
|
@@ -1293,7 +1441,7 @@ function set(node, newValue) {
|
|
|
1293
1441
|
}
|
|
1294
1442
|
function toggle(node) {
|
|
1295
1443
|
const value = getNodeValue(node);
|
|
1296
|
-
if (value === undefined || isBoolean(value)) {
|
|
1444
|
+
if (value === undefined || value === null || isBoolean(value)) {
|
|
1297
1445
|
set(node, !value);
|
|
1298
1446
|
return !value;
|
|
1299
1447
|
}
|
|
@@ -1307,31 +1455,32 @@ function setKey(node, key, newValue, level) {
|
|
|
1307
1455
|
console.warn(`[legend-state] Set an HTMLElement into state. You probably don't want to do that.`);
|
|
1308
1456
|
}
|
|
1309
1457
|
}
|
|
1310
|
-
if (node.root.locked && !node.root.set) {
|
|
1311
|
-
// This happens when modifying a locked observable such as a computed.
|
|
1312
|
-
// If merging this could be happening deep in a hierarchy so we don't want to throw errors so we'll just do nothing.
|
|
1313
|
-
// This could happen during persistence local load for example.
|
|
1314
|
-
if (globalState.isMerging) {
|
|
1315
|
-
return;
|
|
1316
|
-
}
|
|
1317
|
-
else {
|
|
1318
|
-
throw new Error(process.env.NODE_ENV === 'development'
|
|
1319
|
-
? '[legend-state] Cannot modify an observable while it is locked. Please make sure that you unlock the observable before making changes.'
|
|
1320
|
-
: '[legend-state] Modified locked observable');
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
1458
|
const isRoot = !node.parent && key === '_';
|
|
1459
|
+
if (node.parent && !getNodeValue(node)) {
|
|
1460
|
+
return set(node, { [key]: newValue });
|
|
1461
|
+
}
|
|
1324
1462
|
// Get the child node for updating and notifying
|
|
1325
1463
|
const childNode = isRoot ? node : getChildNode(node, key, isFunction(newValue) ? newValue : undefined);
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1464
|
+
if (isObservable(newValue)) {
|
|
1465
|
+
setToObservable(childNode, newValue);
|
|
1466
|
+
}
|
|
1467
|
+
else {
|
|
1468
|
+
// Set the raw value on the parent object
|
|
1469
|
+
const { newValue: savedValue, prevValue, parentValue } = setNodeValue(childNode, newValue);
|
|
1470
|
+
const isFunc = isFunction(savedValue);
|
|
1471
|
+
const isPrim = isPrimitive(savedValue) || savedValue instanceof Date;
|
|
1472
|
+
if (savedValue !== prevValue) {
|
|
1473
|
+
updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level);
|
|
1474
|
+
}
|
|
1475
|
+
if (!isPrim) {
|
|
1476
|
+
childNode.needsExtract = true;
|
|
1477
|
+
}
|
|
1478
|
+
extractFunctionOrComputed(node, parentValue, key, savedValue);
|
|
1479
|
+
if (isFunc) {
|
|
1480
|
+
return savedValue;
|
|
1481
|
+
}
|
|
1332
1482
|
}
|
|
1333
|
-
|
|
1334
|
-
return isFunc ? savedValue : isRoot ? getProxy(node) : getProxy(node, key);
|
|
1483
|
+
return isRoot ? getProxy(node) : getProxy(node, key);
|
|
1335
1484
|
}
|
|
1336
1485
|
function assign(node, value) {
|
|
1337
1486
|
const proxy = getProxy(node);
|
|
@@ -1356,7 +1505,13 @@ function deleteFn(node, key) {
|
|
|
1356
1505
|
key = node.key;
|
|
1357
1506
|
node = node.parent;
|
|
1358
1507
|
}
|
|
1359
|
-
|
|
1508
|
+
const value = getNodeValue(node);
|
|
1509
|
+
if (isArray(value)) {
|
|
1510
|
+
collectionSetter(node, value, 'splice', key, 1);
|
|
1511
|
+
}
|
|
1512
|
+
else {
|
|
1513
|
+
setKey(node, key !== null && key !== void 0 ? key : '_', symbolDelete, /*level*/ -1);
|
|
1514
|
+
}
|
|
1360
1515
|
}
|
|
1361
1516
|
function handlerMapSet(node, p, value) {
|
|
1362
1517
|
const vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
@@ -1436,7 +1591,7 @@ function handlerMapSet(node, p, value) {
|
|
|
1436
1591
|
function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRoot, level) {
|
|
1437
1592
|
if (!childNode)
|
|
1438
1593
|
childNode = node;
|
|
1439
|
-
// Make sure we don't call too many listeners for
|
|
1594
|
+
// Make sure we don't call too many listeners for every property set
|
|
1440
1595
|
beginBatch();
|
|
1441
1596
|
let hasADiff = isPrim;
|
|
1442
1597
|
let whenOptimizedOnlyIf = false;
|
|
@@ -1466,30 +1621,41 @@ function extractPromise(node, value, setter) {
|
|
|
1466
1621
|
value
|
|
1467
1622
|
.then((value) => {
|
|
1468
1623
|
setter ? setter({ value }) : set(node, value);
|
|
1469
|
-
node.state.
|
|
1624
|
+
node.state.assign({
|
|
1625
|
+
isLoaded: true,
|
|
1626
|
+
error: undefined,
|
|
1627
|
+
});
|
|
1470
1628
|
})
|
|
1471
1629
|
.catch((error) => {
|
|
1472
1630
|
node.state.error.set(error);
|
|
1473
1631
|
});
|
|
1474
1632
|
}
|
|
1475
1633
|
function extractFunctionOrComputed(node, obj, k, v) {
|
|
1634
|
+
var _a;
|
|
1476
1635
|
if (isPromise(v)) {
|
|
1477
1636
|
const childNode = getChildNode(node, k);
|
|
1478
1637
|
extractPromise(childNode, v);
|
|
1479
1638
|
setNodeValue(childNode, undefined);
|
|
1480
1639
|
}
|
|
1640
|
+
else if (isObservable(v)) {
|
|
1641
|
+
const value = getNodeValue(node);
|
|
1642
|
+
value[k] = () => v;
|
|
1643
|
+
extractFunction(node, k, value[k]);
|
|
1644
|
+
}
|
|
1481
1645
|
else if (typeof v === 'function') {
|
|
1646
|
+
const childNode = (_a = node.children) === null || _a === void 0 ? void 0 : _a.get(k);
|
|
1482
1647
|
extractFunction(node, k, v);
|
|
1483
|
-
|
|
1648
|
+
// If child was previously activated, then peek the new linked observable to make sure it's activated
|
|
1649
|
+
if (childNode && !childNode.lazy) {
|
|
1650
|
+
if (isObservable(v)) {
|
|
1651
|
+
const vNode = getNode(v);
|
|
1652
|
+
peek(vNode);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1484
1655
|
}
|
|
1485
1656
|
else if (typeof v == 'object' && v !== null && v !== undefined) {
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
extractFunction(node, k, v, childNode);
|
|
1489
|
-
delete obj[k];
|
|
1490
|
-
}
|
|
1491
|
-
else {
|
|
1492
|
-
return true;
|
|
1657
|
+
if (isObservable(v)) {
|
|
1658
|
+
extractFunction(node, k, v);
|
|
1493
1659
|
}
|
|
1494
1660
|
}
|
|
1495
1661
|
}
|
|
@@ -1500,181 +1666,348 @@ function get(node, options) {
|
|
|
1500
1666
|
return peek(node);
|
|
1501
1667
|
}
|
|
1502
1668
|
function peek(node) {
|
|
1503
|
-
|
|
1669
|
+
if (node.dirtyFn) {
|
|
1670
|
+
node.dirtyFn();
|
|
1671
|
+
globalState.dirtyNodes.delete(node);
|
|
1672
|
+
node.dirtyFn = undefined;
|
|
1673
|
+
}
|
|
1674
|
+
let value = getNodeValue(node);
|
|
1504
1675
|
// If node is not yet lazily computed go do that
|
|
1505
1676
|
const lazy = node.lazy;
|
|
1506
1677
|
if (lazy) {
|
|
1678
|
+
const lazyFn = node.lazyFn;
|
|
1507
1679
|
delete node.lazy;
|
|
1508
|
-
if (isFunction(node) || isFunction(
|
|
1509
|
-
activateNodeFunction(node,
|
|
1680
|
+
if (isFunction(node) || isFunction(lazyFn)) {
|
|
1681
|
+
value = activateNodeFunction(node, lazyFn);
|
|
1510
1682
|
}
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1683
|
+
}
|
|
1684
|
+
if (lazy || node.needsExtract) {
|
|
1685
|
+
for (const key in value) {
|
|
1686
|
+
if (hasOwnProperty.call(value, key)) {
|
|
1687
|
+
extractFunctionOrComputed(node, value, key, value[key]);
|
|
1516
1688
|
}
|
|
1517
1689
|
}
|
|
1518
1690
|
}
|
|
1519
|
-
// Check if computed needs to activate
|
|
1520
|
-
checkActivate(node);
|
|
1521
1691
|
return value;
|
|
1522
1692
|
}
|
|
1523
|
-
function
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
};
|
|
1533
|
-
// The onSet function handles the observable being set
|
|
1534
|
-
// and forwards the set elsewhere
|
|
1535
|
-
const updateLastSync = (fn) => {
|
|
1536
|
-
state.lastSync.value = fn;
|
|
1537
|
-
};
|
|
1538
|
-
// The subscribe function runs a function that listens to
|
|
1539
|
-
// a data source and sends updates into the observable
|
|
1540
|
-
const subscribe = (fn) => {
|
|
1541
|
-
if (!state.subscriber) {
|
|
1542
|
-
state.subscriber = fn;
|
|
1543
|
-
}
|
|
1544
|
-
};
|
|
1545
|
-
const cache = (fn) => {
|
|
1546
|
-
if (!state.cacheOptions) {
|
|
1547
|
-
state.cacheOptions = isFunction(fn) ? fn() : fn;
|
|
1548
|
-
}
|
|
1549
|
-
};
|
|
1550
|
-
const retry = (params) => {
|
|
1551
|
-
if (!state.retryOptions) {
|
|
1552
|
-
state.retryOptions = params;
|
|
1553
|
-
}
|
|
1554
|
-
};
|
|
1555
|
-
// The proxy function simply marks the node as a proxy with this function
|
|
1556
|
-
// so that child nodes will be created with this function, and then simply
|
|
1557
|
-
// activated as a function
|
|
1558
|
-
const proxy = (fn) => {
|
|
1559
|
-
node.proxyFn2 = fn;
|
|
1560
|
-
};
|
|
1561
|
-
return {
|
|
1562
|
-
onSet,
|
|
1563
|
-
proxy,
|
|
1564
|
-
cache,
|
|
1565
|
-
retry,
|
|
1566
|
-
subscribe,
|
|
1567
|
-
updateLastSync,
|
|
1568
|
-
obs$: getProxy(node),
|
|
1569
|
-
};
|
|
1693
|
+
function reactivateNode(node, lazyFn) {
|
|
1694
|
+
var _a, _b;
|
|
1695
|
+
(_a = node.activatedObserveDispose) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
1696
|
+
node.activatedObserveDispose = undefined;
|
|
1697
|
+
(_b = node.linkedToNodeDispose) === null || _b === void 0 ? void 0 : _b.call(node);
|
|
1698
|
+
node.linkedToNodeDispose = undefined;
|
|
1699
|
+
node.linkedToNode = undefined;
|
|
1700
|
+
node.lazyFn = lazyFn;
|
|
1701
|
+
node.lazy = true;
|
|
1570
1702
|
}
|
|
1571
1703
|
function activateNodeFunction(node, lazyFn) {
|
|
1572
|
-
let prevTarget
|
|
1573
|
-
let curTarget
|
|
1704
|
+
// let prevTarget$: Observable<any>;
|
|
1705
|
+
// let curTarget$: Observable<any>;
|
|
1574
1706
|
let update;
|
|
1575
|
-
const activator = (isFunction(node) ? node : lazyFn);
|
|
1576
1707
|
let wasPromise;
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1708
|
+
let ignoreThisUpdate;
|
|
1709
|
+
const activateFn = lazyFn;
|
|
1710
|
+
const doRetry = () => { var _a; return (_a = node.state) === null || _a === void 0 ? void 0 : _a.refreshNum.set((v) => v + 1); };
|
|
1711
|
+
let activatedValue;
|
|
1712
|
+
let disposes = [];
|
|
1713
|
+
let refreshFn;
|
|
1714
|
+
function markDirty() {
|
|
1715
|
+
node.dirtyFn = refreshFn;
|
|
1716
|
+
globalState.dirtyNodes.add(node);
|
|
1717
|
+
}
|
|
1718
|
+
node.activatedObserveDispose = observe(() => {
|
|
1719
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1720
|
+
// const params = createNodeActivationParams(node);
|
|
1580
1721
|
// Run the function at this node
|
|
1581
|
-
let value =
|
|
1582
|
-
// If target is an observable,
|
|
1583
|
-
// and set up an onSet to write changes back to it
|
|
1722
|
+
let value = activateFn();
|
|
1723
|
+
// If target is an observable, make this node a link to it
|
|
1584
1724
|
if (isObservable(value)) {
|
|
1585
|
-
|
|
1586
|
-
curTarget$ = value;
|
|
1587
|
-
params.onSet(({ value: newValue, getPrevious }) => {
|
|
1588
|
-
// Don't set the target observable if the target has changed since the last run
|
|
1589
|
-
if (!prevTarget$ || curTarget$ === prevTarget$) {
|
|
1590
|
-
// Set the node value back to what it was before before setting it.
|
|
1591
|
-
// This is a workaround for linked objects because it might not notify
|
|
1592
|
-
// if setting a property of an object
|
|
1593
|
-
// TODO: Is there a way to not do this? Or at least only do it in a
|
|
1594
|
-
// small subset of cases?
|
|
1595
|
-
setNodeValue(getNode(curTarget$), getPrevious());
|
|
1596
|
-
// Set the value on the curTarget
|
|
1597
|
-
curTarget$.set(newValue);
|
|
1598
|
-
}
|
|
1599
|
-
});
|
|
1600
|
-
// Get the value from the observable because we still want the raw value
|
|
1601
|
-
// for the effect.
|
|
1602
|
-
value = value.get();
|
|
1725
|
+
value = setToObservable(node, value);
|
|
1603
1726
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1727
|
+
if (isFunction(value)) {
|
|
1728
|
+
value = value();
|
|
1729
|
+
}
|
|
1730
|
+
const activated = value === null || value === void 0 ? void 0 : value[symbolActivated];
|
|
1731
|
+
if (activated) {
|
|
1732
|
+
node.activationState = activated;
|
|
1733
|
+
value = undefined;
|
|
1606
1734
|
}
|
|
1735
|
+
ignoreThisUpdate = false;
|
|
1736
|
+
wasPromise = isPromise(value);
|
|
1607
1737
|
// Activate this node if not activated already (may be called recursively)
|
|
1608
1738
|
// TODO: Is calling recursively bad? If so can it be fixed?
|
|
1609
1739
|
if (!node.activated) {
|
|
1610
1740
|
node.activated = true;
|
|
1741
|
+
const isCached = !!((_a = node.activationState) === null || _a === void 0 ? void 0 : _a.cache);
|
|
1742
|
+
wasPromise = wasPromise || !!isCached;
|
|
1611
1743
|
const activateNodeFn = wasPromise ? globalState.activateNode : activateNodeBase;
|
|
1612
|
-
update = activateNodeFn(node,
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1744
|
+
const { update: newUpdate, value: newValue } = activateNodeFn(node, doRetry, !!wasPromise, value);
|
|
1745
|
+
update = newUpdate;
|
|
1746
|
+
value = newValue !== null && newValue !== void 0 ? newValue : activated === null || activated === void 0 ? void 0 : activated.initial;
|
|
1747
|
+
}
|
|
1748
|
+
else if (node.activationState) {
|
|
1749
|
+
if (!node.activationState.persistedRetry && !node.activationState.waitFor) {
|
|
1750
|
+
const activated = node.activationState;
|
|
1751
|
+
if ((_c = (_b = node.state) === null || _b === void 0 ? void 0 : _b.peek()) === null || _c === void 0 ? void 0 : _c.sync) {
|
|
1752
|
+
node.state.sync();
|
|
1753
|
+
ignoreThisUpdate = true;
|
|
1754
|
+
}
|
|
1755
|
+
else {
|
|
1756
|
+
value =
|
|
1757
|
+
(_e = (_d = activated.get) === null || _d === void 0 ? void 0 : _d.call(activated, {
|
|
1758
|
+
updateLastSync: noop,
|
|
1759
|
+
setMode: noop,
|
|
1760
|
+
lastSync: undefined,
|
|
1761
|
+
value: undefined,
|
|
1762
|
+
refresh: doRetry,
|
|
1763
|
+
})) !== null && _e !== void 0 ? _e : activated.initial;
|
|
1626
1764
|
}
|
|
1627
1765
|
}
|
|
1628
1766
|
else {
|
|
1629
|
-
|
|
1630
|
-
|
|
1767
|
+
ignoreThisUpdate = true;
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
// value is undefined if it's in a persisted retry
|
|
1771
|
+
wasPromise = wasPromise || isPromise(value);
|
|
1772
|
+
get(getNode((_f = node.state) === null || _f === void 0 ? void 0 : _f.refreshNum));
|
|
1773
|
+
return value;
|
|
1774
|
+
}, (e) => {
|
|
1775
|
+
if (!ignoreThisUpdate) {
|
|
1776
|
+
const { value, nodes, refresh } = e;
|
|
1777
|
+
refreshFn = refresh;
|
|
1778
|
+
if (!wasPromise || !globalState.isLoadingRemote$.peek()) {
|
|
1779
|
+
if (wasPromise) {
|
|
1780
|
+
if (node.activationState) {
|
|
1781
|
+
const { initial } = node.activationState;
|
|
1782
|
+
if (value && isPromise(value)) {
|
|
1783
|
+
// Extract the promise to make it set the value/error when it comes in
|
|
1784
|
+
extractPromise(node, value, update);
|
|
1785
|
+
}
|
|
1786
|
+
// Set this to undefined only if it's replacing the activation function,
|
|
1787
|
+
// so we don't overwrite it if it already has real data from either local
|
|
1788
|
+
// cache or a previous run
|
|
1789
|
+
if (isFunction(getNodeValue(node))) {
|
|
1790
|
+
setNodeValue(node, initial !== null && initial !== void 0 ? initial : undefined);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
else if (node.activated) {
|
|
1794
|
+
// Extract the promise to make it set the value/error when it comes in
|
|
1795
|
+
extractPromise(node, value, update);
|
|
1796
|
+
// Set this to undefined only if it's replacing the activation function,
|
|
1797
|
+
// so we don't overwrite it if it already has real data from either local
|
|
1798
|
+
// cache or a previous run
|
|
1799
|
+
if (isFunction(getNodeValue(node))) {
|
|
1800
|
+
setNodeValue(node, undefined);
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
else {
|
|
1805
|
+
activatedValue = value;
|
|
1806
|
+
if (node.state.isLoaded.peek()) {
|
|
1807
|
+
set(node, value);
|
|
1808
|
+
}
|
|
1809
|
+
else {
|
|
1810
|
+
setNodeValue(node, value);
|
|
1811
|
+
node.state.assign({
|
|
1812
|
+
isLoaded: true,
|
|
1813
|
+
error: undefined,
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1631
1817
|
}
|
|
1818
|
+
disposes.forEach((fn) => fn());
|
|
1819
|
+
disposes = [];
|
|
1820
|
+
nodes === null || nodes === void 0 ? void 0 : nodes.forEach(({ node }) => {
|
|
1821
|
+
disposes.push(onChange(node, markDirty, { immediate: true }));
|
|
1822
|
+
});
|
|
1632
1823
|
}
|
|
1633
|
-
|
|
1824
|
+
e.cancel = true;
|
|
1825
|
+
}, { fromComputed: true });
|
|
1826
|
+
return activatedValue;
|
|
1634
1827
|
}
|
|
1635
|
-
const activateNodeBase = (globalState.activateNode = function activateNodeBase(node, refresh, wasPromise) {
|
|
1636
|
-
const { onSetFn, subscriber } = node.activationState;
|
|
1637
|
-
let isSetting = false;
|
|
1828
|
+
const activateNodeBase = (globalState.activateNode = function activateNodeBase(node, refresh, wasPromise, value) {
|
|
1638
1829
|
if (!node.state) {
|
|
1639
1830
|
node.state = createObservable({
|
|
1640
1831
|
isLoaded: false,
|
|
1641
1832
|
}, false, extractPromise, getProxy);
|
|
1642
1833
|
}
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1834
|
+
let isSetting = false;
|
|
1835
|
+
let isSettingFromSubscribe = false;
|
|
1836
|
+
let _mode = 'set';
|
|
1837
|
+
if (node.activationState) {
|
|
1838
|
+
const { onSet, subscribe, get: getFn, initial } = node.activationState;
|
|
1839
|
+
value = getFn
|
|
1840
|
+
? runWithRetry(node, { attemptNum: 0 }, () => {
|
|
1841
|
+
return getFn({
|
|
1842
|
+
updateLastSync: noop,
|
|
1843
|
+
setMode: (mode) => (_mode = mode),
|
|
1844
|
+
lastSync: undefined,
|
|
1845
|
+
value: undefined,
|
|
1846
|
+
refresh,
|
|
1847
|
+
});
|
|
1848
|
+
})
|
|
1849
|
+
: undefined;
|
|
1850
|
+
// TODO Should this have lastSync and value somehow?
|
|
1851
|
+
if (value == undefined || value === null) {
|
|
1852
|
+
value = initial;
|
|
1853
|
+
}
|
|
1854
|
+
if (onSet) {
|
|
1855
|
+
let allChanges = [];
|
|
1856
|
+
let latestValue = undefined;
|
|
1857
|
+
let runNumber = 0;
|
|
1858
|
+
const runChanges = (listenerParams) => {
|
|
1859
|
+
// Don't call the set if this is the first value coming in
|
|
1860
|
+
if (allChanges.length > 0) {
|
|
1861
|
+
let changes;
|
|
1862
|
+
let value;
|
|
1863
|
+
let getPrevious;
|
|
1864
|
+
if (listenerParams) {
|
|
1865
|
+
changes = listenerParams.changes;
|
|
1866
|
+
value = listenerParams.value;
|
|
1867
|
+
getPrevious = listenerParams.getPrevious;
|
|
1868
|
+
}
|
|
1869
|
+
else {
|
|
1870
|
+
// If this is called by flushPending then get the change array
|
|
1871
|
+
// that we've been building up.
|
|
1872
|
+
changes = allChanges;
|
|
1873
|
+
value = latestValue;
|
|
1874
|
+
getPrevious = createPreviousHandler(value, changes);
|
|
1875
|
+
}
|
|
1876
|
+
allChanges = [];
|
|
1877
|
+
latestValue = undefined;
|
|
1878
|
+
globalState.pendingNodes.delete(node);
|
|
1879
|
+
runNumber++;
|
|
1880
|
+
const thisRunNumber = runNumber;
|
|
1881
|
+
const run = () => {
|
|
1882
|
+
if (thisRunNumber !== runNumber) {
|
|
1883
|
+
// set may get called multiple times before it loads so ignore any previous runs
|
|
1884
|
+
return;
|
|
1885
|
+
}
|
|
1886
|
+
const retryAttempts = { attemptNum: 0 };
|
|
1887
|
+
return runWithRetry(node, retryAttempts, (eventRetry) => {
|
|
1888
|
+
const cancelRetry = () => {
|
|
1889
|
+
eventRetry.cancel = true;
|
|
1890
|
+
};
|
|
1891
|
+
return new Promise((resolve, reject) => {
|
|
1892
|
+
isSetting = true;
|
|
1893
|
+
let isProm = false;
|
|
1894
|
+
batch(() => {
|
|
1895
|
+
try {
|
|
1896
|
+
const val = onSet({
|
|
1897
|
+
value,
|
|
1898
|
+
changes,
|
|
1899
|
+
getPrevious,
|
|
1900
|
+
node,
|
|
1901
|
+
update,
|
|
1902
|
+
refresh,
|
|
1903
|
+
retryNum: retryAttempts.attemptNum,
|
|
1904
|
+
cancelRetry,
|
|
1905
|
+
fromSubscribe: isSettingFromSubscribe,
|
|
1906
|
+
});
|
|
1907
|
+
isProm = isPromise(val);
|
|
1908
|
+
if (isProm) {
|
|
1909
|
+
val.then(resolve).catch(reject);
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
catch (e) {
|
|
1913
|
+
reject(e);
|
|
1914
|
+
}
|
|
1915
|
+
}, () => {
|
|
1916
|
+
if (!isProm) {
|
|
1917
|
+
isSetting = false;
|
|
1918
|
+
resolve();
|
|
1919
|
+
}
|
|
1920
|
+
});
|
|
1921
|
+
});
|
|
1922
|
+
});
|
|
1923
|
+
};
|
|
1924
|
+
whenReady(node.state.isLoaded, run);
|
|
1653
1925
|
}
|
|
1654
|
-
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1926
|
+
};
|
|
1927
|
+
const onChangeImmediate = ({ value, changes }) => {
|
|
1928
|
+
if (!isSetting || isSettingFromSubscribe) {
|
|
1929
|
+
if (changes.length > 1 || !isFunction(changes[0].prevAtPath)) {
|
|
1930
|
+
latestValue = value;
|
|
1931
|
+
if (allChanges.length > 0) {
|
|
1932
|
+
changes = changes.filter((change) => !isArraySubset(allChanges[0].path, change.path));
|
|
1933
|
+
}
|
|
1934
|
+
allChanges.push(...changes);
|
|
1935
|
+
globalState.pendingNodes.set(node, runChanges);
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
};
|
|
1939
|
+
// Create an immediate listener to mark this node as pending. Then actually run
|
|
1940
|
+
// the changes at the end of the batch so everything is properly batched.
|
|
1941
|
+
// However, this can be short circuited if the user calls get() or peek()
|
|
1942
|
+
// in which case the set needs to run immediately so that the values are up to date.
|
|
1943
|
+
onChange(node, onChangeImmediate, { immediate: true });
|
|
1944
|
+
onChange(node, runChanges);
|
|
1945
|
+
}
|
|
1946
|
+
if (process.env.NODE_ENV === 'development' && node.activationState.cache) {
|
|
1947
|
+
// TODO Better message
|
|
1948
|
+
console.log('[legend-state] Using cache without setting up persistence first');
|
|
1949
|
+
}
|
|
1950
|
+
if (process.env.NODE_ENV === 'development' && node.activationState.retry) {
|
|
1951
|
+
// TODO Better message
|
|
1952
|
+
console.log('[legend-state] Using retry without setting up persistence first');
|
|
1953
|
+
}
|
|
1954
|
+
if (subscribe) {
|
|
1955
|
+
const updateFromSubscribe = (params) => {
|
|
1956
|
+
whenReady(node.state.isLoaded, () => {
|
|
1957
|
+
isSettingFromSubscribe = true;
|
|
1958
|
+
update(params);
|
|
1959
|
+
isSettingFromSubscribe = false;
|
|
1960
|
+
});
|
|
1961
|
+
};
|
|
1962
|
+
subscribe({ node, update: updateFromSubscribe, refresh });
|
|
1963
|
+
}
|
|
1665
1964
|
}
|
|
1666
|
-
const update = ({ value }) => {
|
|
1965
|
+
const update = ({ value, mode }) => {
|
|
1667
1966
|
// TODO: This isSetting might not be necessary? Tests still work if removing it.
|
|
1668
1967
|
// Write tests that would break it if removed? I'd guess a combination of subscribe and
|
|
1669
1968
|
if (!isSetting) {
|
|
1670
|
-
|
|
1969
|
+
isSetting = true;
|
|
1970
|
+
if (_mode === 'assign' || mode === 'assign') {
|
|
1971
|
+
assign(node, value);
|
|
1972
|
+
}
|
|
1973
|
+
else if (_mode === 'merge' || mode === 'merge') {
|
|
1974
|
+
mergeIntoObservable(getProxy(node), value);
|
|
1975
|
+
}
|
|
1976
|
+
else {
|
|
1977
|
+
set(node, value);
|
|
1978
|
+
}
|
|
1979
|
+
isSetting = false;
|
|
1671
1980
|
}
|
|
1672
1981
|
};
|
|
1673
|
-
|
|
1674
|
-
subscriber({ update, refresh });
|
|
1675
|
-
}
|
|
1676
|
-
return { update };
|
|
1982
|
+
return { update, value };
|
|
1677
1983
|
});
|
|
1984
|
+
function setToObservable(node, value) {
|
|
1985
|
+
var _a;
|
|
1986
|
+
// If the computed is a proxy to another observable
|
|
1987
|
+
// link it to the target observable
|
|
1988
|
+
const linkedNode = getNode(value);
|
|
1989
|
+
if (linkedNode !== node && (linkedNode === null || linkedNode === void 0 ? void 0 : linkedNode.linkedToNode) !== node) {
|
|
1990
|
+
const prevNode = node.linkedToNode;
|
|
1991
|
+
node.linkedToNode = linkedNode;
|
|
1992
|
+
if (!linkedNode.linkedFromNodes) {
|
|
1993
|
+
linkedNode.linkedFromNodes = new Set();
|
|
1994
|
+
}
|
|
1995
|
+
linkedNode.linkedFromNodes.add(node);
|
|
1996
|
+
peek(linkedNode);
|
|
1997
|
+
(_a = node.linkedToNodeDispose) === null || _a === void 0 ? void 0 : _a.call(node);
|
|
1998
|
+
node.linkedToNodeDispose = onChange(linkedNode, () => {
|
|
1999
|
+
value = peek(linkedNode);
|
|
2000
|
+
set(node, value);
|
|
2001
|
+
}, { initial: true });
|
|
2002
|
+
// If the target observable is different then notify for the change
|
|
2003
|
+
if (prevNode) {
|
|
2004
|
+
const value = getNodeValue(linkedNode);
|
|
2005
|
+
const prevValue = getNodeValue(prevNode);
|
|
2006
|
+
notify(node, value, prevValue, 0);
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
return value;
|
|
2010
|
+
}
|
|
1678
2011
|
|
|
1679
2012
|
const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
|
|
1680
2013
|
function ObservablePrimitiveClass(node) {
|
|
@@ -1691,8 +2024,14 @@ function proto(key, fn) {
|
|
|
1691
2024
|
return fn.call(this, this._node, ...args);
|
|
1692
2025
|
};
|
|
1693
2026
|
}
|
|
1694
|
-
proto('peek',
|
|
1695
|
-
|
|
2027
|
+
proto('peek', (node) => {
|
|
2028
|
+
flushPending();
|
|
2029
|
+
return peek(node);
|
|
2030
|
+
});
|
|
2031
|
+
proto('get', (node, options) => {
|
|
2032
|
+
flushPending();
|
|
2033
|
+
return get(node, options);
|
|
2034
|
+
});
|
|
1696
2035
|
proto('set', set);
|
|
1697
2036
|
proto('onChange', onChange);
|
|
1698
2037
|
// Getters
|
|
@@ -1704,7 +2043,7 @@ Object.defineProperty(ObservablePrimitiveClass.prototype, symbolGetNode, {
|
|
|
1704
2043
|
});
|
|
1705
2044
|
ObservablePrimitiveClass.prototype.toggle = function () {
|
|
1706
2045
|
const value = this.peek();
|
|
1707
|
-
if (value === undefined || isBoolean(value)) {
|
|
2046
|
+
if (value === undefined || value === null || isBoolean(value)) {
|
|
1708
2047
|
this.set(!value);
|
|
1709
2048
|
}
|
|
1710
2049
|
else if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
@@ -1723,89 +2062,25 @@ function observable(value) {
|
|
|
1723
2062
|
function observablePrimitive(value) {
|
|
1724
2063
|
return createObservable(value, true, extractPromise, getProxy, ObservablePrimitiveClass);
|
|
1725
2064
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
function computed(compute, set$1) {
|
|
1729
|
-
// Create an observable for this computed variable
|
|
1730
|
-
const obs = observable();
|
|
1731
|
-
lockObservable(obs, true);
|
|
2065
|
+
function syncState(obs) {
|
|
1732
2066
|
const node = getNode(obs);
|
|
1733
|
-
node.
|
|
1734
|
-
|
|
1735
|
-
const setInner = function (val) {
|
|
1736
|
-
const prevNode = node.linkedToNode;
|
|
1737
|
-
// If it was previously linked to a node remove self
|
|
1738
|
-
// from its linkedFromNodes
|
|
1739
|
-
if (prevNode) {
|
|
1740
|
-
prevNode.linkedFromNodes.delete(node);
|
|
1741
|
-
node.linkedToNode = undefined;
|
|
1742
|
-
}
|
|
1743
|
-
const { parentOther } = node;
|
|
1744
|
-
if (isObservable(val)) {
|
|
1745
|
-
// If the computed is a proxy to another observable
|
|
1746
|
-
// link it to the target observable
|
|
1747
|
-
const linkedNode = getNode(val);
|
|
1748
|
-
node.linkedToNode = linkedNode;
|
|
1749
|
-
if (!linkedNode.linkedFromNodes) {
|
|
1750
|
-
linkedNode.linkedFromNodes = new Set();
|
|
1751
|
-
}
|
|
1752
|
-
linkedNode.linkedFromNodes.add(node);
|
|
1753
|
-
if (node.parentOther) {
|
|
1754
|
-
onChange(linkedNode, ({ value }) => {
|
|
1755
|
-
setNodeValue(node.parentOther, value);
|
|
1756
|
-
}, { initial: true });
|
|
1757
|
-
}
|
|
1758
|
-
// If the target observable is different then notify for the change
|
|
1759
|
-
if (prevNode) {
|
|
1760
|
-
const value = getNodeValue(linkedNode);
|
|
1761
|
-
const prevValue = getNodeValue(prevNode);
|
|
1762
|
-
notify(node, value, prevValue, 0);
|
|
1763
|
-
}
|
|
1764
|
-
}
|
|
1765
|
-
else if (val !== obs.peek()) {
|
|
1766
|
-
// Unlock computed node before setting the value
|
|
1767
|
-
lockObservable(obs, false);
|
|
1768
|
-
const setter = isSetAfterActivated ? set : setNodeValue;
|
|
1769
|
-
// Update the computed value
|
|
1770
|
-
setter(node, val);
|
|
1771
|
-
// If the computed is a child of an observable set the value on it
|
|
1772
|
-
if (parentOther) {
|
|
1773
|
-
let didUnlock = false;
|
|
1774
|
-
if (parentOther.root.locked) {
|
|
1775
|
-
parentOther.root.locked = false;
|
|
1776
|
-
didUnlock = true;
|
|
1777
|
-
}
|
|
1778
|
-
setter(parentOther, val);
|
|
1779
|
-
if (didUnlock) {
|
|
1780
|
-
parentOther.root.locked = true;
|
|
1781
|
-
}
|
|
1782
|
-
}
|
|
1783
|
-
// Re-lock the computed node
|
|
1784
|
-
lockObservable(obs, true);
|
|
1785
|
-
}
|
|
1786
|
-
else if (parentOther) {
|
|
1787
|
-
setNodeValue(parentOther, val);
|
|
1788
|
-
}
|
|
1789
|
-
isSetAfterActivated = true;
|
|
1790
|
-
};
|
|
1791
|
-
// Lazily activate the observable when get is called
|
|
1792
|
-
node.root.activate = () => {
|
|
1793
|
-
node.root.activate = undefined;
|
|
1794
|
-
observe(compute, ({ value }) => {
|
|
1795
|
-
if (isPromise(value)) {
|
|
1796
|
-
value.then((v) => setInner(v));
|
|
1797
|
-
}
|
|
1798
|
-
else {
|
|
1799
|
-
setInner(value);
|
|
1800
|
-
}
|
|
1801
|
-
}, { immediate: true, fromComputed: true });
|
|
1802
|
-
};
|
|
1803
|
-
if (set$1) {
|
|
1804
|
-
node.root.set = (value) => {
|
|
1805
|
-
batch(() => set$1(value));
|
|
1806
|
-
};
|
|
2067
|
+
if (!node.state) {
|
|
2068
|
+
peek(node);
|
|
1807
2069
|
}
|
|
1808
|
-
|
|
2070
|
+
if (!node.state) {
|
|
2071
|
+
node.state = observable({});
|
|
2072
|
+
}
|
|
2073
|
+
return node.state;
|
|
2074
|
+
}
|
|
2075
|
+
globalState.isLoadingRemote$ = observable(false);
|
|
2076
|
+
|
|
2077
|
+
function computed(compute, set) {
|
|
2078
|
+
return observable(set
|
|
2079
|
+
? activated({
|
|
2080
|
+
get: compute,
|
|
2081
|
+
onSet: ({ value }) => set(value),
|
|
2082
|
+
})
|
|
2083
|
+
: compute);
|
|
1809
2084
|
}
|
|
1810
2085
|
|
|
1811
2086
|
function configureLegendState({ observableFunctions, observableProperties: observableProperties$1, }) {
|
|
@@ -1859,86 +2134,14 @@ function event() {
|
|
|
1859
2134
|
}
|
|
1860
2135
|
|
|
1861
2136
|
function proxy(get, set) {
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
if (!target) {
|
|
1871
|
-
// Note: Coercing typescript to allow undefined for set in computed because we don't want the public interface to allow undefined
|
|
1872
|
-
target = computed(() => get(key), (set ? (value) => set(key, value) : undefined));
|
|
1873
|
-
mapTargets.set(key, target);
|
|
1874
|
-
extractFunction(node, key, target, getNode(target));
|
|
1875
|
-
if (node.parentOther) {
|
|
1876
|
-
onChange(getNode(target), ({ value, getPrevious }) => {
|
|
1877
|
-
const previous = getPrevious();
|
|
1878
|
-
// Set the raw value on the proxy's parent
|
|
1879
|
-
setNodeValue(node.parentOther, node.root._);
|
|
1880
|
-
// Notify the proxy
|
|
1881
|
-
notify(getChildNode(node, key), value, previous, 0);
|
|
1882
|
-
});
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
return target;
|
|
1886
|
-
};
|
|
1887
|
-
return obs;
|
|
1888
|
-
}
|
|
1889
|
-
|
|
1890
|
-
function _when(predicate, effect, checkReady) {
|
|
1891
|
-
// If predicate is a regular Promise skip all the observable stuff
|
|
1892
|
-
if (isPromise(predicate)) {
|
|
1893
|
-
return effect ? predicate.then(effect) : predicate;
|
|
1894
|
-
}
|
|
1895
|
-
let value;
|
|
1896
|
-
// Create a wrapping fn that calls the effect if predicate returns true
|
|
1897
|
-
function run(e) {
|
|
1898
|
-
const ret = computeSelector(predicate);
|
|
1899
|
-
if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
1900
|
-
value = ret;
|
|
1901
|
-
// Set cancel so that observe does not track anymore
|
|
1902
|
-
e.cancel = true;
|
|
1903
|
-
}
|
|
1904
|
-
return value;
|
|
1905
|
-
}
|
|
1906
|
-
function doEffect() {
|
|
1907
|
-
// If value is truthy then run the effect
|
|
1908
|
-
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
1909
|
-
}
|
|
1910
|
-
// Run in an observe
|
|
1911
|
-
observe(run, doEffect);
|
|
1912
|
-
// If first run resulted in a truthy value just return it.
|
|
1913
|
-
// It will have set e.cancel so no need to dispose
|
|
1914
|
-
if (isPromise(value)) {
|
|
1915
|
-
return effect ? value.then(effect) : value;
|
|
1916
|
-
}
|
|
1917
|
-
else if (value !== undefined) {
|
|
1918
|
-
return Promise.resolve(value);
|
|
1919
|
-
}
|
|
1920
|
-
else {
|
|
1921
|
-
// Wrap it in a promise
|
|
1922
|
-
const promise = new Promise((resolve) => {
|
|
1923
|
-
if (effect) {
|
|
1924
|
-
const originalEffect = effect;
|
|
1925
|
-
effect = (value) => {
|
|
1926
|
-
const effectValue = originalEffect(value);
|
|
1927
|
-
resolve(effectValue);
|
|
1928
|
-
};
|
|
1929
|
-
}
|
|
1930
|
-
else {
|
|
1931
|
-
effect = resolve;
|
|
1932
|
-
}
|
|
1933
|
-
});
|
|
1934
|
-
return promise;
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
function when(predicate, effect) {
|
|
1938
|
-
return _when(predicate, effect, false);
|
|
1939
|
-
}
|
|
1940
|
-
function whenReady(predicate, effect) {
|
|
1941
|
-
return _when(predicate, effect, true);
|
|
2137
|
+
return observable(activated({
|
|
2138
|
+
lookup: (key) => set
|
|
2139
|
+
? activated({
|
|
2140
|
+
get: () => get(key),
|
|
2141
|
+
onSet: ({ value }) => set(key, value),
|
|
2142
|
+
})
|
|
2143
|
+
: get(key),
|
|
2144
|
+
}));
|
|
1942
2145
|
}
|
|
1943
2146
|
|
|
1944
2147
|
const internal = {
|
|
@@ -1951,11 +2154,13 @@ const internal = {
|
|
|
1951
2154
|
observableFns,
|
|
1952
2155
|
optimized,
|
|
1953
2156
|
peek,
|
|
2157
|
+
runWithRetry,
|
|
1954
2158
|
set,
|
|
1955
2159
|
setAtPath,
|
|
1956
2160
|
setNodeValue,
|
|
2161
|
+
symbolActivated,
|
|
1957
2162
|
symbolDelete,
|
|
1958
2163
|
};
|
|
1959
2164
|
|
|
1960
|
-
export { ObservablePrimitiveClass, batch, beginBatch, beginTracking,
|
|
2165
|
+
export { ObservablePrimitiveClass, activated, batch, beginBatch, beginTracking, computeSelector, computed, configureLegendState, constructObjectWithPath, deconstructObjectWithPath, endBatch, endTracking, event, extraPrimitiveActivators, extraPrimitiveProps, findIDKey, getNode, getNodeValue, getObservableIndex, hasOwnProperty, internal, isArray, isBoolean, isDate, isEmpty, isFunction, isNullOrUndefined, isObject, isObservable, isObservableValueReady, isPrimitive, isPromise, isString, isSymbol, mergeIntoObservable, observable, observablePrimitive, observe, opaqueObject, optimized, proxy, setAtPath, setInObservableAtPath, setSilently, setupTracking, symbolDelete, syncState, trackSelector, tracking, updateTracking, when, whenReady };
|
|
1961
2166
|
//# sourceMappingURL=index.mjs.map
|