@legendapp/state 2.0.1 → 2.1.0-next.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 +6 -0
- package/history.js +1 -1
- package/history.js.map +1 -1
- package/history.mjs +1 -1
- package/history.mjs.map +1 -1
- package/index.d.ts +4 -2
- package/index.js +558 -408
- package/index.js.map +1 -1
- package/index.mjs +558 -408
- package/index.mjs.map +1 -1
- package/package.json +9 -1
- package/persist.d.ts +1 -1
- package/persist.js +77 -80
- package/persist.js.map +1 -1
- package/persist.mjs +79 -80
- package/persist.mjs.map +1 -1
- package/react-hooks/usePersistedObservable.d.ts +2 -1
- package/react-hooks/usePersistedObservable.js.map +1 -1
- package/react-hooks/usePersistedObservable.mjs.map +1 -1
- package/react.js +0 -2
- package/react.js.map +1 -1
- package/react.mjs +0 -2
- package/react.mjs.map +1 -1
- package/src/ObservableObject.d.ts +1 -1
- package/src/createObservable.d.ts +1 -1
- package/src/globals.d.ts +7 -3
- package/src/helpers.d.ts +1 -3
- package/src/observable.d.ts +11 -2
- package/src/observableInterfaces.d.ts +32 -15
- package/src/persist/persistObservable.d.ts +6 -7
- package/src/react-hooks/usePersistedObservable.d.ts +2 -1
package/index.mjs
CHANGED
|
@@ -58,9 +58,17 @@ const extraPrimitiveActivators = new Map();
|
|
|
58
58
|
const extraPrimitiveProps = new Map();
|
|
59
59
|
const globalState = {
|
|
60
60
|
isLoadingLocal: false,
|
|
61
|
-
isLoadingRemote: false,
|
|
62
61
|
isMerging: false,
|
|
62
|
+
isLoadingRemote$: undefined,
|
|
63
|
+
onChangeRemote: undefined,
|
|
63
64
|
};
|
|
65
|
+
function isObservable(obs) {
|
|
66
|
+
return !!obs && !!obs[symbolGetNode];
|
|
67
|
+
}
|
|
68
|
+
function isComputed(obs) {
|
|
69
|
+
var _a;
|
|
70
|
+
return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isComputed);
|
|
71
|
+
}
|
|
64
72
|
function checkActivate(node) {
|
|
65
73
|
var _a;
|
|
66
74
|
const root = node.root;
|
|
@@ -87,12 +95,13 @@ function setNodeValue(node, newValue) {
|
|
|
87
95
|
const prevValue = parentValue[key];
|
|
88
96
|
const isFunc = isFunction(newValue);
|
|
89
97
|
// Compute newValue if newValue is a function or an observable
|
|
90
|
-
newValue =
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
newValue = !parentNode.isAssigning && isFunc ? newValue(prevValue) : newValue;
|
|
99
|
+
// If setting an observable, set a link to the observable instead
|
|
100
|
+
if (isObservable(newValue) && !isComputed(newValue)) {
|
|
101
|
+
const val = newValue;
|
|
102
|
+
node.lazy = () => val;
|
|
103
|
+
newValue = undefined;
|
|
104
|
+
}
|
|
96
105
|
try {
|
|
97
106
|
parentNode.isSetting = (parentNode.isSetting || 0) + 1;
|
|
98
107
|
// Save the new value
|
|
@@ -126,7 +135,13 @@ function getNodeValue(node) {
|
|
|
126
135
|
}
|
|
127
136
|
return child;
|
|
128
137
|
}
|
|
129
|
-
|
|
138
|
+
const cloneFunction = (originalFunction) => {
|
|
139
|
+
const length = originalFunction.length;
|
|
140
|
+
return length > 1
|
|
141
|
+
? (arg1, arg2) => originalFunction(arg1, arg2)
|
|
142
|
+
: (...args) => originalFunction(...args);
|
|
143
|
+
};
|
|
144
|
+
function getChildNode(node, key, asFunction) {
|
|
130
145
|
var _a;
|
|
131
146
|
// Get the child by key
|
|
132
147
|
let child = (_a = node.children) === null || _a === void 0 ? void 0 : _a.get(key);
|
|
@@ -138,6 +153,12 @@ function getChildNode(node, key) {
|
|
|
138
153
|
key,
|
|
139
154
|
lazy: true,
|
|
140
155
|
};
|
|
156
|
+
if (asFunction) {
|
|
157
|
+
child = Object.assign(cloneFunction(asFunction), child);
|
|
158
|
+
}
|
|
159
|
+
else if (node.proxyFn2) {
|
|
160
|
+
child = Object.assign(node.proxyFn2.bind(node, key), child);
|
|
161
|
+
}
|
|
141
162
|
if (!node.children) {
|
|
142
163
|
node.children = new Map();
|
|
143
164
|
}
|
|
@@ -159,6 +180,7 @@ function ensureNodeValue(node) {
|
|
|
159
180
|
return value;
|
|
160
181
|
}
|
|
161
182
|
function findIDKey(obj, node) {
|
|
183
|
+
var _a, _b;
|
|
162
184
|
let idKey = isObject(obj)
|
|
163
185
|
? 'id' in obj
|
|
164
186
|
? 'id'
|
|
@@ -171,7 +193,8 @@ function findIDKey(obj, node) {
|
|
|
171
193
|
: undefined
|
|
172
194
|
: undefined;
|
|
173
195
|
if (!idKey && node.parent) {
|
|
174
|
-
const
|
|
196
|
+
const k = node.key + '_keyExtractor';
|
|
197
|
+
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'];
|
|
175
198
|
if (keyExtractor && isFunction(keyExtractor)) {
|
|
176
199
|
idKey = keyExtractor;
|
|
177
200
|
}
|
|
@@ -427,15 +450,19 @@ function endBatch(force) {
|
|
|
427
450
|
}
|
|
428
451
|
}
|
|
429
452
|
|
|
430
|
-
function createObservable(value, makePrimitive, createObject, createPrimitive) {
|
|
453
|
+
function createObservable(value, makePrimitive, extractPromise, createObject, createPrimitive) {
|
|
431
454
|
const valueIsPromise = isPromise(value);
|
|
455
|
+
const valueIsFunction = isFunction(value);
|
|
432
456
|
const root = {
|
|
433
457
|
_: value,
|
|
434
458
|
};
|
|
435
|
-
|
|
459
|
+
let node = {
|
|
436
460
|
root,
|
|
437
461
|
lazy: true,
|
|
438
462
|
};
|
|
463
|
+
if (valueIsFunction) {
|
|
464
|
+
node = Object.assign(cloneFunction(value), node);
|
|
465
|
+
}
|
|
439
466
|
const prim = makePrimitive || isActualPrimitive(value);
|
|
440
467
|
const obs = prim
|
|
441
468
|
? new createPrimitive(node)
|
|
@@ -446,6 +473,176 @@ function createObservable(value, makePrimitive, createObject, createPrimitive) {
|
|
|
446
473
|
return obs;
|
|
447
474
|
}
|
|
448
475
|
|
|
476
|
+
function isEvent(obs) {
|
|
477
|
+
var _a;
|
|
478
|
+
return obs && ((_a = obs[symbolGetNode]) === null || _a === void 0 ? void 0 : _a.isEvent);
|
|
479
|
+
}
|
|
480
|
+
function computeSelector(selector, e, retainObservable) {
|
|
481
|
+
let c = selector;
|
|
482
|
+
if (isFunction(c)) {
|
|
483
|
+
c = e ? c(e) : c();
|
|
484
|
+
}
|
|
485
|
+
return isObservable(c) && !retainObservable ? c.get() : c;
|
|
486
|
+
}
|
|
487
|
+
function getObservableIndex(obs) {
|
|
488
|
+
const node = getNode(obs);
|
|
489
|
+
const n = +node.key;
|
|
490
|
+
return n - n < 1 ? +n : -1;
|
|
491
|
+
}
|
|
492
|
+
function opaqueObject(value) {
|
|
493
|
+
if (value) {
|
|
494
|
+
value[symbolOpaque] = true;
|
|
495
|
+
}
|
|
496
|
+
return value;
|
|
497
|
+
}
|
|
498
|
+
function lockObservable(obs, value) {
|
|
499
|
+
var _a;
|
|
500
|
+
const root = (_a = getNode(obs)) === null || _a === void 0 ? void 0 : _a.root;
|
|
501
|
+
if (root) {
|
|
502
|
+
root.locked = value;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
|
|
506
|
+
let o = obj;
|
|
507
|
+
let oFull = fullObj;
|
|
508
|
+
if (path.length > 0) {
|
|
509
|
+
for (let i = 0; i < path.length; i++) {
|
|
510
|
+
const p = path[i];
|
|
511
|
+
if (i === path.length - 1) {
|
|
512
|
+
// Don't set if the value is the same. This prevents creating a new key
|
|
513
|
+
// when setting undefined on an object without this key
|
|
514
|
+
if (o[p] !== value) {
|
|
515
|
+
o[p] = value;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
else if (o[p] === symbolDelete) {
|
|
519
|
+
// If this was previously deleted, restore it
|
|
520
|
+
if (oFull) {
|
|
521
|
+
o[p] = oFull[p];
|
|
522
|
+
restore === null || restore === void 0 ? void 0 : restore(path.slice(0, i + 1), o[p]);
|
|
523
|
+
}
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
else if (o[p] === undefined || o[p] === null) {
|
|
527
|
+
o[p] = pathTypes[i] === 'array' ? [] : {};
|
|
528
|
+
}
|
|
529
|
+
o = o[p];
|
|
530
|
+
if (oFull) {
|
|
531
|
+
oFull = oFull[p];
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
obj = value;
|
|
537
|
+
}
|
|
538
|
+
return obj;
|
|
539
|
+
}
|
|
540
|
+
function setInObservableAtPath(obs, path, pathTypes, value, mode) {
|
|
541
|
+
let o = obs;
|
|
542
|
+
let v = value;
|
|
543
|
+
for (let i = 0; i < path.length; i++) {
|
|
544
|
+
const p = path[i];
|
|
545
|
+
if (!o.peek()[p] && pathTypes[i] === 'array') {
|
|
546
|
+
o[p].set([]);
|
|
547
|
+
}
|
|
548
|
+
o = o[p];
|
|
549
|
+
v = v[p];
|
|
550
|
+
}
|
|
551
|
+
if (v === symbolDelete) {
|
|
552
|
+
o.delete();
|
|
553
|
+
}
|
|
554
|
+
// Assign if possible, or set otherwise
|
|
555
|
+
else if (mode === 'assign' && o.assign && isObject(o.peek())) {
|
|
556
|
+
o.assign(v);
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
o.set(v);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
function mergeIntoObservable(target, ...sources) {
|
|
563
|
+
beginBatch();
|
|
564
|
+
globalState.isMerging = true;
|
|
565
|
+
for (let i = 0; i < sources.length; i++) {
|
|
566
|
+
target = _mergeIntoObservable(target, sources[i]);
|
|
567
|
+
}
|
|
568
|
+
globalState.isMerging = false;
|
|
569
|
+
endBatch();
|
|
570
|
+
return target;
|
|
571
|
+
}
|
|
572
|
+
function _mergeIntoObservable(target, source) {
|
|
573
|
+
var _a;
|
|
574
|
+
if (isObservable(source)) {
|
|
575
|
+
source = source.peek();
|
|
576
|
+
}
|
|
577
|
+
const needsSet = isObservable(target);
|
|
578
|
+
const targetValue = needsSet ? target.peek() : target;
|
|
579
|
+
const isTargetArr = isArray(targetValue);
|
|
580
|
+
const isTargetObj = !isTargetArr && isObject(targetValue);
|
|
581
|
+
if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) ||
|
|
582
|
+
(isTargetArr && isArray(source) && targetValue.length > 0)) {
|
|
583
|
+
const keys = Object.keys(source);
|
|
584
|
+
for (let i = 0; i < keys.length; i++) {
|
|
585
|
+
const key = keys[i];
|
|
586
|
+
const sourceValue = source[key];
|
|
587
|
+
if (sourceValue === symbolDelete) {
|
|
588
|
+
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete) ? target[key].delete() : delete target[key];
|
|
589
|
+
}
|
|
590
|
+
else {
|
|
591
|
+
const isObj = isObject(sourceValue);
|
|
592
|
+
const isArr = !isObj && isArray(sourceValue);
|
|
593
|
+
const targetChild = target[key];
|
|
594
|
+
if ((isObj || isArr) && targetChild && (needsSet || !isEmpty(targetChild))) {
|
|
595
|
+
if (!needsSet && (!targetChild || (isObj ? !isObject(targetChild) : !isArray(targetChild)))) {
|
|
596
|
+
target[key] = sourceValue;
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
_mergeIntoObservable(targetChild, sourceValue);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
needsSet
|
|
604
|
+
? targetChild.set(sourceValue)
|
|
605
|
+
: (target[key] = sourceValue);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
else if (source !== undefined) {
|
|
611
|
+
needsSet ? target.set(source) : (target = source);
|
|
612
|
+
}
|
|
613
|
+
return target;
|
|
614
|
+
}
|
|
615
|
+
function constructObjectWithPath(path, pathTypes, value) {
|
|
616
|
+
let out;
|
|
617
|
+
if (path.length > 0) {
|
|
618
|
+
let o = (out = {});
|
|
619
|
+
for (let i = 0; i < path.length; i++) {
|
|
620
|
+
const p = path[i];
|
|
621
|
+
o[p] = i === path.length - 1 ? value : pathTypes[i] === 'array' ? [] : {};
|
|
622
|
+
o = o[p];
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
out = value;
|
|
627
|
+
}
|
|
628
|
+
return out;
|
|
629
|
+
}
|
|
630
|
+
function deconstructObjectWithPath(path, pathTypes, value) {
|
|
631
|
+
let o = value;
|
|
632
|
+
for (let i = 0; i < path.length; i++) {
|
|
633
|
+
const p = path[i];
|
|
634
|
+
o = o ? o[p] : pathTypes[i] === 'array' ? [] : {};
|
|
635
|
+
}
|
|
636
|
+
return o;
|
|
637
|
+
}
|
|
638
|
+
function isObservableValueReady(value) {
|
|
639
|
+
return !!value && ((!isObject(value) && !isArray(value)) || !isEmpty(value));
|
|
640
|
+
}
|
|
641
|
+
function setSilently(obs, newValue) {
|
|
642
|
+
const node = getNode(obs);
|
|
643
|
+
return setNodeValue(node, newValue).newValue;
|
|
644
|
+
}
|
|
645
|
+
|
|
449
646
|
function onChange(node, callback, options = {}) {
|
|
450
647
|
const { initial, immediate, noArgs } = options;
|
|
451
648
|
const { trackingType } = options;
|
|
@@ -484,6 +681,23 @@ function onChange(node, callback, options = {}) {
|
|
|
484
681
|
return () => listeners.delete(listener);
|
|
485
682
|
}
|
|
486
683
|
|
|
684
|
+
function setupTracking(nodes, update, noArgs, immediate) {
|
|
685
|
+
let listeners = [];
|
|
686
|
+
// Listen to tracked nodes
|
|
687
|
+
nodes === null || nodes === void 0 ? void 0 : nodes.forEach((tracked) => {
|
|
688
|
+
const { node, track } = tracked;
|
|
689
|
+
listeners.push(onChange(node, update, { trackingType: track, immediate, noArgs }));
|
|
690
|
+
});
|
|
691
|
+
return () => {
|
|
692
|
+
if (listeners) {
|
|
693
|
+
for (let i = 0; i < listeners.length; i++) {
|
|
694
|
+
listeners[i]();
|
|
695
|
+
}
|
|
696
|
+
listeners = undefined;
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
|
|
487
701
|
let trackCount = 0;
|
|
488
702
|
const trackingQueue = [];
|
|
489
703
|
const tracking = {
|
|
@@ -523,56 +737,148 @@ function updateTracking(node, track) {
|
|
|
523
737
|
}
|
|
524
738
|
}
|
|
525
739
|
|
|
526
|
-
|
|
527
|
-
'copyWithin',
|
|
528
|
-
'fill',
|
|
529
|
-
'from',
|
|
530
|
-
'pop',
|
|
531
|
-
'push',
|
|
532
|
-
'reverse',
|
|
533
|
-
'shift',
|
|
534
|
-
'sort',
|
|
535
|
-
'splice',
|
|
536
|
-
'unshift',
|
|
537
|
-
]);
|
|
538
|
-
const ArrayLoopers = new Set([
|
|
539
|
-
'every',
|
|
540
|
-
'filter',
|
|
541
|
-
'find',
|
|
542
|
-
'findIndex',
|
|
543
|
-
'forEach',
|
|
544
|
-
'includes',
|
|
545
|
-
'join',
|
|
546
|
-
'map',
|
|
547
|
-
'some',
|
|
548
|
-
]);
|
|
549
|
-
const ArrayLoopersReturn = new Set(['filter', 'find']);
|
|
550
|
-
const observableProperties = new Map();
|
|
551
|
-
const observableFns = new Map([
|
|
552
|
-
['get', get],
|
|
553
|
-
['set', set],
|
|
554
|
-
['peek', peek],
|
|
555
|
-
['onChange', onChange],
|
|
556
|
-
['assign', assign],
|
|
557
|
-
['delete', deleteFn],
|
|
558
|
-
['toggle', toggle],
|
|
559
|
-
]);
|
|
560
|
-
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
561
|
-
// eslint-disable-next-line no-var
|
|
562
|
-
var __devUpdateNodes = new Set();
|
|
563
|
-
}
|
|
564
|
-
function collectionSetter(node, target, prop, ...args) {
|
|
740
|
+
function trackSelector(selector, update, observeEvent, observeOptions, createResubscribe) {
|
|
565
741
|
var _a;
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
742
|
+
let nodes;
|
|
743
|
+
let value;
|
|
744
|
+
let dispose;
|
|
745
|
+
let tracker;
|
|
746
|
+
let resubscribe;
|
|
747
|
+
let updateFn = update;
|
|
748
|
+
if (isObservable(selector)) {
|
|
749
|
+
value = selector.peek();
|
|
750
|
+
dispose = selector.onChange(update);
|
|
751
|
+
resubscribe = createResubscribe ? selector.onChange(update) : undefined;
|
|
752
|
+
}
|
|
753
|
+
else {
|
|
754
|
+
// Compute the selector inside a tracking context
|
|
755
|
+
beginTracking();
|
|
756
|
+
value = selector ? computeSelector(selector, observeEvent, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.fromComputed) : selector;
|
|
757
|
+
tracker = tracking.current;
|
|
758
|
+
nodes = tracker.nodes;
|
|
759
|
+
endTracking();
|
|
760
|
+
if ((process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') && tracker && nodes) {
|
|
761
|
+
(_a = tracker.traceListeners) === null || _a === void 0 ? void 0 : _a.call(tracker, nodes);
|
|
762
|
+
if (tracker.traceUpdates) {
|
|
763
|
+
updateFn = tracker.traceUpdates(update);
|
|
764
|
+
}
|
|
765
|
+
// Clear tracing so it doesn't leak to other components
|
|
766
|
+
tracker.traceListeners = undefined;
|
|
767
|
+
tracker.traceUpdates = undefined;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
if (!(observeEvent === null || observeEvent === void 0 ? void 0 : observeEvent.cancel)) {
|
|
771
|
+
// Do tracing if it was requested
|
|
772
|
+
// useSyncExternalStore doesn't subscribe until after the component mount.
|
|
773
|
+
// We want to subscribe immediately so we don't miss any updates
|
|
774
|
+
dispose = setupTracking(nodes, updateFn, false, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.immediate);
|
|
775
|
+
resubscribe = createResubscribe ? () => setupTracking(nodes, updateFn) : undefined;
|
|
776
|
+
}
|
|
777
|
+
return { value, dispose, resubscribe };
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function observe(selectorOrRun, reactionOrOptions, options) {
|
|
781
|
+
let reaction;
|
|
782
|
+
if (isFunction(reactionOrOptions)) {
|
|
783
|
+
reaction = reactionOrOptions;
|
|
784
|
+
}
|
|
785
|
+
else {
|
|
786
|
+
options = reactionOrOptions;
|
|
787
|
+
}
|
|
788
|
+
let dispose;
|
|
789
|
+
const e = { num: 0 };
|
|
790
|
+
// Wrap it in a function so it doesn't pass all the arguments to run()
|
|
791
|
+
const update = function () {
|
|
792
|
+
if (e.onCleanup) {
|
|
793
|
+
e.onCleanup();
|
|
794
|
+
e.onCleanup = undefined;
|
|
795
|
+
}
|
|
796
|
+
// Run in a batch so changes don't happen until we're done tracking here
|
|
797
|
+
beginBatch();
|
|
798
|
+
// Run the function/selector
|
|
799
|
+
delete e.value;
|
|
800
|
+
// Dispose listeners from previous run
|
|
801
|
+
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
802
|
+
const { dispose: _dispose, value } = trackSelector(selectorOrRun, update, e, options);
|
|
803
|
+
dispose = _dispose;
|
|
804
|
+
e.value = value;
|
|
805
|
+
if (e.onCleanupReaction) {
|
|
806
|
+
e.onCleanupReaction();
|
|
807
|
+
e.onCleanupReaction = undefined;
|
|
808
|
+
}
|
|
809
|
+
endBatch();
|
|
810
|
+
// Call the reaction if there is one and the value changed
|
|
811
|
+
if (reaction &&
|
|
812
|
+
((options === null || options === void 0 ? void 0 : options.fromComputed) || ((e.num > 0 || !isEvent(selectorOrRun)) && e.previous !== e.value))) {
|
|
813
|
+
reaction(e);
|
|
814
|
+
}
|
|
815
|
+
// Update the previous value
|
|
816
|
+
e.previous = e.value;
|
|
817
|
+
// Increment the counter
|
|
818
|
+
e.num++;
|
|
819
|
+
};
|
|
820
|
+
update();
|
|
821
|
+
// Return function calling dispose because dispose may be changed in update()
|
|
822
|
+
return () => {
|
|
823
|
+
var _a, _b;
|
|
824
|
+
(_a = e.onCleanup) === null || _a === void 0 ? void 0 : _a.call(e);
|
|
825
|
+
e.onCleanup = undefined;
|
|
826
|
+
(_b = e.onCleanupReaction) === null || _b === void 0 ? void 0 : _b.call(e);
|
|
827
|
+
e.onCleanupReaction = undefined;
|
|
828
|
+
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
const ArrayModifiers = new Set([
|
|
833
|
+
'copyWithin',
|
|
834
|
+
'fill',
|
|
835
|
+
'from',
|
|
836
|
+
'pop',
|
|
837
|
+
'push',
|
|
838
|
+
'reverse',
|
|
839
|
+
'shift',
|
|
840
|
+
'sort',
|
|
841
|
+
'splice',
|
|
842
|
+
'unshift',
|
|
843
|
+
]);
|
|
844
|
+
const ArrayLoopers = new Set([
|
|
845
|
+
'every',
|
|
846
|
+
'filter',
|
|
847
|
+
'find',
|
|
848
|
+
'findIndex',
|
|
849
|
+
'forEach',
|
|
850
|
+
'includes',
|
|
851
|
+
'join',
|
|
852
|
+
'map',
|
|
853
|
+
'some',
|
|
854
|
+
]);
|
|
855
|
+
const ArrayLoopersReturn = new Set(['filter', 'find']);
|
|
856
|
+
const observableProperties = new Map();
|
|
857
|
+
const observableFns = new Map([
|
|
858
|
+
['get', get],
|
|
859
|
+
['set', set],
|
|
860
|
+
['peek', peek],
|
|
861
|
+
['onChange', onChange],
|
|
862
|
+
['assign', assign],
|
|
863
|
+
['delete', deleteFn],
|
|
864
|
+
['toggle', toggle],
|
|
865
|
+
]);
|
|
866
|
+
if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
|
|
867
|
+
// eslint-disable-next-line no-var
|
|
868
|
+
var __devUpdateNodes = new Set();
|
|
869
|
+
}
|
|
870
|
+
function collectionSetter(node, target, prop, ...args) {
|
|
871
|
+
var _a;
|
|
872
|
+
const prevValue = (isArray(target) && target.slice()) || target;
|
|
873
|
+
const ret = target[prop].apply(target, args);
|
|
874
|
+
if (node) {
|
|
875
|
+
const hasParent = isChildNodeValue(node);
|
|
876
|
+
const key = hasParent ? node.key : '_';
|
|
877
|
+
const parentValue = hasParent ? getNodeValue(node.parent) : node.root;
|
|
878
|
+
// Set the object to the previous value first
|
|
879
|
+
parentValue[key] = prevValue;
|
|
880
|
+
// Then set with the new value so it notifies with the correct prevValue
|
|
881
|
+
setKey((_a = node.parent) !== null && _a !== void 0 ? _a : node, key, target);
|
|
576
882
|
}
|
|
577
883
|
// Return the original value
|
|
578
884
|
return ret;
|
|
@@ -761,10 +1067,10 @@ function updateNodes(parent, obj, prevValue) {
|
|
|
761
1067
|
}
|
|
762
1068
|
return retValue !== null && retValue !== void 0 ? retValue : false;
|
|
763
1069
|
}
|
|
764
|
-
function getProxy(node, p) {
|
|
1070
|
+
function getProxy(node, p, asFunction) {
|
|
765
1071
|
// Get the child node if p prop
|
|
766
1072
|
if (p !== undefined)
|
|
767
|
-
node = getChildNode(node, p);
|
|
1073
|
+
node = getChildNode(node, p, asFunction);
|
|
768
1074
|
// Create a proxy if not already cached and return it
|
|
769
1075
|
return (node.proxy || (node.proxy = new Proxy(node, proxyHandler)));
|
|
770
1076
|
}
|
|
@@ -842,6 +1148,15 @@ const proxyHandler = {
|
|
|
842
1148
|
if (isObject(value) && value[symbolOpaque]) {
|
|
843
1149
|
return vProp;
|
|
844
1150
|
}
|
|
1151
|
+
const fnOrComputed = (_a = node.functions) === null || _a === void 0 ? void 0 : _a.get(p);
|
|
1152
|
+
if (fnOrComputed) {
|
|
1153
|
+
if (isObservable(fnOrComputed)) {
|
|
1154
|
+
return fnOrComputed;
|
|
1155
|
+
}
|
|
1156
|
+
else {
|
|
1157
|
+
return getProxy(node, p, fnOrComputed);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
845
1160
|
// Handle function calls
|
|
846
1161
|
if (isFunction(vProp)) {
|
|
847
1162
|
if (isArray(value)) {
|
|
@@ -888,16 +1203,11 @@ const proxyHandler = {
|
|
|
888
1203
|
// Update that this primitive node was accessed for observers
|
|
889
1204
|
if (isArray(value) && p === 'length') {
|
|
890
1205
|
updateTracking(node, true);
|
|
891
|
-
// } else if (!isPrimitive(value)) {
|
|
892
|
-
// updateTracking(getChildNode(node, p));
|
|
893
1206
|
return vProp;
|
|
894
1207
|
}
|
|
895
1208
|
}
|
|
896
|
-
|
|
897
|
-
if (
|
|
898
|
-
return fnOrComputed;
|
|
899
|
-
}
|
|
900
|
-
if (p === 'state' && node.state) {
|
|
1209
|
+
// TODOV3: Remove "state"
|
|
1210
|
+
if (vProp === undefined && (p === 'state' || p === '_state') && node.state) {
|
|
901
1211
|
return node.state;
|
|
902
1212
|
}
|
|
903
1213
|
// Return an observable proxy to the property
|
|
@@ -962,6 +1272,10 @@ const proxyHandler = {
|
|
|
962
1272
|
const value = getNodeValue(node);
|
|
963
1273
|
return Reflect.has(value, prop);
|
|
964
1274
|
},
|
|
1275
|
+
apply(target, thisArg, argArray) {
|
|
1276
|
+
// If it's a function call it as a function
|
|
1277
|
+
return Reflect.apply(target, thisArg, argArray);
|
|
1278
|
+
},
|
|
965
1279
|
};
|
|
966
1280
|
function set(node, newValue) {
|
|
967
1281
|
if (node.parent) {
|
|
@@ -1002,7 +1316,7 @@ function setKey(node, key, newValue, level) {
|
|
|
1002
1316
|
}
|
|
1003
1317
|
const isRoot = !node.parent && key === '_';
|
|
1004
1318
|
// Get the child node for updating and notifying
|
|
1005
|
-
const childNode = isRoot ? node : getChildNode(node, key);
|
|
1319
|
+
const childNode = isRoot ? node : getChildNode(node, key, isFunction(newValue) ? newValue : undefined);
|
|
1006
1320
|
// Set the raw value on the parent object
|
|
1007
1321
|
const { newValue: savedValue, prevValue, parentValue } = setNodeValue(childNode, newValue);
|
|
1008
1322
|
const isFunc = isFunction(savedValue);
|
|
@@ -1141,7 +1455,7 @@ function extractPromise(node, value) {
|
|
|
1141
1455
|
if (!node.state) {
|
|
1142
1456
|
node.state = createObservable({
|
|
1143
1457
|
isLoaded: false,
|
|
1144
|
-
}, false, getProxy);
|
|
1458
|
+
}, false, extractPromise, getProxy);
|
|
1145
1459
|
}
|
|
1146
1460
|
value
|
|
1147
1461
|
.then((value) => {
|
|
@@ -1158,6 +1472,7 @@ function extractFunctionOrComputed(node, obj, k, v) {
|
|
|
1158
1472
|
}
|
|
1159
1473
|
else if (typeof v === 'function') {
|
|
1160
1474
|
extractFunction(node, k, v);
|
|
1475
|
+
delete obj[k];
|
|
1161
1476
|
}
|
|
1162
1477
|
else if (typeof v == 'object' && v !== null && v !== undefined) {
|
|
1163
1478
|
const childNode = getNode(v);
|
|
@@ -1180,195 +1495,130 @@ function peek(node) {
|
|
|
1180
1495
|
const value = getNodeValue(node);
|
|
1181
1496
|
// If node is not yet lazily computed go do that
|
|
1182
1497
|
if (node.lazy) {
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1498
|
+
if (isFunction(node) || isFunction(node.lazy)) {
|
|
1499
|
+
activateNodeFunction(node);
|
|
1500
|
+
}
|
|
1501
|
+
else {
|
|
1502
|
+
for (const key in value) {
|
|
1503
|
+
if (hasOwnProperty.call(value, key)) {
|
|
1504
|
+
extractFunctionOrComputed(node, value, key, value[key]);
|
|
1505
|
+
}
|
|
1187
1506
|
}
|
|
1188
1507
|
}
|
|
1508
|
+
delete node.lazy;
|
|
1189
1509
|
}
|
|
1190
1510
|
// Check if computed needs to activate
|
|
1191
1511
|
checkActivate(node);
|
|
1192
1512
|
return value;
|
|
1193
1513
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
function
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
}
|
|
1209
|
-
function getObservableIndex(obs) {
|
|
1210
|
-
const node = getNode(obs);
|
|
1211
|
-
const n = +node.key;
|
|
1212
|
-
return n - n < 1 ? +n : -1;
|
|
1213
|
-
}
|
|
1214
|
-
function opaqueObject(value) {
|
|
1215
|
-
if (value) {
|
|
1216
|
-
value[symbolOpaque] = true;
|
|
1217
|
-
}
|
|
1218
|
-
return value;
|
|
1219
|
-
}
|
|
1220
|
-
function lockObservable(obs, value) {
|
|
1221
|
-
var _a;
|
|
1222
|
-
const root = (_a = getNode(obs)) === null || _a === void 0 ? void 0 : _a.root;
|
|
1223
|
-
if (root) {
|
|
1224
|
-
root.locked = value;
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
function setAtPath(obj, path, pathTypes, value, fullObj, restore) {
|
|
1228
|
-
let o = obj;
|
|
1229
|
-
let oFull = fullObj;
|
|
1230
|
-
if (path.length > 0) {
|
|
1231
|
-
for (let i = 0; i < path.length; i++) {
|
|
1232
|
-
const p = path[i];
|
|
1233
|
-
if (i === path.length - 1) {
|
|
1234
|
-
// Don't set if the value is the same. This prevents creating a new key
|
|
1235
|
-
// when setting undefined on an object without this key
|
|
1236
|
-
if (o[p] !== value) {
|
|
1237
|
-
o[p] = value;
|
|
1514
|
+
function activateNodeFunction(node) {
|
|
1515
|
+
let dispose;
|
|
1516
|
+
let subscribed = false;
|
|
1517
|
+
let isSetting = false;
|
|
1518
|
+
// The onSet function handles the observable being set
|
|
1519
|
+
// and forwards the set elsewhere
|
|
1520
|
+
const onSet = (setter) => {
|
|
1521
|
+
const doSet = (params) => {
|
|
1522
|
+
// Don't call the set if this is the first value coming in
|
|
1523
|
+
if (params.changes.length > 1 || !isFunction(params.changes[0].prevAtPath)) {
|
|
1524
|
+
isSetting = true;
|
|
1525
|
+
try {
|
|
1526
|
+
params.isRemote = globalState.isLoadingRemote$.peek();
|
|
1527
|
+
setter(params);
|
|
1238
1528
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
// If this was previously deleted, restore it
|
|
1242
|
-
if (oFull) {
|
|
1243
|
-
o[p] = oFull[p];
|
|
1244
|
-
restore === null || restore === void 0 ? void 0 : restore(path.slice(0, i + 1), o[p]);
|
|
1529
|
+
finally {
|
|
1530
|
+
isSetting = false;
|
|
1245
1531
|
}
|
|
1246
|
-
break;
|
|
1247
1532
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1533
|
+
};
|
|
1534
|
+
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
1535
|
+
dispose = onChange(node, doSet, { immediate: true });
|
|
1536
|
+
};
|
|
1537
|
+
// The subscribe function runs a function that listens to
|
|
1538
|
+
// a data source and sends updates into the observable
|
|
1539
|
+
const subscribe = (fn) => {
|
|
1540
|
+
if (!subscribed) {
|
|
1541
|
+
subscribed = true;
|
|
1542
|
+
fn({
|
|
1543
|
+
update: ({ value }) => {
|
|
1544
|
+
globalState.onChangeRemote(() => {
|
|
1545
|
+
set(node, value);
|
|
1546
|
+
});
|
|
1547
|
+
},
|
|
1548
|
+
});
|
|
1549
|
+
}
|
|
1550
|
+
};
|
|
1551
|
+
// The proxy function simply marks the node as a proxy with this function
|
|
1552
|
+
// so that child nodes will be created with this function, and then simply
|
|
1553
|
+
// activated as a function
|
|
1554
|
+
const proxy = (fn) => {
|
|
1555
|
+
node.proxyFn2 = fn;
|
|
1556
|
+
};
|
|
1557
|
+
if (!node.state) {
|
|
1558
|
+
node.state = createObservable({
|
|
1559
|
+
isLoaded: false,
|
|
1560
|
+
}, false, extractPromise, getProxy);
|
|
1561
|
+
}
|
|
1562
|
+
const { isLoaded } = node.state;
|
|
1563
|
+
let prevTarget$;
|
|
1564
|
+
let curTarget$;
|
|
1565
|
+
let wasPromise;
|
|
1566
|
+
const activator = (isFunction(node) ? node : node.lazy);
|
|
1567
|
+
observe(() => {
|
|
1568
|
+
// Run the function at this node
|
|
1569
|
+
let value = activator({ onSet, subscribe, proxy });
|
|
1570
|
+
// If target is an observable, get() it to make sure we listen to its changes
|
|
1571
|
+
// and set up an onSet to write changes back to it
|
|
1572
|
+
if (isObservable(value)) {
|
|
1573
|
+
prevTarget$ = curTarget$;
|
|
1574
|
+
curTarget$ = value;
|
|
1575
|
+
onSet(({ value: newValue, getPrevious }) => {
|
|
1576
|
+
// Don't set the target observable if the target has changed since the last run
|
|
1577
|
+
if (!prevTarget$ || curTarget$ === prevTarget$) {
|
|
1578
|
+
// Set the node value back to what it was before before setting it.
|
|
1579
|
+
// This is a workaround for linked objects because it might not notify
|
|
1580
|
+
// if setting a property of an object
|
|
1581
|
+
// TODO: Is there a way to not do this? Or at least only do it in a
|
|
1582
|
+
// small subset of cases?
|
|
1583
|
+
setNodeValue(getNode(curTarget$), getPrevious());
|
|
1584
|
+
// Set the value on the curTarget
|
|
1585
|
+
curTarget$.set(newValue);
|
|
1586
|
+
}
|
|
1587
|
+
});
|
|
1588
|
+
// Get the value from the observable because we still want the raw value
|
|
1589
|
+
// for the effect.
|
|
1590
|
+
value = value.get();
|
|
1591
|
+
}
|
|
1592
|
+
if (isPromise(value)) {
|
|
1593
|
+
wasPromise = true;
|
|
1594
|
+
extractPromise(node, value);
|
|
1595
|
+
value = undefined;
|
|
1596
|
+
}
|
|
1597
|
+
return value;
|
|
1598
|
+
}, ({ value }) => {
|
|
1599
|
+
if (!isSetting) {
|
|
1600
|
+
const doSet = () => {
|
|
1601
|
+
set(node, value);
|
|
1602
|
+
isLoaded.set(true);
|
|
1603
|
+
};
|
|
1604
|
+
if (wasPromise) {
|
|
1605
|
+
wasPromise = false;
|
|
1606
|
+
globalState.onChangeRemote(doSet);
|
|
1250
1607
|
}
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
oFull = oFull[p];
|
|
1608
|
+
else {
|
|
1609
|
+
doSet();
|
|
1254
1610
|
}
|
|
1255
1611
|
}
|
|
1256
|
-
}
|
|
1257
|
-
else {
|
|
1258
|
-
obj = value;
|
|
1259
|
-
}
|
|
1260
|
-
return obj;
|
|
1612
|
+
}, { immediate: true, fromComputed: true });
|
|
1261
1613
|
}
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
o = o[p];
|
|
1271
|
-
v = v[p];
|
|
1272
|
-
}
|
|
1273
|
-
if (v === symbolDelete) {
|
|
1274
|
-
o.delete();
|
|
1275
|
-
}
|
|
1276
|
-
// Assign if possible, or set otherwise
|
|
1277
|
-
else if (mode === 'assign' && o.assign && isObject(o.peek())) {
|
|
1278
|
-
o.assign(v);
|
|
1279
|
-
}
|
|
1280
|
-
else {
|
|
1281
|
-
o.set(v);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
function mergeIntoObservable(target, ...sources) {
|
|
1285
|
-
beginBatch();
|
|
1286
|
-
globalState.isMerging = true;
|
|
1287
|
-
for (let i = 0; i < sources.length; i++) {
|
|
1288
|
-
target = _mergeIntoObservable(target, sources[i]);
|
|
1289
|
-
}
|
|
1290
|
-
globalState.isMerging = false;
|
|
1291
|
-
endBatch();
|
|
1292
|
-
return target;
|
|
1293
|
-
}
|
|
1294
|
-
function _mergeIntoObservable(target, source) {
|
|
1295
|
-
var _a;
|
|
1296
|
-
const needsSet = isObservable(target);
|
|
1297
|
-
const targetValue = needsSet ? target.peek() : target;
|
|
1298
|
-
const isTargetArr = isArray(targetValue);
|
|
1299
|
-
const isTargetObj = !isTargetArr && isObject(targetValue);
|
|
1300
|
-
if ((isTargetObj && isObject(source) && !isEmpty(targetValue)) ||
|
|
1301
|
-
(isTargetArr && isArray(source) && targetValue.length > 0)) {
|
|
1302
|
-
const keys = Object.keys(source);
|
|
1303
|
-
for (let i = 0; i < keys.length; i++) {
|
|
1304
|
-
const key = keys[i];
|
|
1305
|
-
const sourceValue = source[key];
|
|
1306
|
-
if (sourceValue === symbolDelete) {
|
|
1307
|
-
needsSet && ((_a = target[key]) === null || _a === void 0 ? void 0 : _a.delete) ? target[key].delete() : delete target[key];
|
|
1308
|
-
}
|
|
1309
|
-
else {
|
|
1310
|
-
const isObj = isObject(sourceValue);
|
|
1311
|
-
const isArr = !isObj && isArray(sourceValue);
|
|
1312
|
-
const targetChild = target[key];
|
|
1313
|
-
if ((isObj || isArr) && targetChild && (needsSet || !isEmpty(targetChild))) {
|
|
1314
|
-
if (!needsSet && (!targetChild || (isObj ? !isObject(targetChild) : !isArray(targetChild)))) {
|
|
1315
|
-
target[key] = sourceValue;
|
|
1316
|
-
}
|
|
1317
|
-
else {
|
|
1318
|
-
_mergeIntoObservable(targetChild, sourceValue);
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1321
|
-
else {
|
|
1322
|
-
needsSet
|
|
1323
|
-
? targetChild.set(sourceValue)
|
|
1324
|
-
: (target[key] = sourceValue);
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
else if (source !== undefined) {
|
|
1330
|
-
needsSet ? target.set(source) : (target = source);
|
|
1331
|
-
}
|
|
1332
|
-
return target;
|
|
1333
|
-
}
|
|
1334
|
-
function constructObjectWithPath(path, pathTypes, value) {
|
|
1335
|
-
let out;
|
|
1336
|
-
if (path.length > 0) {
|
|
1337
|
-
let o = (out = {});
|
|
1338
|
-
for (let i = 0; i < path.length; i++) {
|
|
1339
|
-
const p = path[i];
|
|
1340
|
-
o[p] = i === path.length - 1 ? value : pathTypes[i] === 'array' ? [] : {};
|
|
1341
|
-
o = o[p];
|
|
1342
|
-
}
|
|
1343
|
-
}
|
|
1344
|
-
else {
|
|
1345
|
-
out = value;
|
|
1346
|
-
}
|
|
1347
|
-
return out;
|
|
1348
|
-
}
|
|
1349
|
-
function deconstructObjectWithPath(path, pathTypes, value) {
|
|
1350
|
-
let o = value;
|
|
1351
|
-
for (let i = 0; i < path.length; i++) {
|
|
1352
|
-
const p = path[i];
|
|
1353
|
-
o = o ? o[p] : pathTypes[i] === 'array' ? [] : {};
|
|
1354
|
-
}
|
|
1355
|
-
return o;
|
|
1356
|
-
}
|
|
1357
|
-
function isObservableValueReady(value) {
|
|
1358
|
-
return !!value && ((!isObject(value) && !isArray(value)) || !isEmpty(value));
|
|
1359
|
-
}
|
|
1360
|
-
function setSilently(obs, newValue) {
|
|
1361
|
-
const node = getNode(obs);
|
|
1362
|
-
return setNodeValue(node, newValue).newValue;
|
|
1363
|
-
}
|
|
1364
|
-
|
|
1365
|
-
const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
|
|
1366
|
-
function ObservablePrimitiveClass(node) {
|
|
1367
|
-
this._node = node;
|
|
1368
|
-
// Bind to this
|
|
1369
|
-
for (let i = 0; i < fns.length; i++) {
|
|
1370
|
-
const key = fns[i];
|
|
1371
|
-
this[key] = this[key].bind(this);
|
|
1614
|
+
|
|
1615
|
+
const fns = ['get', 'set', 'peek', 'onChange', 'toggle'];
|
|
1616
|
+
function ObservablePrimitiveClass(node) {
|
|
1617
|
+
this._node = node;
|
|
1618
|
+
// Bind to this
|
|
1619
|
+
for (let i = 0; i < fns.length; i++) {
|
|
1620
|
+
const key = fns[i];
|
|
1621
|
+
this[key] = this[key].bind(this);
|
|
1372
1622
|
}
|
|
1373
1623
|
}
|
|
1374
1624
|
// Add observable functions to prototype
|
|
@@ -1403,122 +1653,76 @@ ObservablePrimitiveClass.prototype.delete = function () {
|
|
|
1403
1653
|
return this;
|
|
1404
1654
|
};
|
|
1405
1655
|
|
|
1406
|
-
function
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
return createObservable(value, true, getProxy, ObservablePrimitiveClass);
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
function setupTracking(nodes, update, noArgs, immediate) {
|
|
1414
|
-
let listeners = [];
|
|
1415
|
-
// Listen to tracked nodes
|
|
1416
|
-
nodes === null || nodes === void 0 ? void 0 : nodes.forEach((tracked) => {
|
|
1417
|
-
const { node, track } = tracked;
|
|
1418
|
-
listeners.push(onChange(node, update, { trackingType: track, immediate, noArgs }));
|
|
1419
|
-
});
|
|
1420
|
-
return () => {
|
|
1421
|
-
if (listeners) {
|
|
1422
|
-
for (let i = 0; i < listeners.length; i++) {
|
|
1423
|
-
listeners[i]();
|
|
1424
|
-
}
|
|
1425
|
-
listeners = undefined;
|
|
1426
|
-
}
|
|
1427
|
-
};
|
|
1428
|
-
}
|
|
1429
|
-
|
|
1430
|
-
function trackSelector(selector, update, observeEvent, observeOptions, createResubscribe) {
|
|
1431
|
-
var _a;
|
|
1432
|
-
let nodes;
|
|
1433
|
-
let value;
|
|
1434
|
-
let dispose;
|
|
1435
|
-
let tracker;
|
|
1436
|
-
let resubscribe;
|
|
1437
|
-
let updateFn = update;
|
|
1438
|
-
if (isObservable(selector)) {
|
|
1439
|
-
value = selector.peek();
|
|
1440
|
-
dispose = selector.onChange(update);
|
|
1441
|
-
resubscribe = createResubscribe ? selector.onChange(update) : undefined;
|
|
1656
|
+
function _when(predicate, effect, checkReady) {
|
|
1657
|
+
// If predicate is a regular Promise skip all the observable stuff
|
|
1658
|
+
if (isPromise(predicate)) {
|
|
1659
|
+
return effect ? predicate.then(effect) : predicate;
|
|
1442
1660
|
}
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
(_a = tracker.traceListeners) === null || _a === void 0 ? void 0 : _a.call(tracker, nodes);
|
|
1452
|
-
if (tracker.traceUpdates) {
|
|
1453
|
-
updateFn = tracker.traceUpdates(update);
|
|
1454
|
-
}
|
|
1455
|
-
// Clear tracing so it doesn't leak to other components
|
|
1456
|
-
tracker.traceListeners = undefined;
|
|
1457
|
-
tracker.traceUpdates = undefined;
|
|
1661
|
+
let value;
|
|
1662
|
+
// Create a wrapping fn that calls the effect if predicate returns true
|
|
1663
|
+
function run(e) {
|
|
1664
|
+
const ret = computeSelector(predicate);
|
|
1665
|
+
if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
1666
|
+
value = ret;
|
|
1667
|
+
// Set cancel so that observe does not track anymore
|
|
1668
|
+
e.cancel = true;
|
|
1458
1669
|
}
|
|
1670
|
+
return value;
|
|
1459
1671
|
}
|
|
1460
|
-
|
|
1461
|
-
//
|
|
1462
|
-
|
|
1463
|
-
// We want to subscribe immediately so we don't miss any updates
|
|
1464
|
-
dispose = setupTracking(nodes, updateFn, false, observeOptions === null || observeOptions === void 0 ? void 0 : observeOptions.immediate);
|
|
1465
|
-
resubscribe = createResubscribe ? () => setupTracking(nodes, updateFn) : undefined;
|
|
1672
|
+
function doEffect() {
|
|
1673
|
+
// If value is truthy then run the effect
|
|
1674
|
+
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
1466
1675
|
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1676
|
+
// Run in an observe
|
|
1677
|
+
observe(run, doEffect);
|
|
1678
|
+
// If first run resulted in a truthy value just return it.
|
|
1679
|
+
// It will have set e.cancel so no need to dispose
|
|
1680
|
+
if (isPromise(value)) {
|
|
1681
|
+
return effect ? value.then(effect) : value;
|
|
1682
|
+
}
|
|
1683
|
+
else if (value !== undefined) {
|
|
1684
|
+
return Promise.resolve(value);
|
|
1474
1685
|
}
|
|
1475
1686
|
else {
|
|
1476
|
-
|
|
1687
|
+
// Wrap it in a promise
|
|
1688
|
+
const promise = new Promise((resolve) => {
|
|
1689
|
+
if (effect) {
|
|
1690
|
+
const originalEffect = effect;
|
|
1691
|
+
effect = (value) => {
|
|
1692
|
+
const effectValue = originalEffect(value);
|
|
1693
|
+
resolve(effectValue);
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
else {
|
|
1697
|
+
effect = resolve;
|
|
1698
|
+
}
|
|
1699
|
+
});
|
|
1700
|
+
return promise;
|
|
1477
1701
|
}
|
|
1478
|
-
let dispose;
|
|
1479
|
-
const e = { num: 0 };
|
|
1480
|
-
// Wrap it in a function so it doesn't pass all the arguments to run()
|
|
1481
|
-
const update = function () {
|
|
1482
|
-
if (e.onCleanup) {
|
|
1483
|
-
e.onCleanup();
|
|
1484
|
-
e.onCleanup = undefined;
|
|
1485
|
-
}
|
|
1486
|
-
// Run in a batch so changes don't happen until we're done tracking here
|
|
1487
|
-
beginBatch();
|
|
1488
|
-
// Run the function/selector
|
|
1489
|
-
delete e.value;
|
|
1490
|
-
// Dispose listeners from previous run
|
|
1491
|
-
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
1492
|
-
const { dispose: _dispose, value } = trackSelector(selectorOrRun, update, e, options);
|
|
1493
|
-
dispose = _dispose;
|
|
1494
|
-
e.value = value;
|
|
1495
|
-
if (e.onCleanupReaction) {
|
|
1496
|
-
e.onCleanupReaction();
|
|
1497
|
-
e.onCleanupReaction = undefined;
|
|
1498
|
-
}
|
|
1499
|
-
endBatch();
|
|
1500
|
-
// Call the reaction if there is one and the value changed
|
|
1501
|
-
if (reaction &&
|
|
1502
|
-
(e.num > 0 || !isEvent(selectorOrRun)) &&
|
|
1503
|
-
(e.previous !== e.value || (options === null || options === void 0 ? void 0 : options.fromComputed))) {
|
|
1504
|
-
reaction(e);
|
|
1505
|
-
}
|
|
1506
|
-
// Update the previous value
|
|
1507
|
-
e.previous = e.value;
|
|
1508
|
-
// Increment the counter
|
|
1509
|
-
e.num++;
|
|
1510
|
-
};
|
|
1511
|
-
update();
|
|
1512
|
-
// Return function calling dispose because dispose may be changed in update()
|
|
1513
|
-
return () => {
|
|
1514
|
-
var _a, _b;
|
|
1515
|
-
(_a = e.onCleanup) === null || _a === void 0 ? void 0 : _a.call(e);
|
|
1516
|
-
e.onCleanup = undefined;
|
|
1517
|
-
(_b = e.onCleanupReaction) === null || _b === void 0 ? void 0 : _b.call(e);
|
|
1518
|
-
e.onCleanupReaction = undefined;
|
|
1519
|
-
dispose === null || dispose === void 0 ? void 0 : dispose();
|
|
1520
|
-
};
|
|
1521
1702
|
}
|
|
1703
|
+
function when(predicate, effect) {
|
|
1704
|
+
return _when(predicate, effect, false);
|
|
1705
|
+
}
|
|
1706
|
+
function whenReady(predicate, effect) {
|
|
1707
|
+
return _when(predicate, effect, true);
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
function observable(value) {
|
|
1711
|
+
return createObservable(value, false, extractPromise, getProxy, ObservablePrimitiveClass);
|
|
1712
|
+
}
|
|
1713
|
+
function observablePrimitive(value) {
|
|
1714
|
+
return createObservable(value, true, extractPromise, getProxy, ObservablePrimitiveClass);
|
|
1715
|
+
}
|
|
1716
|
+
globalState.isLoadingRemote$ = observable(false);
|
|
1717
|
+
globalState.onChangeRemote = function onChangeRemote(cb) {
|
|
1718
|
+
when(() => !globalState.isLoadingRemote$.get(), () => {
|
|
1719
|
+
// Remote changes should only update local state
|
|
1720
|
+
globalState.isLoadingRemote$.set(true);
|
|
1721
|
+
batch(cb, () => {
|
|
1722
|
+
globalState.isLoadingRemote$.set(false);
|
|
1723
|
+
});
|
|
1724
|
+
});
|
|
1725
|
+
};
|
|
1522
1726
|
|
|
1523
1727
|
function computed(compute, set$1) {
|
|
1524
1728
|
// Create an observable for this computed variable
|
|
@@ -1682,60 +1886,6 @@ function proxy(get, set) {
|
|
|
1682
1886
|
return obs;
|
|
1683
1887
|
}
|
|
1684
1888
|
|
|
1685
|
-
function _when(predicate, effect, checkReady) {
|
|
1686
|
-
// If predicate is a regular Promise skip all the observable stuff
|
|
1687
|
-
if (isPromise(predicate)) {
|
|
1688
|
-
return effect ? predicate.then(effect) : predicate;
|
|
1689
|
-
}
|
|
1690
|
-
let value;
|
|
1691
|
-
// Create a wrapping fn that calls the effect if predicate returns true
|
|
1692
|
-
function run(e) {
|
|
1693
|
-
const ret = computeSelector(predicate);
|
|
1694
|
-
if (!isPromise(ret) && (checkReady ? isObservableValueReady(ret) : ret)) {
|
|
1695
|
-
value = ret;
|
|
1696
|
-
// Set cancel so that observe does not track anymore
|
|
1697
|
-
e.cancel = true;
|
|
1698
|
-
}
|
|
1699
|
-
return value;
|
|
1700
|
-
}
|
|
1701
|
-
function doEffect() {
|
|
1702
|
-
// If value is truthy then run the effect
|
|
1703
|
-
effect === null || effect === void 0 ? void 0 : effect(value);
|
|
1704
|
-
}
|
|
1705
|
-
// Run in an observe
|
|
1706
|
-
observe(run, doEffect);
|
|
1707
|
-
// If first run resulted in a truthy value just return it.
|
|
1708
|
-
// It will have set e.cancel so no need to dispose
|
|
1709
|
-
if (isPromise(value)) {
|
|
1710
|
-
return effect ? value.then(effect) : value;
|
|
1711
|
-
}
|
|
1712
|
-
else if (value !== undefined) {
|
|
1713
|
-
return Promise.resolve(value);
|
|
1714
|
-
}
|
|
1715
|
-
else {
|
|
1716
|
-
// Wrap it in a promise
|
|
1717
|
-
const promise = new Promise((resolve) => {
|
|
1718
|
-
if (effect) {
|
|
1719
|
-
const originalEffect = effect;
|
|
1720
|
-
effect = (value) => {
|
|
1721
|
-
const effectValue = originalEffect(value);
|
|
1722
|
-
resolve(effectValue);
|
|
1723
|
-
};
|
|
1724
|
-
}
|
|
1725
|
-
else {
|
|
1726
|
-
effect = resolve;
|
|
1727
|
-
}
|
|
1728
|
-
});
|
|
1729
|
-
return promise;
|
|
1730
|
-
}
|
|
1731
|
-
}
|
|
1732
|
-
function when(predicate, effect) {
|
|
1733
|
-
return _when(predicate, effect, false);
|
|
1734
|
-
}
|
|
1735
|
-
function whenReady(predicate, effect) {
|
|
1736
|
-
return _when(predicate, effect, true);
|
|
1737
|
-
}
|
|
1738
|
-
|
|
1739
1889
|
const internal = {
|
|
1740
1890
|
ensureNodeValue,
|
|
1741
1891
|
findIDKey,
|