@legendapp/state 1.11.1 → 2.0.0-beta.0
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/CHANGELOG.md +0 -4
- package/index.d.ts +2 -3
- package/index.js +220 -226
- package/index.js.map +1 -1
- package/index.mjs +220 -224
- package/index.mjs.map +1 -1
- package/package.json +21 -24
- package/persist-plugins/async-storage.d.ts +14 -0
- package/persist-plugins/async-storage.js +100 -0
- package/persist-plugins/async-storage.js.map +1 -0
- package/persist-plugins/async-storage.mjs +98 -0
- package/persist-plugins/async-storage.mjs.map +1 -0
- package/persist-plugins/fetch.d.ts +10 -0
- package/persist-plugins/fetch.js +22 -0
- package/persist-plugins/fetch.js.map +1 -0
- package/persist-plugins/fetch.mjs +20 -0
- package/persist-plugins/fetch.mjs.map +1 -0
- package/persist-plugins/firebase.d.ts +51 -0
- package/persist-plugins/firebase.js +692 -0
- package/persist-plugins/firebase.js.map +1 -0
- package/persist-plugins/firebase.mjs +690 -0
- package/persist-plugins/firebase.mjs.map +1 -0
- package/persist-plugins/indexeddb.d.ts +2 -3
- package/persist-plugins/indexeddb.js +1 -16
- package/persist-plugins/indexeddb.js.map +1 -1
- package/persist-plugins/indexeddb.mjs +1 -16
- package/persist-plugins/indexeddb.mjs.map +1 -1
- package/persist-plugins/local-storage.d.ts +1 -2
- package/persist-plugins/local-storage.js +1 -5
- package/persist-plugins/local-storage.js.map +1 -1
- package/persist-plugins/local-storage.mjs +1 -5
- package/persist-plugins/local-storage.mjs.map +1 -1
- package/persist-plugins/mmkv.d.ts +4 -4
- package/persist-plugins/mmkv.js +6 -4
- package/persist-plugins/mmkv.js.map +1 -1
- package/persist-plugins/mmkv.mjs +6 -4
- package/persist-plugins/mmkv.mjs.map +1 -1
- package/persist-plugins/query.d.ts +20 -0
- package/persist-plugins/query.js +89 -0
- package/persist-plugins/query.js.map +1 -0
- package/persist-plugins/query.mjs +87 -0
- package/persist-plugins/query.mjs.map +1 -0
- package/persist.js +170 -143
- package/persist.js.map +1 -1
- package/persist.mjs +171 -144
- package/persist.mjs.map +1 -1
- package/react-hooks/usePersistedObservable.d.ts +2 -2
- package/react-hooks/usePersistedObservable.js +1 -6
- package/react-hooks/usePersistedObservable.js.map +1 -1
- package/react-hooks/usePersistedObservable.mjs +1 -6
- package/react-hooks/usePersistedObservable.mjs.map +1 -1
- package/react.d.ts +1 -6
- package/react.js +47 -99
- package/react.js.map +1 -1
- package/react.mjs +47 -100
- package/react.mjs.map +1 -1
- package/src/ObservableObject.d.ts +4 -0
- package/src/batching.d.ts +0 -7
- package/src/globals.d.ts +1 -5
- package/src/is.d.ts +1 -0
- package/src/observable.d.ts +5 -3
- package/src/observableInterfaces.d.ts +93 -69
- package/src/observe.d.ts +1 -1
- package/src/persist/observablePersistRemoteFunctionsAdapter.d.ts +2 -0
- package/src/persist/persistObservable.d.ts +10 -13
- package/src/persist-plugins/async-storage.d.ts +14 -0
- package/src/persist-plugins/fetch.d.ts +10 -0
- package/src/persist-plugins/firebase.d.ts +51 -0
- package/src/persist-plugins/indexeddb.d.ts +2 -3
- package/src/persist-plugins/local-storage.d.ts +1 -2
- package/src/persist-plugins/mmkv.d.ts +4 -4
- package/src/persist-plugins/query.d.ts +20 -0
- package/src/react/For.d.ts +1 -1
- package/src/react/react-globals.d.ts +3 -0
- package/src/react/reactInterfaces.d.ts +1 -1
- package/src/react/reactive-observer.d.ts +1 -5
- package/src/react/useObservableState.d.ts +2 -0
- package/src/react/useSelector.d.ts +1 -1
- package/src/react/useWhen.d.ts +3 -0
- package/src/react-hooks/usePersistedObservable.d.ts +2 -2
- package/src/trackSelector.d.ts +1 -1
- package/src/tracking.d.ts +2 -3
- package/config/disableDeprecationWarnings.d.ts +0 -1
- package/config/disableDeprecationWarnings.js +0 -10
- package/config/disableDeprecationWarnings.js.map +0 -1
- package/config/disableDeprecationWarnings.mjs +0 -8
- package/config/disableDeprecationWarnings.mjs.map +0 -1
- package/config/enableReactDirectRender.d.ts +0 -7
- package/config/enableReactDirectRender.js +0 -77
- package/config/enableReactDirectRender.js.map +0 -1
- package/config/enableReactDirectRender.mjs +0 -74
- package/config/enableReactDirectRender.mjs.map +0 -1
- package/react-components.d.ts +0 -2
- package/react-components.js +0 -44
- package/react-components.js.map +0 -1
- package/react-components.mjs +0 -31
- package/react-components.mjs.map +0 -1
- package/react-native-components.d.ts +0 -2
- package/react-native-components.js +0 -67
- package/react-native-components.js.map +0 -1
- package/react-native-components.mjs +0 -54
- package/react-native-components.mjs.map +0 -1
- package/src/config/disableDeprecationWarnings.d.ts +0 -1
- package/src/config/enableReactDirectRender.d.ts +0 -7
- package/src/react/enableLegendStateReact.d.ts +0 -1
- package/src/react-components/react-components.d.ts +0 -7
- package/src/react-native-components/rn-components.d.ts +0 -21
- package/types.d.ts +0 -13
package/index.js
CHANGED
|
@@ -54,25 +54,20 @@ let trackCount = 0;
|
|
|
54
54
|
const trackingQueue = [];
|
|
55
55
|
const tracking = {
|
|
56
56
|
current: undefined,
|
|
57
|
-
inRender: false,
|
|
58
57
|
};
|
|
59
|
-
function beginTracking(
|
|
58
|
+
function beginTracking() {
|
|
60
59
|
// Keep a copy of the previous tracking context so it can be restored
|
|
61
60
|
// when this context is complete
|
|
62
61
|
trackingQueue.push(tracking.current);
|
|
63
62
|
trackCount++;
|
|
64
|
-
tracking.inRender = inRender;
|
|
65
63
|
tracking.current = {};
|
|
66
64
|
}
|
|
67
|
-
function endTracking(
|
|
65
|
+
function endTracking() {
|
|
68
66
|
// Restore the previous tracking context
|
|
69
67
|
trackCount--;
|
|
70
68
|
if (trackCount < 0) {
|
|
71
69
|
trackCount = 0;
|
|
72
70
|
}
|
|
73
|
-
if (fromRender) {
|
|
74
|
-
tracking.inRender = false;
|
|
75
|
-
}
|
|
76
71
|
tracking.current = trackingQueue.pop();
|
|
77
72
|
}
|
|
78
73
|
function updateTracking(node, track) {
|
|
@@ -99,22 +94,18 @@ const symbolGetNode = Symbol('getNode');
|
|
|
99
94
|
const symbolDelete = /* @__PURE__ */ Symbol('delete');
|
|
100
95
|
const symbolOpaque = Symbol('opaque');
|
|
101
96
|
const optimized = Symbol('optimized');
|
|
102
|
-
const extraPrimitiveActivators = new Map();
|
|
103
|
-
const extraPrimitiveProps = new Map();
|
|
104
|
-
const __devExtractFunctionsAndComputedsNodes = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' ? new Set() : undefined;
|
|
105
97
|
const globalState = {
|
|
106
98
|
isLoadingLocal: false,
|
|
107
99
|
isLoadingRemote: false,
|
|
108
100
|
isMerging: false,
|
|
109
|
-
noDepWarn: false,
|
|
110
101
|
};
|
|
111
102
|
function checkActivate(node) {
|
|
112
103
|
var _a;
|
|
113
104
|
const root = node.root;
|
|
114
105
|
(_a = root.activate) === null || _a === void 0 ? void 0 : _a.call(root);
|
|
115
|
-
if (root.
|
|
116
|
-
root.
|
|
117
|
-
delete root.
|
|
106
|
+
if (root.toActivate) {
|
|
107
|
+
root.toActivate.forEach(checkActivate);
|
|
108
|
+
delete root.toActivate;
|
|
118
109
|
}
|
|
119
110
|
}
|
|
120
111
|
function getNode(obs) {
|
|
@@ -165,7 +156,7 @@ function setNodeValue(node, newValue) {
|
|
|
165
156
|
if (parentNode.root.locked && parentNode.root.set) {
|
|
166
157
|
parentNode.root.set(parentNode.root._);
|
|
167
158
|
}
|
|
168
|
-
return { prevValue, newValue };
|
|
159
|
+
return { prevValue, newValue, parentValue };
|
|
169
160
|
}
|
|
170
161
|
const arrNodeKeys = [];
|
|
171
162
|
function getNodeValue(node) {
|
|
@@ -239,37 +230,11 @@ function extractFunction(node, key, fnOrComputed, computedChildNode) {
|
|
|
239
230
|
}
|
|
240
231
|
node.functions.set(key, fnOrComputed);
|
|
241
232
|
if (computedChildNode) {
|
|
242
|
-
computedChildNode.
|
|
243
|
-
if (!node.root.
|
|
244
|
-
node.root.
|
|
245
|
-
}
|
|
246
|
-
node.root.computedChildrenNeedingActivation.push(computedChildNode);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
function extractFunctionsAndComputeds(obj, node) {
|
|
250
|
-
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') &&
|
|
251
|
-
typeof __devExtractFunctionsAndComputedsNodes !== 'undefined') {
|
|
252
|
-
if (__devExtractFunctionsAndComputedsNodes.has(obj)) {
|
|
253
|
-
console.error('[legend-state] Circular reference detected in object. You may want to use opaqueObject to stop traversing child nodes.', obj);
|
|
254
|
-
return false;
|
|
255
|
-
}
|
|
256
|
-
__devExtractFunctionsAndComputedsNodes.add(obj);
|
|
257
|
-
}
|
|
258
|
-
for (const k in obj) {
|
|
259
|
-
const v = obj[k];
|
|
260
|
-
if (typeof v === 'function') {
|
|
261
|
-
extractFunction(node, k, v);
|
|
262
|
-
}
|
|
263
|
-
else if (typeof v == 'object' && v !== null && v !== undefined) {
|
|
264
|
-
const childNode = getNode(v);
|
|
265
|
-
if (childNode === null || childNode === void 0 ? void 0 : childNode.isComputed) {
|
|
266
|
-
extractFunction(node, k, v, childNode);
|
|
267
|
-
delete obj[k];
|
|
268
|
-
}
|
|
269
|
-
else if (!v[symbolOpaque]) {
|
|
270
|
-
extractFunctionsAndComputeds(obj[k], getChildNode(node, k));
|
|
271
|
-
}
|
|
233
|
+
computedChildNode.parentOther = getChildNode(node, key);
|
|
234
|
+
if (!node.root.toActivate) {
|
|
235
|
+
node.root.toActivate = [];
|
|
272
236
|
}
|
|
237
|
+
node.root.toActivate.push(computedChildNode);
|
|
273
238
|
}
|
|
274
239
|
}
|
|
275
240
|
|
|
@@ -278,6 +243,7 @@ let numInBatch = 0;
|
|
|
278
243
|
let isRunningBatch = false;
|
|
279
244
|
let didDelayEndBatch = false;
|
|
280
245
|
let _afterBatch = [];
|
|
246
|
+
let _queuedBatches = [];
|
|
281
247
|
let _batchMap = new Map();
|
|
282
248
|
function onActionTimeout() {
|
|
283
249
|
if (_batchMap.size > 0) {
|
|
@@ -399,11 +365,7 @@ function batchNotifyChanges(changesInBatch, immediate) {
|
|
|
399
365
|
const listenerFn = arr[i];
|
|
400
366
|
const { track, noArgs, listener } = listenerFn;
|
|
401
367
|
if (!listenersNotified.has(listener)) {
|
|
402
|
-
const ok = track === true
|
|
403
|
-
? level <= 0
|
|
404
|
-
: track === optimized
|
|
405
|
-
? whenOptimizedOnlyIf && level <= 0
|
|
406
|
-
: true;
|
|
368
|
+
const ok = track === true ? level <= 0 : track === optimized ? whenOptimizedOnlyIf && level <= 0 : true;
|
|
407
369
|
// Notify if listener is not shallow or if this is the first level
|
|
408
370
|
if (ok) {
|
|
409
371
|
// Create listenerParams if not already created
|
|
@@ -425,6 +387,8 @@ function batchNotifyChanges(changesInBatch, immediate) {
|
|
|
425
387
|
});
|
|
426
388
|
}
|
|
427
389
|
function runBatch() {
|
|
390
|
+
// Save batch locally and reset _batchMap first because a new batch could begin while looping over callbacks.
|
|
391
|
+
// This can happen with observableComputed for example.
|
|
428
392
|
const map = _batchMap;
|
|
429
393
|
_batchMap = new Map();
|
|
430
394
|
const changesInBatch = new Map();
|
|
@@ -439,7 +403,15 @@ function runBatch() {
|
|
|
439
403
|
}
|
|
440
404
|
function batch(fn, onComplete) {
|
|
441
405
|
if (onComplete) {
|
|
442
|
-
|
|
406
|
+
// If there's an onComplete we need a batch that's fully isolated from others to ensure it wraps only the given changes.
|
|
407
|
+
// So if already batching, push this batch onto a queue and run it after the current batch is fully done.
|
|
408
|
+
if (isRunningBatch) {
|
|
409
|
+
_queuedBatches.push([fn, onComplete]);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
_afterBatch.push(onComplete);
|
|
414
|
+
}
|
|
443
415
|
}
|
|
444
416
|
beginBatch();
|
|
445
417
|
try {
|
|
@@ -489,29 +461,21 @@ function endBatch(force) {
|
|
|
489
461
|
didDelayEndBatch = false;
|
|
490
462
|
endBatch(true);
|
|
491
463
|
}
|
|
464
|
+
const queued = _queuedBatches;
|
|
465
|
+
if (queued.length) {
|
|
466
|
+
_queuedBatches = [];
|
|
467
|
+
for (let i = 0; i < queued.length; i++) {
|
|
468
|
+
const [fn, onComplete] = queued[i];
|
|
469
|
+
batch(fn, onComplete);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
492
472
|
}
|
|
493
473
|
}
|
|
494
474
|
}
|
|
495
|
-
function afterBatch(fn) {
|
|
496
|
-
if (numInBatch > 0) {
|
|
497
|
-
_afterBatch.push(fn);
|
|
498
|
-
}
|
|
499
|
-
else {
|
|
500
|
-
fn();
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
475
|
|
|
504
476
|
function onChange(node, callback, options = {}) {
|
|
505
477
|
const { initial, immediate, noArgs } = options;
|
|
506
|
-
|
|
507
|
-
// Temporary migration of string to symbol
|
|
508
|
-
// TODOV2 remove this
|
|
509
|
-
if (trackingType === 'optimize') {
|
|
510
|
-
if (process.env.NODE_ENV === 'development' && !globalState.noDepWarn) {
|
|
511
|
-
console.warn('[legend-state]: "optimize" prop is deprecated and will be removed in version 2.0. Please import { optimize } from "@legendapp/state" and use that instead.');
|
|
512
|
-
}
|
|
513
|
-
trackingType = optimized;
|
|
514
|
-
}
|
|
478
|
+
const { trackingType } = options;
|
|
515
479
|
let listeners = immediate ? node.listenersImmediate : node.listeners;
|
|
516
480
|
if (!listeners) {
|
|
517
481
|
listeners = new Set();
|
|
@@ -529,11 +493,6 @@ function onChange(node, callback, options = {}) {
|
|
|
529
493
|
noArgs,
|
|
530
494
|
};
|
|
531
495
|
listeners.add(listener);
|
|
532
|
-
let parent = node.parent;
|
|
533
|
-
while (parent && !parent.descendantHasListener) {
|
|
534
|
-
parent.descendantHasListener = true;
|
|
535
|
-
parent = parent.parent;
|
|
536
|
-
}
|
|
537
496
|
if (initial) {
|
|
538
497
|
const value = getNodeValue(node);
|
|
539
498
|
callback({
|
|
@@ -606,7 +565,11 @@ function collectionSetter(node, target, prop, ...args) {
|
|
|
606
565
|
// Return the original value
|
|
607
566
|
return ret;
|
|
608
567
|
}
|
|
568
|
+
function getKeys(obj, isArr, isMap) {
|
|
569
|
+
return isArr ? undefined : obj ? (isMap ? Array.from(obj.keys()) : Object.keys(obj)) : [];
|
|
570
|
+
}
|
|
609
571
|
function updateNodes(parent, obj, prevValue) {
|
|
572
|
+
var _a, _b;
|
|
610
573
|
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') &&
|
|
611
574
|
typeof __devUpdateNodes !== 'undefined' &&
|
|
612
575
|
isObject(obj)) {
|
|
@@ -635,8 +598,10 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
635
598
|
let prevChildrenById;
|
|
636
599
|
let moved;
|
|
637
600
|
const isMap = obj instanceof Map;
|
|
638
|
-
const keys = obj
|
|
639
|
-
const keysPrev = prevValue
|
|
601
|
+
const keys = getKeys(obj, isArr, isMap);
|
|
602
|
+
const keysPrev = getKeys(prevValue, isArr, isMap);
|
|
603
|
+
const length = ((_a = (keys || obj)) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
604
|
+
const lengthPrev = ((_b = (keysPrev || prevValue)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
640
605
|
let idField;
|
|
641
606
|
let isIdFieldFunction;
|
|
642
607
|
let hasADiff = false;
|
|
@@ -699,79 +664,77 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
699
664
|
}
|
|
700
665
|
}
|
|
701
666
|
if (obj && !isPrimitive(obj)) {
|
|
702
|
-
|
|
703
|
-
hasADiff = hasADiff || (keys === null || keys === void 0 ? void 0 : keys.length) !== (keysPrev === null || keysPrev === void 0 ? void 0 : keysPrev.length);
|
|
667
|
+
hasADiff = hasADiff || length !== lengthPrev;
|
|
704
668
|
const isArrDiff = hasADiff;
|
|
705
669
|
let didMove = false;
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
729
|
-
else if (prevChild !== undefined && prevChild.key !== key) {
|
|
730
|
-
const valuePrevChild = prevValue[prevChild.key];
|
|
731
|
-
// If array length changed then move the original node to the current position.
|
|
732
|
-
// That should be faster than notifying every single element that
|
|
733
|
-
// it's in a new position.
|
|
734
|
-
if (isArrDiff) {
|
|
735
|
-
child = prevChild;
|
|
736
|
-
parent.children.delete(child.key);
|
|
737
|
-
child.key = key;
|
|
738
|
-
moved.push([key, child]);
|
|
739
|
-
}
|
|
740
|
-
didMove = true;
|
|
741
|
-
// And check for diff against the previous value in the previous position
|
|
742
|
-
isDiff = valuePrevChild !== value;
|
|
743
|
-
}
|
|
670
|
+
for (let i = 0; i < length; i++) {
|
|
671
|
+
const key = isArr ? i + '' : keys[i];
|
|
672
|
+
const value = isMap ? obj.get(key) : obj[key];
|
|
673
|
+
const prev = isMap ? prevValue === null || prevValue === void 0 ? void 0 : prevValue.get(key) : prevValue === null || prevValue === void 0 ? void 0 : prevValue[key];
|
|
674
|
+
let isDiff = value !== prev;
|
|
675
|
+
if (isDiff) {
|
|
676
|
+
extractFunctionOrComputed(parent, obj, key, value);
|
|
677
|
+
const id = idField && value
|
|
678
|
+
? isIdFieldFunction
|
|
679
|
+
? idField(value)
|
|
680
|
+
: value[idField]
|
|
681
|
+
: undefined;
|
|
682
|
+
let child = getChildNode(parent, key);
|
|
683
|
+
// Detect moves within an array. Need to move the original proxy to the new position to keep
|
|
684
|
+
// the proxy stable, so that listeners to this node will be unaffected by the array shift.
|
|
685
|
+
if (isArr && id !== undefined) {
|
|
686
|
+
// Find the previous position of this element in the array
|
|
687
|
+
const prevChild = id !== undefined ? prevChildrenById === null || prevChildrenById === void 0 ? void 0 : prevChildrenById.get(id) : undefined;
|
|
688
|
+
if (!prevChild) {
|
|
689
|
+
// This id was not in the array before so it does not need to notify children
|
|
690
|
+
isDiff = false;
|
|
691
|
+
hasADiff = true;
|
|
744
692
|
}
|
|
745
|
-
if (
|
|
746
|
-
|
|
747
|
-
// If
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
693
|
+
else if (prevChild !== undefined && prevChild.key !== key) {
|
|
694
|
+
const valuePrevChild = prevValue[prevChild.key];
|
|
695
|
+
// If array length changed then move the original node to the current position.
|
|
696
|
+
// That should be faster than notifying every single element that
|
|
697
|
+
// it's in a new position.
|
|
698
|
+
if (isArrDiff) {
|
|
699
|
+
child = prevChild;
|
|
700
|
+
parent.children.delete(child.key);
|
|
701
|
+
child.key = key;
|
|
702
|
+
moved.push([key, child]);
|
|
755
703
|
}
|
|
704
|
+
didMove = true;
|
|
705
|
+
// And check for diff against the previous value in the previous position
|
|
706
|
+
isDiff = valuePrevChild !== value;
|
|
756
707
|
}
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
708
|
+
}
|
|
709
|
+
if (isDiff) {
|
|
710
|
+
// Array has a new / modified element
|
|
711
|
+
// If object iterate through its children
|
|
712
|
+
if (isPrimitive(value)) {
|
|
713
|
+
hasADiff = true;
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
// Always need to updateNodes so we notify through all children
|
|
717
|
+
const updatedNodes = updateNodes(child, value, prev);
|
|
718
|
+
hasADiff = hasADiff || updatedNodes;
|
|
765
719
|
}
|
|
766
720
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
721
|
+
if (isDiff || !isArrDiff) {
|
|
722
|
+
// Notify for this child if this element is different and it has listeners
|
|
723
|
+
// Or if the position changed in an array whose length did not change
|
|
724
|
+
// But do not notify child if the parent is an array with changing length -
|
|
725
|
+
// the array's listener will cover it
|
|
726
|
+
if (child.listeners || child.listenersImmediate) {
|
|
727
|
+
notify(child, value, prev, 0, !isArrDiff);
|
|
728
|
+
}
|
|
772
729
|
}
|
|
773
730
|
}
|
|
774
731
|
}
|
|
732
|
+
if (moved) {
|
|
733
|
+
for (let i = 0; i < moved.length; i++) {
|
|
734
|
+
const [key, child] = moved[i];
|
|
735
|
+
parent.children.set(key, child);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
775
738
|
// The full array does not need to re-render if the length is the same
|
|
776
739
|
// So don't notify shallow listeners
|
|
777
740
|
retValue = hasADiff || didMove;
|
|
@@ -849,18 +812,6 @@ const proxyHandler = {
|
|
|
849
812
|
if (property) {
|
|
850
813
|
return property.get(node);
|
|
851
814
|
}
|
|
852
|
-
const isValuePrimitive = isPrimitive(value);
|
|
853
|
-
// If accessing a key that doesn't already exist, and this node has been activated with extra keys
|
|
854
|
-
// then return the values that were set. This is used by enableLegendStateReact for example.
|
|
855
|
-
if (value === undefined || value === null || isValuePrimitive) {
|
|
856
|
-
if (extraPrimitiveProps.size && (node.isActivatedPrimitive || extraPrimitiveActivators.has(p))) {
|
|
857
|
-
node.isActivatedPrimitive = true;
|
|
858
|
-
const vPrim = extraPrimitiveProps.get(p);
|
|
859
|
-
if (vPrim !== undefined) {
|
|
860
|
-
return isFunction(vPrim) ? vPrim(getProxy(node)) : vPrim;
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
815
|
const vProp = value === null || value === void 0 ? void 0 : value[p];
|
|
865
816
|
if (isObject(value) && value[symbolOpaque]) {
|
|
866
817
|
return vProp;
|
|
@@ -984,10 +935,7 @@ const proxyHandler = {
|
|
|
984
935
|
},
|
|
985
936
|
};
|
|
986
937
|
function set(node, newValue) {
|
|
987
|
-
if (
|
|
988
|
-
newValue.then((v) => set(node, v)).catch((error) => set(node, { error }));
|
|
989
|
-
}
|
|
990
|
-
else if (node.parent) {
|
|
938
|
+
if (node.parent) {
|
|
991
939
|
return setKey(node.parent, node.key, newValue);
|
|
992
940
|
}
|
|
993
941
|
else {
|
|
@@ -1027,12 +975,13 @@ function setKey(node, key, newValue, level) {
|
|
|
1027
975
|
// Get the child node for updating and notifying
|
|
1028
976
|
const childNode = isRoot ? node : getChildNode(node, key);
|
|
1029
977
|
// Set the raw value on the parent object
|
|
1030
|
-
const { newValue: savedValue, prevValue } = setNodeValue(childNode, newValue);
|
|
1031
|
-
const isFunc = isFunction(
|
|
978
|
+
const { newValue: savedValue, prevValue, parentValue } = setNodeValue(childNode, newValue);
|
|
979
|
+
const isFunc = isFunction(savedValue);
|
|
1032
980
|
const isPrim = isPrimitive(savedValue) || savedValue instanceof Date;
|
|
1033
981
|
if (savedValue !== prevValue) {
|
|
1034
982
|
updateNodesAndNotify(node, savedValue, prevValue, childNode, isPrim, isRoot, level);
|
|
1035
983
|
}
|
|
984
|
+
extractFunctionOrComputed(node, parentValue, key, savedValue);
|
|
1036
985
|
return isFunc ? savedValue : isRoot ? getProxy(node) : getProxy(node, key);
|
|
1037
986
|
}
|
|
1038
987
|
function assign(node, value) {
|
|
@@ -1159,6 +1108,51 @@ function updateNodesAndNotify(node, newValue, prevValue, childNode, isPrim, isRo
|
|
|
1159
1108
|
}
|
|
1160
1109
|
endBatch();
|
|
1161
1110
|
}
|
|
1111
|
+
function extractPromise(node, value) {
|
|
1112
|
+
value.status = 'pending';
|
|
1113
|
+
value
|
|
1114
|
+
.then((value) => {
|
|
1115
|
+
set(node, value);
|
|
1116
|
+
})
|
|
1117
|
+
.catch((error) => {
|
|
1118
|
+
set(node, { error, status: 'rejected' });
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
const __devExtractFunctionsAndComputedsNodes = process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test' ? new Set() : undefined;
|
|
1122
|
+
function extractFunctionOrComputed(node, obj, k, v) {
|
|
1123
|
+
if (isPromise(v)) {
|
|
1124
|
+
extractPromise(getChildNode(node, k), v);
|
|
1125
|
+
}
|
|
1126
|
+
else if (typeof v === 'function') {
|
|
1127
|
+
extractFunction(node, k, v);
|
|
1128
|
+
}
|
|
1129
|
+
else if (typeof v == 'object' && v !== null && v !== undefined) {
|
|
1130
|
+
const childNode = getNode(v);
|
|
1131
|
+
if (childNode === null || childNode === void 0 ? void 0 : childNode.isComputed) {
|
|
1132
|
+
extractFunction(node, k, v, childNode);
|
|
1133
|
+
delete obj[k];
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
return true;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
function extractFunctionsAndComputeds(node, obj) {
|
|
1141
|
+
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') &&
|
|
1142
|
+
typeof __devExtractFunctionsAndComputedsNodes !== 'undefined') {
|
|
1143
|
+
if (__devExtractFunctionsAndComputedsNodes.has(obj)) {
|
|
1144
|
+
console.error('[legend-state] Circular reference detected in object. You may want to use opaqueObject to stop traversing child nodes.', obj);
|
|
1145
|
+
return false;
|
|
1146
|
+
}
|
|
1147
|
+
__devExtractFunctionsAndComputedsNodes.add(obj);
|
|
1148
|
+
}
|
|
1149
|
+
for (const k in obj) {
|
|
1150
|
+
const v = obj[k];
|
|
1151
|
+
if (v && extractFunctionOrComputed(node, obj, k, v) && !v[symbolOpaque]) {
|
|
1152
|
+
extractFunctionsAndComputeds(getChildNode(node, k), v);
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1162
1156
|
|
|
1163
1157
|
function isObservable(obs) {
|
|
1164
1158
|
return obs && !!obs[symbolGetNode];
|
|
@@ -1249,53 +1243,50 @@ function setInObservableAtPath(obs, path, value, mode) {
|
|
|
1249
1243
|
function mergeIntoObservable(target, ...sources) {
|
|
1250
1244
|
beginBatch();
|
|
1251
1245
|
globalState.isMerging = true;
|
|
1252
|
-
|
|
1246
|
+
for (let i = 0; i < sources.length; i++) {
|
|
1247
|
+
target = _mergeIntoObservable(target, sources[i]);
|
|
1248
|
+
}
|
|
1253
1249
|
globalState.isMerging = false;
|
|
1254
1250
|
endBatch();
|
|
1255
|
-
return
|
|
1251
|
+
return target;
|
|
1256
1252
|
}
|
|
1257
|
-
function _mergeIntoObservable(target,
|
|
1253
|
+
function _mergeIntoObservable(target, source) {
|
|
1258
1254
|
var _a;
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
const targetChild = target[key];
|
|
1280
|
-
if ((isObj || isArr) && targetChild && (needsSet || !isEmpty(targetChild))) {
|
|
1281
|
-
if (!needsSet && (!targetChild || (isObj ? !isObject(targetChild) : !isArray(targetChild)))) {
|
|
1282
|
-
target[key] = sourceValue;
|
|
1283
|
-
}
|
|
1284
|
-
else {
|
|
1285
|
-
_mergeIntoObservable(targetChild, sourceValue);
|
|
1286
|
-
}
|
|
1255
|
+
const needsSet = isObservable(target);
|
|
1256
|
+
const targetValue = needsSet ? target.peek() : target;
|
|
1257
|
+
const isTargetArr = isArray(targetValue);
|
|
1258
|
+
const isTargetObj = !isTargetArr && isObject(targetValue);
|
|
1259
|
+
if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) ||
|
|
1260
|
+
(isTargetArr && isArray(source) && targetValue.length > 0)) {
|
|
1261
|
+
const keys = Object.keys(source);
|
|
1262
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1263
|
+
const key = keys[i];
|
|
1264
|
+
const sourceValue = source[key];
|
|
1265
|
+
if (sourceValue === symbolDelete) {
|
|
1266
|
+
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete) ? target[key].delete() : delete target[key];
|
|
1267
|
+
}
|
|
1268
|
+
else {
|
|
1269
|
+
const isObj = isObject(sourceValue);
|
|
1270
|
+
const isArr = !isObj && isArray(sourceValue);
|
|
1271
|
+
const targetChild = target[key];
|
|
1272
|
+
if ((isObj || isArr) && targetChild && (needsSet || !isEmpty(targetChild))) {
|
|
1273
|
+
if (!needsSet && (!targetChild || (isObj ? !isObject(targetChild) : !isArray(targetChild)))) {
|
|
1274
|
+
target[key] = sourceValue;
|
|
1287
1275
|
}
|
|
1288
1276
|
else {
|
|
1289
|
-
|
|
1290
|
-
? targetChild.set(sourceValue)
|
|
1291
|
-
: (target[key] = sourceValue);
|
|
1277
|
+
_mergeIntoObservable(targetChild, sourceValue);
|
|
1292
1278
|
}
|
|
1293
1279
|
}
|
|
1280
|
+
else {
|
|
1281
|
+
needsSet
|
|
1282
|
+
? targetChild.set(sourceValue)
|
|
1283
|
+
: (target[key] = sourceValue);
|
|
1284
|
+
}
|
|
1294
1285
|
}
|
|
1295
1286
|
}
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1287
|
+
}
|
|
1288
|
+
else if (source !== undefined) {
|
|
1289
|
+
needsSet ? target.set(source) : (target = source);
|
|
1299
1290
|
}
|
|
1300
1291
|
return target;
|
|
1301
1292
|
}
|
|
@@ -1374,7 +1365,7 @@ ObservablePrimitiveClass.prototype.delete = function () {
|
|
|
1374
1365
|
function createObservable(value, makePrimitive) {
|
|
1375
1366
|
const valueIsPromise = isPromise(value);
|
|
1376
1367
|
const root = {
|
|
1377
|
-
_:
|
|
1368
|
+
_: value,
|
|
1378
1369
|
};
|
|
1379
1370
|
const node = {
|
|
1380
1371
|
root,
|
|
@@ -1384,19 +1375,14 @@ function createObservable(value, makePrimitive) {
|
|
|
1384
1375
|
? new ObservablePrimitiveClass(node)
|
|
1385
1376
|
: getProxy(node);
|
|
1386
1377
|
if (valueIsPromise) {
|
|
1387
|
-
value
|
|
1388
|
-
obs.set({ error });
|
|
1389
|
-
});
|
|
1390
|
-
value.then((value) => {
|
|
1391
|
-
obs.set(value);
|
|
1392
|
-
});
|
|
1378
|
+
extractPromise(node, value);
|
|
1393
1379
|
}
|
|
1394
1380
|
else if (!prim) {
|
|
1395
1381
|
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
1396
1382
|
__devExtractFunctionsAndComputedsNodes.clear();
|
|
1397
1383
|
}
|
|
1398
1384
|
if (value) {
|
|
1399
|
-
extractFunctionsAndComputeds(
|
|
1385
|
+
extractFunctionsAndComputeds(node, value);
|
|
1400
1386
|
}
|
|
1401
1387
|
}
|
|
1402
1388
|
return obs;
|
|
@@ -1425,7 +1411,7 @@ function setupTracking(nodes, update, noArgs, immediate) {
|
|
|
1425
1411
|
};
|
|
1426
1412
|
}
|
|
1427
1413
|
|
|
1428
|
-
function trackSelector(selector, update, observeEvent, observeOptions, createResubscribe
|
|
1414
|
+
function trackSelector(selector, update, observeEvent, observeOptions, createResubscribe) {
|
|
1429
1415
|
var _a;
|
|
1430
1416
|
let nodes;
|
|
1431
1417
|
let value;
|
|
@@ -1441,11 +1427,11 @@ function trackSelector(selector, update, observeEvent, observeOptions, createRes
|
|
|
1441
1427
|
}
|
|
1442
1428
|
else {
|
|
1443
1429
|
// Compute the selector inside a tracking context
|
|
1444
|
-
beginTracking(
|
|
1430
|
+
beginTracking();
|
|
1445
1431
|
value = selector ? computeSelector(selector, observeEvent, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.retainObservable) : selector;
|
|
1446
1432
|
tracker = tracking.current;
|
|
1447
1433
|
nodes = tracker.nodes;
|
|
1448
|
-
endTracking(
|
|
1434
|
+
endTracking();
|
|
1449
1435
|
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') && tracker && nodes) {
|
|
1450
1436
|
(_a = tracker.traceListeners) === null || _a === void 0 ? void 0 : _a.call(tracker, nodes);
|
|
1451
1437
|
if (tracker.traceUpdates) {
|
|
@@ -1496,6 +1482,7 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
1496
1482
|
e.onCleanupReaction();
|
|
1497
1483
|
e.onCleanupReaction = undefined;
|
|
1498
1484
|
}
|
|
1485
|
+
endBatch();
|
|
1499
1486
|
// Call the reaction if there is one and the value changed
|
|
1500
1487
|
if (reaction && (e.num > 0 || !isEvent(selectorOrRun)) && e.previous !== e.value) {
|
|
1501
1488
|
reaction(e);
|
|
@@ -1504,7 +1491,6 @@ function observe(selectorOrRun, reactionOrOptions, options) {
|
|
|
1504
1491
|
e.previous = e.value;
|
|
1505
1492
|
// Increment the counter
|
|
1506
1493
|
e.num++;
|
|
1507
|
-
endBatch();
|
|
1508
1494
|
};
|
|
1509
1495
|
update();
|
|
1510
1496
|
// Return function calling dispose because dispose may be changed in update()
|
|
@@ -1533,7 +1519,7 @@ function computed(compute, set$1) {
|
|
|
1533
1519
|
prevNode.linkedFromNodes.delete(node);
|
|
1534
1520
|
node.linkedToNode = undefined;
|
|
1535
1521
|
}
|
|
1536
|
-
const
|
|
1522
|
+
const { parentOther } = node;
|
|
1537
1523
|
if (isObservable(val)) {
|
|
1538
1524
|
// If the computed is a proxy to another observable
|
|
1539
1525
|
// link it to the target observable
|
|
@@ -1543,9 +1529,9 @@ function computed(compute, set$1) {
|
|
|
1543
1529
|
linkedNode.linkedFromNodes = new Set();
|
|
1544
1530
|
}
|
|
1545
1531
|
linkedNode.linkedFromNodes.add(node);
|
|
1546
|
-
if (node.
|
|
1532
|
+
if (node.parentOther) {
|
|
1547
1533
|
onChange(linkedNode, ({ value }) => {
|
|
1548
|
-
setNodeValue(node.
|
|
1534
|
+
setNodeValue(node.parentOther, value);
|
|
1549
1535
|
}, { initial: true });
|
|
1550
1536
|
}
|
|
1551
1537
|
// If the target observable is different then notify for the change
|
|
@@ -1562,22 +1548,22 @@ function computed(compute, set$1) {
|
|
|
1562
1548
|
// Update the computed value
|
|
1563
1549
|
setter(node, val);
|
|
1564
1550
|
// If the computed is a child of an observable set the value on it
|
|
1565
|
-
if (
|
|
1551
|
+
if (parentOther) {
|
|
1566
1552
|
let didUnlock = false;
|
|
1567
|
-
if (
|
|
1568
|
-
|
|
1553
|
+
if (parentOther.root.locked) {
|
|
1554
|
+
parentOther.root.locked = false;
|
|
1569
1555
|
didUnlock = true;
|
|
1570
1556
|
}
|
|
1571
|
-
setter(
|
|
1557
|
+
setter(parentOther, val);
|
|
1572
1558
|
if (didUnlock) {
|
|
1573
|
-
|
|
1559
|
+
parentOther.root.locked = true;
|
|
1574
1560
|
}
|
|
1575
1561
|
}
|
|
1576
1562
|
// Re-lock the computed node
|
|
1577
1563
|
lockObservable(obs, true);
|
|
1578
1564
|
}
|
|
1579
|
-
else if (
|
|
1580
|
-
setNodeValue(
|
|
1565
|
+
else if (parentOther) {
|
|
1566
|
+
setNodeValue(parentOther, val);
|
|
1581
1567
|
}
|
|
1582
1568
|
isSetAfterActivated = true;
|
|
1583
1569
|
};
|
|
@@ -1665,11 +1651,11 @@ function proxy(get, set) {
|
|
|
1665
1651
|
target = computed(() => get(key), (set ? (value) => set(key, value) : undefined));
|
|
1666
1652
|
mapTargets.set(key, target);
|
|
1667
1653
|
extractFunction(node, key, target, getNode(target));
|
|
1668
|
-
if (node.
|
|
1654
|
+
if (node.parentOther) {
|
|
1669
1655
|
onChange(getNode(target), ({ value, getPrevious }) => {
|
|
1670
1656
|
const previous = getPrevious();
|
|
1671
1657
|
// Set the raw value on the proxy's parent
|
|
1672
|
-
setNodeValue(node.
|
|
1658
|
+
setNodeValue(node.parentOther, node.root._);
|
|
1673
1659
|
// Notify the proxy
|
|
1674
1660
|
notify(getChildNode(node, key), value, previous, 0);
|
|
1675
1661
|
});
|
|
@@ -1681,23 +1667,33 @@ function proxy(get, set) {
|
|
|
1681
1667
|
}
|
|
1682
1668
|
|
|
1683
1669
|
function _when(predicate, effect, checkReady) {
|
|
1670
|
+
// If predicate is a regular Promise skip all the observable stuff
|
|
1671
|
+
if (isPromise(predicate)) {
|
|
1672
|
+
return effect ? predicate.then(effect) : predicate;
|
|
1673
|
+
}
|
|
1684
1674
|
let value;
|
|
1685
1675
|
// Create a wrapping fn that calls the effect if predicate returns true
|
|
1686
1676
|
function run(e) {
|
|
1687
1677
|
const ret = computeSelector(predicate);
|
|
1688
|
-
if (checkReady ? isObservableValueReady(ret) : ret) {
|
|
1678
|
+
if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
1689
1679
|
value = ret;
|
|
1690
|
-
//
|
|
1691
|
-
effect === null || effect === void 0 ? void 0 : effect(ret);
|
|
1692
|
-
// Set cancel so that observe does not track
|
|
1680
|
+
// Set cancel so that observe does not track anymore
|
|
1693
1681
|
e.cancel = true;
|
|
1694
1682
|
}
|
|
1683
|
+
return value;
|
|
1684
|
+
}
|
|
1685
|
+
function doEffect() {
|
|
1686
|
+
// If value is truthy then run the effect
|
|
1687
|
+
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
1695
1688
|
}
|
|
1696
1689
|
// Run in an observe
|
|
1697
|
-
observe(run);
|
|
1690
|
+
observe(run, doEffect);
|
|
1698
1691
|
// If first run resulted in a truthy value just return it.
|
|
1699
1692
|
// It will have set e.cancel so no need to dispose
|
|
1700
|
-
if (value
|
|
1693
|
+
if (isPromise(value)) {
|
|
1694
|
+
return effect ? value.then(effect) : value;
|
|
1695
|
+
}
|
|
1696
|
+
else if (value !== undefined) {
|
|
1701
1697
|
return Promise.resolve(value);
|
|
1702
1698
|
}
|
|
1703
1699
|
else {
|
|
@@ -1740,7 +1736,6 @@ const internal = {
|
|
|
1740
1736
|
};
|
|
1741
1737
|
|
|
1742
1738
|
exports.ObservablePrimitiveClass = ObservablePrimitiveClass;
|
|
1743
|
-
exports.afterBatch = afterBatch;
|
|
1744
1739
|
exports.batch = batch;
|
|
1745
1740
|
exports.beginBatch = beginBatch;
|
|
1746
1741
|
exports.beginTracking = beginTracking;
|
|
@@ -1753,12 +1748,11 @@ exports.deconstructObjectWithPath = deconstructObjectWithPath;
|
|
|
1753
1748
|
exports.endBatch = endBatch;
|
|
1754
1749
|
exports.endTracking = endTracking;
|
|
1755
1750
|
exports.event = event;
|
|
1756
|
-
exports.extraPrimitiveActivators = extraPrimitiveActivators;
|
|
1757
|
-
exports.extraPrimitiveProps = extraPrimitiveProps;
|
|
1758
1751
|
exports.findIDKey = findIDKey;
|
|
1759
1752
|
exports.getNode = getNode;
|
|
1760
1753
|
exports.getNodeValue = getNodeValue;
|
|
1761
1754
|
exports.getObservableIndex = getObservableIndex;
|
|
1755
|
+
exports.hasOwnProperty = hasOwnProperty;
|
|
1762
1756
|
exports.internal = internal;
|
|
1763
1757
|
exports.isArray = isArray;
|
|
1764
1758
|
exports.isBoolean = isBoolean;
|