@praxisjs/devtools 0.2.6 → 0.2.7
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/CHANGELOG.md +16 -0
- package/assets/uno.generated.css +2 -1
- package/dist/index.js +14 -4
- package/package.json +5 -5
- package/src/__tests__/debug.test.ts +56 -0
- package/src/__tests__/event-bus.test.ts +47 -0
- package/src/__tests__/registry.test.ts +55 -0
- package/src/__tests__/trace.test.ts +51 -0
- package/src/core/event-bus.ts +17 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @praxisjs/devtools
|
|
2
2
|
|
|
3
|
+
## 0.2.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 029ef04: Event bus handlers no longer short-circuit on the first error — all handlers run and errors are collected into an `AggregateError`.
|
|
8
|
+
- Updated dependencies [029ef04]
|
|
9
|
+
- Updated dependencies [029ef04]
|
|
10
|
+
- Updated dependencies [029ef04]
|
|
11
|
+
- Updated dependencies [029ef04]
|
|
12
|
+
- Updated dependencies [029ef04]
|
|
13
|
+
- Updated dependencies [029ef04]
|
|
14
|
+
- @praxisjs/core@1.1.0
|
|
15
|
+
- @praxisjs/decorators@0.6.0
|
|
16
|
+
- @praxisjs/runtime@0.2.6
|
|
17
|
+
- @praxisjs/jsx@0.3.5
|
|
18
|
+
|
|
3
19
|
## 0.2.6
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/assets/uno.generated.css
CHANGED
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { StatelessComponent as k, StatefulComponent as K } from "@praxisjs/core"
|
|
|
3
3
|
import { Component as x, State as O, Prop as ie, Emit as Tn, createMethodDecorator as jn, createGetterObserverDecorator as Fn, createFieldDecorator as Ln, ClassBehavior as An, createClassDecorator as Nn } from "@praxisjs/decorators";
|
|
4
4
|
import { render as Ft } from "@praxisjs/runtime";
|
|
5
5
|
import { computed as Bn } from "@praxisjs/core/internal";
|
|
6
|
-
const ir = "data:image/svg+xml,%3csvg%20width='1024'%20height='1024'%20viewBox='0%200%201024%201024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M605.411%20445.66L641.322%20498.293L641.342%20498.278L697.538%20578.57L742.673%20512.806L512.5%20178.878L281.327%20512.806L512.5%20848.182L603.519%20715.561L650.559%20782.134L512.701%20983L187%20510.478L512.701%2040L837%20510.478L698.206%20712.709L668.895%20671.104L604.033%20578.775L512%20712.504L373.199%20511.5L512.233%20309.092L584.13%20414.469L536.746%20480.456L513.69%20445.66L466.305%20511.5L512.166%20577.425L556.48%20513.91L605.411%20445.66Z'%20fill='url(%23paint0_linear_3024_20)'/%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_3024_20'%20x1='512'%20y1='40'%20x2='512'%20y2='983'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%239B76FF'%20stop-opacity='0.86'/%3e%3cstop%20offset='1'%20stop-color='%232D246B'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e", Rn = '*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }:host{all:initial;display:block;font-family:Inter,ui-sans-serif,system-ui,-apple-system,sans-serif}*{box-sizing:border-box}input::placeholder{color:#6f6a8f}input:focus{outline:none;box-shadow:0 0 0 2px #9b90e64d}::-webkit-scrollbar{width:4px;height:4px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#9b90e633;border-radius:2px}::-webkit-scrollbar-thumb:hover{background:#9b90e666}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.bottom-0{bottom:0}.bottom-5{bottom:1.25rem}.left-0{left:0}.right-0{right:0}.right-5{right:1.25rem}.top-0{top:0}.top-full{top:100%}.z-\\[2147483647\\]{z-index:2147483647}.z-10{z-index:10}.grid{display:grid}.grid-cols-\\[1\\.2fr_0\\.8fr_1fr_auto\\]{grid-template-columns:1.2fr .8fr 1fr auto}.m6{margin:1.5rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mr-\\[2px\\]{margin-right:2px}.ms{margin-inline-start:1rem}.mt-1{margin-top:.25rem}.box-border{box-sizing:border-box}.inline-block{display:inline-block}.h-\\[13px\\]{height:13px}.h-\\[22px\\]{height:22px}.h-\\[2px\\]{height:2px}.h-\\[32px\\]{height:32px}.h-\\[6px\\]{height:6px}.h-1,.h1{height:.25rem}.h-10{height:2.5rem}.h-3{height:.75rem}.h-7{height:1.75rem}.h-full{height:100%}.h-screen{height:100vh}.h2{height:.5rem}.max-w-\\[200px\\]{max-width:200px}.min-w-0{min-width:0}.w-\\[13px\\]{width:13px}.w-\\[22px\\]{width:22px}.w-\\[2px\\]{width:2px}.w-\\[6px\\]{width:6px}.w-1{width:.25rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-4{width:1rem}.w-full{width:100%}.w-px{width:1px}.flex{display:flex}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.cursor-\\[ew-resize\\]{cursor:ew-resize}.cursor-\\[ns-resize\\]{cursor:ns-resize}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;user-select:none}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-\\[2px\\]{gap:2px}.gap-\\[3px\\]{gap:3px}.gap-\\[6px\\]{gap:6px}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.b,.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-border{--un-border-opacity:.25;border-color:rgba(155,144,230,var(--un-border-opacity))}.border-warn{--un-border-opacity:1;border-color:rgb(217 119 6 / var(--un-border-opacity))}.hover\\:border-accent:hover{--un-border-opacity:1;border-color:rgb(155 144 230 / var(--un-border-opacity))}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.bg-\\[rgba\\(124\\,109\\,214\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(124,109,214,var(--un-bg-opacity))}.bg-\\[rgba\\(14\\,165\\,122\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(14,165,122,var(--un-bg-opacity))}.bg-\\[rgba\\(155\\,144\\,230\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(155,144,230,var(--un-bg-opacity))}.bg-\\[rgba\\(217\\,119\\,6\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(217,119,6,var(--un-bg-opacity))}.bg-\\[rgba\\(220\\,38\\,38\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(220,38,38,var(--un-bg-opacity))}.bg-\\[rgba\\(74\\,222\\,128\\,0\\.12\\)\\]{--un-bg-opacity:.12;background-color:rgba(74,222,128,var(--un-bg-opacity))}.bg-accent{--un-bg-opacity:1;background-color:rgb(155 144 230 / var(--un-bg-opacity))}.bg-bg{--un-bg-opacity:1;background-color:rgb(15 13 23 / var(--un-bg-opacity))}.bg-border{--un-bg-opacity:.25;background-color:rgba(155,144,230,var(--un-bg-opacity))}.bg-header{--un-bg-opacity:1;background-color:rgb(22 19 38 / var(--un-bg-opacity))}.bg-input,.bg-section{--un-bg-opacity:1;background-color:rgb(27 24 48 / var(--un-bg-opacity))}.bg-selected{--un-bg-opacity:1;background-color:rgb(34 30 61 / var(--un-bg-opacity))}.bg-soft{--un-bg-opacity:.18;background-color:rgba(155,144,230,var(--un-bg-opacity))}.bg-subtle{--un-bg-opacity:1;background-color:rgb(111 106 143 / var(--un-bg-opacity))}.bg-success{--un-bg-opacity:1;background-color:rgb(14 165 122 / var(--un-bg-opacity))}.bg-transparent{background-color:transparent}.hover\\:bg-accent:hover{--un-bg-opacity:1;background-color:rgb(155 144 230 / var(--un-bg-opacity))}.hover\\:bg-section:hover{--un-bg-opacity:1;background-color:rgb(27 24 48 / var(--un-bg-opacity))}.hover\\:bg-soft:hover{--un-bg-opacity:.18;background-color:rgba(155,144,230,var(--un-bg-opacity))}.p-1{padding:.25rem}.px{padding-left:1rem;padding-right:1rem}.px-\\[6px\\]{padding-left:6px;padding-right:6px}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-\\[2px\\]{padding-top:2px;padding-bottom:2px}.py-\\[3px\\]{padding-top:3px;padding-bottom:3px}.py-\\[4px\\]{padding-top:4px;padding-bottom:4px}.py-\\[5px\\]{padding-top:5px;padding-bottom:5px}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pl-\\[10px\\]{padding-left:10px}.pl-\\[56px\\]{padding-left:56px}.pl-1{padding-left:.25rem}.pr-\\[14px\\]{padding-right:14px}.pr-3{padding-right:.75rem}.text-center{text-align:center}.text-right{text-align:right}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-\\[12px\\]{font-size:12px}.text-\\[20px\\]{font-size:20px}.text-\\[9px\\]{font-size:9px}.text-\\[\\#0ea57a\\]{--un-text-opacity:1;color:rgb(14 165 122 / var(--un-text-opacity))}.text-\\[\\#4ade80\\]{--un-text-opacity:1;color:rgb(74 222 128 / var(--un-text-opacity))}.text-\\[\\#7c6dd6\\]{--un-text-opacity:1;color:rgb(124 109 214 / var(--un-text-opacity))}.text-\\[\\#9b90e6\\],.text-accent{--un-text-opacity:1;color:rgb(155 144 230 / var(--un-text-opacity))}.text-\\[\\#d97706\\],.text-warn{--un-text-opacity:1;color:rgb(217 119 6 / var(--un-text-opacity))}.text-\\[\\#dc2626\\]{--un-text-opacity:1;color:rgb(220 38 38 / var(--un-text-opacity))}.text-muted{--un-text-opacity:1;color:rgb(199 195 230 / var(--un-text-opacity))}.text-subtle{--un-text-opacity:1;color:rgb(111 106 143 / var(--un-text-opacity))}.text-text,.hover\\:text-text:hover{--un-text-opacity:1;color:rgb(244 242 255 / var(--un-text-opacity))}.color-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.hover\\:color-muted:hover{--un-text-opacity:1;color:rgb(199 195 230 / var(--un-text-opacity))}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\\[0\\.07em\\]{letter-spacing:.07em}.tracking-\\[0\\.12em\\]{letter-spacing:.12em}.tracking-widest{letter-spacing:.1em}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.uppercase{text-transform:uppercase}.tabular-nums{--un-numeric-spacing:tabular-nums;font-variant-numeric:var(--un-ordinal) var(--un-slashed-zero) var(--un-numeric-figure) var(--un-numeric-spacing) var(--un-numeric-fraction)}.shadow{--un-shadow:var(--un-shadow-inset) 0 1px 3px 0 var(--un-shadow-color, rgb(0 0 0 / .1)),var(--un-shadow-inset) 0 1px 2px -1px var(--un-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.shadow-\\[0_8px_32px_rgba\\(0\\,0\\,0\\,0\\.7\\)\\]{--un-shadow:0 8px 32px var(--un-shadow-color, rgba(0, 0, 0, .7));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.shadow-lg{--un-shadow:var(--un-shadow-inset) 0 10px 15px -3px var(--un-shadow-color, rgb(0 0 0 / .1)),var(--un-shadow-inset) 0 4px 6px -4px var(--un-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.hover\\:shadow-\\[0_8px_32px_rgba\\(56\\,189\\,248\\,0\\.1\\)\\]:hover{--un-shadow:0 8px 32px var(--un-shadow-color, rgba(56, 189, 248, .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}';
|
|
6
|
+
const ir = "data:image/svg+xml,%3csvg%20width='1024'%20height='1024'%20viewBox='0%200%201024%201024'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cpath%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M605.411%20445.66L641.322%20498.293L641.342%20498.278L697.538%20578.57L742.673%20512.806L512.5%20178.878L281.327%20512.806L512.5%20848.182L603.519%20715.561L650.559%20782.134L512.701%20983L187%20510.478L512.701%2040L837%20510.478L698.206%20712.709L668.895%20671.104L604.033%20578.775L512%20712.504L373.199%20511.5L512.233%20309.092L584.13%20414.469L536.746%20480.456L513.69%20445.66L466.305%20511.5L512.166%20577.425L556.48%20513.91L605.411%20445.66Z'%20fill='url(%23paint0_linear_3024_20)'/%3e%3cdefs%3e%3clinearGradient%20id='paint0_linear_3024_20'%20x1='512'%20y1='40'%20x2='512'%20y2='983'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20stop-color='%239B76FF'%20stop-opacity='0.86'/%3e%3cstop%20offset='1'%20stop-color='%232D246B'/%3e%3c/linearGradient%3e%3c/defs%3e%3c/svg%3e", Rn = '*,:before,:after{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }::backdrop{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 rgb(0 0 0 / 0);--un-ring-shadow:0 0 rgb(0 0 0 / 0);--un-shadow-inset: ;--un-shadow:0 0 rgb(0 0 0 / 0);--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgb(147 197 253 / .5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }:host{all:initial;display:block;font-family:Inter,ui-sans-serif,system-ui,-apple-system,sans-serif}*{box-sizing:border-box}input::placeholder{color:#6f6a8f}input:focus{outline:none;box-shadow:0 0 0 2px #9b90e64d}::-webkit-scrollbar{width:4px;height:4px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#9b90e633;border-radius:2px}::-webkit-scrollbar-thumb:hover{background:#9b90e666}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.container{max-width:1536px}}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.bottom-0{bottom:0}.bottom-5{bottom:1.25rem}.left-0{left:0}.right-0{right:0}.right-5{right:1.25rem}.top-0{top:0}.top-full{top:100%}.z-\\[2147483647\\]{z-index:2147483647}.z-10{z-index:10}.grid{display:grid}.grid-cols-\\[1\\.2fr_0\\.8fr_1fr_auto\\]{grid-template-columns:1.2fr .8fr 1fr auto}.m6{margin:1.5rem}.mx-1{margin-left:.25rem;margin-right:.25rem}.mr-\\[2px\\]{margin-right:2px}.ms{margin-inline-start:1rem}.mt-1{margin-top:.25rem}.box-border{box-sizing:border-box}.inline-block{display:inline-block}.h-\\[13px\\]{height:13px}.h-\\[22px\\]{height:22px}.h-\\[2px\\]{height:2px}.h-\\[32px\\]{height:32px}.h-\\[6px\\]{height:6px}.h-1,.h1{height:.25rem}.h-10{height:2.5rem}.h-3,.h3{height:.75rem}.h-7{height:1.75rem}.h-full{height:100%}.h-screen{height:100vh}.h2{height:.5rem}.max-w-\\[200px\\]{max-width:200px}.min-w-0{min-width:0}.w-\\[13px\\]{width:13px}.w-\\[22px\\]{width:22px}.w-\\[2px\\]{width:2px}.w-\\[6px\\]{width:6px}.w-1{width:.25rem}.w-10{width:2.5rem}.w-12{width:3rem}.w-4{width:1rem}.w-full{width:100%}.w-px{width:1px}.flex{display:flex}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.cursor-\\[ew-resize\\]{cursor:ew-resize}.cursor-\\[ns-resize\\]{cursor:ns-resize}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;user-select:none}.items-center{align-items:center}.items-stretch{align-items:stretch}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-\\[2px\\]{gap:2px}.gap-\\[3px\\]{gap:3px}.gap-\\[6px\\]{gap:6px}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.b,.border{border-width:1px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-border{--un-border-opacity:.25;border-color:rgba(155,144,230,var(--un-border-opacity))}.border-warn{--un-border-opacity:1;border-color:rgb(217 119 6 / var(--un-border-opacity))}.hover\\:border-accent:hover{--un-border-opacity:1;border-color:rgb(155 144 230 / var(--un-border-opacity))}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.bg-\\[rgba\\(124\\,109\\,214\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(124,109,214,var(--un-bg-opacity))}.bg-\\[rgba\\(14\\,165\\,122\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(14,165,122,var(--un-bg-opacity))}.bg-\\[rgba\\(155\\,144\\,230\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(155,144,230,var(--un-bg-opacity))}.bg-\\[rgba\\(217\\,119\\,6\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(217,119,6,var(--un-bg-opacity))}.bg-\\[rgba\\(220\\,38\\,38\\,0\\.14\\)\\]{--un-bg-opacity:.14;background-color:rgba(220,38,38,var(--un-bg-opacity))}.bg-\\[rgba\\(74\\,222\\,128\\,0\\.12\\)\\]{--un-bg-opacity:.12;background-color:rgba(74,222,128,var(--un-bg-opacity))}.bg-accent{--un-bg-opacity:1;background-color:rgb(155 144 230 / var(--un-bg-opacity))}.bg-bg{--un-bg-opacity:1;background-color:rgb(15 13 23 / var(--un-bg-opacity))}.bg-border{--un-bg-opacity:.25;background-color:rgba(155,144,230,var(--un-bg-opacity))}.bg-header{--un-bg-opacity:1;background-color:rgb(22 19 38 / var(--un-bg-opacity))}.bg-input,.bg-section{--un-bg-opacity:1;background-color:rgb(27 24 48 / var(--un-bg-opacity))}.bg-selected{--un-bg-opacity:1;background-color:rgb(34 30 61 / var(--un-bg-opacity))}.bg-soft{--un-bg-opacity:.18;background-color:rgba(155,144,230,var(--un-bg-opacity))}.bg-subtle{--un-bg-opacity:1;background-color:rgb(111 106 143 / var(--un-bg-opacity))}.bg-success{--un-bg-opacity:1;background-color:rgb(14 165 122 / var(--un-bg-opacity))}.bg-transparent{background-color:transparent}.hover\\:bg-accent:hover{--un-bg-opacity:1;background-color:rgb(155 144 230 / var(--un-bg-opacity))}.hover\\:bg-section:hover{--un-bg-opacity:1;background-color:rgb(27 24 48 / var(--un-bg-opacity))}.hover\\:bg-soft:hover{--un-bg-opacity:.18;background-color:rgba(155,144,230,var(--un-bg-opacity))}.p-1{padding:.25rem}.px{padding-left:1rem;padding-right:1rem}.px-\\[6px\\]{padding-left:6px;padding-right:6px}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-\\[2px\\]{padding-top:2px;padding-bottom:2px}.py-\\[3px\\]{padding-top:3px;padding-bottom:3px}.py-\\[4px\\]{padding-top:4px;padding-bottom:4px}.py-\\[5px\\]{padding-top:5px;padding-bottom:5px}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.pl-\\[10px\\]{padding-left:10px}.pl-\\[56px\\]{padding-left:56px}.pl-1{padding-left:.25rem}.pr-\\[14px\\]{padding-right:14px}.pr-3{padding-right:.75rem}.text-center{text-align:center}.text-right{text-align:right}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-\\[12px\\]{font-size:12px}.text-\\[20px\\]{font-size:20px}.text-\\[9px\\]{font-size:9px}.text-\\[\\#0ea57a\\]{--un-text-opacity:1;color:rgb(14 165 122 / var(--un-text-opacity))}.text-\\[\\#4ade80\\]{--un-text-opacity:1;color:rgb(74 222 128 / var(--un-text-opacity))}.text-\\[\\#7c6dd6\\]{--un-text-opacity:1;color:rgb(124 109 214 / var(--un-text-opacity))}.text-\\[\\#9b90e6\\],.text-accent{--un-text-opacity:1;color:rgb(155 144 230 / var(--un-text-opacity))}.text-\\[\\#d97706\\],.text-warn{--un-text-opacity:1;color:rgb(217 119 6 / var(--un-text-opacity))}.text-\\[\\#dc2626\\]{--un-text-opacity:1;color:rgb(220 38 38 / var(--un-text-opacity))}.text-muted{--un-text-opacity:1;color:rgb(199 195 230 / var(--un-text-opacity))}.text-subtle{--un-text-opacity:1;color:rgb(111 106 143 / var(--un-text-opacity))}.text-text,.hover\\:text-text:hover{--un-text-opacity:1;color:rgb(244 242 255 / var(--un-text-opacity))}.color-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity))}.hover\\:color-muted:hover{--un-text-opacity:1;color:rgb(199 195 230 / var(--un-text-opacity))}.font-bold{font-weight:700}.font-semibold{font-weight:600}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-\\[0\\.07em\\]{letter-spacing:.07em}.tracking-\\[0\\.12em\\]{letter-spacing:.12em}.tracking-widest{letter-spacing:.1em}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}.uppercase{text-transform:uppercase}.tabular-nums{--un-numeric-spacing:tabular-nums;font-variant-numeric:var(--un-ordinal) var(--un-slashed-zero) var(--un-numeric-figure) var(--un-numeric-spacing) var(--un-numeric-fraction)}.shadow{--un-shadow:var(--un-shadow-inset) 0 1px 3px 0 var(--un-shadow-color, rgb(0 0 0 / .1)),var(--un-shadow-inset) 0 1px 2px -1px var(--un-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.shadow-\\[0_8px_32px_rgba\\(0\\,0\\,0\\,0\\.7\\)\\]{--un-shadow:0 8px 32px var(--un-shadow-color, rgba(0, 0, 0, .7));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.shadow-lg{--un-shadow:var(--un-shadow-inset) 0 10px 15px -3px var(--un-shadow-color, rgb(0 0 0 / .1)),var(--un-shadow-inset) 0 4px 6px -4px var(--un-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.hover\\:shadow-\\[0_8px_32px_rgba\\(56\\,189\\,248\\,0\\.1\\)\\]:hover{--un-shadow:0 8px 32px var(--un-shadow-color, rgba(56, 189, 248, .1));box-shadow:var(--un-ring-offset-shadow),var(--un-ring-shadow),var(--un-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--un-blur) var(--un-brightness) var(--un-contrast) var(--un-drop-shadow) var(--un-grayscale) var(--un-hue-rotate) var(--un-invert) var(--un-saturate) var(--un-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}';
|
|
7
7
|
class Un {
|
|
8
8
|
constructor() {
|
|
9
9
|
this.handlers = /* @__PURE__ */ new Map();
|
|
@@ -12,9 +12,19 @@ class Un {
|
|
|
12
12
|
return this.handlers.has(t) || this.handlers.set(t, /* @__PURE__ */ new Set()), this.handlers.get(t).add(r), () => this.handlers.get(t)?.delete(r);
|
|
13
13
|
}
|
|
14
14
|
emit(t, r) {
|
|
15
|
-
this.handlers.get(t)
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const n = this.handlers.get(t);
|
|
16
|
+
if (!n) return;
|
|
17
|
+
const o = [];
|
|
18
|
+
for (const i of n)
|
|
19
|
+
try {
|
|
20
|
+
i(r);
|
|
21
|
+
} catch (s) {
|
|
22
|
+
o.push(s);
|
|
23
|
+
}
|
|
24
|
+
if (o.length === 1)
|
|
25
|
+
throw o[0];
|
|
26
|
+
if (o.length > 1)
|
|
27
|
+
throw new AggregateError(o, "Multiple event handler errors");
|
|
18
28
|
}
|
|
19
29
|
}
|
|
20
30
|
const Gn = 200;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisjs/devtools",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@unocss/reset": "^66.6.2",
|
|
15
|
-
"@praxisjs/core": "1.
|
|
16
|
-
"@praxisjs/decorators": "0.
|
|
17
|
-
"@praxisjs/jsx": "0.3.
|
|
18
|
-
"@praxisjs/runtime": "0.2.
|
|
15
|
+
"@praxisjs/core": "1.1.0",
|
|
16
|
+
"@praxisjs/decorators": "0.6.0",
|
|
17
|
+
"@praxisjs/jsx": "0.3.5",
|
|
18
|
+
"@praxisjs/runtime": "0.2.6",
|
|
19
19
|
"@praxisjs/shared": "0.2.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
@@ -241,6 +241,62 @@ describe("Debug — field decorator with computed value", () => {
|
|
|
241
241
|
});
|
|
242
242
|
});
|
|
243
243
|
|
|
244
|
+
// ── Async method decorator ────────────────────────────────────────────────────
|
|
245
|
+
|
|
246
|
+
describe("Debug — async method decorator", () => {
|
|
247
|
+
it("timing is recorded for the synchronous wrapper (documents limitation: async duration is not measured)", () => {
|
|
248
|
+
// @Debug wraps methods synchronously. For async methods, the recorded duration
|
|
249
|
+
// covers only until the Promise is returned, not until it resolves.
|
|
250
|
+
const ctx = mockMethodCtx("fetchData");
|
|
251
|
+
const original = vi.fn(async () => {
|
|
252
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
253
|
+
return "done";
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
Debug()(original as never, ctx);
|
|
257
|
+
|
|
258
|
+
class Comp { async fetchData() { return "done"; } }
|
|
259
|
+
const instance = new Comp();
|
|
260
|
+
ctx.runInitializers(instance);
|
|
261
|
+
Registry.instance.registerComponent(instance, "Comp");
|
|
262
|
+
|
|
263
|
+
// Call and await
|
|
264
|
+
const promise = (instance as unknown as Record<string, () => unknown>).fetchData() as Promise<unknown>;
|
|
265
|
+
expect(promise).toBeInstanceOf(Promise);
|
|
266
|
+
|
|
267
|
+
// Timeline entry is recorded synchronously (before the promise resolves)
|
|
268
|
+
const entry = Registry.instance.getTimeline().find((t) => t.type === "method:call");
|
|
269
|
+
expect(entry).toBeDefined();
|
|
270
|
+
expect(entry?.label).toContain("fetchData");
|
|
271
|
+
// Duration is near-zero since it only measured until Promise was returned
|
|
272
|
+
expect(typeof entry?.data.duration).toBe("number");
|
|
273
|
+
|
|
274
|
+
return promise;
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// ── Empty constructor name ─────────────────────────────────────────────────────
|
|
279
|
+
|
|
280
|
+
describe("Debug — class with empty constructor name", () => {
|
|
281
|
+
it("falls back gracefully when constructor.name is empty string", () => {
|
|
282
|
+
const ctx = mockMethodCtx("doWork");
|
|
283
|
+
const original = vi.fn(() => 42);
|
|
284
|
+
|
|
285
|
+
Debug()(original as never, ctx);
|
|
286
|
+
|
|
287
|
+
// Simulate a class whose constructor.name is empty (e.g. minified code)
|
|
288
|
+
const instance = Object.create({ constructor: { name: "" } }) as object;
|
|
289
|
+
ctx.runInitializers(instance);
|
|
290
|
+
|
|
291
|
+
expect(() => {
|
|
292
|
+
(instance as Record<string, () => void>).doWork();
|
|
293
|
+
}).not.toThrow();
|
|
294
|
+
|
|
295
|
+
const entry = Registry.instance.getTimeline().find((t) => t.type === "method:call");
|
|
296
|
+
expect(entry).toBeDefined();
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
|
|
244
300
|
// ── Getter decorator ──────────────────────────────────────────────────────────
|
|
245
301
|
|
|
246
302
|
describe("Debug — getter decorator", () => {
|
|
@@ -73,4 +73,51 @@ describe("EventBus", () => {
|
|
|
73
73
|
bus2.emit("event", "data");
|
|
74
74
|
expect(handler).not.toHaveBeenCalled();
|
|
75
75
|
});
|
|
76
|
+
|
|
77
|
+
it("handler that throws does not prevent subsequent handlers from being called", () => {
|
|
78
|
+
const bus = new EventBus();
|
|
79
|
+
const h1 = vi.fn().mockImplementation(() => { throw new Error("h1 failed"); });
|
|
80
|
+
const h2 = vi.fn();
|
|
81
|
+
const h3 = vi.fn();
|
|
82
|
+
bus.on("event", h1);
|
|
83
|
+
bus.on("event", h2);
|
|
84
|
+
bus.on("event", h3);
|
|
85
|
+
expect(() => bus.emit("event", "payload")).toThrow();
|
|
86
|
+
expect(h2).toHaveBeenCalledWith("payload");
|
|
87
|
+
expect(h3).toHaveBeenCalledWith("payload");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("handlers are called in registration order", () => {
|
|
91
|
+
const bus = new EventBus();
|
|
92
|
+
const order: number[] = [];
|
|
93
|
+
bus.on("event", () => { order.push(1); });
|
|
94
|
+
bus.on("event", () => { order.push(2); });
|
|
95
|
+
bus.on("event", () => { order.push(3); });
|
|
96
|
+
bus.emit("event", null);
|
|
97
|
+
expect(order).toEqual([1, 2, 3]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("error from a throwing handler is re-thrown after all handlers run", () => {
|
|
101
|
+
const bus = new EventBus();
|
|
102
|
+
const err = new Error("boom");
|
|
103
|
+
bus.on("event", () => { throw err; });
|
|
104
|
+
const h2 = vi.fn();
|
|
105
|
+
bus.on("event", h2);
|
|
106
|
+
expect(() => bus.emit("event", "x")).toThrow(err);
|
|
107
|
+
expect(h2).toHaveBeenCalledOnce();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("throws AggregateError when multiple handlers throw", () => {
|
|
111
|
+
const bus = new EventBus();
|
|
112
|
+
bus.on("event", () => { throw new Error("first"); });
|
|
113
|
+
bus.on("event", () => { throw new Error("second"); });
|
|
114
|
+
let caught: unknown;
|
|
115
|
+
try {
|
|
116
|
+
bus.emit("event", null);
|
|
117
|
+
} catch (e) {
|
|
118
|
+
caught = e;
|
|
119
|
+
}
|
|
120
|
+
expect(caught).toBeInstanceOf(AggregateError);
|
|
121
|
+
expect((caught as AggregateError).errors).toHaveLength(2);
|
|
122
|
+
});
|
|
76
123
|
});
|
|
@@ -329,3 +329,58 @@ describe("Registry timeline cap", () => {
|
|
|
329
329
|
expect(registry.getTimeline().length).toBe(200);
|
|
330
330
|
});
|
|
331
331
|
});
|
|
332
|
+
|
|
333
|
+
describe("Registry — rapid signal updates", () => {
|
|
334
|
+
it("records all rapid updates within the same millisecond separately", () => {
|
|
335
|
+
const registry = Registry.instance;
|
|
336
|
+
const instance = {};
|
|
337
|
+
registry.registerSignal(instance, "count", 0, "Counter");
|
|
338
|
+
|
|
339
|
+
// Perform multiple rapid updates (may share the same Date.now() value)
|
|
340
|
+
registry.updateSignal(instance, "count", 1, 0);
|
|
341
|
+
registry.updateSignal(instance, "count", 2, 1);
|
|
342
|
+
registry.updateSignal(instance, "count", 3, 2);
|
|
343
|
+
|
|
344
|
+
const signal = registry.getSignals()[0];
|
|
345
|
+
// initial + 3 updates = 4 history entries
|
|
346
|
+
expect(signal.history).toHaveLength(4);
|
|
347
|
+
expect(signal.history.map((h) => h.value)).toEqual([0, 1, 2, 3]);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
describe("Registry — re-registering same signal", () => {
|
|
352
|
+
it("overwrites the previous entry when the same instance+key is re-registered", () => {
|
|
353
|
+
const registry = Registry.instance;
|
|
354
|
+
const instance = {};
|
|
355
|
+
registry.registerSignal(instance, "x", 10, "Comp");
|
|
356
|
+
registry.registerSignal(instance, "x", 99, "Comp");
|
|
357
|
+
|
|
358
|
+
const signals = registry.getSignals();
|
|
359
|
+
expect(signals).toHaveLength(1);
|
|
360
|
+
expect(signals[0].value).toBe(99);
|
|
361
|
+
expect(signals[0].history).toHaveLength(1);
|
|
362
|
+
expect(signals[0].history[0].value).toBe(99);
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
describe("Registry timeline cap — oldest entry removed", () => {
|
|
367
|
+
it("removes the oldest entry when the 201st entry is pushed", () => {
|
|
368
|
+
const registry = Registry.instance;
|
|
369
|
+
const instance = {};
|
|
370
|
+
registry.registerComponent(instance, "Comp");
|
|
371
|
+
registry.registerSignal(instance, "n", 0, "Comp");
|
|
372
|
+
|
|
373
|
+
// Push exactly 200 entries
|
|
374
|
+
for (let i = 1; i <= 200; i++) {
|
|
375
|
+
registry.updateSignal(instance, "n", i, i - 1);
|
|
376
|
+
}
|
|
377
|
+
const firstId = registry.getTimeline()[0].id;
|
|
378
|
+
|
|
379
|
+
// Push one more — the oldest should be evicted
|
|
380
|
+
registry.updateSignal(instance, "n", 201, 200);
|
|
381
|
+
|
|
382
|
+
const timeline = registry.getTimeline();
|
|
383
|
+
expect(timeline).toHaveLength(200);
|
|
384
|
+
expect(timeline[0].id).not.toBe(firstId);
|
|
385
|
+
});
|
|
386
|
+
});
|
|
@@ -110,6 +110,57 @@ describe("Trace — onBeforeMount()", () => {
|
|
|
110
110
|
});
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
+
describe("Trace — class with no render() method", () => {
|
|
114
|
+
it("does not crash and no duration is recorded when render is absent", () => {
|
|
115
|
+
class NoRender {
|
|
116
|
+
onBeforeMount() {}
|
|
117
|
+
}
|
|
118
|
+
const Traced = applyTrace(NoRender);
|
|
119
|
+
const instance = new Traced() as unknown as Record<string, () => void>;
|
|
120
|
+
|
|
121
|
+
const registry = Registry.instance;
|
|
122
|
+
instance.onBeforeMount();
|
|
123
|
+
|
|
124
|
+
// render does not exist — calling it should not be attempted
|
|
125
|
+
expect(instance.render).toBeUndefined();
|
|
126
|
+
|
|
127
|
+
// No component:render timeline entries should exist
|
|
128
|
+
const renderEntries = registry.getTimeline().filter((e) => e.type === "component:render");
|
|
129
|
+
expect(renderEntries).toHaveLength(0);
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
describe("Trace — lifecycle hook call order", () => {
|
|
134
|
+
it("calls onBeforeMount → render → (async) onMount in correct order", async () => {
|
|
135
|
+
const order: string[] = [];
|
|
136
|
+
|
|
137
|
+
class App {
|
|
138
|
+
onBeforeMount() { order.push("onBeforeMount"); }
|
|
139
|
+
render() { order.push("render"); return "html"; }
|
|
140
|
+
onMount() { order.push("onMount"); }
|
|
141
|
+
}
|
|
142
|
+
const Traced = applyTrace(App);
|
|
143
|
+
const instance = new Traced() as {
|
|
144
|
+
onBeforeMount: () => void;
|
|
145
|
+
render: () => string;
|
|
146
|
+
onMount: () => void;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
const registry = Registry.instance;
|
|
150
|
+
|
|
151
|
+
// Simulate the component lifecycle
|
|
152
|
+
instance.onBeforeMount();
|
|
153
|
+
instance.render();
|
|
154
|
+
|
|
155
|
+
// onMount is called async (via the framework's create() hook), simulate it
|
|
156
|
+
registry.registerComponent(instance, "App");
|
|
157
|
+
instance.onMount();
|
|
158
|
+
|
|
159
|
+
// The original methods (including Trace wrappers) run in call order
|
|
160
|
+
expect(order).toEqual(["onBeforeMount", "render", "onMount"]);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
113
164
|
describe("Trace — lifecycle hooks", () => {
|
|
114
165
|
const hooks = ["onMount", "onUnmount", "onBeforeUpdate", "onUpdate", "onAfterUpdate"] as const;
|
|
115
166
|
|
package/src/core/event-bus.ts
CHANGED
|
@@ -12,8 +12,22 @@ export class EventBus {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
emit(event: string, payload: unknown): void {
|
|
15
|
-
this.handlers.get(event)
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const handlers = this.handlers.get(event);
|
|
16
|
+
if (!handlers) return;
|
|
17
|
+
|
|
18
|
+
const errors: unknown[] = [];
|
|
19
|
+
for (const h of handlers) {
|
|
20
|
+
try {
|
|
21
|
+
h(payload);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
errors.push(err);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (errors.length === 1) {
|
|
28
|
+
throw errors[0];
|
|
29
|
+
} else if (errors.length > 1) {
|
|
30
|
+
throw new AggregateError(errors, "Multiple event handler errors");
|
|
31
|
+
}
|
|
18
32
|
}
|
|
19
33
|
}
|