mutts 1.0.12 → 1.0.14
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/BROWSER_ASYNC_POLYFILL.md +79 -0
- package/README.md +7 -4
- package/dist/browser.cjs +150 -27
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +1440 -2
- package/dist/browser.dev.cjs +17 -3
- 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 +137 -28
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/{index-yK0HVxHv.cjs → index-BnTNC9eC.cjs} +347 -156
- package/dist/chunks/index-BnTNC9eC.cjs.map +1 -0
- package/dist/chunks/{index-BUop6B2U.esm.js → index-CAWVZL7P.esm.js} +345 -154
- package/dist/chunks/index-CAWVZL7P.esm.js.map +1 -0
- package/dist/chunks/node-Df_5r_WA.cjs +187 -0
- package/dist/chunks/node-Df_5r_WA.cjs.map +1 -0
- package/dist/chunks/node-DuIduHw3.esm.js +185 -0
- package/dist/chunks/node-DuIduHw3.esm.js.map +1 -0
- package/dist/chunks/{proxy-D2C49sXH.esm.js → proxy-C2lnvvbx.esm.js} +943 -272
- package/dist/chunks/proxy-C2lnvvbx.esm.js.map +1 -0
- package/dist/chunks/{proxy-BvM4yewA.cjs → proxy-HA_QQnd5.cjs} +959 -273
- package/dist/chunks/proxy-HA_QQnd5.cjs.map +1 -0
- package/dist/debug.cjs +571 -173
- package/dist/debug.cjs.map +1 -1
- package/dist/debug.d.ts +96 -80
- package/dist/debug.esm.js +567 -173
- package/dist/debug.esm.js.map +1 -1
- package/dist/devtools/panel.js.map +1 -1
- package/dist/mutts.umd.js +4351 -3366
- 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 +18 -4
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.dev.cjs +18 -4
- 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-Bx2PhORg.d.ts → types.d.ts} +42 -15
- package/docs/ai/api-reference.md +105 -13
- package/docs/ai/manual.md +77 -29
- package/docs/debug-getReason.md +161 -0
- package/docs/flavored.md +98 -1
- package/docs/reactive/advanced.md +184 -12
- package/docs/reactive/attend.md +32 -0
- package/docs/reactive/core.md +40 -6
- package/docs/reactive/debugging.md +40 -15
- package/docs/reactive.md +4 -1
- package/package.json +13 -9
- package/dist/chunks/index-BUop6B2U.esm.js.map +0 -1
- package/dist/chunks/index-yK0HVxHv.cjs.map +0 -1
- package/dist/chunks/node-Bo7WU5S2.esm.js +0 -96
- package/dist/chunks/node-Bo7WU5S2.esm.js.map +0 -1
- package/dist/chunks/node-Dd0esp5F.cjs +0 -98
- package/dist/chunks/node-Dd0esp5F.cjs.map +0 -1
- package/dist/chunks/proxy-BvM4yewA.cjs.map +0 -1
- package/dist/chunks/proxy-D2C49sXH.esm.js.map +0 -1
- package/dist/index.d.ts +0 -1322
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { u as decorator, p as captioned, aa as options, y as effect, ap as markWithRoot, Y as link, F as flavored, af as tag, a9 as reactive, ai as touched1, U as isReactive, ah as touched, K as getState, aq as dependant, J as getActiveEffect, ar as getEffectNode, as as chainExternalReason, at as keysOf, au as objectsWithDeepWatchers, av as effectToDeepWatchedObjects, ak as untracked, aw as deepWatchers, Q as isNonReactive, al as unwrap, ax as registerDeepWatcher, a2 as named, ay as rootFunctionSymbol, a8 as proxyToObject, az as getRoot, aA as inertDepth, v as deepCompare, aB as optionCall, ad as root, aC as FoolProof, E as flavorOptions, aD as effectHistory, q as captured, aE as unreactiveProperties, g as addUnreactiveProps, aF as __runInitializers, aG as __esDecorate, n as atomic, aH as contentRef, aI as notifyPropertyChange, aJ as metaProtos, aK as wrapProtos, aL as objectParents, aM as watchers, aN as effectToReactiveObjects, a3 as objectToProxy } from './proxy-C2lnvvbx.esm.js';
|
|
2
2
|
|
|
3
3
|
// Integrated with `using` statement via Symbol.dispose
|
|
4
4
|
const fr = new FinalizationRegistry((f) => f());
|
|
@@ -256,46 +256,57 @@ function buildPatches(history, A, B, offset, finalX, finalY, finalD, finalK, vOf
|
|
|
256
256
|
var _a, _b;
|
|
257
257
|
const events = Symbol('events');
|
|
258
258
|
const hooks = Symbol('hooks');
|
|
259
|
+
function getEventMap(target) {
|
|
260
|
+
return target[events];
|
|
261
|
+
}
|
|
262
|
+
function getHookSet(target) {
|
|
263
|
+
return target[hooks];
|
|
264
|
+
}
|
|
259
265
|
const eventBehavior = {
|
|
260
266
|
on(eventOrEvents, cb) {
|
|
267
|
+
const self = this;
|
|
268
|
+
const eventMap = getEventMap(self);
|
|
261
269
|
if (typeof eventOrEvents === 'object') {
|
|
262
270
|
for (const e of Object.keys(eventOrEvents)) {
|
|
263
271
|
this.on(e, eventOrEvents[e]);
|
|
264
272
|
}
|
|
265
273
|
}
|
|
266
274
|
else if (cb !== undefined) {
|
|
267
|
-
const callbacks =
|
|
275
|
+
const callbacks = eventMap.get(eventOrEvents) ?? new Set();
|
|
268
276
|
if (!callbacks.has(cb))
|
|
269
277
|
callbacks.add(cb);
|
|
270
|
-
|
|
278
|
+
eventMap.set(eventOrEvents, callbacks);
|
|
271
279
|
}
|
|
272
280
|
return () => this.off(eventOrEvents, cb);
|
|
273
281
|
},
|
|
274
282
|
off(eventOrEvents, cb) {
|
|
283
|
+
const self = this;
|
|
284
|
+
const eventMap = getEventMap(self);
|
|
275
285
|
if (typeof eventOrEvents === 'object') {
|
|
276
286
|
for (const e of Object.keys(eventOrEvents)) {
|
|
277
287
|
this.off(e, eventOrEvents[e]);
|
|
278
288
|
}
|
|
279
289
|
}
|
|
280
290
|
else if (cb !== null && cb !== undefined) {
|
|
281
|
-
const callbacks =
|
|
291
|
+
const callbacks = eventMap.get(eventOrEvents);
|
|
282
292
|
if (callbacks) {
|
|
283
293
|
callbacks.delete(cb);
|
|
284
294
|
if (!callbacks.size)
|
|
285
|
-
|
|
295
|
+
eventMap.delete(eventOrEvents);
|
|
286
296
|
}
|
|
287
297
|
}
|
|
288
298
|
else {
|
|
289
299
|
// Remove all listeners for this event
|
|
290
|
-
|
|
300
|
+
eventMap.delete(eventOrEvents);
|
|
291
301
|
}
|
|
292
302
|
},
|
|
293
303
|
emit(event, ...args) {
|
|
294
|
-
const
|
|
304
|
+
const self = this;
|
|
305
|
+
const callbacks = getEventMap(self).get(event);
|
|
295
306
|
if (callbacks)
|
|
296
307
|
for (const cb of callbacks)
|
|
297
308
|
cb.apply(this, args);
|
|
298
|
-
for (const cb of
|
|
309
|
+
for (const cb of getHookSet(self))
|
|
299
310
|
cb.call(this, event, ...args);
|
|
300
311
|
},
|
|
301
312
|
};
|
|
@@ -305,7 +316,7 @@ function perEvent(eventful, fct, use) {
|
|
|
305
316
|
get(target, prop) {
|
|
306
317
|
if (typeof prop !== 'string')
|
|
307
318
|
return target[prop];
|
|
308
|
-
if (use && !eventful
|
|
319
|
+
if (use && !getEventMap(eventful).has(prop) && !getHookSet(eventful).size)
|
|
309
320
|
return () => { };
|
|
310
321
|
// Return cached function or create and cache
|
|
311
322
|
let cached = cache.get(prop);
|
|
@@ -744,7 +755,7 @@ function chainPromise(given) {
|
|
|
744
755
|
return chained;
|
|
745
756
|
}
|
|
746
757
|
|
|
747
|
-
function attend(source, callback) {
|
|
758
|
+
const attend = captioned(function attend(source, callback) {
|
|
748
759
|
const enumerate = typeof source === 'function'
|
|
749
760
|
? source
|
|
750
761
|
: Array.isArray(source)
|
|
@@ -755,14 +766,16 @@ function attend(source, callback) {
|
|
|
755
766
|
? () => source.values()
|
|
756
767
|
: () => Object.keys(source);
|
|
757
768
|
const keyEffects = new Map();
|
|
758
|
-
const
|
|
769
|
+
const callbackLabel = callback.name ? callback.name : '';
|
|
770
|
+
const outer = effect `attend`(({ ascend }) => {
|
|
759
771
|
const keys = new Set();
|
|
760
772
|
for (const key of enumerate())
|
|
761
773
|
keys.add(key);
|
|
762
774
|
for (const key of keys) {
|
|
763
775
|
if (keyEffects.has(key))
|
|
764
776
|
continue;
|
|
765
|
-
|
|
777
|
+
const indexRef = { value: key };
|
|
778
|
+
keyEffects.set(key, ascend(() => effect `attend${callbackLabel ? `:${callbackLabel}` : ''}:${key}`((access) => callback(indexRef.value, access))));
|
|
766
779
|
}
|
|
767
780
|
for (const key of Array.from(keyEffects.keys())) {
|
|
768
781
|
if (!keys.has(key)) {
|
|
@@ -777,17 +790,50 @@ function attend(source, callback) {
|
|
|
777
790
|
stop(reason);
|
|
778
791
|
keyEffects.clear();
|
|
779
792
|
};
|
|
780
|
-
}
|
|
781
|
-
|
|
793
|
+
}, {
|
|
794
|
+
name: 'attend',
|
|
795
|
+
callbackIndex: 1,
|
|
796
|
+
warn: (message) => options.warn(`[reactive] ${message}`),
|
|
797
|
+
});
|
|
798
|
+
/**
|
|
799
|
+
* Lifts a callback that returns an object into a reactive object that automatically
|
|
800
|
+
* synchronizes with the source object returned by the callback.
|
|
801
|
+
*
|
|
802
|
+
* The returned reactive object will update whenever the callback's dependencies change,
|
|
803
|
+
* efficiently syncing only the properties that differ from the previous result using
|
|
804
|
+
* Object.assign(). Properties that no longer exist in the source are automatically removed.
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```typescript
|
|
808
|
+
* const user = reactive({ name: 'John', age: 30 })
|
|
809
|
+
* const profile = lift(() => ({
|
|
810
|
+
* displayName: user.name.toUpperCase(),
|
|
811
|
+
* isAdult: user.age >= 18,
|
|
812
|
+
* description: `${user.name} is ${user.age} years old`
|
|
813
|
+
* }))
|
|
814
|
+
*
|
|
815
|
+
* console.log(profile.displayName) // JOHN
|
|
816
|
+
* console.log(profile.isAdult) // true
|
|
817
|
+
*
|
|
818
|
+
* user.name = 'Jane'
|
|
819
|
+
* console.log(profile.displayName) // JANE
|
|
820
|
+
* console.log(profile.description) // Jane is 30 years old
|
|
821
|
+
* ```
|
|
822
|
+
*
|
|
823
|
+
* @param cb Callback function that returns an object
|
|
824
|
+
* @returns A reactive object synchronized with the callback's result, with a [cleanup] property to stop tracking
|
|
825
|
+
*/
|
|
826
|
+
const lift = captioned(function lift(cb) {
|
|
782
827
|
let result;
|
|
783
828
|
let rawResult;
|
|
784
|
-
const
|
|
829
|
+
const resultName = `lift:${cb.name || 'anonymous'}`;
|
|
830
|
+
const liftCleanup = effect `lift:${cb.name}`(markWithRoot((access) => {
|
|
785
831
|
const source = cb(access);
|
|
786
832
|
if (!source || typeof source !== 'object')
|
|
787
833
|
throw new Error('lift callback must return an array or object');
|
|
788
834
|
const sourceProto = Object.getPrototypeOf(source);
|
|
789
835
|
if (!result) {
|
|
790
|
-
rawResult = Array.isArray(source) ? [] : Object.create(sourceProto);
|
|
836
|
+
rawResult = tag(resultName, Array.isArray(source) ? [] : Object.create(sourceProto));
|
|
791
837
|
result = reactive(rawResult);
|
|
792
838
|
}
|
|
793
839
|
if (sourceProto !== Object.getPrototypeOf(result))
|
|
@@ -798,6 +844,7 @@ function lift(cb) {
|
|
|
798
844
|
res.splice(indexA, sliceA.length, ...sliceB);
|
|
799
845
|
}
|
|
800
846
|
else {
|
|
847
|
+
const recordResult = rawResult;
|
|
801
848
|
for (const key of Object.keys(source)) {
|
|
802
849
|
const had = key in rawResult;
|
|
803
850
|
const newDesc = Object.getOwnPropertyDescriptor(source, key);
|
|
@@ -806,7 +853,7 @@ function lift(cb) {
|
|
|
806
853
|
const sameAccessor = oldDesc && newDesc.get && oldDesc.get === newDesc.get;
|
|
807
854
|
Object.defineProperty(rawResult, key, newDesc);
|
|
808
855
|
if (!sameAccessor &&
|
|
809
|
-
|
|
856
|
+
recordResult[key] !==
|
|
810
857
|
(oldDesc ? (oldDesc.get ? oldDesc.get() : oldDesc.value) : undefined))
|
|
811
858
|
touched1(rawResult, { type: 'set', prop: key }, key);
|
|
812
859
|
}
|
|
@@ -817,13 +864,16 @@ function lift(cb) {
|
|
|
817
864
|
}
|
|
818
865
|
for (const key of Object.keys(rawResult))
|
|
819
866
|
if (!(key in source)) {
|
|
820
|
-
delete
|
|
867
|
+
delete recordResult[key];
|
|
821
868
|
touched1(rawResult, { type: 'del', prop: key }, key);
|
|
822
869
|
}
|
|
823
870
|
}
|
|
824
871
|
}, cb));
|
|
825
872
|
return link(result, liftCleanup);
|
|
826
|
-
}
|
|
873
|
+
}, {
|
|
874
|
+
name: 'lift',
|
|
875
|
+
warn: (message) => options.warn(`[reactive] ${message}`),
|
|
876
|
+
});
|
|
827
877
|
/**
|
|
828
878
|
* Reactively maps an array source through `fn`, producing a lazy reactive output array.
|
|
829
879
|
*
|
|
@@ -843,16 +893,26 @@ function lift(cb) {
|
|
|
843
893
|
*/
|
|
844
894
|
function morphArray(source, fn, options) {
|
|
845
895
|
if (typeof source !== 'function' && !isReactive(source) && options?.pure === true) {
|
|
846
|
-
return source.map((i) => fn(i));
|
|
896
|
+
return source.map((i) => fn(i, { index: 0 }));
|
|
847
897
|
}
|
|
848
898
|
let track;
|
|
849
899
|
const itemEffects = new Map();
|
|
850
|
-
const cache = [];
|
|
900
|
+
const cache = tag(`morph:${fn.name || 'anonymous'}`, []);
|
|
851
901
|
let input = [];
|
|
902
|
+
function currentCleanupReason() {
|
|
903
|
+
const activeEffect = getActiveEffect();
|
|
904
|
+
if (!activeEffect)
|
|
905
|
+
return undefined;
|
|
906
|
+
const node = getEffectNode(activeEffect);
|
|
907
|
+
return node.currentReason;
|
|
908
|
+
}
|
|
909
|
+
function stopEntry(entry) {
|
|
910
|
+
entry.stop(chainExternalReason({ type: 'stopped', chain: currentCleanupReason() }));
|
|
911
|
+
}
|
|
852
912
|
function stopItem(key) {
|
|
853
913
|
const entry = itemEffects.get(key);
|
|
854
914
|
if (entry) {
|
|
855
|
-
entry
|
|
915
|
+
stopEntry(entry);
|
|
856
916
|
itemEffects.delete(key);
|
|
857
917
|
}
|
|
858
918
|
}
|
|
@@ -860,20 +920,33 @@ function morphArray(source, fn, options) {
|
|
|
860
920
|
const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(input));
|
|
861
921
|
if (isPure) {
|
|
862
922
|
track(() => {
|
|
863
|
-
cache[key] = fn(input);
|
|
923
|
+
cache[key] = fn(input, { index: key });
|
|
864
924
|
});
|
|
865
925
|
}
|
|
866
926
|
else {
|
|
867
|
-
const
|
|
868
|
-
const stop = track(() => effect.
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
delete cache[indexRef.value];
|
|
927
|
+
const position = reactive({ index: key });
|
|
928
|
+
const stop = track(() => effect.opaque `morph:${fn.name}:${key}`((access) => {
|
|
929
|
+
if (access.reaction) {
|
|
930
|
+
delete cache[position.index];
|
|
872
931
|
touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
873
|
-
|
|
874
|
-
|
|
932
|
+
const activeEffect = getActiveEffect();
|
|
933
|
+
let chain;
|
|
934
|
+
if (activeEffect) {
|
|
935
|
+
const node = getEffectNode(activeEffect);
|
|
936
|
+
chain = node.currentReason;
|
|
937
|
+
}
|
|
938
|
+
stop?.({
|
|
939
|
+
type: 'invalidate',
|
|
940
|
+
cause: chainExternalReason(!access.reaction || access.reaction === true
|
|
941
|
+
? { type: 'stopped', chain }
|
|
942
|
+
: access.reaction),
|
|
943
|
+
chain: chainExternalReason(chain),
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
else
|
|
947
|
+
cache[position.index] = fn(input, position, access);
|
|
875
948
|
}));
|
|
876
|
-
itemEffects.set(key, { stop,
|
|
949
|
+
itemEffects.set(key, { stop, position });
|
|
877
950
|
}
|
|
878
951
|
}
|
|
879
952
|
const proxy = reactive(cache, {
|
|
@@ -889,40 +962,64 @@ function morphArray(source, fn, options) {
|
|
|
889
962
|
return Reflect.has(input, prop);
|
|
890
963
|
},
|
|
891
964
|
});
|
|
892
|
-
const stopMain = effect
|
|
965
|
+
const stopMain = effect `morph:${fn.name}`(({ ascend }) => {
|
|
893
966
|
track = ascend;
|
|
894
967
|
const newInput = [...(typeof source === 'function' ? source() : source)];
|
|
895
968
|
const diffs = arrayDiff(input, newInput).toSorted((a, b) => b.indexA - a.indexA);
|
|
896
969
|
if (diffs.length > 0) {
|
|
970
|
+
const reusable = new Map();
|
|
971
|
+
for (const [index, entry] of itemEffects) {
|
|
972
|
+
const value = input[index];
|
|
973
|
+
const entries = reusable.get(value);
|
|
974
|
+
if (entries)
|
|
975
|
+
entries.push({ index, entry });
|
|
976
|
+
else
|
|
977
|
+
reusable.set(value, [{ index, entry }]);
|
|
978
|
+
}
|
|
979
|
+
const nextEffects = new Map();
|
|
980
|
+
const reused = new Set();
|
|
981
|
+
const nextCache = new Map();
|
|
982
|
+
for (let index = 0; index < newInput.length; index++) {
|
|
983
|
+
const entries = reusable.get(newInput[index]);
|
|
984
|
+
const reusedEntry = entries?.shift();
|
|
985
|
+
if (!reusedEntry)
|
|
986
|
+
continue;
|
|
987
|
+
const { index: previousIndex, entry } = reusedEntry;
|
|
988
|
+
reused.add(previousIndex);
|
|
989
|
+
nextEffects.set(index, entry);
|
|
990
|
+
if (entry.position.index !== index)
|
|
991
|
+
entry.position.index = index;
|
|
992
|
+
else if (Object.hasOwn(cache, previousIndex))
|
|
993
|
+
nextCache.set(index, cache[previousIndex]);
|
|
994
|
+
}
|
|
995
|
+
for (const [index, entry] of itemEffects) {
|
|
996
|
+
if (!reused.has(index))
|
|
997
|
+
stopEntry(entry);
|
|
998
|
+
}
|
|
999
|
+
itemEffects.clear();
|
|
1000
|
+
for (const [index, entry] of nextEffects)
|
|
1001
|
+
itemEffects.set(index, entry);
|
|
1002
|
+
const previousLength = cache.length;
|
|
1003
|
+
cache.length = newInput.length;
|
|
1004
|
+
for (let i = 0; i < Math.max(previousLength, newInput.length); i++)
|
|
1005
|
+
delete cache[i];
|
|
1006
|
+
for (const [index, value] of nextCache)
|
|
1007
|
+
cache[index] = value;
|
|
1008
|
+
const eagerIndices = new Set();
|
|
897
1009
|
for (const diff of diffs) {
|
|
898
|
-
|
|
899
|
-
for (let i =
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
if (
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
}
|
|
912
|
-
// Re-add them with shifted indices
|
|
913
|
-
for (const [idx, entry] of entries) {
|
|
914
|
-
if (idx >= diff.indexA + diff.sliceA.length) {
|
|
915
|
-
const newIdx = idx + shift;
|
|
916
|
-
entry.index.value = newIdx;
|
|
917
|
-
itemEffects.set(newIdx, entry);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
// Splice the cache
|
|
922
|
-
cache.splice(diff.indexA, diff.sliceA.length, ...new Array(diff.sliceB.length).fill(undefined));
|
|
923
|
-
// Make holes for lazy computation
|
|
924
|
-
for (let i = diff.indexA; i < diff.indexA + diff.sliceB.length; i++)
|
|
925
|
-
delete cache[i];
|
|
1010
|
+
const max = Math.max(diff.sliceA.length, diff.sliceB.length);
|
|
1011
|
+
for (let i = 0; i < max; i++)
|
|
1012
|
+
eagerIndices.add(diff.indexA + i);
|
|
1013
|
+
}
|
|
1014
|
+
for (const index of eagerIndices) {
|
|
1015
|
+
if (index < 0 || index >= newInput.length || Object.hasOwn(cache, index))
|
|
1016
|
+
continue;
|
|
1017
|
+
const value = newInput[index];
|
|
1018
|
+
const isPure = options?.pure === true || (typeof options?.pure === 'function' && options.pure(value));
|
|
1019
|
+
if (isPure)
|
|
1020
|
+
continue;
|
|
1021
|
+
stopItem(index);
|
|
1022
|
+
computeItem(index, value);
|
|
926
1023
|
}
|
|
927
1024
|
const invalidates = new Set([keysOf]);
|
|
928
1025
|
if (input.length !== newInput.length)
|
|
@@ -963,12 +1060,18 @@ function morphMap(source, fn, options) {
|
|
|
963
1060
|
}
|
|
964
1061
|
let track;
|
|
965
1062
|
const itemEffects = new Map();
|
|
966
|
-
const cache = new Map();
|
|
1063
|
+
const cache = tag(`morph:${fn.name || 'anonymous'}`, new Map());
|
|
967
1064
|
Object.defineProperty(cache, 'constructor', { value: Object, enumerable: false });
|
|
968
1065
|
function stopItem(key) {
|
|
969
1066
|
const stop = itemEffects.get(key);
|
|
970
1067
|
if (stop) {
|
|
971
|
-
|
|
1068
|
+
const activeEffect = getActiveEffect();
|
|
1069
|
+
let chain;
|
|
1070
|
+
if (activeEffect) {
|
|
1071
|
+
const node = getEffectNode(activeEffect);
|
|
1072
|
+
chain = node.currentReason;
|
|
1073
|
+
}
|
|
1074
|
+
stop({ type: 'stopped', chain });
|
|
972
1075
|
itemEffects.delete(key);
|
|
973
1076
|
}
|
|
974
1077
|
}
|
|
@@ -978,12 +1081,25 @@ function morphMap(source, fn, options) {
|
|
|
978
1081
|
cache.set(key, track(() => fn(val, key)));
|
|
979
1082
|
}
|
|
980
1083
|
else {
|
|
981
|
-
const stop = track(() => effect.
|
|
982
|
-
|
|
1084
|
+
const stop = track(() => effect.opaque `morph:${fn.name}:${key}`((access) => {
|
|
1085
|
+
const next = source.get(key);
|
|
1086
|
+
if (next === undefined && !source.has(key))
|
|
1087
|
+
return;
|
|
1088
|
+
cache.set(key, fn(next, key, access));
|
|
983
1089
|
return (reason) => {
|
|
984
1090
|
cache.delete(key);
|
|
985
1091
|
touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
986
|
-
|
|
1092
|
+
const activeEffect = getActiveEffect();
|
|
1093
|
+
let chain;
|
|
1094
|
+
if (activeEffect) {
|
|
1095
|
+
const node = getEffectNode(activeEffect);
|
|
1096
|
+
chain = node.currentReason;
|
|
1097
|
+
}
|
|
1098
|
+
stop?.({
|
|
1099
|
+
type: 'invalidate',
|
|
1100
|
+
cause: chainExternalReason(reason ?? { type: 'stopped', chain }),
|
|
1101
|
+
chain: chainExternalReason(chain),
|
|
1102
|
+
});
|
|
987
1103
|
};
|
|
988
1104
|
}));
|
|
989
1105
|
itemEffects.set(key, stop);
|
|
@@ -1027,7 +1143,7 @@ function morphMap(source, fn, options) {
|
|
|
1027
1143
|
},
|
|
1028
1144
|
});
|
|
1029
1145
|
let stateSnapshot = getState(source);
|
|
1030
|
-
const stopMain = effect
|
|
1146
|
+
const stopMain = effect `morph:${fn.name}`(({ ascend }) => {
|
|
1031
1147
|
track = ascend;
|
|
1032
1148
|
dependant(source, keysOf);
|
|
1033
1149
|
while ('evolution' in stateSnapshot) {
|
|
@@ -1074,7 +1190,13 @@ function morphRecord(source, fn, options) {
|
|
|
1074
1190
|
function stopItem(key) {
|
|
1075
1191
|
const stop = itemEffects.get(key);
|
|
1076
1192
|
if (stop) {
|
|
1077
|
-
|
|
1193
|
+
const activeEffect = getActiveEffect();
|
|
1194
|
+
let chain;
|
|
1195
|
+
if (activeEffect) {
|
|
1196
|
+
const node = getEffectNode(activeEffect);
|
|
1197
|
+
chain = node.currentReason;
|
|
1198
|
+
}
|
|
1199
|
+
stop({ type: 'stopped', chain });
|
|
1078
1200
|
itemEffects.delete(key);
|
|
1079
1201
|
}
|
|
1080
1202
|
}
|
|
@@ -1084,12 +1206,22 @@ function morphRecord(source, fn, options) {
|
|
|
1084
1206
|
cache[key] = track(() => fn(val, key));
|
|
1085
1207
|
}
|
|
1086
1208
|
else {
|
|
1087
|
-
const stop = track(() => effect.
|
|
1209
|
+
const stop = track(() => effect.opaque `morph:${fn.name}:${key}`((access) => {
|
|
1088
1210
|
cache[key] = fn(source[key], key, access);
|
|
1089
1211
|
return (reason) => {
|
|
1090
1212
|
delete cache[key];
|
|
1091
1213
|
touched1(cache, { type: 'invalidate', prop: 'morph' }, String(key));
|
|
1092
|
-
|
|
1214
|
+
const activeEffect = getActiveEffect();
|
|
1215
|
+
let chain;
|
|
1216
|
+
if (activeEffect) {
|
|
1217
|
+
const node = getEffectNode(activeEffect);
|
|
1218
|
+
chain = node.currentReason;
|
|
1219
|
+
}
|
|
1220
|
+
stop?.({
|
|
1221
|
+
type: 'invalidate',
|
|
1222
|
+
cause: chainExternalReason(reason ?? { type: 'stopped', chain }),
|
|
1223
|
+
chain: chainExternalReason(chain),
|
|
1224
|
+
});
|
|
1093
1225
|
};
|
|
1094
1226
|
}));
|
|
1095
1227
|
itemEffects.set(key, stop);
|
|
@@ -1116,7 +1248,7 @@ function morphRecord(source, fn, options) {
|
|
|
1116
1248
|
},
|
|
1117
1249
|
});
|
|
1118
1250
|
let stateSnapshot = getState(source);
|
|
1119
|
-
const stopMain = effect
|
|
1251
|
+
const stopMain = effect `morph:${fn.name}`(({ ascend }) => {
|
|
1120
1252
|
track = ascend;
|
|
1121
1253
|
// Track only structural changes on source
|
|
1122
1254
|
dependant(source, keysOf);
|
|
@@ -1157,7 +1289,7 @@ function morphRecord(source, fn, options) {
|
|
|
1157
1289
|
* // Changing users[0].name only recomputes names[0]
|
|
1158
1290
|
* ```
|
|
1159
1291
|
*/
|
|
1160
|
-
const morph = flavored(function morph(source, fn, options) {
|
|
1292
|
+
const morph = captioned(flavored(function morph(source, fn, options) {
|
|
1161
1293
|
if (Array.isArray(source) || typeof source === 'function')
|
|
1162
1294
|
return morphArray(source, fn, options);
|
|
1163
1295
|
if (source instanceof Map)
|
|
@@ -1167,6 +1299,10 @@ const morph = flavored(function morph(source, fn, options) {
|
|
|
1167
1299
|
get pure() {
|
|
1168
1300
|
return (source, fn, _opt) => this(source, fn, { pure: true });
|
|
1169
1301
|
},
|
|
1302
|
+
}), {
|
|
1303
|
+
name: 'morph',
|
|
1304
|
+
callbackIndex: 1,
|
|
1305
|
+
warn: (message) => options.warn(`[reactive] ${message}`),
|
|
1170
1306
|
});
|
|
1171
1307
|
|
|
1172
1308
|
/**
|
|
@@ -1192,7 +1328,7 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
1192
1328
|
const wrappedCallback = markWithRoot((() => callback(target)), callback);
|
|
1193
1329
|
registerDeepWatcher();
|
|
1194
1330
|
// Use the existing effect system to register dependencies
|
|
1195
|
-
return effect
|
|
1331
|
+
return effect `deepWatch`(() => {
|
|
1196
1332
|
// Mark the target object as having deep watchers
|
|
1197
1333
|
objectsWithDeepWatchers.add(target);
|
|
1198
1334
|
// Track which objects this effect is watching for cleanup
|
|
@@ -1256,7 +1392,7 @@ function deepWatch(target, callback, { immediate = false } = {}) {
|
|
|
1256
1392
|
traverseAndTrack(target);
|
|
1257
1393
|
// Only call the callback if immediate is true or if it's not the first run
|
|
1258
1394
|
if (immediate) {
|
|
1259
|
-
untracked(() => callback(target));
|
|
1395
|
+
untracked `deepWatch:callback`(() => callback(target));
|
|
1260
1396
|
}
|
|
1261
1397
|
immediate = true;
|
|
1262
1398
|
// Return a cleanup function that properly removes deep watcher tracking
|
|
@@ -1317,13 +1453,16 @@ function memoizeFunction(fn, opts) {
|
|
|
1317
1453
|
for (const arg of args) {
|
|
1318
1454
|
node = getBranch(node, arg);
|
|
1319
1455
|
}
|
|
1456
|
+
if (inertDepth > 0) {
|
|
1457
|
+
return fn.apply(this, args);
|
|
1458
|
+
}
|
|
1320
1459
|
dependant(node, 'memoize');
|
|
1321
1460
|
if ('result' in node) {
|
|
1322
1461
|
if (options.onMemoizationDiscrepancy) {
|
|
1323
1462
|
const wasVerification = options.isVerificationRun;
|
|
1324
1463
|
options.isVerificationRun = true;
|
|
1325
1464
|
try {
|
|
1326
|
-
const fresh = untracked(() => fn.apply(this, args));
|
|
1465
|
+
const fresh = untracked `memoize:verify-calculation`(() => fn.apply(this, args));
|
|
1327
1466
|
if (!deepCompare(node.result, fresh)) {
|
|
1328
1467
|
optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'calculation');
|
|
1329
1468
|
}
|
|
@@ -1336,7 +1475,7 @@ function memoizeFunction(fn, opts) {
|
|
|
1336
1475
|
}
|
|
1337
1476
|
// Create memoize internal effect to track dependencies and invalidate cache
|
|
1338
1477
|
// Use untracked to prevent the effect creation from being affected by parent effects
|
|
1339
|
-
node.cleanup = root(() => effect
|
|
1478
|
+
node.cleanup = root `memoize:root`(() => effect `memoize`(() => {
|
|
1340
1479
|
// Execute the function and track its dependencies
|
|
1341
1480
|
// The function execution will automatically track dependencies on reactive objects
|
|
1342
1481
|
node.result = fn.apply(this, args);
|
|
@@ -1347,7 +1486,17 @@ function memoizeFunction(fn, opts) {
|
|
|
1347
1486
|
// Lazy memoization: stop the effect so it doesn't re-run immediately.
|
|
1348
1487
|
// It will be re-created on next access.
|
|
1349
1488
|
if (node.cleanup) {
|
|
1350
|
-
|
|
1489
|
+
const activeEffect = getActiveEffect();
|
|
1490
|
+
let chain;
|
|
1491
|
+
if (activeEffect) {
|
|
1492
|
+
const effectNode = getEffectNode(activeEffect);
|
|
1493
|
+
chain = effectNode.currentReason;
|
|
1494
|
+
}
|
|
1495
|
+
node.cleanup({
|
|
1496
|
+
type: 'invalidate',
|
|
1497
|
+
cause: chainExternalReason(reason ?? { type: 'stopped', chain }),
|
|
1498
|
+
chain: chainExternalReason(chain),
|
|
1499
|
+
});
|
|
1351
1500
|
node.cleanup = undefined;
|
|
1352
1501
|
}
|
|
1353
1502
|
};
|
|
@@ -1356,7 +1505,7 @@ function memoizeFunction(fn, opts) {
|
|
|
1356
1505
|
const wasVerification = options.isVerificationRun;
|
|
1357
1506
|
options.isVerificationRun = true;
|
|
1358
1507
|
try {
|
|
1359
|
-
const fresh = untracked(() => fn.apply(this, args));
|
|
1508
|
+
const fresh = untracked `memoize:verify-comparison`(() => fn.apply(this, args));
|
|
1360
1509
|
if (!deepCompare(node.result, fresh)) {
|
|
1361
1510
|
optionCall('onMemoizationDiscrepancy', node.result, fresh, fn, args, 'comparison');
|
|
1362
1511
|
}
|
|
@@ -1548,12 +1697,12 @@ const memoize = flavored(makeMemoizeDecorator(), {
|
|
|
1548
1697
|
function organized(source, apply, baseTarget = {}) {
|
|
1549
1698
|
const observedSource = reactive(source);
|
|
1550
1699
|
const target = reactive(baseTarget);
|
|
1551
|
-
const stop = attend(()
|
|
1700
|
+
const stop = attend `organized:entries`(function enumerateObservedSourceKeys() {
|
|
1552
1701
|
const keys = [];
|
|
1553
1702
|
for (const key in observedSource)
|
|
1554
1703
|
keys.push(key);
|
|
1555
1704
|
return keys;
|
|
1556
|
-
}, (key)
|
|
1705
|
+
}, function applyObservedSourceKey(key) {
|
|
1557
1706
|
const sourceKey = key;
|
|
1558
1707
|
const accessBase = {
|
|
1559
1708
|
key: sourceKey,
|
|
@@ -1591,7 +1740,7 @@ function organize(target, property, access) {
|
|
|
1591
1740
|
|
|
1592
1741
|
//#region watch
|
|
1593
1742
|
const unsetYet = Symbol('unset-yet');
|
|
1594
|
-
const watch = flavored(function watch(value, //object | ((dep: DependencyAccess) => object),
|
|
1743
|
+
const watch = captioned(flavored(function watch(value, //object | ((dep: DependencyAccess) => object),
|
|
1595
1744
|
changed, options = {}) {
|
|
1596
1745
|
return typeof value === 'function'
|
|
1597
1746
|
? watchCallBack(value, changed, options)
|
|
@@ -1607,11 +1756,14 @@ changed, options = {}) {
|
|
|
1607
1756
|
get immediate() {
|
|
1608
1757
|
return flavorOptions(this, { immediate: true });
|
|
1609
1758
|
},
|
|
1759
|
+
}), {
|
|
1760
|
+
name: 'watch',
|
|
1761
|
+
warn: (message) => options.warn(`[reactive] ${message}`),
|
|
1610
1762
|
});
|
|
1611
1763
|
function watchObject(value, changed, { immediate = false, deep = false } = {}) {
|
|
1612
1764
|
if (deep)
|
|
1613
1765
|
return deepWatch(value, changed, { immediate });
|
|
1614
|
-
return effect
|
|
1766
|
+
return effect `watch:object`(() => {
|
|
1615
1767
|
dependant(value);
|
|
1616
1768
|
if (immediate)
|
|
1617
1769
|
changed(value);
|
|
@@ -1621,16 +1773,16 @@ function watchObject(value, changed, { immediate = false, deep = false } = {}) {
|
|
|
1621
1773
|
function watchCallBack(value, changed, { immediate = false, deep = false } = {}) {
|
|
1622
1774
|
let oldValue = unsetYet;
|
|
1623
1775
|
let deepCleanup;
|
|
1624
|
-
const cbCleanup = effect
|
|
1776
|
+
const cbCleanup = effect `watch:callback`(markWithRoot((access) => {
|
|
1625
1777
|
const newValue = value(access);
|
|
1626
1778
|
if (oldValue !== newValue) {
|
|
1627
1779
|
const old = oldValue;
|
|
1628
1780
|
if (old === unsetYet) {
|
|
1629
1781
|
if (immediate)
|
|
1630
|
-
untracked(() => changed(newValue));
|
|
1782
|
+
untracked `watch:changed`(() => changed(newValue));
|
|
1631
1783
|
}
|
|
1632
1784
|
else
|
|
1633
|
-
untracked(() => changed(newValue, old));
|
|
1785
|
+
untracked `watch:changed`(() => changed(newValue, old));
|
|
1634
1786
|
}
|
|
1635
1787
|
oldValue = newValue;
|
|
1636
1788
|
if (deep) {
|
|
@@ -1657,7 +1809,7 @@ function watchCallBack(value, changed, { immediate = false, deep = false } = {})
|
|
|
1657
1809
|
function when(predicate, timeout) {
|
|
1658
1810
|
return new Promise((resolve, reject) => {
|
|
1659
1811
|
let timer;
|
|
1660
|
-
const stop = effect
|
|
1812
|
+
const stop = effect `watch:when`((access) => {
|
|
1661
1813
|
try {
|
|
1662
1814
|
const value = predicate(access);
|
|
1663
1815
|
if (value) {
|
|
@@ -1764,7 +1916,7 @@ function resource(fetcher, options = {}) {
|
|
|
1764
1916
|
// Solve race conditions: make sure a new fast request is not overloaded by a slow old one
|
|
1765
1917
|
let counter = 0;
|
|
1766
1918
|
return lazyInit(resource, () => {
|
|
1767
|
-
link(resource, effect
|
|
1919
|
+
link(resource, effect `watch:resource`((access) => {
|
|
1768
1920
|
// Track reload signal to enable manual reloading
|
|
1769
1921
|
void reloadSignal.value;
|
|
1770
1922
|
const id = ++counter;
|
|
@@ -1930,6 +2082,7 @@ let ReactiveArrayWrapper = (() => {
|
|
|
1930
2082
|
return super.findLastIndex((v, i, a) => predicate.call(thisArg, reactive(v), i, a), thisArg);
|
|
1931
2083
|
}
|
|
1932
2084
|
flat(depth) {
|
|
2085
|
+
dependant(this, keysOf);
|
|
1933
2086
|
return reactive(super.flat(depth));
|
|
1934
2087
|
}
|
|
1935
2088
|
flatMap(callbackfn, thisArg) {
|
|
@@ -1941,14 +2094,28 @@ let ReactiveArrayWrapper = (() => {
|
|
|
1941
2094
|
}, thisArg);
|
|
1942
2095
|
}
|
|
1943
2096
|
includes(searchElement, fromIndex) {
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
2097
|
+
const target = unwrap(searchElement);
|
|
2098
|
+
const length = this.length;
|
|
2099
|
+
let start = fromIndex ?? 0;
|
|
2100
|
+
if (start < 0)
|
|
2101
|
+
start = Math.max(length + start, 0);
|
|
2102
|
+
for (let i = start; i < length; i++) {
|
|
2103
|
+
const value = unwrap(this[i]);
|
|
2104
|
+
if (value === target)
|
|
2105
|
+
return true;
|
|
2106
|
+
}
|
|
2107
|
+
return false;
|
|
1947
2108
|
}
|
|
1948
2109
|
indexOf(searchElement, fromIndex) {
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
2110
|
+
const target = unwrap(searchElement);
|
|
2111
|
+
const length = this.length;
|
|
2112
|
+
let start = fromIndex ?? 0;
|
|
2113
|
+
if (start < 0)
|
|
2114
|
+
start = Math.max(length + start, 0);
|
|
2115
|
+
for (let i = start; i < length; i++)
|
|
2116
|
+
if (unwrap(this[i]) === target)
|
|
2117
|
+
return i;
|
|
2118
|
+
return -1;
|
|
1952
2119
|
}
|
|
1953
2120
|
join(separator) {
|
|
1954
2121
|
return super.join(separator);
|
|
@@ -1958,9 +2125,17 @@ let ReactiveArrayWrapper = (() => {
|
|
|
1958
2125
|
return super.keys();
|
|
1959
2126
|
}
|
|
1960
2127
|
lastIndexOf(searchElement, fromIndex) {
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
2128
|
+
const target = unwrap(searchElement);
|
|
2129
|
+
const length = this.length;
|
|
2130
|
+
let start = fromIndex ?? length - 1;
|
|
2131
|
+
if (start < 0)
|
|
2132
|
+
start = length + start;
|
|
2133
|
+
if (start >= length)
|
|
2134
|
+
start = length - 1;
|
|
2135
|
+
for (let i = start; i >= 0; i--)
|
|
2136
|
+
if (unwrap(this[i]) === target)
|
|
2137
|
+
return i;
|
|
2138
|
+
return -1;
|
|
1964
2139
|
}
|
|
1965
2140
|
map(callbackfn, thisArg) {
|
|
1966
2141
|
return reactive(super.map((v, i, a) => unwrap(callbackfn.call(thisArg, reactive(v), i, a)), thisArg));
|
|
@@ -2000,13 +2175,25 @@ let ReactiveArrayWrapper = (() => {
|
|
|
2000
2175
|
return super.sort(wrappedCompare);
|
|
2001
2176
|
}
|
|
2002
2177
|
splice(start, deleteCount, ...items) {
|
|
2178
|
+
const length = this.length;
|
|
2179
|
+
const normalizedStart = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
|
|
2180
|
+
const actualDeleteCount = arguments.length === 1
|
|
2181
|
+
? length - normalizedStart
|
|
2182
|
+
: Math.min(Math.max(deleteCount, 0), length - normalizedStart);
|
|
2183
|
+
const structural = actualDeleteCount > 0 || items.length > 0;
|
|
2184
|
+
let result;
|
|
2003
2185
|
if (arguments.length > 2)
|
|
2004
|
-
|
|
2005
|
-
if (arguments.length === 2)
|
|
2006
|
-
|
|
2007
|
-
if (arguments.length === 1)
|
|
2008
|
-
|
|
2009
|
-
|
|
2186
|
+
result = super.splice(start, deleteCount, ...items.map(unwrap));
|
|
2187
|
+
else if (arguments.length === 2)
|
|
2188
|
+
result = super.splice(start, deleteCount);
|
|
2189
|
+
else if (arguments.length === 1)
|
|
2190
|
+
result = super.splice(start);
|
|
2191
|
+
else
|
|
2192
|
+
result = [];
|
|
2193
|
+
if (structural && this.length === length) {
|
|
2194
|
+
touched(this, { type: 'set', prop: 'length' }, ['length']);
|
|
2195
|
+
}
|
|
2196
|
+
return reactive(result);
|
|
2010
2197
|
}
|
|
2011
2198
|
unshift(...items) {
|
|
2012
2199
|
return super.unshift(...items.map(unwrap));
|
|
@@ -2061,6 +2248,12 @@ let ReactiveArrayWrapper = (() => {
|
|
|
2061
2248
|
_a;
|
|
2062
2249
|
})();
|
|
2063
2250
|
|
|
2251
|
+
// These abstract classes are prototype tables for the reactive proxy, not classes
|
|
2252
|
+
// that are instantiated directly. `this` is the original Map/WeakMap target when
|
|
2253
|
+
// a method is reached through the proxy meta-prototype path, so calls like
|
|
2254
|
+
// `this.get()` or `this.entries()` intentionally re-enter the proxy machinery.
|
|
2255
|
+
// Do not mechanically rewrite them to `super.*` as if these were real subclass
|
|
2256
|
+
// instances; that would bypass parts of the designed reactive dispatch.
|
|
2064
2257
|
/**
|
|
2065
2258
|
* Reactive wrapper around JavaScript's WeakMap class
|
|
2066
2259
|
* Only tracks individual key operations, no size tracking (WeakMap limitation)
|
|
@@ -2109,10 +2302,8 @@ class ReactiveMap extends Map {
|
|
|
2109
2302
|
if (hadEntries) {
|
|
2110
2303
|
const evolution = { type: 'bunch', method: 'clear' };
|
|
2111
2304
|
// Clear triggers all effects since all keys are affected
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
touched(contentRef(this), evolution);
|
|
2115
|
-
});
|
|
2305
|
+
touched1(this, evolution, 'size');
|
|
2306
|
+
touched(contentRef(this), evolution);
|
|
2116
2307
|
}
|
|
2117
2308
|
}
|
|
2118
2309
|
entries() {
|
|
@@ -2150,10 +2341,8 @@ class ReactiveMap extends Map {
|
|
|
2150
2341
|
const result = super.delete(key);
|
|
2151
2342
|
if (hadKey) {
|
|
2152
2343
|
const evolution = { type: 'del', prop: key };
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
touched1(this, evolution, 'size');
|
|
2156
|
-
});
|
|
2344
|
+
touched1(contentRef(this), evolution, key);
|
|
2345
|
+
touched1(this, evolution, 'size');
|
|
2157
2346
|
}
|
|
2158
2347
|
return result;
|
|
2159
2348
|
}
|
|
@@ -2171,17 +2360,21 @@ class ReactiveMap extends Map {
|
|
|
2171
2360
|
const reactiveValue = reactive(value);
|
|
2172
2361
|
super.set(key, reactiveValue);
|
|
2173
2362
|
if (!hadKey || oldValue !== reactiveValue) {
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
touched1(this, evolution, 'size');
|
|
2179
|
-
});
|
|
2363
|
+
notifyPropertyChange(contentRef(this), key, oldValue, reactiveValue, hadKey);
|
|
2364
|
+
// Also notify size change for Map (WeakMap doesn't track size)
|
|
2365
|
+
const evolution = { type: hadKey ? 'set' : 'add', prop: key };
|
|
2366
|
+
touched1(this, evolution, 'size');
|
|
2180
2367
|
}
|
|
2181
2368
|
return this;
|
|
2182
2369
|
}
|
|
2183
2370
|
}
|
|
2184
2371
|
|
|
2372
|
+
// These abstract classes are prototype tables for the reactive proxy, not classes
|
|
2373
|
+
// that are instantiated directly. `this` is the original Set/WeakSet target when
|
|
2374
|
+
// a method is reached through the proxy meta-prototype path, so calls like
|
|
2375
|
+
// `this.has()` or `this.entries()` intentionally re-enter the proxy machinery.
|
|
2376
|
+
// Do not mechanically rewrite them to `super.*` as if these were real subclass
|
|
2377
|
+
// instances; that would bypass parts of the designed reactive dispatch.
|
|
2185
2378
|
/**
|
|
2186
2379
|
* Reactive wrapper around JavaScript's WeakSet class
|
|
2187
2380
|
* Only tracks individual value operations, no size tracking (WeakSet limitation)
|
|
@@ -2226,10 +2419,8 @@ class ReactiveSet extends Set {
|
|
|
2226
2419
|
if (!had) {
|
|
2227
2420
|
const evolution = { type: 'add', prop: reactiveValue };
|
|
2228
2421
|
// touch for value-specific and aggregate dependencies
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
touched1(this, evolution, 'size');
|
|
2232
|
-
});
|
|
2422
|
+
touched1(contentRef(this), evolution, reactiveValue);
|
|
2423
|
+
touched1(this, evolution, 'size');
|
|
2233
2424
|
}
|
|
2234
2425
|
return this;
|
|
2235
2426
|
}
|
|
@@ -2238,10 +2429,8 @@ class ReactiveSet extends Set {
|
|
|
2238
2429
|
super.clear();
|
|
2239
2430
|
if (hadEntries) {
|
|
2240
2431
|
const evolution = { type: 'bunch', method: 'clear' };
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
touched(contentRef(this), evolution);
|
|
2244
|
-
});
|
|
2432
|
+
touched1(this, evolution, 'size');
|
|
2433
|
+
touched(contentRef(this), evolution);
|
|
2245
2434
|
}
|
|
2246
2435
|
}
|
|
2247
2436
|
delete(value) {
|
|
@@ -2249,10 +2438,8 @@ class ReactiveSet extends Set {
|
|
|
2249
2438
|
const res = super.delete(value);
|
|
2250
2439
|
if (had) {
|
|
2251
2440
|
const evolution = { type: 'del', prop: value };
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
touched1(this, evolution, 'size');
|
|
2255
|
-
});
|
|
2441
|
+
touched1(contentRef(this), evolution, value);
|
|
2442
|
+
touched1(this, evolution, 'size');
|
|
2256
2443
|
}
|
|
2257
2444
|
return res;
|
|
2258
2445
|
}
|
|
@@ -2356,59 +2543,62 @@ function isCached(object, propertyKey) {
|
|
|
2356
2543
|
function cache(object, propertyKey, value) {
|
|
2357
2544
|
Object.defineProperty(object, propertyKey, { value });
|
|
2358
2545
|
}
|
|
2546
|
+
function descriptorBase(descriptor) {
|
|
2547
|
+
return function descriptorDecorator(...properties) {
|
|
2548
|
+
return (Base) => {
|
|
2549
|
+
return class extends Base {
|
|
2550
|
+
constructor(...args) {
|
|
2551
|
+
super(...args);
|
|
2552
|
+
for (const key of properties) {
|
|
2553
|
+
const existing = Object.getOwnPropertyDescriptor(this, key);
|
|
2554
|
+
Object.defineProperty(this, key, Object.assign(existing || {}, descriptor));
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
};
|
|
2558
|
+
};
|
|
2559
|
+
};
|
|
2560
|
+
}
|
|
2359
2561
|
/**
|
|
2360
2562
|
* Creates a decorator that modifies property descriptors for specified properties
|
|
2361
2563
|
* @param descriptor - The descriptor properties to apply
|
|
2362
2564
|
* @returns A class decorator that applies the descriptor to specified properties
|
|
2363
2565
|
*/
|
|
2364
|
-
const descriptor =
|
|
2365
|
-
return (...properties) => (Base) => {
|
|
2366
|
-
return class extends Base {
|
|
2367
|
-
constructor(...args) {
|
|
2368
|
-
super(...args);
|
|
2369
|
-
for (const key of properties) {
|
|
2370
|
-
const existing = Object.getOwnPropertyDescriptor(this, key);
|
|
2371
|
-
Object.defineProperty(this, key, Object.assign(existing || {}, descriptor));
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
};
|
|
2375
|
-
};
|
|
2376
|
-
}, {
|
|
2566
|
+
const descriptor = Object.assign(descriptorBase, {
|
|
2377
2567
|
/**
|
|
2378
2568
|
* enumerable: true
|
|
2379
2569
|
*/
|
|
2380
2570
|
get enumerable() {
|
|
2381
|
-
return
|
|
2571
|
+
return descriptorBase({ enumerable: true });
|
|
2382
2572
|
},
|
|
2383
2573
|
/**
|
|
2384
2574
|
* enumerable: false
|
|
2385
2575
|
*/
|
|
2386
2576
|
get hidden() {
|
|
2387
|
-
return
|
|
2577
|
+
return descriptorBase({ enumerable: false });
|
|
2388
2578
|
},
|
|
2389
2579
|
/**
|
|
2390
2580
|
* configurable: true
|
|
2391
2581
|
*/
|
|
2392
2582
|
get configurable() {
|
|
2393
|
-
return
|
|
2583
|
+
return descriptorBase({ configurable: true });
|
|
2394
2584
|
},
|
|
2395
2585
|
/**
|
|
2396
2586
|
* configurable: false
|
|
2397
2587
|
*/
|
|
2398
2588
|
get frozen() {
|
|
2399
|
-
return
|
|
2589
|
+
return descriptorBase({ configurable: false });
|
|
2400
2590
|
},
|
|
2401
2591
|
/**
|
|
2402
2592
|
* writable: true
|
|
2403
2593
|
*/
|
|
2404
2594
|
get writable() {
|
|
2405
|
-
return
|
|
2595
|
+
return descriptorBase({ writable: true });
|
|
2406
2596
|
},
|
|
2407
2597
|
/**
|
|
2408
2598
|
* writable: false
|
|
2409
2599
|
*/
|
|
2410
2600
|
get readonly() {
|
|
2411
|
-
return
|
|
2601
|
+
return descriptorBase({ writable: false });
|
|
2412
2602
|
},
|
|
2413
2603
|
});
|
|
2414
2604
|
/**
|
|
@@ -2537,24 +2727,25 @@ function throttle(delay) {
|
|
|
2537
2727
|
});
|
|
2538
2728
|
}
|
|
2539
2729
|
|
|
2540
|
-
var version$1 = "1.0.
|
|
2730
|
+
var version$1 = "1.0.14";
|
|
2541
2731
|
var pkg = {
|
|
2542
2732
|
version: version$1};
|
|
2543
2733
|
|
|
2544
2734
|
const { version } = pkg;
|
|
2545
2735
|
const GLOBAL_MUTTS_KEY = '__MUTTS_INSTANCE__';
|
|
2736
|
+
const runtimeGlobals = globalThis;
|
|
2546
2737
|
const globalScope = (typeof globalThis !== 'undefined'
|
|
2547
2738
|
? globalThis
|
|
2548
|
-
:
|
|
2549
|
-
? window
|
|
2550
|
-
:
|
|
2551
|
-
? global
|
|
2739
|
+
: runtimeGlobals.window
|
|
2740
|
+
? runtimeGlobals.window
|
|
2741
|
+
: runtimeGlobals.global
|
|
2742
|
+
? runtimeGlobals.global
|
|
2552
2743
|
: false);
|
|
2553
2744
|
if (globalScope) {
|
|
2554
2745
|
let source = 'mutts/index';
|
|
2555
2746
|
try {
|
|
2556
|
-
if (
|
|
2557
|
-
source = __filename;
|
|
2747
|
+
if (runtimeGlobals.__filename)
|
|
2748
|
+
source = runtimeGlobals.__filename;
|
|
2558
2749
|
else if (typeof import.meta !== 'undefined' && import.meta.url) {
|
|
2559
2750
|
source = import.meta.url;
|
|
2560
2751
|
}
|
|
@@ -2574,4 +2765,4 @@ if (globalScope) {
|
|
|
2574
2765
|
}
|
|
2575
2766
|
|
|
2576
2767
|
export { ArrayReadForward as A, unreactive as B, watch as C, Destroyable as D, Eventful as E, when as F, Indexable as I, DestructionError as a, allocated as b, allocatedValues as c, arrayDiff as d, attend as e, cache as f, cached as g, callOnGC as h, chainPromise as i, debounce as j, deepWatch as k, deprecated as l, descriptor as m, destructor as n, forwardArray as o, getAt as p, isCached as q, lift as r, memoize as s, morph as t, organize as u, organized as v, profileInfo as w, resource as x, setAt as y, throttle as z };
|
|
2577
|
-
//# sourceMappingURL=index-
|
|
2768
|
+
//# sourceMappingURL=index-CAWVZL7P.esm.js.map
|