what-core 0.6.8 → 0.6.9
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/compiler.js +59 -91
- package/dist/compiler.js.map +3 -3
- package/dist/compiler.min.js +1 -1
- package/dist/compiler.min.js.map +3 -3
- package/dist/devtools.js.map +1 -1
- package/dist/devtools.min.js.map +1 -1
- package/dist/index.js +59 -91
- package/dist/index.js.map +3 -3
- package/dist/index.min.js +6 -6
- package/dist/index.min.js.map +3 -3
- package/dist/render.js +59 -91
- package/dist/render.js.map +3 -3
- package/dist/render.min.js +2 -2
- package/dist/render.min.js.map +3 -3
- package/dist/testing.js +59 -91
- package/dist/testing.js.map +3 -3
- package/dist/testing.min.js +1 -1
- package/dist/testing.min.js.map +3 -3
- package/package.json +2 -2
- package/src/dom.js +31 -22
- package/src/reactive.js +36 -59
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "what-core",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "What Framework - The closest framework to vanilla JS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
"license": "MIT",
|
|
74
74
|
"repository": {
|
|
75
75
|
"type": "git",
|
|
76
|
-
"url": "https://github.com/CelsianJs/what-framework"
|
|
76
|
+
"url": "git+https://github.com/CelsianJs/what-framework.git"
|
|
77
77
|
},
|
|
78
78
|
"bugs": {
|
|
79
79
|
"url": "https://github.com/CelsianJs/what-framework/issues"
|
package/src/dom.js
CHANGED
|
@@ -589,28 +589,8 @@ function applyProps(el, newProps, oldProps, isSvg) {
|
|
|
589
589
|
}
|
|
590
590
|
|
|
591
591
|
function setProp(el, key, value, isSvg) {
|
|
592
|
-
//
|
|
593
|
-
|
|
594
|
-
if (typeof console !== 'undefined') {
|
|
595
|
-
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
596
|
-
}
|
|
597
|
-
el.removeAttribute(getDomAttributeName(key));
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
// Reactive function props — wrap in effect for fine-grained updates
|
|
601
|
-
if (typeof value === 'function' && !(key.startsWith('on') && key.length > 2) && key !== 'ref') {
|
|
602
|
-
if (!el._propEffects) el._propEffects = {};
|
|
603
|
-
if (el._propEffects[key]) {
|
|
604
|
-
try { el._propEffects[key](); } catch (e) { /* already disposed */ }
|
|
605
|
-
}
|
|
606
|
-
el._propEffects[key] = effect(() => {
|
|
607
|
-
const resolved = value();
|
|
608
|
-
setProp(el, key, resolved, isSvg);
|
|
609
|
-
});
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// Event handlers
|
|
592
|
+
// Event handlers are not URL-bearing attributes; keep this fast path ahead of
|
|
593
|
+
// URL sanitization so hot event mount paths do not pay attr normalization costs.
|
|
614
594
|
if (key.startsWith('on') && key.length > 2) {
|
|
615
595
|
let eventName = key.slice(2);
|
|
616
596
|
let useCapture = false;
|
|
@@ -636,6 +616,35 @@ function setProp(el, key, value, isSvg) {
|
|
|
636
616
|
return;
|
|
637
617
|
}
|
|
638
618
|
|
|
619
|
+
// Refs are object/function assignments, not DOM URL sinks. Keep them out of
|
|
620
|
+
// URL sanitization when setProp is reached directly by reactive updates.
|
|
621
|
+
if (key === 'ref') {
|
|
622
|
+
if (typeof value === 'function') value(el);
|
|
623
|
+
else if (value) value.current = el;
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Sanitize URL attributes before property assignment or setAttribute can commit them.
|
|
628
|
+
if (!isSafeUrlAttributeValue(key, value)) {
|
|
629
|
+
if (typeof console !== 'undefined') {
|
|
630
|
+
console.warn(`[what] Blocked unsafe URL in "${key}" attribute: ${value}`);
|
|
631
|
+
}
|
|
632
|
+
el.removeAttribute(getDomAttributeName(key));
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
// Reactive function props — wrap in effect for fine-grained updates
|
|
636
|
+
if (typeof value === 'function') {
|
|
637
|
+
if (!el._propEffects) el._propEffects = {};
|
|
638
|
+
if (el._propEffects[key]) {
|
|
639
|
+
try { el._propEffects[key](); } catch (e) { /* already disposed */ }
|
|
640
|
+
}
|
|
641
|
+
el._propEffects[key] = effect(() => {
|
|
642
|
+
const resolved = value();
|
|
643
|
+
setProp(el, key, resolved, isSvg);
|
|
644
|
+
});
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
|
|
639
648
|
// className / class
|
|
640
649
|
if (key === 'className' || key === 'class') {
|
|
641
650
|
if (isSvg) {
|
package/src/reactive.js
CHANGED
|
@@ -323,36 +323,13 @@ function _runEffect(e) {
|
|
|
323
323
|
|
|
324
324
|
// Stable effect fast path: deps don't change, skip cleanup/re-subscribe.
|
|
325
325
|
if (e._stable) {
|
|
326
|
-
|
|
327
|
-
try { e._cleanup(); } catch (err) {
|
|
328
|
-
if (__DEV__) console.warn('[what] Error in effect cleanup:', err);
|
|
329
|
-
}
|
|
330
|
-
e._cleanup = null;
|
|
331
|
-
}
|
|
332
|
-
const prev = currentEffect;
|
|
333
|
-
currentEffect = null; // Don't re-track deps (already subscribed)
|
|
334
|
-
try {
|
|
335
|
-
const result = e.fn();
|
|
336
|
-
if (typeof result === 'function') e._cleanup = result;
|
|
337
|
-
} catch (err) {
|
|
338
|
-
if (__devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
339
|
-
if (__DEV__) console.warn('[what] Error in stable effect:', err);
|
|
340
|
-
} finally {
|
|
341
|
-
currentEffect = prev;
|
|
342
|
-
}
|
|
343
|
-
if (__DEV__ && __devtools?.onEffectRun) __devtools.onEffectRun(e);
|
|
326
|
+
runStableEffect(e);
|
|
344
327
|
return;
|
|
345
328
|
}
|
|
346
329
|
|
|
347
330
|
cleanup(e);
|
|
348
331
|
// Run effect cleanup from previous run
|
|
349
|
-
|
|
350
|
-
try { e._cleanup(); } catch (err) {
|
|
351
|
-
if (__devtools?.onError) __devtools.onError(err, { type: 'effect-cleanup', effect: e });
|
|
352
|
-
if (__DEV__) console.warn('[what] Error in effect cleanup:', err);
|
|
353
|
-
}
|
|
354
|
-
e._cleanup = null;
|
|
355
|
-
}
|
|
332
|
+
runEffectCleanup(e, 'effect cleanup');
|
|
356
333
|
const prev = currentEffect;
|
|
357
334
|
currentEffect = e;
|
|
358
335
|
try {
|
|
@@ -376,14 +353,41 @@ function _disposeEffect(e) {
|
|
|
376
353
|
if (__DEV__ && __devtools) __devtools.onEffectDispose(e);
|
|
377
354
|
cleanup(e);
|
|
378
355
|
// Run cleanup on dispose
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
356
|
+
runEffectCleanup(e, 'effect cleanup on dispose');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function reportEffectCleanupError(err, e, phase) {
|
|
360
|
+
if (__devtools?.onError) __devtools.onError(err, { type: 'effect-cleanup', effect: e, phase });
|
|
361
|
+
if (__DEV__) console.warn(`[what] Error in ${phase}:`, err);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function runEffectCleanup(e, phase) {
|
|
365
|
+
if (!e._cleanup) return;
|
|
366
|
+
const cleanupFn = e._cleanup;
|
|
367
|
+
e._cleanup = null;
|
|
368
|
+
try {
|
|
369
|
+
cleanupFn();
|
|
370
|
+
} catch (err) {
|
|
371
|
+
reportEffectCleanupError(err, e, phase);
|
|
384
372
|
}
|
|
385
373
|
}
|
|
386
374
|
|
|
375
|
+
function runStableEffect(e) {
|
|
376
|
+
const prev = currentEffect;
|
|
377
|
+
currentEffect = null; // Don't re-track deps (already subscribed)
|
|
378
|
+
try {
|
|
379
|
+
runEffectCleanup(e, 'stable effect cleanup');
|
|
380
|
+
const result = e.fn();
|
|
381
|
+
if (typeof result === 'function') e._cleanup = result;
|
|
382
|
+
} catch (err) {
|
|
383
|
+
if (__devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
384
|
+
if (__DEV__) console.warn('[what] Error in stable effect:', err);
|
|
385
|
+
} finally {
|
|
386
|
+
currentEffect = prev;
|
|
387
|
+
}
|
|
388
|
+
if (__DEV__ && __devtools?.onEffectRun) __devtools.onEffectRun(e);
|
|
389
|
+
}
|
|
390
|
+
|
|
387
391
|
function cleanup(e) {
|
|
388
392
|
const deps = e.deps;
|
|
389
393
|
for (let i = 0; i < deps.length; i++) deps[i].delete(e);
|
|
@@ -413,21 +417,7 @@ function notify(subs) {
|
|
|
413
417
|
// _onNotify may call notify() recursively — tracked by notifyDepth.
|
|
414
418
|
e._onNotify();
|
|
415
419
|
} else if (batchDepth === 0 && e._stable) {
|
|
416
|
-
|
|
417
|
-
const prev = currentEffect;
|
|
418
|
-
currentEffect = null;
|
|
419
|
-
try {
|
|
420
|
-
const result = e.fn();
|
|
421
|
-
if (typeof result === 'function') {
|
|
422
|
-
if (e._cleanup) try { e._cleanup(); } catch (err) {}
|
|
423
|
-
e._cleanup = result;
|
|
424
|
-
}
|
|
425
|
-
} catch (err) {
|
|
426
|
-
if (__devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
427
|
-
if (__DEV__) console.warn('[what] Error in stable effect:', err);
|
|
428
|
-
} finally {
|
|
429
|
-
currentEffect = prev;
|
|
430
|
-
}
|
|
420
|
+
runStableEffect(e);
|
|
431
421
|
} else if (!e._pending) {
|
|
432
422
|
e._pending = true;
|
|
433
423
|
const level = e._level;
|
|
@@ -450,20 +440,7 @@ function notify(subs) {
|
|
|
450
440
|
if (e._onNotify) {
|
|
451
441
|
e._onNotify();
|
|
452
442
|
} else if (batchDepth === 0 && e._stable) {
|
|
453
|
-
|
|
454
|
-
currentEffect = null;
|
|
455
|
-
try {
|
|
456
|
-
const result = e.fn();
|
|
457
|
-
if (typeof result === 'function') {
|
|
458
|
-
if (e._cleanup) try { e._cleanup(); } catch (err) {}
|
|
459
|
-
e._cleanup = result;
|
|
460
|
-
}
|
|
461
|
-
} catch (err) {
|
|
462
|
-
if (__devtools?.onError) __devtools.onError(err, { type: 'effect', effect: e });
|
|
463
|
-
if (__DEV__) console.warn('[what] Error in stable effect:', err);
|
|
464
|
-
} finally {
|
|
465
|
-
currentEffect = prev;
|
|
466
|
-
}
|
|
443
|
+
runStableEffect(e);
|
|
467
444
|
} else if (!e._pending) {
|
|
468
445
|
e._pending = true;
|
|
469
446
|
const level = e._level;
|