mutts 1.0.10 → 1.0.11
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/README.md +3 -3
- package/dist/browser.cjs +395 -987
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +2 -2
- package/dist/browser.dev.cjs +13 -9
- package/dist/browser.dev.cjs.map +1 -1
- package/dist/browser.dev.d.ts +2 -2
- package/dist/browser.dev.esm.js +2 -2
- package/dist/browser.esm.js +15 -13
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/{async-browser-BU_IfxYD.cjs → async-browser-Dgr5CreQ.cjs} +13 -11
- package/dist/chunks/async-browser-Dgr5CreQ.cjs.map +1 -0
- package/dist/chunks/{index-CaaQQlPJ.esm.js → index-Sf74wXTV.esm.js} +384 -981
- package/dist/chunks/index-Sf74wXTV.esm.js.map +1 -0
- package/dist/chunks/{node-nKJBk8iJ.esm.js → node-Bo7WU5S2.esm.js} +2 -2
- package/dist/chunks/{node-nKJBk8iJ.esm.js.map → node-Bo7WU5S2.esm.js.map} +1 -1
- package/dist/chunks/{proxy-Dtg-bJ3T.cjs → proxy-Cc79Lrzj.cjs} +414 -339
- package/dist/chunks/proxy-Cc79Lrzj.cjs.map +1 -0
- package/dist/chunks/{proxy-r7lARftl.esm.js → proxy-D2C49sXH.esm.js} +401 -330
- package/dist/chunks/proxy-D2C49sXH.esm.js.map +1 -0
- package/dist/debug.cjs +17 -3
- package/dist/debug.cjs.map +1 -1
- package/dist/debug.d.ts +2 -2
- package/dist/debug.esm.js +17 -3
- package/dist/debug.esm.js.map +1 -1
- package/dist/index.d.ts +84 -209
- package/dist/mutts.umd.js +842 -1362
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/node.cjs +13 -9
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.dev.cjs +13 -9
- package/dist/node.dev.cjs.map +1 -1
- package/dist/node.dev.d.ts +2 -2
- package/dist/node.dev.esm.js +3 -3
- package/dist/node.esm.js +3 -3
- package/dist/{types-W5vD6m2n.d.ts → types-Bx2PhORg.d.ts} +38 -47
- package/docs/ai/api-reference.md +0 -14
- package/docs/ai/manual.md +2 -22
- package/docs/reactive/advanced.md +13 -14
- package/docs/reactive/attend.md +1 -2
- package/docs/reactive/collections.md +2 -149
- package/docs/reactive/core.md +218 -96
- package/docs/reactive/debugging.md +2 -2
- package/docs/reactive/resource.md +1 -1
- package/docs/reactive.md +1 -3
- package/docs/zone.md +1 -1
- package/package.json +18 -9
- package/dist/chunks/async-browser-BU_IfxYD.cjs.map +0 -1
- package/dist/chunks/index-CaaQQlPJ.esm.js.map +0 -1
- package/dist/chunks/proxy-Dtg-bJ3T.cjs.map +0 -1
- package/dist/chunks/proxy-r7lARftl.esm.js.map +0 -1
- package/docs/reactive/scan.md +0 -324
package/dist/browser.cjs
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
require('./chunks/async-browser-
|
|
4
|
-
var proxy = require('./chunks/proxy-
|
|
3
|
+
require('./chunks/async-browser-Dgr5CreQ.cjs');
|
|
4
|
+
var proxy = require('./chunks/proxy-Cc79Lrzj.cjs');
|
|
5
5
|
var asyncCore = require('./chunks/async-core-CRLKP3l-.cjs');
|
|
6
6
|
require('./chunks/async-node-3PrbVAbB.cjs');
|
|
7
7
|
require('node:async_hooks');
|
|
8
8
|
|
|
9
|
+
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
9
10
|
// Integrated with `using` statement via Symbol.dispose
|
|
10
11
|
const fr = new FinalizationRegistry((f) => f());
|
|
11
12
|
/**
|
|
@@ -750,211 +751,6 @@ function chainPromise(given) {
|
|
|
750
751
|
return chained;
|
|
751
752
|
}
|
|
752
753
|
|
|
753
|
-
const memoizedRegistry = new WeakMap();
|
|
754
|
-
const wrapperRegistry = new WeakMap();
|
|
755
|
-
function getBranch(tree, key) {
|
|
756
|
-
tree.branches ?? (tree.branches = new WeakMap());
|
|
757
|
-
let branch = tree.branches.get(key);
|
|
758
|
-
if (!branch) {
|
|
759
|
-
branch = {};
|
|
760
|
-
tree.branches.set(key, branch);
|
|
761
|
-
}
|
|
762
|
-
return branch;
|
|
763
|
-
}
|
|
764
|
-
function memoizeFunction(fn, opts) {
|
|
765
|
-
const fnRoot = proxy.getRoot(fn);
|
|
766
|
-
const existing = memoizedRegistry.get(fnRoot);
|
|
767
|
-
if (existing)
|
|
768
|
-
return existing;
|
|
769
|
-
const cacheRoot = {};
|
|
770
|
-
const memoized = proxy.markWithRoot(function memoized(...args) {
|
|
771
|
-
if (args.some((arg) => !(arg && ['object', 'symbol', 'function'].includes(typeof arg)))) {
|
|
772
|
-
if (opts?.lenient)
|
|
773
|
-
return fn.apply(this, args);
|
|
774
|
-
throw new Error('memoize expects non-null object arguments');
|
|
775
|
-
}
|
|
776
|
-
let node = cacheRoot;
|
|
777
|
-
// Note: decorators add `this` as first argument
|
|
778
|
-
for (const arg of args) {
|
|
779
|
-
node = getBranch(node, arg);
|
|
780
|
-
}
|
|
781
|
-
proxy.dependant(node, 'memoize');
|
|
782
|
-
if ('result' in node) {
|
|
783
|
-
if (proxy.options.onMemoizationDiscrepancy) {
|
|
784
|
-
const wasVerification = proxy.options.isVerificationRun;
|
|
785
|
-
proxy.options.isVerificationRun = true;
|
|
786
|
-
try {
|
|
787
|
-
const fresh = proxy.untracked(() => fn.apply(this, args));
|
|
788
|
-
if (!proxy.deepCompare(node.result, fresh)) {
|
|
789
|
-
proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
finally {
|
|
793
|
-
proxy.options.isVerificationRun = wasVerification;
|
|
794
|
-
}
|
|
795
|
-
}
|
|
796
|
-
return node.result;
|
|
797
|
-
}
|
|
798
|
-
// Create memoize internal effect to track dependencies and invalidate cache
|
|
799
|
-
// Use untracked to prevent the effect creation from being affected by parent effects
|
|
800
|
-
node.cleanup = proxy.root(() => proxy.effect.named('memoize')(() => {
|
|
801
|
-
// Execute the function and track its dependencies
|
|
802
|
-
// The function execution will automatically track dependencies on reactive objects
|
|
803
|
-
node.result = fn.apply(this, args);
|
|
804
|
-
return (reason) => {
|
|
805
|
-
// When dependencies change, clear the cache and notify consumers
|
|
806
|
-
delete node.result;
|
|
807
|
-
proxy.touched1(node, { type: 'invalidate', prop: args }, 'memoize');
|
|
808
|
-
// Lazy memoization: stop the effect so it doesn't re-run immediately.
|
|
809
|
-
// It will be re-created on next access.
|
|
810
|
-
if (node.cleanup) {
|
|
811
|
-
node.cleanup({ type: 'invalidate', cause: reason });
|
|
812
|
-
node.cleanup = undefined;
|
|
813
|
-
}
|
|
814
|
-
};
|
|
815
|
-
}, { opaque: true }));
|
|
816
|
-
if (proxy.options.onMemoizationDiscrepancy) {
|
|
817
|
-
const wasVerification = proxy.options.isVerificationRun;
|
|
818
|
-
proxy.options.isVerificationRun = true;
|
|
819
|
-
try {
|
|
820
|
-
const fresh = proxy.untracked(() => fn.apply(this, args));
|
|
821
|
-
if (!proxy.deepCompare(node.result, fresh)) {
|
|
822
|
-
proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
finally {
|
|
826
|
-
proxy.options.isVerificationRun = wasVerification;
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
return node.result;
|
|
830
|
-
}, fn);
|
|
831
|
-
memoizedRegistry.set(fnRoot, memoized);
|
|
832
|
-
memoizedRegistry.set(memoized, memoized);
|
|
833
|
-
return memoized;
|
|
834
|
-
}
|
|
835
|
-
function memoizeObject(target, opts) {
|
|
836
|
-
const existing = memoizedRegistry.get(target);
|
|
837
|
-
if (existing)
|
|
838
|
-
return existing;
|
|
839
|
-
const proxy$1 = new Proxy(target, {
|
|
840
|
-
get(source, prop, receiver) {
|
|
841
|
-
// 1. Walk prototype chain to find descriptor
|
|
842
|
-
let current = source;
|
|
843
|
-
let desc;
|
|
844
|
-
while (current) {
|
|
845
|
-
desc = Object.getOwnPropertyDescriptor(current, prop);
|
|
846
|
-
if (desc)
|
|
847
|
-
break;
|
|
848
|
-
current = Object.getPrototypeOf(current);
|
|
849
|
-
}
|
|
850
|
-
if (!desc)
|
|
851
|
-
return Reflect.get(source, prop, receiver);
|
|
852
|
-
// 2. If getter, memoize
|
|
853
|
-
if (desc.get) {
|
|
854
|
-
const originalGetter = desc.get;
|
|
855
|
-
let wrapper = wrapperRegistry.get(originalGetter);
|
|
856
|
-
if (!wrapper) {
|
|
857
|
-
wrapper = proxy.markWithRoot(proxy.named(`${String(source?.constructor?.name ?? 'Object')}.${String(prop)}`, (that) => {
|
|
858
|
-
return originalGetter.call(that);
|
|
859
|
-
}), {
|
|
860
|
-
propertyKey: prop,
|
|
861
|
-
});
|
|
862
|
-
const origRoot = originalGetter[proxy.rootFunctionSymbol];
|
|
863
|
-
if (origRoot)
|
|
864
|
-
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
865
|
-
wrapperRegistry.set(originalGetter, wrapper);
|
|
866
|
-
}
|
|
867
|
-
const memoized = memoizeFunction(wrapper, opts);
|
|
868
|
-
return memoized(receiver);
|
|
869
|
-
}
|
|
870
|
-
// 3. Otherwise forward
|
|
871
|
-
return Reflect.get(source, prop, receiver);
|
|
872
|
-
},
|
|
873
|
-
// Forward set to the target (source) to ensure it acts as the receiver for reactivity notifications
|
|
874
|
-
set(source, prop, value, _receiver) {
|
|
875
|
-
// By strictly passing `source` as receiver, we ensure that if `source` is a reactive proxy,
|
|
876
|
-
// it recognizes itself and triggers change notifications.
|
|
877
|
-
return Reflect.set(source, prop, value, source);
|
|
878
|
-
},
|
|
879
|
-
});
|
|
880
|
-
proxy.proxyToObject.set(proxy$1, target);
|
|
881
|
-
memoizedRegistry.set(target, proxy$1);
|
|
882
|
-
return proxy$1;
|
|
883
|
-
}
|
|
884
|
-
/**
|
|
885
|
-
* Decorator and function wrapper for memoizing computed values based on reactive dependencies.
|
|
886
|
-
*
|
|
887
|
-
* When used as a decorator on getters or methods, it caches the result and automatically
|
|
888
|
-
* invalidates the cache when reactive dependencies change.
|
|
889
|
-
*
|
|
890
|
-
* When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
|
|
891
|
-
*
|
|
892
|
-
* @example
|
|
893
|
-
* ```typescript
|
|
894
|
-
* class User {
|
|
895
|
-
* @memoize
|
|
896
|
-
* get fullName() {
|
|
897
|
-
* return `${this.firstName} ${this.lastName}`
|
|
898
|
-
* }
|
|
899
|
-
* }
|
|
900
|
-
*
|
|
901
|
-
* // Or as a function wrapper
|
|
902
|
-
* const expensive = memoize((obj: SomeObject) => {
|
|
903
|
-
* return heavyComputation(obj)
|
|
904
|
-
* })
|
|
905
|
-
* ```
|
|
906
|
-
*/
|
|
907
|
-
function makeMemoizeDecorator(memoizeOpts) {
|
|
908
|
-
return proxy.decorator({
|
|
909
|
-
getter(original, target, propertyKey) {
|
|
910
|
-
return function () {
|
|
911
|
-
let wrapper = wrapperRegistry.get(original);
|
|
912
|
-
if (!wrapper) {
|
|
913
|
-
wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(propertyKey)}`, (that) => {
|
|
914
|
-
return original.call(that);
|
|
915
|
-
}), {
|
|
916
|
-
method: original,
|
|
917
|
-
propertyKey,
|
|
918
|
-
});
|
|
919
|
-
const origRoot = original[proxy.rootFunctionSymbol];
|
|
920
|
-
if (origRoot)
|
|
921
|
-
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
922
|
-
wrapperRegistry.set(original, wrapper);
|
|
923
|
-
}
|
|
924
|
-
const memoized = memoizeFunction(wrapper, memoizeOpts);
|
|
925
|
-
return memoized(this);
|
|
926
|
-
};
|
|
927
|
-
},
|
|
928
|
-
method(original, target, name) {
|
|
929
|
-
return function (...args) {
|
|
930
|
-
let wrapper = wrapperRegistry.get(original);
|
|
931
|
-
if (!wrapper) {
|
|
932
|
-
wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(name)}`, (that, ...args) => {
|
|
933
|
-
return original.call(that, ...args);
|
|
934
|
-
}), {
|
|
935
|
-
method: original,
|
|
936
|
-
propertyKey: name,
|
|
937
|
-
});
|
|
938
|
-
const origRoot = original[proxy.rootFunctionSymbol];
|
|
939
|
-
if (origRoot)
|
|
940
|
-
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
941
|
-
wrapperRegistry.set(original, wrapper);
|
|
942
|
-
}
|
|
943
|
-
const memoized = memoizeFunction(wrapper, memoizeOpts);
|
|
944
|
-
return memoized(this, ...args);
|
|
945
|
-
};
|
|
946
|
-
},
|
|
947
|
-
default: (target) => typeof target === 'object'
|
|
948
|
-
? memoizeObject(target, memoizeOpts)
|
|
949
|
-
: memoizeFunction(target, memoizeOpts),
|
|
950
|
-
});
|
|
951
|
-
}
|
|
952
|
-
const memoize = proxy.flavored(makeMemoizeDecorator(), {
|
|
953
|
-
get lenient() {
|
|
954
|
-
return makeMemoizeDecorator({ lenient: true });
|
|
955
|
-
},
|
|
956
|
-
});
|
|
957
|
-
|
|
958
754
|
function attend(source, callback) {
|
|
959
755
|
const enumerate = typeof source === 'function'
|
|
960
756
|
? source
|
|
@@ -966,14 +762,14 @@ function attend(source, callback) {
|
|
|
966
762
|
? () => source.values()
|
|
967
763
|
: () => Object.keys(source);
|
|
968
764
|
const keyEffects = new Map();
|
|
969
|
-
const outer = proxy.effect(({ ascend }) => {
|
|
765
|
+
const outer = proxy.effect.named('attend')(({ ascend }) => {
|
|
970
766
|
const keys = new Set();
|
|
971
767
|
for (const key of enumerate())
|
|
972
768
|
keys.add(key);
|
|
973
769
|
for (const key of keys) {
|
|
974
770
|
if (keyEffects.has(key))
|
|
975
771
|
continue;
|
|
976
|
-
keyEffects.set(key, ascend(() => proxy.effect(() => callback(key))));
|
|
772
|
+
keyEffects.set(key, ascend(() => proxy.effect.named(`attend:${key}`)((access) => callback(key, access))));
|
|
977
773
|
}
|
|
978
774
|
for (const key of Array.from(keyEffects.keys())) {
|
|
979
775
|
if (!keys.has(key)) {
|
|
@@ -989,146 +785,10 @@ function attend(source, callback) {
|
|
|
989
785
|
keyEffects.clear();
|
|
990
786
|
};
|
|
991
787
|
}
|
|
992
|
-
/**
|
|
993
|
-
* Perform a reactive scan over an array of items.
|
|
994
|
-
*
|
|
995
|
-
* This implementation is highly optimized for performance and fine-grained reactivity:
|
|
996
|
-
* - **Incremental Updates**: Changes to an item only trigger re-computation from that
|
|
997
|
-
* point onwards in the result chain.
|
|
998
|
-
* - **Move Optimization**: If items are moved within the array, their accumulated
|
|
999
|
-
* values are reused as long as their predecessor remains the same.
|
|
1000
|
-
* - **Duplicate Support**: Correctly handles multiple occurrences of the same object
|
|
1001
|
-
* instance using an internal occurrence tracking mechanism.
|
|
1002
|
-
* - **Memory Efficient**: Uses `WeakMap` for caching intermediates, which are
|
|
1003
|
-
* automatically cleared when source items are garbage collected.
|
|
1004
|
-
*
|
|
1005
|
-
* @example
|
|
1006
|
-
* ```typescript
|
|
1007
|
-
* const source = reactive([{ val: 1 }, { val: 2 }, { val: 3 }])
|
|
1008
|
-
* const sum = scan(source, (acc, item) => acc + item.val, 0)
|
|
1009
|
-
*
|
|
1010
|
-
* expect([...sum]).toEqual([1, 3, 6])
|
|
1011
|
-
*
|
|
1012
|
-
* // Modifying an item only re-computes subsequent sums
|
|
1013
|
-
* source[1].val = 10
|
|
1014
|
-
* expect([...sum]).toEqual([1, 11, 14])
|
|
1015
|
-
* ```
|
|
1016
|
-
*
|
|
1017
|
-
* @param source The source array of objects (will be made reactive)
|
|
1018
|
-
* @param callback The accumulator function called with (accumulator, currentItem)
|
|
1019
|
-
* @param initialValue The starting value for the accumulation
|
|
1020
|
-
* @returns A reactive array of accumulated values, with a [cleanup] property to stop the tracking
|
|
1021
|
-
*/
|
|
1022
|
-
function scan(source, callback, initialValue) {
|
|
1023
|
-
const observedSource = proxy.reactive(source);
|
|
1024
|
-
const rawResult = [];
|
|
1025
|
-
const result = proxy.reactive(rawResult);
|
|
1026
|
-
// Track effects for each index to dispose them when the array shrinks
|
|
1027
|
-
const indexEffects = new Map();
|
|
1028
|
-
// Mapping from index to its current intermediate object
|
|
1029
|
-
const indexToIntermediate = proxy.reactive([]);
|
|
1030
|
-
const intermediaries = new WeakMap();
|
|
1031
|
-
let Intermediate = (() => {
|
|
1032
|
-
var _a;
|
|
1033
|
-
let _instanceExtraInitializers = [];
|
|
1034
|
-
let _get_acc_decorators;
|
|
1035
|
-
return _a = class Intermediate {
|
|
1036
|
-
constructor(val, prev) {
|
|
1037
|
-
this.val = (proxy.__runInitializers(this, _instanceExtraInitializers), val);
|
|
1038
|
-
this.prev = prev;
|
|
1039
|
-
}
|
|
1040
|
-
get acc() {
|
|
1041
|
-
const prevAcc = this.prev ? this.prev.acc : initialValue;
|
|
1042
|
-
return callback(prevAcc, this.val);
|
|
1043
|
-
}
|
|
1044
|
-
},
|
|
1045
|
-
(() => {
|
|
1046
|
-
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1047
|
-
_get_acc_decorators = [memoize];
|
|
1048
|
-
proxy.__esDecorate(_a, null, _get_acc_decorators, { kind: "getter", name: "acc", static: false, private: false, access: { has: obj => "acc" in obj, get: obj => obj.acc }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
1049
|
-
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1050
|
-
})(),
|
|
1051
|
-
_a;
|
|
1052
|
-
})();
|
|
1053
|
-
function disposeIndex(index) {
|
|
1054
|
-
const stop = indexEffects.get(index);
|
|
1055
|
-
if (stop) {
|
|
1056
|
-
stop();
|
|
1057
|
-
indexEffects.delete(index);
|
|
1058
|
-
Reflect.deleteProperty(indexToIntermediate, index);
|
|
1059
|
-
Reflect.deleteProperty(result, index);
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
const mainEffect = proxy.effect(function scanMainEffect({ ascend }) {
|
|
1063
|
-
const length = observedSource.length;
|
|
1064
|
-
const occurrenceCount = new Map();
|
|
1065
|
-
let prev;
|
|
1066
|
-
for (let i = 0; i < length; i++)
|
|
1067
|
-
if (i in observedSource) {
|
|
1068
|
-
const val = observedSource[i];
|
|
1069
|
-
if (!(val &&
|
|
1070
|
-
(typeof val === 'object' || typeof val === 'function' || typeof val === 'symbol'))) {
|
|
1071
|
-
throw new Error('scan: items must be objects (WeakKey) for intermediate caching');
|
|
1072
|
-
}
|
|
1073
|
-
const count = occurrenceCount.get(val) ?? 0;
|
|
1074
|
-
occurrenceCount.set(val, count + 1);
|
|
1075
|
-
let list = intermediaries.get(val);
|
|
1076
|
-
if (!list) {
|
|
1077
|
-
list = [];
|
|
1078
|
-
intermediaries.set(val, list);
|
|
1079
|
-
}
|
|
1080
|
-
let intermediate = list[count];
|
|
1081
|
-
if (!intermediate) {
|
|
1082
|
-
intermediate = proxy.reactive(new Intermediate(val, prev));
|
|
1083
|
-
list[count] = intermediate;
|
|
1084
|
-
}
|
|
1085
|
-
else {
|
|
1086
|
-
// Update the link.
|
|
1087
|
-
if (proxy.untracked(() => intermediate.prev) !== prev) {
|
|
1088
|
-
intermediate.prev = prev;
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
// Update the reactive mapping for this index
|
|
1092
|
-
if (indexToIntermediate[i] !== intermediate) {
|
|
1093
|
-
indexToIntermediate[i] = intermediate;
|
|
1094
|
-
}
|
|
1095
|
-
// If we don't have an effect for this index yet, create one
|
|
1096
|
-
if (!indexEffects.has(i)) {
|
|
1097
|
-
ascend(() => {
|
|
1098
|
-
const index = i;
|
|
1099
|
-
const stop = proxy.effect(function scanIndexSyncEffect() {
|
|
1100
|
-
const inter = indexToIntermediate[index];
|
|
1101
|
-
if (inter) {
|
|
1102
|
-
const accValue = inter.acc;
|
|
1103
|
-
result[index] = accValue;
|
|
1104
|
-
}
|
|
1105
|
-
});
|
|
1106
|
-
indexEffects.set(index, stop);
|
|
1107
|
-
});
|
|
1108
|
-
}
|
|
1109
|
-
prev = intermediate;
|
|
1110
|
-
}
|
|
1111
|
-
// Cleanup trailing indices
|
|
1112
|
-
for (const index of Array.from(indexEffects.keys())) {
|
|
1113
|
-
if (index >= length)
|
|
1114
|
-
disposeIndex(index);
|
|
1115
|
-
}
|
|
1116
|
-
// Ensure result length matches source length
|
|
1117
|
-
if (rawResult.length !== length) {
|
|
1118
|
-
proxy.FoolProof.set(result, 'length', length, result);
|
|
1119
|
-
}
|
|
1120
|
-
});
|
|
1121
|
-
return proxy.cleanedBy(result, ((reason) => {
|
|
1122
|
-
mainEffect(reason);
|
|
1123
|
-
for (const stop of indexEffects.values())
|
|
1124
|
-
stop(reason);
|
|
1125
|
-
indexEffects.clear();
|
|
1126
|
-
}));
|
|
1127
|
-
}
|
|
1128
788
|
function lift(cb) {
|
|
1129
789
|
let result;
|
|
1130
790
|
let rawResult;
|
|
1131
|
-
const liftCleanup = proxy.effect.named(
|
|
791
|
+
const liftCleanup = proxy.effect.named(`lift:${cb.name}`)(proxy.markWithRoot((access) => {
|
|
1132
792
|
const source = cb(access);
|
|
1133
793
|
if (!source || typeof source !== 'object')
|
|
1134
794
|
throw new Error('lift callback must return an array or object');
|
|
@@ -1141,11 +801,8 @@ function lift(cb) {
|
|
|
1141
801
|
throw new Error('lift callback must return the same type as the previous result');
|
|
1142
802
|
if (Array.isArray(source)) {
|
|
1143
803
|
const res = result;
|
|
1144
|
-
const
|
|
1145
|
-
for (let i = patches.length - 1; i >= 0; i--) {
|
|
1146
|
-
const { indexA, sliceA, sliceB } = patches[i];
|
|
804
|
+
for (const { indexA, sliceA, sliceB } of arrayDiff(res, source).sort((a, b) => a.indexA - b.indexA))
|
|
1147
805
|
res.splice(indexA, sliceA.length, ...sliceB);
|
|
1148
|
-
}
|
|
1149
806
|
}
|
|
1150
807
|
else {
|
|
1151
808
|
for (const key of Object.keys(source)) {
|
|
@@ -1172,7 +829,7 @@ function lift(cb) {
|
|
|
1172
829
|
}
|
|
1173
830
|
}
|
|
1174
831
|
}, cb));
|
|
1175
|
-
return proxy.
|
|
832
|
+
return proxy.link(result, liftCleanup);
|
|
1176
833
|
}
|
|
1177
834
|
/**
|
|
1178
835
|
* Reactively maps an array source through `fn`, producing a lazy reactive output array.
|
|
@@ -1193,7 +850,7 @@ function lift(cb) {
|
|
|
1193
850
|
*/
|
|
1194
851
|
function morphArray(source, fn, options) {
|
|
1195
852
|
if (typeof source !== 'function' && !proxy.isReactive(source) && options?.pure === true) {
|
|
1196
|
-
return source.map(fn);
|
|
853
|
+
return source.map((i) => fn(i));
|
|
1197
854
|
}
|
|
1198
855
|
let track;
|
|
1199
856
|
const itemEffects = new Map();
|
|
@@ -1215,17 +872,14 @@ function morphArray(source, fn, options) {
|
|
|
1215
872
|
}
|
|
1216
873
|
else {
|
|
1217
874
|
const indexRef = { value: key };
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
cache[indexRef.value]
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
};
|
|
1227
|
-
});
|
|
1228
|
-
});
|
|
875
|
+
const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
|
|
876
|
+
cache[indexRef.value] = fn(input, access);
|
|
877
|
+
return (reason) => {
|
|
878
|
+
delete cache[indexRef.value];
|
|
879
|
+
proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
880
|
+
stop?.({ type: 'invalidate', cause: reason });
|
|
881
|
+
};
|
|
882
|
+
}));
|
|
1229
883
|
itemEffects.set(key, { stop, index: indexRef });
|
|
1230
884
|
}
|
|
1231
885
|
}
|
|
@@ -1242,7 +896,7 @@ function morphArray(source, fn, options) {
|
|
|
1242
896
|
return Reflect.has(input, prop);
|
|
1243
897
|
},
|
|
1244
898
|
});
|
|
1245
|
-
const stopMain = proxy.effect.named(
|
|
899
|
+
const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
|
|
1246
900
|
track = ascend;
|
|
1247
901
|
const newInput = [...(typeof source === 'function' ? source() : source)];
|
|
1248
902
|
const diffs = arrayDiff(input, newInput).toSorted((a, b) => b.indexA - a.indexA);
|
|
@@ -1257,7 +911,7 @@ function morphArray(source, fn, options) {
|
|
|
1257
911
|
// We need to move entries in the Map.
|
|
1258
912
|
const entries = Array.from(itemEffects.entries()).sort((a, b) => a[0] - b[0]);
|
|
1259
913
|
// Remove entries that will be shifted
|
|
1260
|
-
for (const [idx,
|
|
914
|
+
for (const [idx, _entry] of entries) {
|
|
1261
915
|
if (idx >= diff.indexA + diff.sliceA.length) {
|
|
1262
916
|
itemEffects.delete(idx);
|
|
1263
917
|
}
|
|
@@ -1289,7 +943,7 @@ function morphArray(source, fn, options) {
|
|
|
1289
943
|
}
|
|
1290
944
|
input = newInput;
|
|
1291
945
|
});
|
|
1292
|
-
return proxy.
|
|
946
|
+
return proxy.link(proxy$1, (reason) => {
|
|
1293
947
|
stopMain(reason);
|
|
1294
948
|
for (const entry of itemEffects.values())
|
|
1295
949
|
entry.stop(reason);
|
|
@@ -1311,7 +965,7 @@ function morphMap(source, fn, options) {
|
|
|
1311
965
|
if (!proxy.isReactive(source) && options?.pure === true) {
|
|
1312
966
|
const res = new Map();
|
|
1313
967
|
for (const [k, v] of source)
|
|
1314
|
-
res.set(k, fn(v));
|
|
968
|
+
res.set(k, fn(v, k));
|
|
1315
969
|
return res;
|
|
1316
970
|
}
|
|
1317
971
|
let track;
|
|
@@ -1328,15 +982,15 @@ function morphMap(source, fn, options) {
|
|
|
1328
982
|
function computeItem(key, val) {
|
|
1329
983
|
const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
|
|
1330
984
|
if (isPure) {
|
|
1331
|
-
cache.set(key, track(() => fn(val)));
|
|
985
|
+
cache.set(key, track(() => fn(val, key)));
|
|
1332
986
|
}
|
|
1333
987
|
else {
|
|
1334
|
-
const stop = track(() => proxy.effect.opaque(() => {
|
|
1335
|
-
cache.set(key, fn(source.get(key)));
|
|
988
|
+
const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
|
|
989
|
+
cache.set(key, fn(source.get(key), key, access));
|
|
1336
990
|
return (reason) => {
|
|
1337
991
|
cache.delete(key);
|
|
1338
992
|
proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
1339
|
-
stop({ type: 'invalidate', cause: reason });
|
|
993
|
+
stop?.({ type: 'invalidate', cause: reason });
|
|
1340
994
|
};
|
|
1341
995
|
}));
|
|
1342
996
|
itemEffects.set(key, stop);
|
|
@@ -1380,7 +1034,7 @@ function morphMap(source, fn, options) {
|
|
|
1380
1034
|
},
|
|
1381
1035
|
});
|
|
1382
1036
|
let stateSnapshot = proxy.getState(source);
|
|
1383
|
-
const stopMain = proxy.effect.named(
|
|
1037
|
+
const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
|
|
1384
1038
|
track = ascend;
|
|
1385
1039
|
proxy.dependant(source, proxy.keysOf);
|
|
1386
1040
|
while ('evolution' in stateSnapshot) {
|
|
@@ -1396,7 +1050,7 @@ function morphMap(source, fn, options) {
|
|
|
1396
1050
|
}
|
|
1397
1051
|
}
|
|
1398
1052
|
});
|
|
1399
|
-
return proxy.
|
|
1053
|
+
return proxy.link(proxy$1, (reason) => {
|
|
1400
1054
|
stopMain(reason);
|
|
1401
1055
|
for (const stop of itemEffects.values())
|
|
1402
1056
|
stop(reason);
|
|
@@ -1418,7 +1072,7 @@ function morphRecord(source, fn, options) {
|
|
|
1418
1072
|
if (!proxy.isReactive(source) && options?.pure === true) {
|
|
1419
1073
|
const res = {};
|
|
1420
1074
|
for (const k of Object.keys(source))
|
|
1421
|
-
res[k] = fn(source[k]);
|
|
1075
|
+
res[k] = fn(source[k], k);
|
|
1422
1076
|
return res;
|
|
1423
1077
|
}
|
|
1424
1078
|
let track;
|
|
@@ -1434,15 +1088,15 @@ function morphRecord(source, fn, options) {
|
|
|
1434
1088
|
function computeItem(key, val) {
|
|
1435
1089
|
const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(val));
|
|
1436
1090
|
if (isPure) {
|
|
1437
|
-
cache[key] = track(() => fn(val));
|
|
1091
|
+
cache[key] = track(() => fn(val, key));
|
|
1438
1092
|
}
|
|
1439
1093
|
else {
|
|
1440
|
-
const stop = track(() => proxy.effect.opaque(() => {
|
|
1441
|
-
cache[key] = fn(source[key]);
|
|
1094
|
+
const stop = track(() => proxy.effect.named(`morph:${fn.name}:${key}`).opaque((access) => {
|
|
1095
|
+
cache[key] = fn(source[key], key, access);
|
|
1442
1096
|
return (reason) => {
|
|
1443
1097
|
delete cache[key];
|
|
1444
1098
|
proxy.touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
1445
|
-
stop({ type: 'invalidate', cause: reason });
|
|
1099
|
+
stop?.({ type: 'invalidate', cause: reason });
|
|
1446
1100
|
};
|
|
1447
1101
|
}));
|
|
1448
1102
|
itemEffects.set(key, stop);
|
|
@@ -1469,7 +1123,7 @@ function morphRecord(source, fn, options) {
|
|
|
1469
1123
|
},
|
|
1470
1124
|
});
|
|
1471
1125
|
let stateSnapshot = proxy.getState(source);
|
|
1472
|
-
const stopMain = proxy.effect.named(
|
|
1126
|
+
const stopMain = proxy.effect.named(`morph:${fn.name}`)(({ ascend }) => {
|
|
1473
1127
|
track = ascend;
|
|
1474
1128
|
// Track only structural changes on source
|
|
1475
1129
|
proxy.dependant(source, proxy.keysOf);
|
|
@@ -1486,7 +1140,7 @@ function morphRecord(source, fn, options) {
|
|
|
1486
1140
|
}
|
|
1487
1141
|
}
|
|
1488
1142
|
});
|
|
1489
|
-
return proxy.
|
|
1143
|
+
return proxy.link(proxy$1, (reason) => {
|
|
1490
1144
|
stopMain(reason);
|
|
1491
1145
|
for (const stop of itemEffects.values())
|
|
1492
1146
|
stop(reason);
|
|
@@ -1545,7 +1199,7 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
1545
1199
|
const wrappedCallback = proxy.markWithRoot((() => callback(target)), callback);
|
|
1546
1200
|
proxy.registerDeepWatcher();
|
|
1547
1201
|
// Use the existing effect system to register dependencies
|
|
1548
|
-
return proxy.effect(() => {
|
|
1202
|
+
return proxy.effect.named('deepWatch')(() => {
|
|
1549
1203
|
// Mark the target object as having deep watchers
|
|
1550
1204
|
proxy.objectsWithDeepWatchers.add(target);
|
|
1551
1205
|
// Track which objects this effect is watching for cleanup
|
|
@@ -1581,35 +1235,24 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
1581
1235
|
}
|
|
1582
1236
|
}
|
|
1583
1237
|
// Also handle array indices and length
|
|
1584
|
-
//
|
|
1585
|
-
if (
|
|
1586
|
-
// Access
|
|
1587
|
-
const length = obj.length;
|
|
1588
|
-
// Access all current array elements to register dependencies
|
|
1589
|
-
for (let i = 0; i < length; i++) {
|
|
1590
|
-
// Access the array element to register dependency
|
|
1591
|
-
const value = obj[i];
|
|
1592
|
-
// Make the value reactive if it's an object
|
|
1593
|
-
const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
|
|
1594
|
-
traverseAndTrack(reactiveValue, depth + 1);
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
// Handle Set values (deep watch values only, not keys since Sets don't have separate keys)
|
|
1598
|
-
else if (obj instanceof Set) {
|
|
1599
|
-
// Access all Set values to register dependencies
|
|
1238
|
+
// Handle arrays and collections using iterators to ensure proxy tracking is triggered
|
|
1239
|
+
if (typeof obj[Symbol.iterator] === 'function') {
|
|
1240
|
+
// Access the iterator to track additions/removals/collection changes
|
|
1600
1241
|
for (const value of obj) {
|
|
1601
1242
|
// Make the value reactive if it's an object
|
|
1602
1243
|
const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
|
|
1603
1244
|
traverseAndTrack(reactiveValue, depth + 1);
|
|
1604
1245
|
}
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
const
|
|
1612
|
-
|
|
1246
|
+
// Explicitly depend on length so array mutations changing count trigger re-evaluation
|
|
1247
|
+
if ('length' in obj) {
|
|
1248
|
+
proxy.dependant(obj, 'length');
|
|
1249
|
+
}
|
|
1250
|
+
// For Maps, also ensure we track values explicitly if the iterator yields entries
|
|
1251
|
+
if (obj instanceof Map) {
|
|
1252
|
+
for (const value of obj.values()) {
|
|
1253
|
+
const reactiveValue = typeof value === 'object' && value !== null ? proxy.reactive(value) : value;
|
|
1254
|
+
traverseAndTrack(reactiveValue, depth + 1);
|
|
1255
|
+
}
|
|
1613
1256
|
}
|
|
1614
1257
|
}
|
|
1615
1258
|
// Note: WeakSet and WeakMap cannot be iterated, so we can't deep watch their contents
|
|
@@ -1646,12 +1289,217 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
1646
1289
|
proxy.objectsWithDeepWatchers.delete(obj);
|
|
1647
1290
|
}
|
|
1648
1291
|
}
|
|
1649
|
-
// Clean up the tracking data
|
|
1650
|
-
proxy.effectToDeepWatchedObjects.delete(wrappedCallback);
|
|
1292
|
+
// Clean up the tracking data
|
|
1293
|
+
proxy.effectToDeepWatchedObjects.delete(wrappedCallback);
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
const memoizedRegistry = new WeakMap();
|
|
1300
|
+
const wrapperRegistry = new WeakMap();
|
|
1301
|
+
function getBranch(tree, key) {
|
|
1302
|
+
tree.branches ?? (tree.branches = new WeakMap());
|
|
1303
|
+
let branch = tree.branches.get(key);
|
|
1304
|
+
if (!branch) {
|
|
1305
|
+
branch = {};
|
|
1306
|
+
tree.branches.set(key, branch);
|
|
1307
|
+
}
|
|
1308
|
+
return branch;
|
|
1309
|
+
}
|
|
1310
|
+
function memoizeFunction(fn, opts) {
|
|
1311
|
+
const fnRoot = proxy.getRoot(fn);
|
|
1312
|
+
const existing = memoizedRegistry.get(fnRoot);
|
|
1313
|
+
if (existing)
|
|
1314
|
+
return existing;
|
|
1315
|
+
const cacheRoot = {};
|
|
1316
|
+
const memoized = proxy.markWithRoot(function memoized(...args) {
|
|
1317
|
+
if (args.some((arg) => !(arg && ['object', 'symbol', 'function'].includes(typeof arg)))) {
|
|
1318
|
+
if (opts?.lenient)
|
|
1319
|
+
return fn.apply(this, args);
|
|
1320
|
+
throw new Error('memoize expects non-null object arguments');
|
|
1321
|
+
}
|
|
1322
|
+
let node = cacheRoot;
|
|
1323
|
+
// Note: decorators add `this` as first argument
|
|
1324
|
+
for (const arg of args) {
|
|
1325
|
+
node = getBranch(node, arg);
|
|
1326
|
+
}
|
|
1327
|
+
proxy.dependant(node, 'memoize');
|
|
1328
|
+
if ('result' in node) {
|
|
1329
|
+
if (proxy.options.onMemoizationDiscrepancy) {
|
|
1330
|
+
const wasVerification = proxy.options.isVerificationRun;
|
|
1331
|
+
proxy.options.isVerificationRun = true;
|
|
1332
|
+
try {
|
|
1333
|
+
const fresh = proxy.untracked(() => fn.apply(this, args));
|
|
1334
|
+
if (!proxy.deepCompare(node.result, fresh)) {
|
|
1335
|
+
proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
finally {
|
|
1339
|
+
proxy.options.isVerificationRun = wasVerification;
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
return node.result;
|
|
1343
|
+
}
|
|
1344
|
+
// Create memoize internal effect to track dependencies and invalidate cache
|
|
1345
|
+
// Use untracked to prevent the effect creation from being affected by parent effects
|
|
1346
|
+
node.cleanup = proxy.root(() => proxy.effect.named('memoize')(() => {
|
|
1347
|
+
// Execute the function and track its dependencies
|
|
1348
|
+
// The function execution will automatically track dependencies on reactive objects
|
|
1349
|
+
node.result = fn.apply(this, args);
|
|
1350
|
+
return (reason) => {
|
|
1351
|
+
// When dependencies change, clear the cache and notify consumers
|
|
1352
|
+
delete node.result;
|
|
1353
|
+
proxy.touched1(node, { type: 'invalidate', prop: args }, 'memoize');
|
|
1354
|
+
// Lazy memoization: stop the effect so it doesn't re-run immediately.
|
|
1355
|
+
// It will be re-created on next access.
|
|
1356
|
+
if (node.cleanup) {
|
|
1357
|
+
node.cleanup({ type: 'invalidate', cause: reason });
|
|
1358
|
+
node.cleanup = undefined;
|
|
1359
|
+
}
|
|
1360
|
+
};
|
|
1361
|
+
}, { opaque: true }));
|
|
1362
|
+
if (proxy.options.onMemoizationDiscrepancy) {
|
|
1363
|
+
const wasVerification = proxy.options.isVerificationRun;
|
|
1364
|
+
proxy.options.isVerificationRun = true;
|
|
1365
|
+
try {
|
|
1366
|
+
const fresh = proxy.untracked(() => fn.apply(this, args));
|
|
1367
|
+
if (!proxy.deepCompare(node.result, fresh)) {
|
|
1368
|
+
proxy.optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
finally {
|
|
1372
|
+
proxy.options.isVerificationRun = wasVerification;
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
return node.result;
|
|
1376
|
+
}, fn);
|
|
1377
|
+
memoizedRegistry.set(fnRoot, memoized);
|
|
1378
|
+
memoizedRegistry.set(memoized, memoized);
|
|
1379
|
+
return memoized;
|
|
1380
|
+
}
|
|
1381
|
+
function memoizeObject(target, opts) {
|
|
1382
|
+
const existing = memoizedRegistry.get(target);
|
|
1383
|
+
if (existing)
|
|
1384
|
+
return existing;
|
|
1385
|
+
const proxy$1 = new Proxy(target, {
|
|
1386
|
+
get(source, prop, receiver) {
|
|
1387
|
+
// 1. Walk prototype chain to find descriptor
|
|
1388
|
+
let current = source;
|
|
1389
|
+
let desc;
|
|
1390
|
+
while (current) {
|
|
1391
|
+
desc = Object.getOwnPropertyDescriptor(current, prop);
|
|
1392
|
+
if (desc)
|
|
1393
|
+
break;
|
|
1394
|
+
current = Object.getPrototypeOf(current);
|
|
1395
|
+
}
|
|
1396
|
+
if (!desc)
|
|
1397
|
+
return Reflect.get(source, prop, receiver);
|
|
1398
|
+
// 2. If getter, memoize
|
|
1399
|
+
if (desc.get) {
|
|
1400
|
+
const originalGetter = desc.get;
|
|
1401
|
+
let wrapper = wrapperRegistry.get(originalGetter);
|
|
1402
|
+
if (!wrapper) {
|
|
1403
|
+
wrapper = proxy.markWithRoot(proxy.named(`${String(source?.constructor?.name ?? 'Object')}.${String(prop)}`, (that) => {
|
|
1404
|
+
return originalGetter.call(that);
|
|
1405
|
+
}), {
|
|
1406
|
+
propertyKey: prop,
|
|
1407
|
+
});
|
|
1408
|
+
const origRoot = originalGetter[proxy.rootFunctionSymbol];
|
|
1409
|
+
if (origRoot)
|
|
1410
|
+
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
1411
|
+
wrapperRegistry.set(originalGetter, wrapper);
|
|
1412
|
+
}
|
|
1413
|
+
const memoized = memoizeFunction(wrapper, opts);
|
|
1414
|
+
return memoized(receiver);
|
|
1651
1415
|
}
|
|
1652
|
-
|
|
1416
|
+
// 3. Otherwise forward
|
|
1417
|
+
return Reflect.get(source, prop, receiver);
|
|
1418
|
+
},
|
|
1419
|
+
// Forward set to the target (source) to ensure it acts as the receiver for reactivity notifications
|
|
1420
|
+
set(source, prop, value, _receiver) {
|
|
1421
|
+
// By strictly passing `source` as receiver, we ensure that if `source` is a reactive proxy,
|
|
1422
|
+
// it recognizes itself and triggers change notifications.
|
|
1423
|
+
return Reflect.set(source, prop, value, source);
|
|
1424
|
+
},
|
|
1425
|
+
});
|
|
1426
|
+
proxy.proxyToObject.set(proxy$1, target);
|
|
1427
|
+
memoizedRegistry.set(target, proxy$1);
|
|
1428
|
+
return proxy$1;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Decorator and function wrapper for memoizing computed values based on reactive dependencies.
|
|
1432
|
+
*
|
|
1433
|
+
* When used as a decorator on getters or methods, it caches the result and automatically
|
|
1434
|
+
* invalidates the cache when reactive dependencies change.
|
|
1435
|
+
*
|
|
1436
|
+
* When used as a function wrapper, it memoizes based on object arguments (WeakMap-based cache).
|
|
1437
|
+
*
|
|
1438
|
+
* @example
|
|
1439
|
+
* ```typescript
|
|
1440
|
+
* class User {
|
|
1441
|
+
* @memoize
|
|
1442
|
+
* get fullName() {
|
|
1443
|
+
* return `${this.firstName} ${this.lastName}`
|
|
1444
|
+
* }
|
|
1445
|
+
* }
|
|
1446
|
+
*
|
|
1447
|
+
* // Or as a function wrapper
|
|
1448
|
+
* const expensive = memoize((obj: SomeObject) => {
|
|
1449
|
+
* return heavyComputation(obj)
|
|
1450
|
+
* })
|
|
1451
|
+
* ```
|
|
1452
|
+
*/
|
|
1453
|
+
function makeMemoizeDecorator(memoizeOpts) {
|
|
1454
|
+
return proxy.decorator({
|
|
1455
|
+
getter(original, target, propertyKey) {
|
|
1456
|
+
return function () {
|
|
1457
|
+
let wrapper = wrapperRegistry.get(original);
|
|
1458
|
+
if (!wrapper) {
|
|
1459
|
+
wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(propertyKey)}`, (that) => {
|
|
1460
|
+
return original.call(that);
|
|
1461
|
+
}), {
|
|
1462
|
+
method: original,
|
|
1463
|
+
propertyKey,
|
|
1464
|
+
});
|
|
1465
|
+
const origRoot = original[proxy.rootFunctionSymbol];
|
|
1466
|
+
if (origRoot)
|
|
1467
|
+
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
1468
|
+
wrapperRegistry.set(original, wrapper);
|
|
1469
|
+
}
|
|
1470
|
+
const memoized = memoizeFunction(wrapper, memoizeOpts);
|
|
1471
|
+
return memoized(this);
|
|
1472
|
+
};
|
|
1473
|
+
},
|
|
1474
|
+
method(original, target, name) {
|
|
1475
|
+
return function (...args) {
|
|
1476
|
+
let wrapper = wrapperRegistry.get(original);
|
|
1477
|
+
if (!wrapper) {
|
|
1478
|
+
wrapper = proxy.markWithRoot(proxy.named(`${String(target?.constructor?.name ?? target?.name ?? 'Object')}.${String(name)}`, (that, ...args) => {
|
|
1479
|
+
return original.call(that, ...args);
|
|
1480
|
+
}), {
|
|
1481
|
+
method: original,
|
|
1482
|
+
propertyKey: name,
|
|
1483
|
+
});
|
|
1484
|
+
const origRoot = original[proxy.rootFunctionSymbol];
|
|
1485
|
+
if (origRoot)
|
|
1486
|
+
wrapper[proxy.rootFunctionSymbol] = origRoot;
|
|
1487
|
+
wrapperRegistry.set(original, wrapper);
|
|
1488
|
+
}
|
|
1489
|
+
const memoized = memoizeFunction(wrapper, memoizeOpts);
|
|
1490
|
+
return memoized(this, ...args);
|
|
1491
|
+
};
|
|
1492
|
+
},
|
|
1493
|
+
default: (target) => typeof target === 'object'
|
|
1494
|
+
? memoizeObject(target, memoizeOpts)
|
|
1495
|
+
: memoizeFunction(target, memoizeOpts),
|
|
1653
1496
|
});
|
|
1654
1497
|
}
|
|
1498
|
+
const memoize = proxy.flavored(makeMemoizeDecorator(), {
|
|
1499
|
+
get lenient() {
|
|
1500
|
+
return makeMemoizeDecorator({ lenient: true });
|
|
1501
|
+
},
|
|
1502
|
+
});
|
|
1655
1503
|
|
|
1656
1504
|
/**
|
|
1657
1505
|
* Organizes a source object's properties into a target object using a callback function.
|
|
@@ -1727,7 +1575,7 @@ function organized(source, apply, baseTarget = {}) {
|
|
|
1727
1575
|
});
|
|
1728
1576
|
return apply(accessBase, target);
|
|
1729
1577
|
});
|
|
1730
|
-
return proxy.
|
|
1578
|
+
return proxy.link(target, (reason) => stop(reason));
|
|
1731
1579
|
}
|
|
1732
1580
|
/**
|
|
1733
1581
|
* Organizes a property on a target object
|
|
@@ -1770,7 +1618,7 @@ changed, options = {}) {
|
|
|
1770
1618
|
function watchObject(value, changed, { immediate = false, deep = false } = {}) {
|
|
1771
1619
|
if (deep)
|
|
1772
1620
|
return deepWatch(value, changed, { immediate });
|
|
1773
|
-
return proxy.effect(
|
|
1621
|
+
return proxy.effect.named('watch:object')(() => {
|
|
1774
1622
|
proxy.dependant(value);
|
|
1775
1623
|
if (immediate)
|
|
1776
1624
|
changed(value);
|
|
@@ -1780,7 +1628,7 @@ function watchObject(value, changed, { immediate = false, deep = false } = {}) {
|
|
|
1780
1628
|
function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
|
|
1781
1629
|
let oldValue = unsetYet;
|
|
1782
1630
|
let deepCleanup;
|
|
1783
|
-
const cbCleanup = proxy.effect(proxy.markWithRoot(
|
|
1631
|
+
const cbCleanup = proxy.effect.named('watch:callback')(proxy.markWithRoot((access) => {
|
|
1784
1632
|
const newValue = value(access);
|
|
1785
1633
|
if (oldValue !== newValue) {
|
|
1786
1634
|
const old = oldValue;
|
|
@@ -1798,12 +1646,10 @@ function watchCallBack(value, changed, { immediate = false, deep = false } = {})
|
|
|
1798
1646
|
deepCleanup = deepWatch(newValue, (value) => changed(value, value));
|
|
1799
1647
|
}
|
|
1800
1648
|
}, value));
|
|
1801
|
-
return
|
|
1649
|
+
return (() => {
|
|
1802
1650
|
cbCleanup();
|
|
1803
1651
|
if (deepCleanup)
|
|
1804
1652
|
deepCleanup();
|
|
1805
|
-
}, {
|
|
1806
|
-
[proxy.stopped]: { get: () => cbCleanup[proxy.stopped] },
|
|
1807
1653
|
});
|
|
1808
1654
|
}
|
|
1809
1655
|
//#endregion
|
|
@@ -1818,7 +1664,7 @@ function watchCallBack(value, changed, { immediate = false, deep = false } = {})
|
|
|
1818
1664
|
function when(predicate, timeout) {
|
|
1819
1665
|
return new Promise((resolve, reject) => {
|
|
1820
1666
|
let timer;
|
|
1821
|
-
const stop = proxy.effect(
|
|
1667
|
+
const stop = proxy.effect.named('watch:when')((access) => {
|
|
1822
1668
|
try {
|
|
1823
1669
|
const value = predicate(access);
|
|
1824
1670
|
if (value) {
|
|
@@ -1855,7 +1701,7 @@ function shallowNonReactive(obj) {
|
|
|
1855
1701
|
obj = proxy.unwrap(obj);
|
|
1856
1702
|
if (proxy.isNonReactive(obj))
|
|
1857
1703
|
return obj;
|
|
1858
|
-
proxy.
|
|
1704
|
+
obj[proxy.unreactiveProperties] = true;
|
|
1859
1705
|
return obj;
|
|
1860
1706
|
}
|
|
1861
1707
|
function unreactiveApplication(arg1, ...args) {
|
|
@@ -1863,13 +1709,19 @@ function unreactiveApplication(arg1, ...args) {
|
|
|
1863
1709
|
? shallowNonReactive(arg1)
|
|
1864
1710
|
: ((original) => {
|
|
1865
1711
|
// Copy the parent's unreactive properties if they exist
|
|
1866
|
-
const
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1712
|
+
const parentMarker = original.prototype[proxy.unreactiveProperties];
|
|
1713
|
+
// If parent is fully unreactive, child is too
|
|
1714
|
+
if (parentMarker === true) {
|
|
1715
|
+
original.prototype[proxy.unreactiveProperties] = true;
|
|
1716
|
+
}
|
|
1717
|
+
else {
|
|
1718
|
+
const set = new Set(parentMarker || []);
|
|
1719
|
+
// Add all arguments (including the first one)
|
|
1720
|
+
set.add(arg1);
|
|
1721
|
+
for (const arg of args)
|
|
1722
|
+
set.add(arg);
|
|
1723
|
+
proxy.addUnreactiveProps(original.prototype, set);
|
|
1724
|
+
}
|
|
1873
1725
|
return original; // Return the class
|
|
1874
1726
|
});
|
|
1875
1727
|
}
|
|
@@ -1879,11 +1731,26 @@ function unreactiveApplication(arg1, ...args) {
|
|
|
1879
1731
|
*/
|
|
1880
1732
|
const unreactive = proxy.decorator({
|
|
1881
1733
|
class(original) {
|
|
1882
|
-
|
|
1883
|
-
proxy.nonReactiveClass(original);
|
|
1734
|
+
original.prototype[proxy.unreactiveProperties] = true;
|
|
1884
1735
|
},
|
|
1885
1736
|
default: unreactiveApplication,
|
|
1886
1737
|
});
|
|
1738
|
+
//#endregion
|
|
1739
|
+
//#region resource
|
|
1740
|
+
function lazyInit(resource, load) {
|
|
1741
|
+
const creation = proxy.effectHistory.active;
|
|
1742
|
+
let fresh = true;
|
|
1743
|
+
return new Proxy(resource, {
|
|
1744
|
+
[Symbol.toStringTag]: 'LazyInit',
|
|
1745
|
+
get(target, prop) {
|
|
1746
|
+
if (fresh) {
|
|
1747
|
+
proxy.captured(creation, load)();
|
|
1748
|
+
fresh = false;
|
|
1749
|
+
}
|
|
1750
|
+
return target[prop];
|
|
1751
|
+
},
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1887
1754
|
/**
|
|
1888
1755
|
* Creates a reactive resource that automatically tracks async state.
|
|
1889
1756
|
* @param fetcher - Async function that returns the value. Reactive dependencies are tracked.
|
|
@@ -1891,521 +1758,59 @@ const unreactive = proxy.decorator({
|
|
|
1891
1758
|
* @returns Reactive Resource object with value, loading, error, latest properties
|
|
1892
1759
|
*/
|
|
1893
1760
|
function resource(fetcher, options = {}) {
|
|
1894
|
-
const
|
|
1761
|
+
const resource = proxy.reactive({
|
|
1895
1762
|
value: options.initialValue,
|
|
1896
1763
|
loading: true,
|
|
1897
1764
|
error: undefined,
|
|
1898
1765
|
latest: options.initialValue,
|
|
1899
|
-
reload
|
|
1766
|
+
reload() {
|
|
1900
1767
|
reloadSignal.value++;
|
|
1901
1768
|
},
|
|
1902
1769
|
});
|
|
1903
1770
|
const reloadSignal = proxy.reactive({ value: 0 });
|
|
1771
|
+
// Solve race conditions: make sure a new fast request is not overloaded by a slow old one
|
|
1904
1772
|
let counter = 0;
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
result
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
state.latest = result;
|
|
1930
|
-
state.loading = false;
|
|
1931
|
-
}
|
|
1932
|
-
}
|
|
1933
|
-
catch (err) {
|
|
1934
|
-
state.error = err;
|
|
1935
|
-
state.loading = false;
|
|
1936
|
-
}
|
|
1937
|
-
});
|
|
1938
|
-
state.stop = stop;
|
|
1939
|
-
return state;
|
|
1940
|
-
}
|
|
1941
|
-
//#endregion
|
|
1942
|
-
|
|
1943
|
-
// Helper to work around TypeScript limitation: base class expressions cannot reference class type parameters
|
|
1944
|
-
function getRegisterBase() {
|
|
1945
|
-
class RegisterBase extends Indexable(ArrayReadForward, {
|
|
1946
|
-
get(index) {
|
|
1947
|
-
return this[getAt](index);
|
|
1948
|
-
},
|
|
1949
|
-
set(index, value) {
|
|
1950
|
-
this[setAt](index, value);
|
|
1951
|
-
},
|
|
1952
|
-
getLength() {
|
|
1953
|
-
return this.length;
|
|
1954
|
-
},
|
|
1955
|
-
setLength(value) {
|
|
1956
|
-
this.length = value;
|
|
1957
|
-
},
|
|
1958
|
-
}) {
|
|
1959
|
-
toArray() {
|
|
1960
|
-
return Array.from(this);
|
|
1961
|
-
}
|
|
1962
|
-
}
|
|
1963
|
-
return RegisterBase;
|
|
1964
|
-
}
|
|
1965
|
-
let RegisterClass = (() => {
|
|
1966
|
-
var _RegisterClass_instances, _RegisterClass_keyFn, _RegisterClass_keys, _RegisterClass_values, _RegisterClass_usage, _RegisterClass_valueInfo, _RegisterClass_keyEffects, _RegisterClass_ascend, _RegisterClass_events, _RegisterClass_rekeyValue;
|
|
1967
|
-
let _classDecorators = [unreactive];
|
|
1968
|
-
let _classDescriptor;
|
|
1969
|
-
let _classExtraInitializers = [];
|
|
1970
|
-
let _classThis;
|
|
1971
|
-
let _classSuper = getRegisterBase();
|
|
1972
|
-
_classThis = class extends _classSuper {
|
|
1973
|
-
get [(_RegisterClass_keyFn = new WeakMap(), _RegisterClass_keys = new WeakMap(), _RegisterClass_values = new WeakMap(), _RegisterClass_usage = new WeakMap(), _RegisterClass_valueInfo = new WeakMap(), _RegisterClass_keyEffects = new WeakMap(), _RegisterClass_ascend = new WeakMap(), _RegisterClass_events = new WeakMap(), _RegisterClass_instances = new WeakSet(), forwardArray)]() {
|
|
1974
|
-
return this.toArray();
|
|
1975
|
-
}
|
|
1976
|
-
on(eventOrEvents, cb) {
|
|
1977
|
-
// @ts-expect-error Delegate to Eventful
|
|
1978
|
-
return proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").on(eventOrEvents, cb);
|
|
1979
|
-
}
|
|
1980
|
-
off(eventOrEvents, cb) {
|
|
1981
|
-
// @ts-expect-error Delegate to Eventful
|
|
1982
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").off(eventOrEvents, cb);
|
|
1983
|
-
}
|
|
1984
|
-
/**
|
|
1985
|
-
* Register a global hook that receives all events
|
|
1986
|
-
*/
|
|
1987
|
-
hook(cb) {
|
|
1988
|
-
return proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").hook(cb);
|
|
1989
|
-
}
|
|
1990
|
-
constructor(keyFn, initial) {
|
|
1991
|
-
super();
|
|
1992
|
-
_RegisterClass_instances.add(this);
|
|
1993
|
-
_RegisterClass_keyFn.set(this, void 0);
|
|
1994
|
-
_RegisterClass_keys.set(this, void 0);
|
|
1995
|
-
_RegisterClass_values.set(this, void 0);
|
|
1996
|
-
_RegisterClass_usage.set(this, new Map());
|
|
1997
|
-
_RegisterClass_valueInfo.set(this, new Map());
|
|
1998
|
-
_RegisterClass_keyEffects.set(this, new Set());
|
|
1999
|
-
_RegisterClass_ascend.set(this, void 0);
|
|
2000
|
-
_RegisterClass_events.set(this, new Eventful()
|
|
2001
|
-
/**
|
|
2002
|
-
* Register event listeners for CRUD operations
|
|
2003
|
-
*/
|
|
2004
|
-
);
|
|
2005
|
-
/* Moved below initialization */
|
|
2006
|
-
let ascendGet;
|
|
2007
|
-
proxy.effect(({ ascend }) => {
|
|
2008
|
-
ascendGet = ascend;
|
|
2009
|
-
});
|
|
2010
|
-
proxy.__classPrivateFieldSet(this, _RegisterClass_ascend, ascendGet, "f");
|
|
2011
|
-
if (typeof keyFn !== 'function')
|
|
2012
|
-
throw new Error('Register requires a key function');
|
|
2013
|
-
proxy.__classPrivateFieldSet(this, _RegisterClass_keyFn, keyFn, "f");
|
|
2014
|
-
proxy.__classPrivateFieldSet(this, _RegisterClass_keys, proxy.reactive([]), "f");
|
|
2015
|
-
proxy.__classPrivateFieldSet(this, _RegisterClass_values, proxy.reactive(new Map()), "f");
|
|
2016
|
-
if (initial)
|
|
2017
|
-
this.push(...initial);
|
|
2018
|
-
}
|
|
2019
|
-
ensureKey(value) {
|
|
2020
|
-
let info = proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
|
|
2021
|
-
if (info)
|
|
2022
|
-
return info.key;
|
|
2023
|
-
info = { key: undefined };
|
|
2024
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").set(value, info);
|
|
2025
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_ascend, "f").call(this, () => {
|
|
2026
|
-
const stop = proxy.effect(({ reaction }) => {
|
|
2027
|
-
const nextKey = proxy.__classPrivateFieldGet(this, _RegisterClass_keyFn, "f").call(this, value);
|
|
2028
|
-
this.assertValidKey(nextKey);
|
|
2029
|
-
const previousKey = info.key;
|
|
2030
|
-
if (reaction && previousKey !== undefined && !Object.is(nextKey, previousKey))
|
|
2031
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_instances, "m", _RegisterClass_rekeyValue).call(this, value, previousKey, nextKey);
|
|
2032
|
-
info.key = nextKey;
|
|
2033
|
-
});
|
|
2034
|
-
info.stop = stop;
|
|
2035
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").add(stop);
|
|
2036
|
-
});
|
|
2037
|
-
if (info.key === undefined)
|
|
2038
|
-
throw new Error('Register key function must return a property key');
|
|
2039
|
-
return info.key;
|
|
2040
|
-
}
|
|
2041
|
-
assertValidKey(key) {
|
|
2042
|
-
const type = typeof key;
|
|
2043
|
-
if (type !== 'string' && type !== 'number' && type !== 'symbol')
|
|
2044
|
-
throw new Error('Register key function must return a property key');
|
|
2045
|
-
}
|
|
2046
|
-
setKeyValue(key, value, index) {
|
|
2047
|
-
const existing = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2048
|
-
if (existing !== undefined && existing !== value) {
|
|
2049
|
-
this.cleanupValue(existing);
|
|
2050
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
|
|
2051
|
-
if (index !== undefined) {
|
|
2052
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('update', existing, value, key, index);
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
else {
|
|
2056
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
|
|
2057
|
-
}
|
|
2058
|
-
}
|
|
2059
|
-
cleanupValue(value) {
|
|
2060
|
-
const info = proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
|
|
2061
|
-
if (!info)
|
|
2062
|
-
return;
|
|
2063
|
-
const stop = info.stop;
|
|
2064
|
-
if (stop) {
|
|
2065
|
-
info.stop = undefined;
|
|
2066
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").delete(stop);
|
|
2067
|
-
stop();
|
|
2068
|
-
}
|
|
2069
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").delete(value);
|
|
2070
|
-
}
|
|
2071
|
-
disposeKeyEffects() {
|
|
2072
|
-
for (const value of Array.from(proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").keys()))
|
|
2073
|
-
this.cleanupValue(value);
|
|
2074
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keyEffects, "f").clear();
|
|
2075
|
-
}
|
|
2076
|
-
incrementUsage(key) {
|
|
2077
|
-
const count = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key) ?? 0;
|
|
2078
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count + 1);
|
|
2079
|
-
}
|
|
2080
|
-
decrementUsage(key, index) {
|
|
2081
|
-
const count = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(key);
|
|
2082
|
-
if (!count)
|
|
2083
|
-
return;
|
|
2084
|
-
if (count <= 1) {
|
|
2085
|
-
const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2086
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(key);
|
|
2087
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").delete(key);
|
|
2088
|
-
if (value !== undefined) {
|
|
2089
|
-
this.cleanupValue(value);
|
|
2090
|
-
const idx = index ?? proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
|
|
2091
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('delete', value, key, idx);
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2094
|
-
else {
|
|
2095
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(key, count - 1);
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
normalizeIndex(index, allowEnd = false) {
|
|
2099
|
-
const length = this.length;
|
|
2100
|
-
let resolved = index;
|
|
2101
|
-
if (resolved < 0)
|
|
2102
|
-
resolved = Math.max(length + resolved, 0);
|
|
2103
|
-
if (resolved > length) {
|
|
2104
|
-
if (allowEnd)
|
|
2105
|
-
resolved = length;
|
|
2106
|
-
else
|
|
2107
|
-
throw new RangeError('Index out of bounds');
|
|
2108
|
-
}
|
|
2109
|
-
if (!allowEnd && resolved === length)
|
|
2110
|
-
throw new RangeError('Index out of bounds');
|
|
2111
|
-
return resolved;
|
|
2112
|
-
}
|
|
2113
|
-
assignAt(index, key, value) {
|
|
2114
|
-
const oldKey = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index];
|
|
2115
|
-
if (oldKey !== undefined && Object.is(oldKey, key)) {
|
|
2116
|
-
const oldValue = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2117
|
-
this.setKeyValue(key, value);
|
|
2118
|
-
if (oldValue !== undefined && oldValue !== value) {
|
|
2119
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('update', oldValue, value, key, index);
|
|
2120
|
-
}
|
|
2121
|
-
return;
|
|
2122
|
-
}
|
|
2123
|
-
if (oldKey !== undefined)
|
|
2124
|
-
this.decrementUsage(oldKey);
|
|
2125
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index] = key;
|
|
2126
|
-
this.incrementUsage(key);
|
|
2127
|
-
this.setKeyValue(key, value);
|
|
2128
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
|
|
2129
|
-
}
|
|
2130
|
-
insertKeyValue(index, key, value) {
|
|
2131
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(index, 0, key);
|
|
2132
|
-
this.incrementUsage(key);
|
|
2133
|
-
this.setKeyValue(key, value);
|
|
2134
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('add', value, key, index);
|
|
2135
|
-
}
|
|
2136
|
-
rebuildFrom(values) {
|
|
2137
|
-
this.disposeKeyEffects();
|
|
2138
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(0, proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length);
|
|
2139
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
|
|
2140
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
|
|
2141
|
-
for (const value of values) {
|
|
2142
|
-
const key = this.ensureKey(value);
|
|
2143
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").push(key);
|
|
2144
|
-
this.incrementUsage(key);
|
|
2145
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").set(key, value);
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
get length() {
|
|
2149
|
-
return proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length;
|
|
2150
|
-
}
|
|
2151
|
-
[(_RegisterClass_rekeyValue = function _RegisterClass_rekeyValue(value, oldKey, newKey) {
|
|
2152
|
-
if (Object.is(oldKey, newKey))
|
|
2153
|
-
return;
|
|
2154
|
-
const existingValue = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(newKey);
|
|
2155
|
-
if (existingValue !== undefined && existingValue !== value)
|
|
2156
|
-
throw new Error(`Register key collision for key ${String(newKey)}`);
|
|
2157
|
-
const count = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(oldKey);
|
|
2158
|
-
if (!count)
|
|
2159
|
-
return;
|
|
2160
|
-
const existingCount = proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").get(newKey) ?? 0;
|
|
2161
|
-
this.setKeyValue(newKey, value);
|
|
2162
|
-
let index = -1;
|
|
2163
|
-
for (let i = 0; i < proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length; i++)
|
|
2164
|
-
if (Object.is(proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[i], oldKey)) {
|
|
2165
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[i] = newKey;
|
|
2166
|
-
if (index === -1)
|
|
2167
|
-
index = i;
|
|
2168
|
-
}
|
|
2169
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").set(newKey, existingCount + count);
|
|
2170
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").delete(oldKey);
|
|
2171
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").delete(oldKey);
|
|
2172
|
-
const updatedInfo = proxy.__classPrivateFieldGet(this, _RegisterClass_valueInfo, "f").get(value);
|
|
2173
|
-
if (updatedInfo)
|
|
2174
|
-
updatedInfo.key = newKey;
|
|
2175
|
-
if (index !== -1) {
|
|
2176
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_events, "f").emit('rekey', value, oldKey, newKey, index);
|
|
2177
|
-
}
|
|
2178
|
-
}, getAt)](index) {
|
|
2179
|
-
const key = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f")[index];
|
|
2180
|
-
return key === undefined ? undefined : proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2181
|
-
}
|
|
2182
|
-
[setAt](index, value) {
|
|
2183
|
-
const key = this.ensureKey(value);
|
|
2184
|
-
if (index === this.length) {
|
|
2185
|
-
this.insertKeyValue(index, key, value);
|
|
2186
|
-
return;
|
|
2187
|
-
}
|
|
2188
|
-
const normalized = this.normalizeIndex(index);
|
|
2189
|
-
this.assignAt(normalized, key, value);
|
|
2190
|
-
}
|
|
2191
|
-
push(...items) {
|
|
2192
|
-
for (const item of items) {
|
|
2193
|
-
const key = this.ensureKey(item);
|
|
2194
|
-
this.insertKeyValue(this.length, key, item);
|
|
2195
|
-
}
|
|
2196
|
-
return this.length;
|
|
2197
|
-
}
|
|
2198
|
-
pop() {
|
|
2199
|
-
if (!this.length)
|
|
2200
|
-
return undefined;
|
|
2201
|
-
return this.removeAt(this.length - 1);
|
|
2202
|
-
}
|
|
2203
|
-
shift() {
|
|
2204
|
-
if (!this.length)
|
|
2205
|
-
return undefined;
|
|
2206
|
-
return this.removeAt(0);
|
|
2207
|
-
}
|
|
2208
|
-
unshift(...items) {
|
|
2209
|
-
let index = 0;
|
|
2210
|
-
for (const item of items) {
|
|
2211
|
-
const key = this.ensureKey(item);
|
|
2212
|
-
this.insertKeyValue(index++, key, item);
|
|
2213
|
-
}
|
|
2214
|
-
return this.length;
|
|
2215
|
-
}
|
|
2216
|
-
splice(start, deleteCount, ...items) {
|
|
2217
|
-
const normalizedStart = this.normalizeIndex(start, true);
|
|
2218
|
-
const maxDeletions = this.length - normalizedStart;
|
|
2219
|
-
const actualDelete = Math.min(deleteCount === undefined ? maxDeletions : Math.max(deleteCount, 0), maxDeletions);
|
|
2220
|
-
const keysToInsert = [];
|
|
2221
|
-
for (const item of items)
|
|
2222
|
-
keysToInsert.push(this.ensureKey(item));
|
|
2223
|
-
const removedKeys = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(normalizedStart, actualDelete, ...keysToInsert);
|
|
2224
|
-
const removedValues = [];
|
|
2225
|
-
for (let i = 0; i < removedKeys.length; i++) {
|
|
2226
|
-
const key = removedKeys[i];
|
|
2227
|
-
if (key === undefined)
|
|
2228
|
-
continue;
|
|
2229
|
-
const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2230
|
-
this.decrementUsage(key, normalizedStart + i);
|
|
2231
|
-
removedValues.push(value);
|
|
2232
|
-
}
|
|
2233
|
-
for (let i = 0; i < keysToInsert.length; i++) {
|
|
2234
|
-
const key = keysToInsert[i];
|
|
2235
|
-
const value = items[i];
|
|
2236
|
-
this.incrementUsage(key);
|
|
2237
|
-
this.setKeyValue(key, value);
|
|
2238
|
-
}
|
|
2239
|
-
return removedValues;
|
|
2240
|
-
}
|
|
2241
|
-
clear() {
|
|
2242
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").length = 0;
|
|
2243
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").clear();
|
|
2244
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").clear();
|
|
2245
|
-
this.disposeKeyEffects();
|
|
2246
|
-
}
|
|
2247
|
-
get(key) {
|
|
2248
|
-
return proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2249
|
-
}
|
|
2250
|
-
set(key, value) {
|
|
2251
|
-
if (proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
|
|
2252
|
-
this.setKeyValue(key, value);
|
|
2253
|
-
}
|
|
2254
|
-
remove(key) {
|
|
2255
|
-
let index = this.indexOfKey(key);
|
|
2256
|
-
while (index !== -1) {
|
|
2257
|
-
this.removeAt(index);
|
|
2258
|
-
index = this.indexOfKey(key);
|
|
2259
|
-
}
|
|
2260
|
-
}
|
|
2261
|
-
removeAt(index) {
|
|
2262
|
-
const [key] = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").splice(index, 1);
|
|
2263
|
-
if (key === undefined)
|
|
2264
|
-
return undefined;
|
|
2265
|
-
const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2266
|
-
this.decrementUsage(key, index);
|
|
2267
|
-
return value;
|
|
2268
|
-
}
|
|
2269
|
-
/**
|
|
2270
|
-
* Keep only the items for which the predicate returns true.
|
|
2271
|
-
* Items for which the predicate returns false are removed.
|
|
2272
|
-
*
|
|
2273
|
-
* The predicate is evaluated once per distinct key; duplicate keys
|
|
2274
|
-
* will follow the same keep/remove decision.
|
|
2275
|
-
*/
|
|
2276
|
-
keep(predicate) {
|
|
2277
|
-
const decisions = new Map();
|
|
2278
|
-
for (const [index, key] of proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").entries()) {
|
|
2279
|
-
if (decisions.has(key)) {
|
|
2280
|
-
if (!decisions.get(key))
|
|
2281
|
-
this.removeAt(index);
|
|
2282
|
-
continue;
|
|
2283
|
-
}
|
|
2284
|
-
const value = proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(key);
|
|
2285
|
-
const shouldKeep = predicate(value);
|
|
2286
|
-
decisions.set(key, shouldKeep);
|
|
2287
|
-
if (!shouldKeep)
|
|
2288
|
-
this.removeAt(index);
|
|
2289
|
-
}
|
|
2290
|
-
}
|
|
2291
|
-
hasKey(key) {
|
|
2292
|
-
return proxy.__classPrivateFieldGet(this, _RegisterClass_usage, "f").has(key);
|
|
2293
|
-
}
|
|
2294
|
-
indexOfKey(key) {
|
|
2295
|
-
return proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
|
|
2296
|
-
}
|
|
2297
|
-
mapKeys() {
|
|
2298
|
-
return proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").keys();
|
|
2299
|
-
}
|
|
2300
|
-
update(...values) {
|
|
2301
|
-
for (const value of values) {
|
|
2302
|
-
const key = this.ensureKey(value);
|
|
2303
|
-
if (proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key)) {
|
|
2304
|
-
const index = proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").indexOf(key);
|
|
2305
|
-
this.setKeyValue(key, value, index);
|
|
1773
|
+
return lazyInit(resource, () => {
|
|
1774
|
+
proxy.link(resource, proxy.effect.named('watch:resource')((access) => {
|
|
1775
|
+
// Track reload signal to enable manual reloading
|
|
1776
|
+
void reloadSignal.value;
|
|
1777
|
+
const id = ++counter;
|
|
1778
|
+
resource.loading = true;
|
|
1779
|
+
resource.error = undefined;
|
|
1780
|
+
try {
|
|
1781
|
+
const result = fetcher(access);
|
|
1782
|
+
if (result instanceof Promise) {
|
|
1783
|
+
resource.promise = result
|
|
1784
|
+
.then((val) => {
|
|
1785
|
+
if (id === counter) {
|
|
1786
|
+
resource.value = val;
|
|
1787
|
+
resource.latest = val;
|
|
1788
|
+
resource.loading = false;
|
|
1789
|
+
}
|
|
1790
|
+
})
|
|
1791
|
+
.catch((err) => {
|
|
1792
|
+
if (id === counter) {
|
|
1793
|
+
resource.error = err;
|
|
1794
|
+
resource.loading = false;
|
|
1795
|
+
}
|
|
1796
|
+
});
|
|
2306
1797
|
}
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
if (proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").has(key))
|
|
2313
|
-
this.setKeyValue(key, value);
|
|
2314
|
-
else
|
|
2315
|
-
insert(value);
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
|
-
entries() {
|
|
2319
|
-
const self = this;
|
|
2320
|
-
function* iterator() {
|
|
2321
|
-
for (let i = 0; i < proxy.__classPrivateFieldGet(self, _RegisterClass_keys, "f").length; i++) {
|
|
2322
|
-
const val = proxy.__classPrivateFieldGet(self, _RegisterClass_values, "f").get(proxy.__classPrivateFieldGet(self, _RegisterClass_keys, "f")[i]);
|
|
2323
|
-
if (val !== undefined)
|
|
2324
|
-
yield [i, val];
|
|
1798
|
+
else {
|
|
1799
|
+
resource.promise = Promise.resolve();
|
|
1800
|
+
resource.value = result;
|
|
1801
|
+
resource.latest = result;
|
|
1802
|
+
resource.loading = false;
|
|
2325
1803
|
}
|
|
2326
1804
|
}
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
function* iterator() {
|
|
2332
|
-
for (const key of proxy.__classPrivateFieldGet(self, _RegisterClass_keys, "f")) {
|
|
2333
|
-
const value = proxy.__classPrivateFieldGet(self, _RegisterClass_values, "f").get(key);
|
|
2334
|
-
if (value !== undefined)
|
|
2335
|
-
yield value;
|
|
2336
|
-
}
|
|
1805
|
+
catch (err) {
|
|
1806
|
+
resource.promise = Promise.reject(err);
|
|
1807
|
+
resource.error = err;
|
|
1808
|
+
resource.loading = false;
|
|
2337
1809
|
}
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
toString() {
|
|
2341
|
-
return `[Register length=${this.length}]`;
|
|
2342
|
-
}
|
|
2343
|
-
at(index) {
|
|
2344
|
-
const resolved = index < 0 ? this.length + index : index;
|
|
2345
|
-
if (resolved < 0 || resolved >= this.length)
|
|
2346
|
-
return undefined;
|
|
2347
|
-
return this[getAt](resolved);
|
|
2348
|
-
}
|
|
2349
|
-
reverse() {
|
|
2350
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").reverse();
|
|
2351
|
-
return this;
|
|
2352
|
-
}
|
|
2353
|
-
sort(compareFn) {
|
|
2354
|
-
const fwdCompareFn = compareFn
|
|
2355
|
-
? (a, b) => compareFn(proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(a), proxy.__classPrivateFieldGet(this, _RegisterClass_values, "f").get(b))
|
|
2356
|
-
: undefined;
|
|
2357
|
-
proxy.__classPrivateFieldGet(this, _RegisterClass_keys, "f").sort(fwdCompareFn);
|
|
2358
|
-
return this;
|
|
2359
|
-
}
|
|
2360
|
-
fill(value, start = 0, end = this.length) {
|
|
2361
|
-
const values = this.toArray();
|
|
2362
|
-
values.fill(value, start, end);
|
|
2363
|
-
this.rebuildFrom(values);
|
|
2364
|
-
return this;
|
|
2365
|
-
}
|
|
2366
|
-
copyWithin(target, start, end) {
|
|
2367
|
-
const values = this.toArray();
|
|
2368
|
-
values.copyWithin(target, start, end);
|
|
2369
|
-
this.rebuildFrom(values);
|
|
2370
|
-
return this;
|
|
2371
|
-
}
|
|
2372
|
-
};
|
|
2373
|
-
proxy.__setFunctionName(_classThis, "RegisterClass");
|
|
2374
|
-
(() => {
|
|
2375
|
-
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2376
|
-
proxy.__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
2377
|
-
_classThis = _classDescriptor.value;
|
|
2378
|
-
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
2379
|
-
proxy.__runInitializers(_classThis, _classExtraInitializers);
|
|
2380
|
-
})();
|
|
2381
|
-
return _classThis;
|
|
2382
|
-
})();
|
|
2383
|
-
const Register = RegisterClass;
|
|
2384
|
-
/**
|
|
2385
|
-
* Creates a reactive Register - an ordered, array-like collection with stable key-based identity.
|
|
2386
|
-
*
|
|
2387
|
-
* Register combines array semantics (indexable access, ordering, iteration) with Map-like
|
|
2388
|
-
* key-based lookups. Items with the same key share the same value instance, making it ideal
|
|
2389
|
-
* for UI lists keyed by IDs or when you need to preserve identity across reorders.
|
|
2390
|
-
*
|
|
2391
|
-
* @param keyFn - Function that extracts the key from each item
|
|
2392
|
-
* @param initial - Optional initial items to populate the register
|
|
2393
|
-
* @returns A reactive Register instance
|
|
2394
|
-
*
|
|
2395
|
-
* @example
|
|
2396
|
-
* ```typescript
|
|
2397
|
-
* const users = register(
|
|
2398
|
-
* (user: User) => user.id,
|
|
2399
|
-
* [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]
|
|
2400
|
-
* )
|
|
2401
|
-
*
|
|
2402
|
-
* users.push({ id: 3, name: 'Charlie' })
|
|
2403
|
-
* const bob = users.get(2) // Get by key
|
|
2404
|
-
* ```
|
|
2405
|
-
*/
|
|
2406
|
-
function register(keyFn, initial) {
|
|
2407
|
-
return new RegisterClass(keyFn, initial);
|
|
1810
|
+
}));
|
|
1811
|
+
});
|
|
2408
1812
|
}
|
|
1813
|
+
//#endregion
|
|
2409
1814
|
|
|
2410
1815
|
/**
|
|
2411
1816
|
* Converts an iterator to a generator that yields reactive values
|
|
@@ -2488,6 +1893,7 @@ let ReactiveArrayWrapper = (() => {
|
|
|
2488
1893
|
let _classSuper = Array;
|
|
2489
1894
|
let _instanceExtraInitializers = [];
|
|
2490
1895
|
let _fill_decorators;
|
|
1896
|
+
let _copyWithin_decorators;
|
|
2491
1897
|
let _pop_decorators;
|
|
2492
1898
|
let _push_decorators;
|
|
2493
1899
|
let _reverse_decorators;
|
|
@@ -2512,6 +1918,9 @@ let ReactiveArrayWrapper = (() => {
|
|
|
2512
1918
|
fill(value, start, end) {
|
|
2513
1919
|
return super.fill(proxy.unwrap(value), start, end);
|
|
2514
1920
|
}
|
|
1921
|
+
copyWithin(target, start, end) {
|
|
1922
|
+
return super.copyWithin(target, start, end);
|
|
1923
|
+
}
|
|
2515
1924
|
filter(predicate, thisArg) {
|
|
2516
1925
|
return proxy.reactive(super.filter((v, i, a) => predicate.call(thisArg, proxy.reactive(v), i, a), thisArg));
|
|
2517
1926
|
}
|
|
@@ -2613,7 +2022,7 @@ let ReactiveArrayWrapper = (() => {
|
|
|
2613
2022
|
proxy.dependant(this, proxy.keysOf);
|
|
2614
2023
|
return makeReactiveIterator(super.values());
|
|
2615
2024
|
}
|
|
2616
|
-
[(_fill_decorators = [proxy.atomic], _pop_decorators = [proxy.atomic], _push_decorators = [proxy.atomic], _reverse_decorators = [proxy.atomic], _shift_decorators = [proxy.atomic], _sort_decorators = [proxy.atomic], _splice_decorators = [proxy.atomic], _unshift_decorators = [proxy.atomic], Symbol.iterator)]() {
|
|
2025
|
+
[(_fill_decorators = [proxy.atomic], _copyWithin_decorators = [proxy.atomic], _pop_decorators = [proxy.atomic], _push_decorators = [proxy.atomic], _reverse_decorators = [proxy.atomic], _shift_decorators = [proxy.atomic], _sort_decorators = [proxy.atomic], _splice_decorators = [proxy.atomic], _unshift_decorators = [proxy.atomic], Symbol.iterator)]() {
|
|
2617
2026
|
proxy.dependant(this, proxy.keysOf);
|
|
2618
2027
|
return makeReactiveIterator(super[Symbol.iterator]());
|
|
2619
2028
|
}
|
|
@@ -2626,7 +2035,6 @@ let ReactiveArrayWrapper = (() => {
|
|
|
2626
2035
|
: undefined;
|
|
2627
2036
|
return proxy.reactive(super.toSorted(wrappedCompare));
|
|
2628
2037
|
}
|
|
2629
|
-
// biome-ignore lint/complexity/noArguments: Needed to distinguish fn() from fn(undefined)
|
|
2630
2038
|
toSpliced(start, deleteCount, ...items) {
|
|
2631
2039
|
if (arguments.length > 2)
|
|
2632
2040
|
return proxy.reactive(super.toSpliced(start, deleteCount, ...items.map(proxy.unwrap)));
|
|
@@ -2647,6 +2055,7 @@ let ReactiveArrayWrapper = (() => {
|
|
|
2647
2055
|
(() => {
|
|
2648
2056
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
2649
2057
|
proxy.__esDecorate(_a, null, _fill_decorators, { kind: "method", name: "fill", static: false, private: false, access: { has: obj => "fill" in obj, get: obj => obj.fill }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2058
|
+
proxy.__esDecorate(_a, null, _copyWithin_decorators, { kind: "method", name: "copyWithin", static: false, private: false, access: { has: obj => "copyWithin" in obj, get: obj => obj.copyWithin }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2650
2059
|
proxy.__esDecorate(_a, null, _pop_decorators, { kind: "method", name: "pop", static: false, private: false, access: { has: obj => "pop" in obj, get: obj => obj.pop }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2651
2060
|
proxy.__esDecorate(_a, null, _push_decorators, { kind: "method", name: "push", static: false, private: false, access: { has: obj => "push" in obj, get: obj => obj.push }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
2652
2061
|
proxy.__esDecorate(_a, null, _reverse_decorators, { kind: "method", name: "reverse", static: false, private: false, access: { has: obj => "reverse" in obj, get: obj => obj.reverse }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
@@ -2667,18 +2076,18 @@ class ReactiveWeakMap extends WeakMap {
|
|
|
2667
2076
|
// Implement WeakMap interface methods with reactivity
|
|
2668
2077
|
delete(key) {
|
|
2669
2078
|
const hadKey = this.has(key);
|
|
2670
|
-
const result =
|
|
2079
|
+
const result = super.delete(key);
|
|
2671
2080
|
if (hadKey)
|
|
2672
2081
|
proxy.touched1(proxy.contentRef(this), { type: 'del', prop: key }, key);
|
|
2673
2082
|
return result;
|
|
2674
2083
|
}
|
|
2675
2084
|
get(key) {
|
|
2676
2085
|
proxy.dependant(proxy.contentRef(this), key);
|
|
2677
|
-
return proxy.reactive(
|
|
2086
|
+
return proxy.reactive(super.get(key));
|
|
2678
2087
|
}
|
|
2679
2088
|
has(key) {
|
|
2680
2089
|
proxy.dependant(proxy.contentRef(this), key);
|
|
2681
|
-
return
|
|
2090
|
+
return super.has(key);
|
|
2682
2091
|
}
|
|
2683
2092
|
set(key, value) {
|
|
2684
2093
|
const hadKey = this.has(key);
|
|
@@ -2699,16 +2108,18 @@ class ReactiveMap extends Map {
|
|
|
2699
2108
|
// Implement Map interface methods with reactivity
|
|
2700
2109
|
get size() {
|
|
2701
2110
|
proxy.dependant(this, 'size'); // The ReactiveMap instance still goes through proxy
|
|
2702
|
-
return
|
|
2111
|
+
return super.size;
|
|
2703
2112
|
}
|
|
2704
2113
|
clear() {
|
|
2705
2114
|
const hadEntries = this.size > 0;
|
|
2706
|
-
|
|
2115
|
+
super.clear();
|
|
2707
2116
|
if (hadEntries) {
|
|
2708
2117
|
const evolution = { type: 'bunch', method: 'clear' };
|
|
2709
2118
|
// Clear triggers all effects since all keys are affected
|
|
2710
|
-
proxy.
|
|
2711
|
-
|
|
2119
|
+
proxy.batch(() => {
|
|
2120
|
+
proxy.touched1(this, evolution, 'size');
|
|
2121
|
+
proxy.touched(proxy.contentRef(this), evolution);
|
|
2122
|
+
});
|
|
2712
2123
|
}
|
|
2713
2124
|
}
|
|
2714
2125
|
entries() {
|
|
@@ -2743,32 +2154,36 @@ class ReactiveMap extends Map {
|
|
|
2743
2154
|
// Implement Map methods with reactivity
|
|
2744
2155
|
delete(key) {
|
|
2745
2156
|
const hadKey = this.has(key);
|
|
2746
|
-
const result =
|
|
2157
|
+
const result = super.delete(key);
|
|
2747
2158
|
if (hadKey) {
|
|
2748
2159
|
const evolution = { type: 'del', prop: key };
|
|
2749
|
-
proxy.
|
|
2750
|
-
|
|
2160
|
+
proxy.batch(() => {
|
|
2161
|
+
proxy.touched1(proxy.contentRef(this), evolution, key);
|
|
2162
|
+
proxy.touched1(this, evolution, 'size');
|
|
2163
|
+
});
|
|
2751
2164
|
}
|
|
2752
2165
|
return result;
|
|
2753
2166
|
}
|
|
2754
2167
|
get(key) {
|
|
2755
2168
|
proxy.dependant(proxy.contentRef(this), key);
|
|
2756
|
-
return proxy.reactive(
|
|
2169
|
+
return proxy.reactive(super.get(key));
|
|
2757
2170
|
}
|
|
2758
2171
|
has(key) {
|
|
2759
2172
|
proxy.dependant(proxy.contentRef(this), key);
|
|
2760
|
-
return
|
|
2173
|
+
return super.has(key);
|
|
2761
2174
|
}
|
|
2762
2175
|
set(key, value) {
|
|
2763
2176
|
const hadKey = this.has(key);
|
|
2764
2177
|
const oldValue = this.get(key);
|
|
2765
2178
|
const reactiveValue = proxy.reactive(value);
|
|
2766
|
-
|
|
2179
|
+
super.set(key, reactiveValue);
|
|
2767
2180
|
if (!hadKey || oldValue !== reactiveValue) {
|
|
2768
|
-
proxy.
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2181
|
+
proxy.batch(() => {
|
|
2182
|
+
proxy.notifyPropertyChange(proxy.contentRef(this), key, oldValue, reactiveValue, hadKey);
|
|
2183
|
+
// Also notify size change for Map (WeakMap doesn't track size)
|
|
2184
|
+
const evolution = { type: hadKey ? 'set' : 'add', prop: key };
|
|
2185
|
+
proxy.touched1(this, evolution, 'size');
|
|
2186
|
+
});
|
|
2772
2187
|
}
|
|
2773
2188
|
return this;
|
|
2774
2189
|
}
|
|
@@ -2781,7 +2196,7 @@ class ReactiveMap extends Map {
|
|
|
2781
2196
|
class ReactiveWeakSet extends WeakSet {
|
|
2782
2197
|
add(value) {
|
|
2783
2198
|
const had = this.has(value);
|
|
2784
|
-
|
|
2199
|
+
super.add(value);
|
|
2785
2200
|
if (!had) {
|
|
2786
2201
|
// touch the specific value and the collection view
|
|
2787
2202
|
proxy.touched1(proxy.contentRef(this), { type: 'add', prop: value }, value);
|
|
@@ -2791,14 +2206,14 @@ class ReactiveWeakSet extends WeakSet {
|
|
|
2791
2206
|
}
|
|
2792
2207
|
delete(value) {
|
|
2793
2208
|
const had = this.has(value);
|
|
2794
|
-
const res =
|
|
2209
|
+
const res = super.delete(value);
|
|
2795
2210
|
if (had)
|
|
2796
2211
|
proxy.touched1(proxy.contentRef(this), { type: 'del', prop: value }, value);
|
|
2797
2212
|
return res;
|
|
2798
2213
|
}
|
|
2799
2214
|
has(value) {
|
|
2800
2215
|
proxy.dependant(proxy.contentRef(this), value);
|
|
2801
|
-
return
|
|
2216
|
+
return super.has(value);
|
|
2802
2217
|
}
|
|
2803
2218
|
}
|
|
2804
2219
|
/**
|
|
@@ -2814,31 +2229,37 @@ class ReactiveSet extends Set {
|
|
|
2814
2229
|
add(value) {
|
|
2815
2230
|
const had = this.has(value);
|
|
2816
2231
|
const reactiveValue = proxy.reactive(value);
|
|
2817
|
-
|
|
2232
|
+
super.add(reactiveValue);
|
|
2818
2233
|
if (!had) {
|
|
2819
2234
|
const evolution = { type: 'add', prop: reactiveValue };
|
|
2820
2235
|
// touch for value-specific and aggregate dependencies
|
|
2821
|
-
proxy.
|
|
2822
|
-
|
|
2236
|
+
proxy.batch(() => {
|
|
2237
|
+
proxy.touched1(proxy.contentRef(this), evolution, reactiveValue);
|
|
2238
|
+
proxy.touched1(this, evolution, 'size');
|
|
2239
|
+
});
|
|
2823
2240
|
}
|
|
2824
2241
|
return this;
|
|
2825
2242
|
}
|
|
2826
2243
|
clear() {
|
|
2827
2244
|
const hadEntries = this.size > 0;
|
|
2828
|
-
|
|
2245
|
+
super.clear();
|
|
2829
2246
|
if (hadEntries) {
|
|
2830
2247
|
const evolution = { type: 'bunch', method: 'clear' };
|
|
2831
|
-
proxy.
|
|
2832
|
-
|
|
2248
|
+
proxy.batch(() => {
|
|
2249
|
+
proxy.touched1(this, evolution, 'size');
|
|
2250
|
+
proxy.touched(proxy.contentRef(this), evolution);
|
|
2251
|
+
});
|
|
2833
2252
|
}
|
|
2834
2253
|
}
|
|
2835
2254
|
delete(value) {
|
|
2836
2255
|
const had = this.has(value);
|
|
2837
|
-
const res =
|
|
2256
|
+
const res = super.delete(value);
|
|
2838
2257
|
if (had) {
|
|
2839
2258
|
const evolution = { type: 'del', prop: value };
|
|
2840
|
-
proxy.
|
|
2841
|
-
|
|
2259
|
+
proxy.batch(() => {
|
|
2260
|
+
proxy.touched1(proxy.contentRef(this), evolution, value);
|
|
2261
|
+
proxy.touched1(this, evolution, 'size');
|
|
2262
|
+
});
|
|
2842
2263
|
}
|
|
2843
2264
|
return res;
|
|
2844
2265
|
}
|
|
@@ -2877,14 +2298,12 @@ class ReactiveSet extends Set {
|
|
|
2877
2298
|
}
|
|
2878
2299
|
|
|
2879
2300
|
// Register native collection types to use specialized reactive wrappers
|
|
2880
|
-
console.time('mutts-reactive-init');
|
|
2881
2301
|
proxy.metaProtos.set(Array, ReactiveArray.prototype);
|
|
2882
2302
|
proxy.metaProtos.set(Set, ReactiveSet.prototype);
|
|
2883
2303
|
proxy.metaProtos.set(WeakSet, ReactiveWeakSet.prototype);
|
|
2884
2304
|
proxy.metaProtos.set(Map, ReactiveMap.prototype);
|
|
2885
2305
|
proxy.metaProtos.set(WeakMap, ReactiveWeakMap.prototype);
|
|
2886
2306
|
proxy.wrapProtos.set(Array, ReactiveArrayWrapper.prototype);
|
|
2887
|
-
console.timeEnd('mutts-reactive-init');
|
|
2888
2307
|
/**
|
|
2889
2308
|
* Object containing internal reactive system state for debugging and profiling
|
|
2890
2309
|
*/
|
|
@@ -2897,7 +2316,6 @@ const profileInfo = {
|
|
|
2897
2316
|
objectsWithDeepWatchers: proxy.objectsWithDeepWatchers,
|
|
2898
2317
|
deepWatchers: proxy.deepWatchers,
|
|
2899
2318
|
effectToDeepWatchedObjects: proxy.effectToDeepWatchedObjects,
|
|
2900
|
-
nonReactiveObjects: proxy.nonReactiveObjects,
|
|
2901
2319
|
};
|
|
2902
2320
|
|
|
2903
2321
|
// In order to avoid async re-entrance, we could use zone.js or something like that.
|
|
@@ -3063,8 +2481,7 @@ const deprecated = Object.assign(proxy.decorator({
|
|
|
3063
2481
|
},
|
|
3064
2482
|
}), {
|
|
3065
2483
|
warn: (target, propertyKey, message) => {
|
|
3066
|
-
|
|
3067
|
-
console.warn(`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`);
|
|
2484
|
+
proxy.options.warn(`${target.constructor.name}.${String(propertyKey)} is deprecated${message ? `: ${message}` : ''}`);
|
|
3068
2485
|
},
|
|
3069
2486
|
});
|
|
3070
2487
|
/**
|
|
@@ -3127,12 +2544,11 @@ function throttle(delay) {
|
|
|
3127
2544
|
});
|
|
3128
2545
|
}
|
|
3129
2546
|
|
|
3130
|
-
var version$1 = "1.0.
|
|
2547
|
+
var version$1 = "1.0.11";
|
|
3131
2548
|
var pkg = {
|
|
3132
2549
|
version: version$1};
|
|
3133
2550
|
|
|
3134
2551
|
const { version } = pkg;
|
|
3135
|
-
// Singleton verification
|
|
3136
2552
|
const GLOBAL_MUTTS_KEY = '__MUTTS_INSTANCE__';
|
|
3137
2553
|
const globalScope = (typeof globalThis !== 'undefined'
|
|
3138
2554
|
? globalThis
|
|
@@ -3142,28 +2558,16 @@ const globalScope = (typeof globalThis !== 'undefined'
|
|
|
3142
2558
|
? global
|
|
3143
2559
|
: false);
|
|
3144
2560
|
if (globalScope) {
|
|
3145
|
-
// Detect the source of this instance safely across different environments
|
|
3146
2561
|
let source = 'mutts/index';
|
|
3147
|
-
// biome-ignore lint/security/noGlobalEval: Intentional eval for cross-env import.meta detection
|
|
3148
|
-
const viteEval = eval;
|
|
3149
2562
|
try {
|
|
3150
2563
|
if (typeof __filename !== 'undefined')
|
|
3151
2564
|
source = __filename;
|
|
3152
|
-
else {
|
|
3153
|
-
|
|
3154
|
-
const meta = viteEval('import.meta');
|
|
3155
|
-
if (meta && meta.url)
|
|
3156
|
-
source = meta.url;
|
|
2565
|
+
else if (typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href)) }) !== 'undefined' && (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href))) {
|
|
2566
|
+
source = (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('browser.cjs', document.baseURI).href));
|
|
3157
2567
|
}
|
|
3158
2568
|
}
|
|
3159
|
-
catch (
|
|
3160
|
-
|
|
3161
|
-
}
|
|
3162
|
-
const currentSourceInfo = {
|
|
3163
|
-
version,
|
|
3164
|
-
source,
|
|
3165
|
-
timestamp: Date.now(),
|
|
3166
|
-
};
|
|
2569
|
+
catch (_e) { }
|
|
2570
|
+
const currentSourceInfo = { version, source, timestamp: Date.now() };
|
|
3167
2571
|
if (globalScope[GLOBAL_MUTTS_KEY]) {
|
|
3168
2572
|
const existing = globalScope[GLOBAL_MUTTS_KEY];
|
|
3169
2573
|
throw new Error(`[Mutts] Multiple instances detected!\n` +
|
|
@@ -3190,18 +2594,21 @@ exports.Zone = proxy.Zone;
|
|
|
3190
2594
|
exports.ZoneAggregator = proxy.ZoneAggregator;
|
|
3191
2595
|
exports.ZoneHistory = proxy.ZoneHistory;
|
|
3192
2596
|
exports.addBatchCleanup = proxy.addBatchCleanup;
|
|
2597
|
+
exports.addUnreactiveProps = proxy.addUnreactiveProps;
|
|
3193
2598
|
exports.arrayEquals = proxy.arrayEquals;
|
|
2599
|
+
exports.assertUntracked = proxy.assertUntracked;
|
|
3194
2600
|
exports.asyncZone = proxy.asyncZone;
|
|
3195
2601
|
exports.atom = proxy.atom;
|
|
3196
2602
|
exports.atomic = proxy.atomic;
|
|
3197
2603
|
exports.biDi = proxy.biDi;
|
|
2604
|
+
exports.captured = proxy.captured;
|
|
3198
2605
|
exports.caught = proxy.caught;
|
|
3199
|
-
exports.cleanedBy = proxy.cleanedBy;
|
|
3200
|
-
exports.cleanup = proxy.cleanup;
|
|
3201
2606
|
exports.createFlavor = proxy.createFlavor;
|
|
2607
|
+
exports.debugPreset = proxy.debugPreset;
|
|
3202
2608
|
exports.decorator = proxy.decorator;
|
|
3203
2609
|
exports.deepCompare = proxy.deepCompare;
|
|
3204
2610
|
exports.defer = proxy.defer;
|
|
2611
|
+
exports.devPreset = proxy.devPreset;
|
|
3205
2612
|
exports.effect = proxy.effect;
|
|
3206
2613
|
exports.effectAggregator = proxy.effectAggregator;
|
|
3207
2614
|
exports.flavorOptions = proxy.flavorOptions;
|
|
@@ -3210,26 +2617,30 @@ exports.formatCleanupReason = proxy.formatCleanupReason;
|
|
|
3210
2617
|
exports.getActivationLog = proxy.getActivationLog;
|
|
3211
2618
|
exports.getActiveEffect = proxy.getActiveEffect;
|
|
3212
2619
|
exports.getState = proxy.getState;
|
|
3213
|
-
exports.immutables = proxy.immutables;
|
|
3214
2620
|
exports.isConstructor = proxy.isConstructor;
|
|
2621
|
+
exports.isDev = proxy.isDev;
|
|
3215
2622
|
exports.isNonReactive = proxy.isNonReactive;
|
|
3216
2623
|
exports.isObject = proxy.isObject;
|
|
2624
|
+
exports.isProd = proxy.isProd;
|
|
3217
2625
|
exports.isReactive = proxy.isReactive;
|
|
2626
|
+
exports.isTest = proxy.isTest;
|
|
3218
2627
|
exports.legacyDecorator = proxy.legacyDecorator;
|
|
2628
|
+
exports.link = proxy.link;
|
|
3219
2629
|
exports.mixin = proxy.mixin;
|
|
3220
2630
|
exports.modernDecorator = proxy.modernDecorator;
|
|
3221
2631
|
exports.named = proxy.named;
|
|
3222
2632
|
exports.objectToProxy = proxy.objectToProxy;
|
|
3223
2633
|
exports.onEffectThrow = proxy.onEffectThrow;
|
|
2634
|
+
exports.prodPreset = proxy.prodPreset;
|
|
3224
2635
|
exports.proxyToObject = proxy.proxyToObject;
|
|
3225
2636
|
exports.reactive = proxy.reactive;
|
|
3226
2637
|
exports.reactiveOptions = proxy.options;
|
|
3227
2638
|
exports.reset = proxy.reset;
|
|
3228
2639
|
exports.root = proxy.root;
|
|
3229
|
-
exports.stopped = proxy.stopped;
|
|
3230
2640
|
exports.tag = proxy.tag;
|
|
3231
2641
|
exports.touched = proxy.touched;
|
|
3232
2642
|
exports.touched1 = proxy.touched1;
|
|
2643
|
+
exports.unlink = proxy.unlink;
|
|
3233
2644
|
exports.untracked = proxy.untracked;
|
|
3234
2645
|
exports.unwrap = proxy.unwrap;
|
|
3235
2646
|
exports.zip = proxy.zip;
|
|
@@ -3241,7 +2652,6 @@ exports.Destroyable = Destroyable;
|
|
|
3241
2652
|
exports.DestructionError = DestructionError;
|
|
3242
2653
|
exports.Eventful = Eventful;
|
|
3243
2654
|
exports.Indexable = Indexable;
|
|
3244
|
-
exports.Register = Register;
|
|
3245
2655
|
exports.allocated = allocated;
|
|
3246
2656
|
exports.allocatedValues = allocatedValues;
|
|
3247
2657
|
exports.arrayDiff = arrayDiff;
|
|
@@ -3265,9 +2675,7 @@ exports.organize = organize;
|
|
|
3265
2675
|
exports.organized = organized;
|
|
3266
2676
|
exports.profileInfo = profileInfo;
|
|
3267
2677
|
exports.project = morph;
|
|
3268
|
-
exports.register = register;
|
|
3269
2678
|
exports.resource = resource;
|
|
3270
|
-
exports.scan = scan;
|
|
3271
2679
|
exports.setAt = setAt;
|
|
3272
2680
|
exports.throttle = throttle;
|
|
3273
2681
|
exports.unreactive = unreactive;
|