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