mutts 1.0.0 → 1.0.1
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/dist/chunks/{decorator-BXsign4Z.js → decorator-8qjFb7dw.js} +2 -2
- package/dist/chunks/decorator-8qjFb7dw.js.map +1 -0
- package/dist/chunks/{decorator-CPbZNnsX.esm.js → decorator-AbRkXM5O.esm.js} +2 -2
- package/dist/chunks/decorator-AbRkXM5O.esm.js.map +1 -0
- package/dist/decorator.d.ts +1 -1
- package/dist/decorator.esm.js +1 -1
- package/dist/decorator.js +1 -1
- package/dist/destroyable.esm.js +1 -1
- package/dist/destroyable.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +2 -2
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/mutts.umd.js +1 -1
- 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/reactive.d.ts +4 -3
- package/dist/reactive.esm.js +61 -57
- package/dist/reactive.esm.js.map +1 -1
- package/dist/reactive.js +61 -56
- package/dist/reactive.js.map +1 -1
- package/dist/std-decorators.esm.js +1 -1
- package/dist/std-decorators.js +1 -1
- package/docs/reactive.md +616 -0
- package/package.json +1 -2
- package/dist/chunks/decorator-BXsign4Z.js.map +0 -1
- package/dist/chunks/decorator-CPbZNnsX.esm.js.map +0 -1
- package/src/decorator.test.ts +0 -495
- package/src/decorator.ts +0 -205
- package/src/destroyable.test.ts +0 -155
- package/src/destroyable.ts +0 -158
- package/src/eventful.test.ts +0 -380
- package/src/eventful.ts +0 -69
- package/src/index.ts +0 -7
- package/src/indexable.test.ts +0 -388
- package/src/indexable.ts +0 -124
- package/src/promiseChain.test.ts +0 -201
- package/src/promiseChain.ts +0 -99
- package/src/reactive/array.test.ts +0 -923
- package/src/reactive/array.ts +0 -352
- package/src/reactive/core.test.ts +0 -1663
- package/src/reactive/core.ts +0 -866
- package/src/reactive/index.ts +0 -28
- package/src/reactive/interface.test.ts +0 -1477
- package/src/reactive/interface.ts +0 -231
- package/src/reactive/map.test.ts +0 -866
- package/src/reactive/map.ts +0 -162
- package/src/reactive/set.test.ts +0 -289
- package/src/reactive/set.ts +0 -142
- package/src/std-decorators.test.ts +0 -679
- package/src/std-decorators.ts +0 -182
- package/src/utils.ts +0 -52
package/dist/reactive.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var decorator = require('./chunks/decorator-
|
|
3
|
+
var decorator = require('./chunks/decorator-8qjFb7dw.js');
|
|
4
4
|
var indexable = require('./indexable.js');
|
|
5
5
|
|
|
6
6
|
// biome-ignore-all lint/suspicious/noConfusingVoidType: Type 'void' is not assignable to type 'ScopedCallback | undefined'.
|
|
@@ -21,6 +21,7 @@ const deepWatchers = new WeakMap();
|
|
|
21
21
|
const effectToDeepWatchedObjects = new WeakMap();
|
|
22
22
|
// Track objects that should never be reactive and cannot be modified
|
|
23
23
|
const nonReactiveObjects = new WeakSet();
|
|
24
|
+
const absent = Symbol('absent');
|
|
24
25
|
/**
|
|
25
26
|
* Converts an iterator to a generator that yields reactive values
|
|
26
27
|
*/
|
|
@@ -142,7 +143,7 @@ function raiseDeps(objectWatchers, ...keyChains) {
|
|
|
142
143
|
const deps = objectWatchers.get(key);
|
|
143
144
|
if (deps)
|
|
144
145
|
for (const effect of Array.from(deps))
|
|
145
|
-
|
|
146
|
+
atomicEffect(effect);
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
function touched1(obj, evolution, prop) {
|
|
@@ -182,7 +183,6 @@ function getState(obj) {
|
|
|
182
183
|
return state;
|
|
183
184
|
}
|
|
184
185
|
function dependant(obj, prop = allProps) {
|
|
185
|
-
// TODO: avoid depending on property get?
|
|
186
186
|
obj = unwrap(obj);
|
|
187
187
|
if (activeEffect && (typeof prop !== 'symbol' || prop === allProps)) {
|
|
188
188
|
let objectWatchers = watchers.get(obj);
|
|
@@ -214,29 +214,53 @@ let parentEffect;
|
|
|
214
214
|
let batchedEffects;
|
|
215
215
|
// Track which sub-effects have been executed to prevent infinite loops
|
|
216
216
|
// These are all the effects triggered under `activeEffect` and all their sub-effects
|
|
217
|
-
function
|
|
217
|
+
function atomicEffect(effect, immediate) {
|
|
218
218
|
const root = getRoot(effect);
|
|
219
219
|
options?.chain(getRoot(effect), getRoot(activeEffect));
|
|
220
|
-
if (batchedEffects)
|
|
220
|
+
if (batchedEffects) {
|
|
221
221
|
batchedEffects.set(root, effect);
|
|
222
|
+
if (immediate)
|
|
223
|
+
try {
|
|
224
|
+
return effect();
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
batchedEffects.delete(root);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
222
230
|
else {
|
|
223
231
|
const runEffects = [];
|
|
224
232
|
batchedEffects = new Map([[root, effect]]);
|
|
233
|
+
const firstReturn = {};
|
|
225
234
|
try {
|
|
226
235
|
while (batchedEffects.size) {
|
|
227
236
|
if (runEffects.length > options.maxEffectChain)
|
|
228
237
|
throw new ReactiveError('[reactive] Max effect chain reached');
|
|
229
238
|
const [root, effect] = batchedEffects.entries().next().value;
|
|
230
239
|
runEffects.push(root);
|
|
231
|
-
effect();
|
|
240
|
+
const rv = effect();
|
|
241
|
+
if (!('value' in firstReturn))
|
|
242
|
+
firstReturn.value = rv;
|
|
232
243
|
batchedEffects.delete(root);
|
|
233
244
|
}
|
|
245
|
+
return firstReturn.value;
|
|
234
246
|
}
|
|
235
247
|
finally {
|
|
236
248
|
batchedEffects = undefined;
|
|
237
249
|
}
|
|
238
250
|
}
|
|
239
251
|
}
|
|
252
|
+
const atomic = decorator.decorator({
|
|
253
|
+
method(original) {
|
|
254
|
+
return function (...args) {
|
|
255
|
+
return atomicEffect(markWithRoot(() => original.apply(this, args), original), 'immediate');
|
|
256
|
+
};
|
|
257
|
+
},
|
|
258
|
+
default(original) {
|
|
259
|
+
return function (...args) {
|
|
260
|
+
return atomicEffect(markWithRoot(() => original.apply(this, args), original), 'immediate');
|
|
261
|
+
};
|
|
262
|
+
},
|
|
263
|
+
});
|
|
240
264
|
function withEffect(effect, fn, keepParent) {
|
|
241
265
|
if (getRoot(effect) === getRoot(activeEffect))
|
|
242
266
|
return fn();
|
|
@@ -311,7 +335,7 @@ function bubbleUpChange(changedObject, evolution) {
|
|
|
311
335
|
const parentDeepWatchers = deepWatchers.get(parent);
|
|
312
336
|
if (parentDeepWatchers)
|
|
313
337
|
for (const watcher of parentDeepWatchers)
|
|
314
|
-
|
|
338
|
+
atomicEffect(watcher);
|
|
315
339
|
// Continue bubbling up
|
|
316
340
|
bubbleUpChange(parent);
|
|
317
341
|
}
|
|
@@ -340,9 +364,8 @@ const reactiveHandlers = {
|
|
|
340
364
|
// Check if this property is marked as unreactive
|
|
341
365
|
if (obj[unreactiveProperties]?.has(prop) || typeof prop === 'symbol')
|
|
342
366
|
return Reflect.get(obj, prop, receiver);
|
|
343
|
-
const absent = !(prop in obj);
|
|
344
367
|
// Depend if...
|
|
345
|
-
if (!options.instanceMembers || Object.hasOwn(receiver, prop) ||
|
|
368
|
+
if (!options.instanceMembers || Object.hasOwn(receiver, prop) || !Reflect.has(receiver, prop))
|
|
346
369
|
dependant(obj, prop);
|
|
347
370
|
const value = Reflect.get(obj, prop, receiver);
|
|
348
371
|
if (typeof value === 'object' && value !== null) {
|
|
@@ -369,13 +392,12 @@ const reactiveHandlers = {
|
|
|
369
392
|
obj[prop] = newValue;
|
|
370
393
|
return true;
|
|
371
394
|
}
|
|
372
|
-
const oldVal = obj
|
|
373
|
-
const oldPresent = prop in obj;
|
|
395
|
+
const oldVal = Reflect.has(receiver, prop) ? Reflect.get(obj, prop, receiver) : absent;
|
|
374
396
|
track1(obj, prop, oldVal, newValue);
|
|
375
397
|
if (oldVal !== newValue) {
|
|
376
398
|
Reflect.set(obj, prop, newValue, receiver);
|
|
377
399
|
// try to find a "generic" way to express that
|
|
378
|
-
touched1(obj, { type:
|
|
400
|
+
touched1(obj, { type: oldVal !== absent ? 'set' : 'add', prop }, prop);
|
|
379
401
|
}
|
|
380
402
|
return true;
|
|
381
403
|
},
|
|
@@ -519,25 +541,7 @@ function effect(fn, ...args) {
|
|
|
519
541
|
}
|
|
520
542
|
// Mark the runEffect callback with the original function as its root
|
|
521
543
|
markWithRoot(runEffect, fn);
|
|
522
|
-
|
|
523
|
-
if (!batchedEffects) {
|
|
524
|
-
hasEffect(runEffect);
|
|
525
|
-
}
|
|
526
|
-
else {
|
|
527
|
-
const oldBatchedEffects = batchedEffects;
|
|
528
|
-
try {
|
|
529
|
-
// Simulate a hasEffect who batches, but do not execute the batch, give it back to the parent batch,
|
|
530
|
-
// Only the immediate effect has to be executed, the sub-effects will be executed by the parent batch
|
|
531
|
-
batchedEffects = new Map([[fn, runEffect]]);
|
|
532
|
-
runEffect();
|
|
533
|
-
batchedEffects.delete(fn);
|
|
534
|
-
for (const [root, effect] of batchedEffects)
|
|
535
|
-
oldBatchedEffects.set(root, effect);
|
|
536
|
-
}
|
|
537
|
-
finally {
|
|
538
|
-
batchedEffects = oldBatchedEffects;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
544
|
+
atomicEffect(runEffect, 'immediate');
|
|
541
545
|
const mainCleanup = () => {
|
|
542
546
|
if (effectStopped)
|
|
543
547
|
return;
|
|
@@ -558,7 +562,6 @@ function effect(fn, ...args) {
|
|
|
558
562
|
fr.register(callIfCollected, mainCleanup, callIfCollected);
|
|
559
563
|
return callIfCollected;
|
|
560
564
|
}
|
|
561
|
-
// TODO: parentEffect = last non-undefined activeEffect
|
|
562
565
|
// Register this effect to be cleaned up with the parent effect
|
|
563
566
|
let children = effectChildren.get(parentEffect);
|
|
564
567
|
if (!children) {
|
|
@@ -788,28 +791,30 @@ function computedFunction(getter) {
|
|
|
788
791
|
dependant(computedCache, key);
|
|
789
792
|
if (computedCache.has(key))
|
|
790
793
|
return computedCache.get(key);
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
794
|
+
let stopped = false;
|
|
795
|
+
const stop = effect(markWithRoot((dep) => {
|
|
796
|
+
if (stopped)
|
|
797
|
+
return;
|
|
798
|
+
const oldCI = computedInvalidations;
|
|
799
|
+
if (computedCache.has(key)) {
|
|
800
|
+
// This should *not* be called in the cleanup chain, as its effects would be lost and cleaned-up
|
|
801
|
+
for (const cb of invalidations)
|
|
802
|
+
cb();
|
|
803
|
+
invalidations = [];
|
|
804
|
+
computedCache.delete(key);
|
|
805
|
+
touched1(computedCache, { type: 'invalidate', prop: key }, key);
|
|
806
|
+
stop();
|
|
807
|
+
stopped = true;
|
|
808
|
+
}
|
|
809
|
+
else
|
|
810
|
+
try {
|
|
811
|
+
computedInvalidations = invalidations;
|
|
812
|
+
computedCache.set(key, getter(dep));
|
|
802
813
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}
|
|
808
|
-
finally {
|
|
809
|
-
computedInvalidations = oldCI;
|
|
810
|
-
}
|
|
811
|
-
}, getter));
|
|
812
|
-
});
|
|
814
|
+
finally {
|
|
815
|
+
computedInvalidations = oldCI;
|
|
816
|
+
}
|
|
817
|
+
}, getter));
|
|
813
818
|
return computedCache.get(key);
|
|
814
819
|
}
|
|
815
820
|
/**
|
|
@@ -1199,7 +1204,8 @@ class ReactiveArray extends indexable.Indexable(ReactiveBaseArray, {
|
|
|
1199
1204
|
dependant(this);
|
|
1200
1205
|
this[native$2].forEach(callbackfn, thisArg);
|
|
1201
1206
|
}
|
|
1202
|
-
// TODO: re-implement for fun dependencies? (eg - every only check the first ones until it find some)
|
|
1207
|
+
// TODO: re-implement for fun dependencies? (eg - every only check the first ones until it find some),
|
|
1208
|
+
// no need to make it dependant on indexes after the found one
|
|
1203
1209
|
every(callbackfn, thisArg) {
|
|
1204
1210
|
dependant(this);
|
|
1205
1211
|
return this[native$2].every(callbackfn, thisArg);
|
|
@@ -1211,7 +1217,6 @@ class ReactiveArray extends indexable.Indexable(ReactiveBaseArray, {
|
|
|
1211
1217
|
}
|
|
1212
1218
|
|
|
1213
1219
|
const native$1 = Symbol('native');
|
|
1214
|
-
// TODO: [prototypeForwarding]
|
|
1215
1220
|
class ReactiveWeakMap {
|
|
1216
1221
|
constructor(original) {
|
|
1217
1222
|
Object.defineProperties(this, {
|
|
@@ -1334,7 +1339,6 @@ class ReactiveMap {
|
|
|
1334
1339
|
}
|
|
1335
1340
|
|
|
1336
1341
|
const native = Symbol('native');
|
|
1337
|
-
// TODO: [prototypeForwarding]
|
|
1338
1342
|
class ReactiveWeakSet {
|
|
1339
1343
|
constructor(original) {
|
|
1340
1344
|
Object.defineProperties(this, {
|
|
@@ -1455,6 +1459,7 @@ registerNativeReactivity(Array, ReactiveArray);
|
|
|
1455
1459
|
|
|
1456
1460
|
exports.ReactiveBase = ReactiveBase;
|
|
1457
1461
|
exports.ReactiveError = ReactiveError;
|
|
1462
|
+
exports.atomic = atomic;
|
|
1458
1463
|
exports.computed = computed;
|
|
1459
1464
|
exports.effect = effect;
|
|
1460
1465
|
exports.getState = getState;
|