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