mutts 1.0.11 → 1.0.13
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 +5 -2
- package/dist/browser.cjs +237 -2596
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.ts +1407 -2
- package/dist/browser.dev.cjs +44 -43
- 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 +3 -3
- package/dist/chunks/index-CAdnMJev.cjs +2735 -0
- package/dist/chunks/index-CAdnMJev.cjs.map +1 -0
- package/dist/chunks/{index-Sf74wXTV.esm.js → index-XsYTUhHx.esm.js} +200 -77
- package/dist/chunks/index-XsYTUhHx.esm.js.map +1 -0
- package/dist/chunks/{async-node-3PrbVAbB.cjs → node-DrrphEPf.cjs} +4 -4
- package/dist/chunks/node-DrrphEPf.cjs.map +1 -0
- package/dist/chunks/{node-Bo7WU5S2.esm.js → node-NEZvVo4M.esm.js} +2 -2
- package/dist/chunks/{node-Bo7WU5S2.esm.js.map → node-NEZvVo4M.esm.js.map} +1 -1
- package/dist/chunks/{proxy-D2C49sXH.esm.js → proxy-BtmPFjSr.esm.js} +307 -66
- package/dist/chunks/proxy-BtmPFjSr.esm.js.map +1 -0
- package/dist/chunks/{proxy-Cc79Lrzj.cjs → proxy-DBHj3kGK.cjs} +341 -70
- package/dist/chunks/proxy-DBHj3kGK.cjs.map +1 -0
- package/dist/debug.cjs +537 -167
- package/dist/debug.cjs.map +1 -1
- package/dist/debug.d.ts +96 -80
- package/dist/debug.esm.js +533 -166
- package/dist/debug.esm.js.map +1 -1
- package/dist/devtools/panel.js.map +1 -1
- package/dist/mutts.umd.js +508 -140
- 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 +44 -42
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.ts +2 -2
- package/dist/node.dev.cjs +44 -42
- 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} +12 -0
- package/docs/ai/api-reference.md +102 -12
- package/docs/ai/manual.md +60 -24
- package/docs/debug-getReason.md +161 -0
- package/docs/flavored.md +98 -1
- package/docs/reactive/advanced.md +15 -2
- package/docs/reactive/attend.md +32 -0
- package/docs/reactive/core.md +40 -6
- package/docs/reactive/debugging.md +25 -2
- package/docs/reactive.md +2 -0
- package/package.json +2 -3
- package/dist/chunks/async-browser-Dgr5CreQ.cjs +0 -218
- package/dist/chunks/async-browser-Dgr5CreQ.cjs.map +0 -1
- package/dist/chunks/async-core-CRLKP3l-.cjs +0 -29
- package/dist/chunks/async-core-CRLKP3l-.cjs.map +0 -1
- package/dist/chunks/async-node-3PrbVAbB.cjs.map +0 -1
- package/dist/chunks/index-Sf74wXTV.esm.js.map +0 -1
- package/dist/chunks/proxy-Cc79Lrzj.cjs.map +0 -1
- package/dist/chunks/proxy-D2C49sXH.esm.js.map +0 -1
- package/dist/index.d.ts +0 -1322
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var asyncCore = require('./async-core-CRLKP3l-.cjs');
|
|
4
|
-
|
|
5
3
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
4
|
+
// Queue for hooks registered before the environment is ready (circular dependency fix)
|
|
5
|
+
const hooks = new Set();
|
|
6
|
+
const asyncHooks = {
|
|
7
|
+
addHook(hook) {
|
|
8
|
+
hooks.add(hook);
|
|
9
|
+
return () => hooks.delete(hook);
|
|
10
|
+
},
|
|
11
|
+
/**
|
|
12
|
+
* [Hack] Sanitize a promise (or value) to prevent context leaks.
|
|
13
|
+
* Default: Identity function.
|
|
14
|
+
* Browser: Uses Macrotask wrapping to break microtask chains.
|
|
15
|
+
*/
|
|
16
|
+
sanitizePromise(p) {
|
|
17
|
+
return p;
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Register a hook that will be called whenever an asynchronous operation is initiated.
|
|
22
|
+
* The hook should return a restorer function which will be called just before the async callback runs.
|
|
23
|
+
* That restorer should in turn return an undoer function which will be called just after the async callback finishes.
|
|
24
|
+
*/
|
|
25
|
+
const asyncHook = (hook) => asyncHooks.addHook(hook);
|
|
26
|
+
|
|
6
27
|
/**
|
|
7
28
|
* Yields tuples containing elements from each input array, stopping at the longest array length
|
|
8
29
|
* @param args - Arrays to zip together
|
|
@@ -118,13 +139,10 @@ function isOwnAccessor(obj, prop) {
|
|
|
118
139
|
return !!(opd?.get || opd?.set);
|
|
119
140
|
}
|
|
120
141
|
/**
|
|
121
|
-
*
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* @param b - Second value
|
|
126
|
-
* @param cache - Map for circular reference protection (internal use)
|
|
127
|
-
* @returns True if values are deeply equal
|
|
142
|
+
* Symbol used to provide custom comparison logic for an object.
|
|
143
|
+
*/
|
|
144
|
+
const CompareSymbol = Symbol.for('mutts.compare');
|
|
145
|
+
/**
|
|
128
146
|
*/
|
|
129
147
|
function deepCompare(a, b, cache = new Map()) {
|
|
130
148
|
if (a === b)
|
|
@@ -132,6 +150,13 @@ function deepCompare(a, b, cache = new Map()) {
|
|
|
132
150
|
if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) {
|
|
133
151
|
return a === b;
|
|
134
152
|
}
|
|
153
|
+
// Custom comparison support
|
|
154
|
+
if (typeof a[CompareSymbol] === 'function') {
|
|
155
|
+
return a[CompareSymbol](b, (x, y) => deepCompare(x, y, cache));
|
|
156
|
+
}
|
|
157
|
+
if (typeof b[CompareSymbol] === 'function') {
|
|
158
|
+
return b[CompareSymbol](a, (x, y) => deepCompare(x, y, cache));
|
|
159
|
+
}
|
|
135
160
|
// Prototype check
|
|
136
161
|
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
|
|
137
162
|
return false;
|
|
@@ -250,8 +275,9 @@ function named(name, fn) {
|
|
|
250
275
|
});
|
|
251
276
|
return fn;
|
|
252
277
|
}
|
|
253
|
-
const
|
|
254
|
-
|
|
278
|
+
const runtimeGlobals = globalThis;
|
|
279
|
+
const _mode = runtimeGlobals.process?.env?.NODE_ENV ||
|
|
280
|
+
(typeof ({ url: (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('chunks/proxy-DBHj3kGK.cjs', document.baseURI).href)) }) !== 'undefined' && undefined?.MODE) ||
|
|
255
281
|
'production';
|
|
256
282
|
const isDev = _mode === 'development';
|
|
257
283
|
const isProd = _mode === 'production';
|
|
@@ -426,6 +452,93 @@ const decorator = (description) => {
|
|
|
426
452
|
* flavoredGreet.loud('World') // "HELLO, WORLD!"
|
|
427
453
|
* ```
|
|
428
454
|
*/
|
|
455
|
+
const captionedOptionsSymbol = Symbol('mutts.captioned.options');
|
|
456
|
+
function isTemplateStringsArray(value) {
|
|
457
|
+
return (Array.isArray(value) &&
|
|
458
|
+
Object.hasOwn(value, 'raw') &&
|
|
459
|
+
Array.isArray(value.raw));
|
|
460
|
+
}
|
|
461
|
+
function renderTemplate(strings, values) {
|
|
462
|
+
let result = strings[0] ?? '';
|
|
463
|
+
for (let i = 0; i < values.length; i++)
|
|
464
|
+
result += String(values[i]) + (strings[i + 1] ?? '');
|
|
465
|
+
return result;
|
|
466
|
+
}
|
|
467
|
+
function renameCallback(caption, callback) {
|
|
468
|
+
Object.defineProperty(callback, 'name', {
|
|
469
|
+
value: caption,
|
|
470
|
+
writable: false,
|
|
471
|
+
configurable: true,
|
|
472
|
+
});
|
|
473
|
+
return callback;
|
|
474
|
+
}
|
|
475
|
+
function isAnonymousCallback(callback) {
|
|
476
|
+
return !callback.name || callback.name === 'anonymous';
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Wraps a callback-first function so it also accepts a tagged-template call form.
|
|
480
|
+
*
|
|
481
|
+
* The template caption is applied to one callback argument before the base
|
|
482
|
+
* function runs. By default, `captioned` targets the first argument, but
|
|
483
|
+
* `callbackIndex` can point to any callback position.
|
|
484
|
+
*
|
|
485
|
+
* This is intended for APIs such as `effect`, `lift`, or `watch` where naming
|
|
486
|
+
* is useful but should remain separate from the flavor system.
|
|
487
|
+
*
|
|
488
|
+
* Plain calls still work:
|
|
489
|
+
* `run(callback)`
|
|
490
|
+
*
|
|
491
|
+
* Captioned calls add a runtime name to the first callback:
|
|
492
|
+
* `` run`task:${id}`(callback) ``
|
|
493
|
+
*
|
|
494
|
+
* Anonymous uncaptioned callbacks may trigger a warning depending on
|
|
495
|
+
* `shouldWarnAnonymous`.
|
|
496
|
+
*/
|
|
497
|
+
function captioned(fn, options = {}) {
|
|
498
|
+
const settings = {
|
|
499
|
+
callbackIndex: options.callbackIndex ?? 0,
|
|
500
|
+
name: options.name ?? (fn.name || 'callback'),
|
|
501
|
+
rename: options.rename ?? ((caption, callback) => renameCallback(caption, callback)),
|
|
502
|
+
// biome-ignore lint/suspicious/noConsole: This is the whole point here
|
|
503
|
+
warn: options.warn ?? ((message) => console.warn(message)),
|
|
504
|
+
shouldWarnAnonymous: options.shouldWarnAnonymous,
|
|
505
|
+
};
|
|
506
|
+
fn[captionedOptionsSymbol] = settings;
|
|
507
|
+
return new Proxy(fn, {
|
|
508
|
+
get(target, prop, receiver) {
|
|
509
|
+
if (prop === captionedOptionsSymbol)
|
|
510
|
+
return settings;
|
|
511
|
+
return Reflect.get(target, prop, receiver);
|
|
512
|
+
},
|
|
513
|
+
apply(target, thisArg, args) {
|
|
514
|
+
if (isTemplateStringsArray(args[0])) {
|
|
515
|
+
const caption = renderTemplate(args[0], args.slice(1));
|
|
516
|
+
return function captionedCall(...callArgs) {
|
|
517
|
+
const callback = callArgs[settings.callbackIndex];
|
|
518
|
+
if (typeof callback !== 'function')
|
|
519
|
+
throw new TypeError(`${settings.name} template calls require a callback at argument index ${settings.callbackIndex}`);
|
|
520
|
+
const nextArgs = [...callArgs];
|
|
521
|
+
nextArgs[settings.callbackIndex] = settings.rename(caption, callback);
|
|
522
|
+
return Reflect.apply(target, this, nextArgs);
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
const callback = args[settings.callbackIndex];
|
|
526
|
+
if (typeof callback === 'function' && isAnonymousCallback(callback)) {
|
|
527
|
+
const shouldWarn = settings.shouldWarnAnonymous?.(callback, args) ?? true;
|
|
528
|
+
if (shouldWarn)
|
|
529
|
+
settings.warn(`${settings.name}: anonymous callback detected. Use template syntax for automatic naming:\n` +
|
|
530
|
+
` Current: ${settings.name}(() => { ... })\n` +
|
|
531
|
+
` Fix: ${settings.name}\`descriptive-name\`(() => { ... })\n` +
|
|
532
|
+
`The captioned system uses the template literal as the effect name for better debugging.`);
|
|
533
|
+
}
|
|
534
|
+
return Reflect.apply(target, thisArg, args);
|
|
535
|
+
},
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
function inheritCaption(source, target) {
|
|
539
|
+
const settings = source[captionedOptionsSymbol];
|
|
540
|
+
return settings ? captioned(target, settings) : target;
|
|
541
|
+
}
|
|
429
542
|
/**
|
|
430
543
|
* Creates a flavored (extensible) version of a function with chainable property modifiers.
|
|
431
544
|
*/
|
|
@@ -458,7 +571,7 @@ function createFlavor(fn, transform, name) {
|
|
|
458
571
|
};
|
|
459
572
|
if (name)
|
|
460
573
|
named(name, fct);
|
|
461
|
-
return flavored(fct, fn.flavors || {});
|
|
574
|
+
return flavored(inheritCaption(fn, fct), fn.flavors || {});
|
|
462
575
|
}
|
|
463
576
|
/**
|
|
464
577
|
* Creates a new flavored function that merges options objects at a specific index.
|
|
@@ -491,7 +604,7 @@ function flavorOptions(fn, defaultOptions, opts = {}) {
|
|
|
491
604
|
// Preserve arity and options track
|
|
492
605
|
Object.defineProperty(fct, 'length', { value: fn.length });
|
|
493
606
|
fct.optionsIndex = targetIndex;
|
|
494
|
-
return flavored(fct, fn.flavors || {});
|
|
607
|
+
return flavored(inheritCaption(fn, fct), fn.flavors || {});
|
|
495
608
|
}
|
|
496
609
|
|
|
497
610
|
/// <reference lib="esnext.collection" />
|
|
@@ -924,7 +1037,7 @@ class AZone {
|
|
|
924
1037
|
}
|
|
925
1038
|
// [HACK]: Sanitization
|
|
926
1039
|
// See BROWSER_ASYNC_POLYFILL.md
|
|
927
|
-
return
|
|
1040
|
+
return asyncHooks.sanitizePromise(res);
|
|
928
1041
|
}
|
|
929
1042
|
root(fn) {
|
|
930
1043
|
const prev = this.enter();
|
|
@@ -1039,7 +1152,7 @@ _ZoneAggregator_zones = new WeakMap();
|
|
|
1039
1152
|
* ```
|
|
1040
1153
|
*/
|
|
1041
1154
|
const asyncZone = tag('async', new ZoneAggregator());
|
|
1042
|
-
|
|
1155
|
+
asyncHooks.addHook(() => {
|
|
1043
1156
|
// capture state before async boundary
|
|
1044
1157
|
const zone = asyncZone.active;
|
|
1045
1158
|
return () => {
|
|
@@ -1085,6 +1198,7 @@ function resetRegistry() {
|
|
|
1085
1198
|
* @returns The marked function
|
|
1086
1199
|
*/
|
|
1087
1200
|
function markWithRoot(fn, root) {
|
|
1201
|
+
const marked = fn;
|
|
1088
1202
|
// Check for collision
|
|
1089
1203
|
const existingRef = reverseRoots.get(root);
|
|
1090
1204
|
const existing = existingRef?.deref();
|
|
@@ -1099,8 +1213,8 @@ function markWithRoot(fn, root) {
|
|
|
1099
1213
|
// (Last writer wins for the check)
|
|
1100
1214
|
reverseRoots.set(root, new WeakRef(fn));
|
|
1101
1215
|
// Store root mapping as symbol property on the function
|
|
1102
|
-
|
|
1103
|
-
return
|
|
1216
|
+
marked[rootFunctionSymbol] = getRoot(root);
|
|
1217
|
+
return marked;
|
|
1104
1218
|
}
|
|
1105
1219
|
/**
|
|
1106
1220
|
* Gets the root function of a function for effect tracking
|
|
@@ -1120,11 +1234,30 @@ function getRoot(fn) {
|
|
|
1120
1234
|
const effectHistory = tag('effectHistory', new ZoneHistory());
|
|
1121
1235
|
tag('effectHistory.present', effectHistory.present);
|
|
1122
1236
|
asyncZone.add(effectHistory);
|
|
1237
|
+
const externalReason = tag('externalReason', new Zone());
|
|
1238
|
+
asyncZone.add(externalReason);
|
|
1123
1239
|
/**
|
|
1124
1240
|
* Aggregator for zones that need to be tracked along effects.
|
|
1125
1241
|
* ie. in each effect, the active zone of the given zoning will be the one active at effect's definition
|
|
1126
1242
|
*/
|
|
1127
1243
|
const effectAggregator = tag('effectAggregator', new ZoneAggregator(effectHistory.present));
|
|
1244
|
+
effectAggregator.add(externalReason);
|
|
1245
|
+
function chainExternalReason(reason) {
|
|
1246
|
+
const external = externalReason.active;
|
|
1247
|
+
if (!external)
|
|
1248
|
+
return reason;
|
|
1249
|
+
if (!reason)
|
|
1250
|
+
return external;
|
|
1251
|
+
let current = reason;
|
|
1252
|
+
while (current) {
|
|
1253
|
+
if (current.type === 'external' &&
|
|
1254
|
+
external.type === 'external' &&
|
|
1255
|
+
current.detail === external.detail)
|
|
1256
|
+
return reason;
|
|
1257
|
+
current = current.chain;
|
|
1258
|
+
}
|
|
1259
|
+
return { ...reason, chain: chainExternalReason(reason.chain) };
|
|
1260
|
+
}
|
|
1128
1261
|
function isRunning(effect) {
|
|
1129
1262
|
const root = getRoot(effect);
|
|
1130
1263
|
return effectHistory.some((e) => getRoot(e) === root);
|
|
@@ -1132,6 +1265,35 @@ function isRunning(effect) {
|
|
|
1132
1265
|
function getActiveEffect() {
|
|
1133
1266
|
return effectHistory.present.active;
|
|
1134
1267
|
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Captures the current effect context so that deferred code can later
|
|
1270
|
+
* create child effects parented to this point in the effect tree.
|
|
1271
|
+
*
|
|
1272
|
+
* @returns An opaque token to pass to `withEffectContext()`
|
|
1273
|
+
*
|
|
1274
|
+
* @example
|
|
1275
|
+
* ```ts
|
|
1276
|
+
* const ctx = effectContext() // inside an effect or root()
|
|
1277
|
+
* // later, in a deferred callback:
|
|
1278
|
+
* withEffectContext(ctx, () => {
|
|
1279
|
+
* effect(() => { /* child of the captured context */ })
|
|
1280
|
+
* })
|
|
1281
|
+
* ```
|
|
1282
|
+
*/
|
|
1283
|
+
function effectContext() {
|
|
1284
|
+
return effectHistory.active;
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Runs `fn` within a previously captured effect context.
|
|
1288
|
+
* Any effects created inside `fn` become children of the captured parent.
|
|
1289
|
+
*
|
|
1290
|
+
* @param ctx - The context token from `effectContext()`, or `undefined` for root context
|
|
1291
|
+
* @param fn - The function to execute within the restored context
|
|
1292
|
+
* @returns The return value of `fn`
|
|
1293
|
+
*/
|
|
1294
|
+
function withEffectContext(ctx, fn) {
|
|
1295
|
+
return effectHistory.with(ctx, fn);
|
|
1296
|
+
}
|
|
1135
1297
|
const cleanups = new WeakMap();
|
|
1136
1298
|
/**
|
|
1137
1299
|
* Attach cleanup dependencies to an object. When `unlink(obj)` is called,
|
|
@@ -1159,7 +1321,7 @@ const cleanups = new WeakMap();
|
|
|
1159
1321
|
function link(obj, ...cleanupFns) {
|
|
1160
1322
|
const set = cleanups.get(obj);
|
|
1161
1323
|
if (!set)
|
|
1162
|
-
cleanups.set(obj, new Set(cleanupFns.filter(
|
|
1324
|
+
cleanups.set(obj, new Set(cleanupFns.filter((fn) => fn !== undefined)));
|
|
1163
1325
|
else
|
|
1164
1326
|
for (const fn of cleanupFns)
|
|
1165
1327
|
if (fn)
|
|
@@ -1225,18 +1387,61 @@ function formatCleanupReason(reason, depth = 0) {
|
|
|
1225
1387
|
parts.push(',');
|
|
1226
1388
|
parts.push(...formatTrigger(reason.triggers[i]));
|
|
1227
1389
|
}
|
|
1390
|
+
if (reason.chain) {
|
|
1391
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1392
|
+
}
|
|
1393
|
+
return parts;
|
|
1394
|
+
}
|
|
1395
|
+
case 'stopped': {
|
|
1396
|
+
const parts = [`${indent}stopped`];
|
|
1397
|
+
if (reason.detail)
|
|
1398
|
+
parts.push(`(${reason.detail})`);
|
|
1399
|
+
if (reason.chain) {
|
|
1400
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1401
|
+
}
|
|
1402
|
+
return parts;
|
|
1403
|
+
}
|
|
1404
|
+
case 'external': {
|
|
1405
|
+
const parts = [`${indent}external:`, reason.detail];
|
|
1406
|
+
if (reason.chain) {
|
|
1407
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1408
|
+
}
|
|
1409
|
+
return parts;
|
|
1410
|
+
}
|
|
1411
|
+
case 'gc': {
|
|
1412
|
+
const parts = [`${indent}gc`];
|
|
1413
|
+
if (reason.chain) {
|
|
1414
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1415
|
+
}
|
|
1416
|
+
return parts;
|
|
1417
|
+
}
|
|
1418
|
+
case 'error': {
|
|
1419
|
+
const parts = [`${indent}error:`, reason.error];
|
|
1420
|
+
if (reason.chain) {
|
|
1421
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1422
|
+
}
|
|
1423
|
+
return parts;
|
|
1424
|
+
}
|
|
1425
|
+
case 'lineage': {
|
|
1426
|
+
const parts = [
|
|
1427
|
+
`${indent}lineage ←\n`,
|
|
1428
|
+
...formatCleanupReason(reason.parent, depth + 1),
|
|
1429
|
+
];
|
|
1430
|
+
if (reason.chain) {
|
|
1431
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1432
|
+
}
|
|
1433
|
+
return parts;
|
|
1434
|
+
}
|
|
1435
|
+
case 'invalidate': {
|
|
1436
|
+
const parts = [
|
|
1437
|
+
`${indent}invalidate ←\n`,
|
|
1438
|
+
...formatCleanupReason(reason.cause, depth + 1),
|
|
1439
|
+
];
|
|
1440
|
+
if (reason.chain) {
|
|
1441
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1442
|
+
}
|
|
1228
1443
|
return parts;
|
|
1229
1444
|
}
|
|
1230
|
-
case 'stopped':
|
|
1231
|
-
return [`${indent}stopped`];
|
|
1232
|
-
case 'gc':
|
|
1233
|
-
return [`${indent}gc`];
|
|
1234
|
-
case 'error':
|
|
1235
|
-
return [`${indent}error:`, reason.error];
|
|
1236
|
-
case 'lineage':
|
|
1237
|
-
return [`${indent}lineage ←\n`, ...formatCleanupReason(reason.parent, depth + 1)];
|
|
1238
|
-
case 'invalidate':
|
|
1239
|
-
return [`${indent}invalidate ←\n`, ...formatCleanupReason(reason.cause, depth + 1)];
|
|
1240
1445
|
case 'multiple': {
|
|
1241
1446
|
const parts = [];
|
|
1242
1447
|
for (let i = 0; i < reason.reasons.length; i++) {
|
|
@@ -1244,6 +1449,9 @@ function formatCleanupReason(reason, depth = 0) {
|
|
|
1244
1449
|
parts.push('\n');
|
|
1245
1450
|
parts.push(...formatCleanupReason(reason.reasons[i], depth));
|
|
1246
1451
|
}
|
|
1452
|
+
if (reason.chain) {
|
|
1453
|
+
parts.push('\n', ...formatCleanupReason(reason.chain, depth));
|
|
1454
|
+
}
|
|
1247
1455
|
return parts;
|
|
1248
1456
|
}
|
|
1249
1457
|
}
|
|
@@ -1444,6 +1652,8 @@ const options = {
|
|
|
1444
1652
|
asyncMode: 'cancel',
|
|
1445
1653
|
// biome-ignore lint/suspicious/noConsole: This is the whole point here
|
|
1446
1654
|
warn: (...args) => console.warn(...args),
|
|
1655
|
+
// biome-ignore lint/suspicious/noConsole: This is the whole point here
|
|
1656
|
+
error: (...args) => console.error(...args),
|
|
1447
1657
|
/**
|
|
1448
1658
|
* Introspection and debug aids. Set to `null` to disable all debug overhead in production.
|
|
1449
1659
|
*
|
|
@@ -1573,7 +1783,7 @@ function dependant(obj, prop = allProps) {
|
|
|
1573
1783
|
return;
|
|
1574
1784
|
const node = getEffectNode(currentActiveEffect);
|
|
1575
1785
|
if ('dependencyHook' in node) {
|
|
1576
|
-
node.dependencyHook(obj, prop);
|
|
1786
|
+
node.dependencyHook?.(obj, prop);
|
|
1577
1787
|
}
|
|
1578
1788
|
let objectWatchers = exports.watchers.get(obj);
|
|
1579
1789
|
if (!objectWatchers) {
|
|
@@ -1639,6 +1849,9 @@ function formatRoots(roots, limit = 20) {
|
|
|
1639
1849
|
const end = names.slice(-10);
|
|
1640
1850
|
return `${start.join(' → ')} ... (${names.length - 15} more) ... ${end.join(' → ')}`;
|
|
1641
1851
|
}
|
|
1852
|
+
function externalReasonFrom(fn) {
|
|
1853
|
+
return fn.name ? { type: 'external', detail: fn.name } : undefined;
|
|
1854
|
+
}
|
|
1642
1855
|
// Nested map structure for efficient counting and batch cleanup
|
|
1643
1856
|
// batchId -> effect root -> obj -> prop -> count
|
|
1644
1857
|
let activationRegistry;
|
|
@@ -2081,6 +2294,14 @@ function addToBatch(effect, caller, immediate, reason) {
|
|
|
2081
2294
|
// Build reason from pending triggers if not provided
|
|
2082
2295
|
if (!reason && node.pendingTriggers) {
|
|
2083
2296
|
reason = { type: 'propChange', triggers: node.pendingTriggers };
|
|
2297
|
+
// Add chain: if this is being triggered from another effect, get its reason
|
|
2298
|
+
if (caller) {
|
|
2299
|
+
const callerNode = getEffectNode(caller);
|
|
2300
|
+
if (callerNode.currentReason) {
|
|
2301
|
+
reason.chain = callerNode.currentReason;
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
reason = chainExternalReason(reason);
|
|
2084
2305
|
}
|
|
2085
2306
|
node.pendingTriggers = undefined;
|
|
2086
2307
|
if (reason) {
|
|
@@ -2349,7 +2570,7 @@ function executeNext(effectuatedRoots) {
|
|
|
2349
2570
|
}
|
|
2350
2571
|
// Track which sub-effects have been executed to prevent infinite loops
|
|
2351
2572
|
// These are all the effects triggered under `activeEffect` and all their sub-effects
|
|
2352
|
-
function batch(effect, immediate) {
|
|
2573
|
+
function batch(effect, immediate, caller) {
|
|
2353
2574
|
if (broken) {
|
|
2354
2575
|
throw new ReactiveError('[reactive] Reactive system is broken after an unrecoverable error. Call reset() to recover.', { code: exports.ReactiveErrorCode.BrokenEffects });
|
|
2355
2576
|
}
|
|
@@ -2365,11 +2586,12 @@ function batch(effect, immediate) {
|
|
|
2365
2586
|
optionCall('beginChain', roots);
|
|
2366
2587
|
}
|
|
2367
2588
|
// TODO: Consider this has been produced but was useless - it might be more correct ?const caller = executingStack.length > 0 ? getActiveEffect() : undefined
|
|
2368
|
-
const
|
|
2589
|
+
const activeCaller = getActiveEffect();
|
|
2590
|
+
const callerToUse = caller || activeCaller;
|
|
2369
2591
|
// Optimization: If nested and NOT immediate, just join the existing batch
|
|
2370
2592
|
if (!isNewBatch && !immediate) {
|
|
2371
2593
|
for (let i = 0; i < effect.length; i++) {
|
|
2372
|
-
addToBatch(effect[i],
|
|
2594
|
+
addToBatch(effect[i], callerToUse);
|
|
2373
2595
|
}
|
|
2374
2596
|
return;
|
|
2375
2597
|
}
|
|
@@ -2408,7 +2630,7 @@ function batch(effect, immediate) {
|
|
|
2408
2630
|
else {
|
|
2409
2631
|
// Add initial effects to batch and compute dependencies
|
|
2410
2632
|
for (let i = 0; i < effect.length; i++) {
|
|
2411
|
-
addToBatch(effect[i],
|
|
2633
|
+
addToBatch(effect[i], callerToUse, false);
|
|
2412
2634
|
}
|
|
2413
2635
|
computeAllInDegrees(currentBatch);
|
|
2414
2636
|
}
|
|
@@ -2462,6 +2684,11 @@ function batch(effect, immediate) {
|
|
|
2462
2684
|
success = true;
|
|
2463
2685
|
return firstReturn.value;
|
|
2464
2686
|
}
|
|
2687
|
+
catch (error) {
|
|
2688
|
+
if (batchStack.length === 1)
|
|
2689
|
+
optionCall('error', '[reactive] Root batch failure before broken state:', error);
|
|
2690
|
+
throw error;
|
|
2691
|
+
}
|
|
2465
2692
|
finally {
|
|
2466
2693
|
if (!success && batchStack.length === 1) {
|
|
2467
2694
|
broken = true;
|
|
@@ -2562,7 +2789,7 @@ const fr = new FinalizationRegistry((f) => f());
|
|
|
2562
2789
|
* @param options - Options for effect execution
|
|
2563
2790
|
* @returns A cleanup function to stop the effect
|
|
2564
2791
|
*/
|
|
2565
|
-
const effect = named(effectMarker.leave, flavored(function effect(fn, effectOptions = {}) {
|
|
2792
|
+
const effect = captioned(named(effectMarker.leave, flavored(function effect(fn, effectOptions = {}) {
|
|
2566
2793
|
if (effectOptions?.name)
|
|
2567
2794
|
Object.defineProperty(fn, 'name', { value: effectOptions.name });
|
|
2568
2795
|
// Use per-effect asyncMode or fall back to global option
|
|
@@ -2575,7 +2802,10 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2575
2802
|
const prevCleanup = node.cleanup;
|
|
2576
2803
|
node.cleanup = undefined;
|
|
2577
2804
|
try {
|
|
2578
|
-
untracked(() => prevCleanup(node.nextReason || {
|
|
2805
|
+
untracked `effect:cleanup`(() => prevCleanup(chainExternalReason(node.nextReason || {
|
|
2806
|
+
type: 'stopped',
|
|
2807
|
+
chain: node.currentReason,
|
|
2808
|
+
})));
|
|
2579
2809
|
}
|
|
2580
2810
|
catch (error) {
|
|
2581
2811
|
// If we want to report them, we could use options.warn or similar
|
|
@@ -2608,6 +2838,9 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2608
2838
|
}
|
|
2609
2839
|
// Set reaction reason for the upcoming run
|
|
2610
2840
|
access.reaction = node.nextReason || access.reaction;
|
|
2841
|
+
node.currentReason =
|
|
2842
|
+
node.nextReason ||
|
|
2843
|
+
(access.reaction && access.reaction !== true ? access.reaction : undefined);
|
|
2611
2844
|
node.nextReason = undefined;
|
|
2612
2845
|
optionCall('enter', getRoot(fn));
|
|
2613
2846
|
optionCall('effectRun', getRoot(fn), access.reaction);
|
|
@@ -2670,7 +2903,8 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2670
2903
|
// This ensures that when we cancel, the original promise's .catch() handlers are triggered
|
|
2671
2904
|
// We do this by rejecting the race promise, which makes the original promise chain see the rejection
|
|
2672
2905
|
// through the zone-wrapped .then()/.catch() handlers
|
|
2673
|
-
runningPromise = runningPromise
|
|
2906
|
+
runningPromise = runningPromise
|
|
2907
|
+
.catch((error) => {
|
|
2674
2908
|
// Propagate async errors to the effect's error handler
|
|
2675
2909
|
// This ensures onEffectThrow handlers are triggered for async errors
|
|
2676
2910
|
if (error !== cancelError) {
|
|
@@ -2678,6 +2912,10 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2678
2912
|
}
|
|
2679
2913
|
// If thrower didn't throw (handled), we absorb the error.
|
|
2680
2914
|
// If thrower threw (unhandled), it propagates as a new unhandled rejection, which is correct.
|
|
2915
|
+
})
|
|
2916
|
+
.finally(() => {
|
|
2917
|
+
// Clear currentReason when async effect completes
|
|
2918
|
+
node.currentReason = undefined;
|
|
2681
2919
|
});
|
|
2682
2920
|
}
|
|
2683
2921
|
else {
|
|
@@ -2688,7 +2926,13 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2688
2926
|
catch (error) {
|
|
2689
2927
|
debugHooks.decorateError(error, runEffect);
|
|
2690
2928
|
// catcher:self`
|
|
2691
|
-
errorToThrow = error;
|
|
2929
|
+
errorToThrow = error instanceof Error ? error : new Error(String(error));
|
|
2930
|
+
}
|
|
2931
|
+
finally {
|
|
2932
|
+
// Clear currentReason for synchronous effects
|
|
2933
|
+
if (!runningPromise) {
|
|
2934
|
+
node.currentReason = undefined;
|
|
2935
|
+
}
|
|
2692
2936
|
}
|
|
2693
2937
|
// Create cleanup function for next run
|
|
2694
2938
|
node.cleanup = (reason) => {
|
|
@@ -2719,8 +2963,11 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2719
2963
|
const childReason = reason
|
|
2720
2964
|
? reason.type === 'lineage'
|
|
2721
2965
|
? reason
|
|
2722
|
-
: { type: 'lineage', parent: reason }
|
|
2723
|
-
: { type: 'stopped' }
|
|
2966
|
+
: { type: 'lineage', parent: reason, chain: node.currentReason }
|
|
2967
|
+
: (chainExternalReason({ type: 'stopped', chain: node.currentReason }) ?? {
|
|
2968
|
+
type: 'stopped',
|
|
2969
|
+
chain: node.currentReason,
|
|
2970
|
+
});
|
|
2724
2971
|
for (const childCleanup of children)
|
|
2725
2972
|
childCleanup(childReason);
|
|
2726
2973
|
delete node.children;
|
|
@@ -2733,7 +2980,7 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2733
2980
|
const node = getEffectNode(runEffect);
|
|
2734
2981
|
if (debugHooks.isDevtoolsEnabled()) {
|
|
2735
2982
|
const stack = debugHooks.captureStack(); // Robustly skips internal mutts frames
|
|
2736
|
-
if (
|
|
2983
|
+
if (stack) {
|
|
2737
2984
|
node.creationStack = stack;
|
|
2738
2985
|
}
|
|
2739
2986
|
}
|
|
@@ -2793,7 +3040,7 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2793
3040
|
runningPromise = null;
|
|
2794
3041
|
}
|
|
2795
3042
|
try {
|
|
2796
|
-
node.cleanup?.(reason || { type: 'stopped' });
|
|
3043
|
+
node.cleanup?.(chainExternalReason(reason || { type: 'stopped', chain: node.currentReason }));
|
|
2797
3044
|
}
|
|
2798
3045
|
catch (error) {
|
|
2799
3046
|
// Cleanup errors should basically be ignored or at least not stop the world
|
|
@@ -2836,30 +3083,35 @@ const effect = named(effectMarker.leave, flavored(function effect(fn, effectOpti
|
|
|
2836
3083
|
named(name) {
|
|
2837
3084
|
return flavorOptions(this, { name }, { name: 'named' });
|
|
2838
3085
|
},
|
|
2839
|
-
}))
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
return
|
|
2847
|
-
|
|
3086
|
+
})), {
|
|
3087
|
+
name: 'effect',
|
|
3088
|
+
warn: (message) => options.warn(`[reactive] ${message}`),
|
|
3089
|
+
shouldWarnAnonymous: (_callback, args) => !(args[1] && typeof args[1] === 'object' && 'name' in args[1]),
|
|
3090
|
+
});
|
|
3091
|
+
const untracked = captioned(function untracked(fn) {
|
|
3092
|
+
const external = externalReasonFrom(fn);
|
|
3093
|
+
return external
|
|
3094
|
+
? externalReason.with(external, () => effectHistory.present.root(fn))
|
|
3095
|
+
: effectHistory.present.root(fn);
|
|
3096
|
+
});
|
|
2848
3097
|
/**
|
|
2849
3098
|
* Executes a function from a virgin/root context - no parent effect, no tracking
|
|
2850
3099
|
* Creates completely independent effects that won't be cleaned up by any parent
|
|
2851
3100
|
* @param fn - The function to execute
|
|
2852
3101
|
*/
|
|
2853
|
-
function root(fn) {
|
|
2854
|
-
|
|
2855
|
-
|
|
3102
|
+
const root = captioned(function root(fn) {
|
|
3103
|
+
const external = externalReasonFrom(fn);
|
|
3104
|
+
return external
|
|
3105
|
+
? externalReason.with(external, () => effectHistory.root(fn))
|
|
3106
|
+
: effectHistory.root(fn);
|
|
3107
|
+
});
|
|
2856
3108
|
function biDi(received, get, set) {
|
|
2857
3109
|
if (typeof get !== 'function') {
|
|
2858
3110
|
set = get.set;
|
|
2859
3111
|
get = get.get;
|
|
2860
3112
|
}
|
|
2861
3113
|
let programmaticallySetValue = Symbol();
|
|
2862
|
-
effect
|
|
3114
|
+
effect `biDi`(markWithRoot(() => {
|
|
2863
3115
|
const newValue = get();
|
|
2864
3116
|
const pValue = programmaticallySetValue;
|
|
2865
3117
|
programmaticallySetValue = Symbol();
|
|
@@ -3010,7 +3262,8 @@ function collectEffects(obj, evolution, effects, objectWatchers, ...keyChains) {
|
|
|
3010
3262
|
const deps = objectWatchers.get(key);
|
|
3011
3263
|
if (deps) {
|
|
3012
3264
|
// Make sure `some.prop++` does not keep a dependency to `some.props`
|
|
3013
|
-
|
|
3265
|
+
if (sourceEffect)
|
|
3266
|
+
deps.delete(sourceEffect);
|
|
3014
3267
|
for (const effect of deps) {
|
|
3015
3268
|
const runningChain = isRunning(effect);
|
|
3016
3269
|
if (runningChain) {
|
|
@@ -3056,6 +3309,7 @@ function touched(obj, evolution, props) {
|
|
|
3056
3309
|
else
|
|
3057
3310
|
collectEffects(obj, evolution, effects, objectWatchers, objectWatchers.keys());
|
|
3058
3311
|
const triggers = Array.from(effects.keys());
|
|
3312
|
+
const sourceEffect = getActiveEffect();
|
|
3059
3313
|
optionCall('touched', obj, evolution, props, triggers);
|
|
3060
3314
|
// Store pending triggers for CleanupReason before batching
|
|
3061
3315
|
if (options.introspection?.gatherReasons) {
|
|
@@ -3077,7 +3331,7 @@ function touched(obj, evolution, props) {
|
|
|
3077
3331
|
});
|
|
3078
3332
|
}
|
|
3079
3333
|
}
|
|
3080
|
-
batch(triggers);
|
|
3334
|
+
batch(triggers, undefined, sourceEffect);
|
|
3081
3335
|
}
|
|
3082
3336
|
// Bubble up changes if this object has deep watchers
|
|
3083
3337
|
if (objectsWithDeepWatchers.has(obj)) {
|
|
@@ -3151,7 +3405,7 @@ function touchedOpaque(obj, evolution, prop) {
|
|
|
3151
3405
|
}
|
|
3152
3406
|
if (effects.size > 0) {
|
|
3153
3407
|
optionCall('touched', obj, evolution, [prop], Array.from(effects));
|
|
3154
|
-
batch(Array.from(effects));
|
|
3408
|
+
batch(Array.from(effects), undefined, sourceEffect);
|
|
3155
3409
|
}
|
|
3156
3410
|
}
|
|
3157
3411
|
|
|
@@ -3173,9 +3427,10 @@ function addUnreactiveProps(proto, set) {
|
|
|
3173
3427
|
return proto;
|
|
3174
3428
|
}
|
|
3175
3429
|
// Merge sets
|
|
3176
|
-
|
|
3430
|
+
const merged = new Set(existing);
|
|
3431
|
+
proto[unreactiveProperties] = merged;
|
|
3177
3432
|
for (const p of set)
|
|
3178
|
-
|
|
3433
|
+
merged.add(p);
|
|
3179
3434
|
}
|
|
3180
3435
|
// If no set, mark as fully unreactive, otherwise create set
|
|
3181
3436
|
else
|
|
@@ -3274,7 +3529,7 @@ function notifyPropertyChange(targetObj, prop, oldValue, newValue, hadProperty)
|
|
|
3274
3529
|
const origin = { obj: unwrappedObj, prop };
|
|
3275
3530
|
// Deep touch: only notify nested property changes with origin filtering
|
|
3276
3531
|
// Don't notify direct property change - the whole point is to avoid parent effects re-running
|
|
3277
|
-
const changes = untracked(() => recursiveTouch(oldValue, newValue, new WeakMap(), [], origin));
|
|
3532
|
+
const changes = untracked `deepTouch:recursive`(() => recursiveTouch(oldValue, newValue, new WeakMap(), [], origin));
|
|
3278
3533
|
// When deep touch found no child differences, the object identity still changed.
|
|
3279
3534
|
// Migrate watchers from old → new so the dependency chain is preserved.
|
|
3280
3535
|
if (changes.length === 0) {
|
|
@@ -3500,6 +3755,17 @@ const subsRegister = new WeakMap();
|
|
|
3500
3755
|
// Internal untracked flag for setter/getter operations - only used when testing oldValue while setting a value
|
|
3501
3756
|
// TODO: `touched` trigger also compares to old value and should use the internalUntracked flag
|
|
3502
3757
|
let internalUntracked = false;
|
|
3758
|
+
function wrapReactiveValue(obj, prop, value) {
|
|
3759
|
+
if (!isReactive(value) && typeof value === 'object' && value !== null) {
|
|
3760
|
+
const reactiveValue = reactiveObject(value);
|
|
3761
|
+
// Only create back-references if this object needs them
|
|
3762
|
+
if (needsBackReferences(obj)) {
|
|
3763
|
+
addBackReference(reactiveValue, obj, prop);
|
|
3764
|
+
}
|
|
3765
|
+
return reactiveValue;
|
|
3766
|
+
}
|
|
3767
|
+
return value;
|
|
3768
|
+
}
|
|
3503
3769
|
const reactiveHandlers = {
|
|
3504
3770
|
[Symbol.toStringTag]: 'MutTs Reactive',
|
|
3505
3771
|
get(obj, prop, receiver) {
|
|
@@ -3527,6 +3793,10 @@ const reactiveHandlers = {
|
|
|
3527
3793
|
// Symbols: fast-path — no reactivity tracking
|
|
3528
3794
|
if (typeof prop === 'symbol' || prop === 'constructor' || isUnreactiveProp(obj, prop))
|
|
3529
3795
|
return FoolProof.get(obj, prop, receiver);
|
|
3796
|
+
if (!getActiveEffect()) {
|
|
3797
|
+
const value = (subsRegister.get(obj)?.get || FoolProof.get)(obj, prop, receiver);
|
|
3798
|
+
return wrapReactiveValue(obj, prop, value);
|
|
3799
|
+
}
|
|
3530
3800
|
// Check if property exists using a trap-free walk to avoid triggering
|
|
3531
3801
|
// the has-trap cascade on prototype chains of reactive proxies.
|
|
3532
3802
|
const isOwnProp = Object.hasOwn(obj, prop);
|
|
@@ -3566,15 +3836,7 @@ const reactiveHandlers = {
|
|
|
3566
3836
|
// For arrays, use FoolProof.get (Indexer path) for numeric index reactivity.
|
|
3567
3837
|
// For all other objects, inline Reflect.get directly (skips 3 function calls).
|
|
3568
3838
|
const value = (subsRegister.get(obj)?.get || FoolProof.get)(obj, prop, receiver);
|
|
3569
|
-
|
|
3570
|
-
const reactiveValue = reactiveObject(value);
|
|
3571
|
-
// Only create back-references if this object needs them
|
|
3572
|
-
if (needsBackReferences(obj)) {
|
|
3573
|
-
addBackReference(reactiveValue, obj, prop);
|
|
3574
|
-
}
|
|
3575
|
-
return reactiveValue;
|
|
3576
|
-
}
|
|
3577
|
-
return value;
|
|
3839
|
+
return wrapReactiveValue(obj, prop, value);
|
|
3578
3840
|
},
|
|
3579
3841
|
set(obj, prop, value, receiver) {
|
|
3580
3842
|
const unwrapped = unwrap(receiver);
|
|
@@ -3751,6 +4013,7 @@ const reactive = decorator({
|
|
|
3751
4013
|
});
|
|
3752
4014
|
|
|
3753
4015
|
exports.AZone = AZone;
|
|
4016
|
+
exports.CompareSymbol = CompareSymbol;
|
|
3754
4017
|
exports.DecoratorError = DecoratorError;
|
|
3755
4018
|
exports.FoolProof = FoolProof;
|
|
3756
4019
|
exports.IterableWeakMap = IterableWeakMap;
|
|
@@ -3767,13 +4030,17 @@ exports.addUnreactiveProps = addUnreactiveProps;
|
|
|
3767
4030
|
exports.allProps = allProps;
|
|
3768
4031
|
exports.arrayEquals = arrayEquals;
|
|
3769
4032
|
exports.assertUntracked = assertUntracked;
|
|
4033
|
+
exports.asyncHook = asyncHook;
|
|
4034
|
+
exports.asyncHooks = asyncHooks;
|
|
3770
4035
|
exports.asyncZone = asyncZone;
|
|
3771
4036
|
exports.atom = atom;
|
|
3772
4037
|
exports.atomic = atomic;
|
|
3773
4038
|
exports.batch = batch;
|
|
3774
4039
|
exports.biDi = biDi;
|
|
4040
|
+
exports.captioned = captioned;
|
|
3775
4041
|
exports.captured = captured;
|
|
3776
4042
|
exports.caught = caught;
|
|
4043
|
+
exports.chainExternalReason = chainExternalReason;
|
|
3777
4044
|
exports.contentRef = contentRef;
|
|
3778
4045
|
exports.createFlavor = createFlavor;
|
|
3779
4046
|
exports.debugPreset = debugPreset;
|
|
@@ -3785,6 +4052,7 @@ exports.dependant = dependant;
|
|
|
3785
4052
|
exports.devPreset = devPreset;
|
|
3786
4053
|
exports.effect = effect;
|
|
3787
4054
|
exports.effectAggregator = effectAggregator;
|
|
4055
|
+
exports.effectContext = effectContext;
|
|
3788
4056
|
exports.effectHistory = effectHistory;
|
|
3789
4057
|
exports.effectMarker = effectMarker;
|
|
3790
4058
|
exports.effectToDeepWatchedObjects = effectToDeepWatchedObjects;
|
|
@@ -3796,6 +4064,8 @@ exports.getActiveEffect = getActiveEffect;
|
|
|
3796
4064
|
exports.getEffectNode = getEffectNode;
|
|
3797
4065
|
exports.getRoot = getRoot;
|
|
3798
4066
|
exports.getState = getState;
|
|
4067
|
+
exports.hooks = hooks;
|
|
4068
|
+
exports.inheritCaption = inheritCaption;
|
|
3799
4069
|
exports.isConstructor = isConstructor;
|
|
3800
4070
|
exports.isDev = isDev;
|
|
3801
4071
|
exports.isNonReactive = isNonReactive;
|
|
@@ -3833,6 +4103,7 @@ exports.unlink = unlink;
|
|
|
3833
4103
|
exports.unreactiveProperties = unreactiveProperties;
|
|
3834
4104
|
exports.untracked = untracked;
|
|
3835
4105
|
exports.unwrap = unwrap;
|
|
4106
|
+
exports.withEffectContext = withEffectContext;
|
|
3836
4107
|
exports.wrapProtos = wrapProtos;
|
|
3837
4108
|
exports.zip = zip;
|
|
3838
|
-
//# sourceMappingURL=proxy-
|
|
4109
|
+
//# sourceMappingURL=proxy-DBHj3kGK.cjs.map
|