what-core 0.12.3 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-ENARGHSD.min.js +11 -0
- package/dist/chunk-OKM3GKVP.min.js +1 -0
- package/dist/index.min.js +82 -5
- package/dist/render.min.js +1 -1
- package/dist/testing.min.js +1 -1
- package/index.d.ts +369 -43
- package/package.json +1 -1
- package/render.d.ts +7 -0
- package/src/a11y.js +237 -26
- package/src/agent-context.js +1 -1
- package/src/animation.js +13 -6
- package/src/components.js +1 -1
- package/src/data.js +643 -93
- package/src/dom.js +29 -19
- package/src/errors.js +333 -1
- package/src/form.js +330 -31
- package/src/head.js +2 -1
- package/src/hooks.js +30 -20
- package/src/index.js +1 -0
- package/src/reactive.js +31 -14
- package/src/render.js +502 -36
- package/src/scheduler.js +24 -7
- package/src/skeleton.js +16 -1
- package/src/store.js +0 -1
- package/src/testing.js +101 -50
- package/src/warnings.js +83 -0
- package/testing.d.ts +17 -1
- package/dist/chunk-JVEPLFIB.min.js +0 -11
- package/dist/chunk-VTPLA4AS.min.js +0 -1
package/src/reactive.js
CHANGED
|
@@ -30,6 +30,7 @@ export const __DEV__ =
|
|
|
30
30
|
|
|
31
31
|
// DevTools hooks — set by what-devtools when installed.
|
|
32
32
|
// These are no-ops in production (dead-code eliminated with __DEV__).
|
|
33
|
+
/** @type {WhatDevToolsHooks | null} */
|
|
33
34
|
export let __devtools = null;
|
|
34
35
|
|
|
35
36
|
/** @internal Install devtools hooks. Called by what-devtools. */
|
|
@@ -96,7 +97,7 @@ export function signal(initial, debugName) {
|
|
|
96
97
|
// Invalidate lastTracked since value changed — any effect that reads
|
|
97
98
|
// this signal during re-run needs to re-track.
|
|
98
99
|
lastTracked = null;
|
|
99
|
-
if (__DEV__ && __devtools) __devtools.onSignalUpdate(sig);
|
|
100
|
+
if (__DEV__ && __devtools) __devtools.onSignalUpdate?.(sig);
|
|
100
101
|
if (subs.size > 0) notify(subs);
|
|
101
102
|
}
|
|
102
103
|
|
|
@@ -134,11 +135,21 @@ export function signal(initial, debugName) {
|
|
|
134
135
|
sig._signal = true;
|
|
135
136
|
if (__DEV__) {
|
|
136
137
|
sig._subs = subs;
|
|
138
|
+
// Back-reference from the subscriber Set to its signal, for trackSignals()
|
|
139
|
+
// in testing.js. An effect records dependencies as the `subs` Sets it
|
|
140
|
+
// joined (see the read path above), which is one-directional: given an
|
|
141
|
+
// effect you can count its deps but not name them.
|
|
142
|
+
//
|
|
143
|
+
// Deliberately NOT `_owner`. That property is load-bearing for topological
|
|
144
|
+
// level computation, and a signal's Set is documented above as having
|
|
145
|
+
// `_owner === undefined` precisely because signals are level 0. A separate
|
|
146
|
+
// dev-only name keeps that invariant intact.
|
|
147
|
+
subs._signalOwner = sig;
|
|
137
148
|
if (debugName) sig._debugName = debugName;
|
|
138
149
|
}
|
|
139
150
|
|
|
140
151
|
// Notify devtools of signal creation
|
|
141
|
-
if (__DEV__ && __devtools) __devtools.onSignalCreate(sig);
|
|
152
|
+
if (__DEV__ && __devtools) __devtools.onSignalCreate?.(sig);
|
|
142
153
|
|
|
143
154
|
return sig;
|
|
144
155
|
}
|
|
@@ -337,7 +348,7 @@ export function effect(fn, opts) {
|
|
|
337
348
|
// effect could never re-fire anyway, so releasing is safe.
|
|
338
349
|
if (e.deps.length === 0 && e._cleanup === null) {
|
|
339
350
|
e.disposed = true;
|
|
340
|
-
if (__DEV__ && __devtools) __devtools.onEffectDispose(e);
|
|
351
|
+
if (__DEV__ && __devtools) __devtools.onEffectDispose?.(e);
|
|
341
352
|
return _noopDispose;
|
|
342
353
|
}
|
|
343
354
|
|
|
@@ -369,6 +380,7 @@ function _createEffect(fn, lazy) {
|
|
|
369
380
|
// IMPORTANT: V8 optimizes objects with a consistent "hidden class" (shape).
|
|
370
381
|
// All properties must be declared upfront even if null — adding properties
|
|
371
382
|
// later causes shape transitions which deoptimize property access globally.
|
|
383
|
+
/** @type {WhatEffectNode} */
|
|
372
384
|
const e = {
|
|
373
385
|
fn,
|
|
374
386
|
deps: [], // array of subscriber sets (cheaper than Set for typical 1-3 deps)
|
|
@@ -385,7 +397,7 @@ function _createEffect(fn, lazy) {
|
|
|
385
397
|
_cleanup: null, // cleanup function returned by effect fn (declared upfront for shape)
|
|
386
398
|
_epoch: 0, // incremented on cleanup — used by signal lastTracked cache
|
|
387
399
|
};
|
|
388
|
-
if (__DEV__ && __devtools) __devtools.onEffectCreate(e);
|
|
400
|
+
if (__DEV__ && __devtools) __devtools.onEffectCreate?.(e);
|
|
389
401
|
return e;
|
|
390
402
|
}
|
|
391
403
|
|
|
@@ -409,12 +421,12 @@ function _runEffect(e) {
|
|
|
409
421
|
const result = e.fn();
|
|
410
422
|
if (typeof result === 'function') e._cleanup = result;
|
|
411
423
|
} catch (err) {
|
|
412
|
-
if (__devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
424
|
+
if (__devtools?.onError) __devtools.onError?.(err, { type: 'effect', effect: e });
|
|
413
425
|
if (__DEV__) console.warn('[what] Error in stable effect:', err);
|
|
414
426
|
} finally {
|
|
415
427
|
currentEffect = prev;
|
|
416
428
|
}
|
|
417
|
-
if (__DEV__ && __devtools?.onEffectRun) __devtools.onEffectRun(e);
|
|
429
|
+
if (__DEV__ && __devtools?.onEffectRun) __devtools.onEffectRun?.(e);
|
|
418
430
|
return;
|
|
419
431
|
}
|
|
420
432
|
|
|
@@ -426,7 +438,7 @@ function _runEffect(e) {
|
|
|
426
438
|
// Run effect cleanup from previous run
|
|
427
439
|
if (e._cleanup) {
|
|
428
440
|
try { e._cleanup(); } catch (err) {
|
|
429
|
-
if (__DEV__ && __devtools?.onError) __devtools.onError(err, { type: 'effect-cleanup', effect: e });
|
|
441
|
+
if (__DEV__ && __devtools?.onError) __devtools.onError?.(err, { type: 'effect-cleanup', effect: e });
|
|
430
442
|
if (__DEV__) console.warn('[what] Error in effect cleanup:', err);
|
|
431
443
|
}
|
|
432
444
|
e._cleanup = null;
|
|
@@ -441,7 +453,7 @@ function _runEffect(e) {
|
|
|
441
453
|
}
|
|
442
454
|
} catch (err) {
|
|
443
455
|
if (err === NEEDS_UPSTREAM) throw err; // Iterative eval sentinel — not a real error
|
|
444
|
-
if (__DEV__ && __devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
456
|
+
if (__DEV__ && __devtools?.onError) __devtools.onError?.(err, { type: 'effect', effect: e });
|
|
445
457
|
throw err;
|
|
446
458
|
} finally {
|
|
447
459
|
currentEffect = prev;
|
|
@@ -458,12 +470,12 @@ function _runEffect(e) {
|
|
|
458
470
|
e._stable = true;
|
|
459
471
|
}
|
|
460
472
|
|
|
461
|
-
if (__DEV__ && __devtools?.onEffectRun) __devtools.onEffectRun(e);
|
|
473
|
+
if (__DEV__ && __devtools?.onEffectRun) __devtools.onEffectRun?.(e);
|
|
462
474
|
}
|
|
463
475
|
|
|
464
476
|
function _disposeEffect(e) {
|
|
465
477
|
e.disposed = true;
|
|
466
|
-
if (__DEV__ && __devtools) __devtools.onEffectDispose(e);
|
|
478
|
+
if (__DEV__ && __devtools) __devtools.onEffectDispose?.(e);
|
|
467
479
|
cleanup(e);
|
|
468
480
|
// Run cleanup on dispose
|
|
469
481
|
if (e._cleanup) {
|
|
@@ -509,11 +521,11 @@ function _processSubscriber(e) {
|
|
|
509
521
|
try {
|
|
510
522
|
const result = e.fn();
|
|
511
523
|
if (typeof result === 'function') {
|
|
512
|
-
if (e._cleanup) try { e._cleanup(); } catch
|
|
524
|
+
if (e._cleanup) try { e._cleanup(); } catch { /* ignore */ }
|
|
513
525
|
e._cleanup = result;
|
|
514
526
|
}
|
|
515
527
|
} catch (err) {
|
|
516
|
-
if (__DEV__ && __devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
528
|
+
if (__DEV__ && __devtools?.onError) __devtools.onError?.(err, { type: 'effect', effect: e });
|
|
517
529
|
if (__DEV__) console.warn('[what] Error in stable effect:', err);
|
|
518
530
|
} finally {
|
|
519
531
|
currentEffect = prev;
|
|
@@ -617,7 +629,7 @@ function flush() {
|
|
|
617
629
|
_runEffect(e);
|
|
618
630
|
} catch (err) {
|
|
619
631
|
if (err === NEEDS_UPSTREAM) throw err;
|
|
620
|
-
if (__DEV__ && __devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
632
|
+
if (__DEV__ && __devtools?.onError) __devtools.onError?.(err, { type: 'effect', effect: e });
|
|
621
633
|
// Surface in production too — an uncaught reactive-update error is a
|
|
622
634
|
// real bug; staying silent (as the old throw-out-of-flush did once it
|
|
623
635
|
// escaped) hides it. console.error never aborts the batch.
|
|
@@ -786,6 +798,7 @@ export function createRoot(fn) {
|
|
|
786
798
|
const prevRoot = currentRoot;
|
|
787
799
|
const prevOwner = currentOwner;
|
|
788
800
|
const root = {
|
|
801
|
+
/** @type {Array<() => void>} */
|
|
789
802
|
disposals: [],
|
|
790
803
|
owner: currentOwner, // parent owner for ownership tree
|
|
791
804
|
children: [], // child roots (ownership tree)
|
|
@@ -856,6 +869,7 @@ export function _createItemScope(fn) {
|
|
|
856
869
|
const prevRoot = currentRoot;
|
|
857
870
|
const prevOwner = currentOwner;
|
|
858
871
|
const scope = {
|
|
872
|
+
/** @type {Array<() => void>} */
|
|
859
873
|
disposals: [],
|
|
860
874
|
owner: null, // No parent registration
|
|
861
875
|
children: [], // Kept for compat with effects that create sub-roots
|
|
@@ -914,6 +928,7 @@ if (__DEV__ && typeof WeakRef !== 'undefined') {
|
|
|
914
928
|
// needed before the devtools entry point runs; once devtools install, the
|
|
915
929
|
// buffer is drained and subsequent creations flow through the real hooks.
|
|
916
930
|
const PREINSTALL_CAP = 2000;
|
|
931
|
+
/** @type {{ signals: Set<any>, effects: Set<any>, components: any[] }} */
|
|
917
932
|
const buffer = { signals: new Set(), effects: new Set(), components: [] };
|
|
918
933
|
__devtools = {
|
|
919
934
|
__isPreinstallBuffer: true,
|
|
@@ -940,9 +955,10 @@ if (__DEV__ && typeof WeakRef !== 'undefined') {
|
|
|
940
955
|
* __setDevToolsHooks replaces the placeholder. Returns arrays of live refs.
|
|
941
956
|
*/
|
|
942
957
|
export function __drainPreinstallBuffer() {
|
|
943
|
-
if (!__DEV__) return { signals: [], effects: [], components: [] };
|
|
958
|
+
if (!__DEV__) return /** @type {{ signals: any[], effects: any[], components: any[] }} */ ({ signals: [], effects: [], components: [] });
|
|
944
959
|
// If the current __devtools is the real one (no __isPreinstallBuffer), the
|
|
945
960
|
// caller installed late and there is nothing to drain from this side.
|
|
961
|
+
/** @type {{ signals: any[], effects: any[], components: any[] }} */
|
|
946
962
|
const out = { signals: [], effects: [], components: [] };
|
|
947
963
|
const buf = (typeof __preinstallSnapshot !== 'undefined') ? __preinstallSnapshot : null;
|
|
948
964
|
if (!buf) return out;
|
|
@@ -954,6 +970,7 @@ export function __drainPreinstallBuffer() {
|
|
|
954
970
|
|
|
955
971
|
// Capture the placeholder buffer at module load so __drainPreinstallBuffer
|
|
956
972
|
// can return it AFTER __setDevToolsHooks has replaced __devtools.
|
|
973
|
+
/** @type {WhatDevToolsHooks['__buffer'] | null} */
|
|
957
974
|
let __preinstallSnapshot = null;
|
|
958
975
|
if (__DEV__ && __devtools?.__isPreinstallBuffer) {
|
|
959
976
|
__preinstallSnapshot = __devtools.__buffer;
|