@pyreon/core 0.24.4 → 0.24.6

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.
Files changed (56) hide show
  1. package/lib/analysis/index.js.html +1 -1
  2. package/lib/index.js +53 -31
  3. package/package.json +2 -6
  4. package/src/compat-marker.ts +0 -79
  5. package/src/compat-shared.ts +0 -80
  6. package/src/component.ts +0 -98
  7. package/src/context.ts +0 -349
  8. package/src/defer.ts +0 -279
  9. package/src/dynamic.ts +0 -32
  10. package/src/env.d.ts +0 -6
  11. package/src/error-boundary.ts +0 -90
  12. package/src/for.ts +0 -51
  13. package/src/h.ts +0 -80
  14. package/src/index.ts +0 -80
  15. package/src/jsx-dev-runtime.ts +0 -2
  16. package/src/jsx-runtime.ts +0 -747
  17. package/src/lazy.ts +0 -25
  18. package/src/lifecycle.ts +0 -152
  19. package/src/manifest.ts +0 -579
  20. package/src/map-array.ts +0 -42
  21. package/src/portal.ts +0 -39
  22. package/src/props.ts +0 -269
  23. package/src/ref.ts +0 -32
  24. package/src/show.ts +0 -121
  25. package/src/style.ts +0 -102
  26. package/src/suspense.ts +0 -52
  27. package/src/telemetry.ts +0 -120
  28. package/src/tests/compat-marker.test.ts +0 -96
  29. package/src/tests/compat-shared.test.ts +0 -99
  30. package/src/tests/component.test.ts +0 -281
  31. package/src/tests/context.test.ts +0 -629
  32. package/src/tests/core.test.ts +0 -1290
  33. package/src/tests/cx.test.ts +0 -70
  34. package/src/tests/defer.test.ts +0 -359
  35. package/src/tests/dynamic.test.ts +0 -87
  36. package/src/tests/error-boundary.test.ts +0 -181
  37. package/src/tests/extract-props-overloads.types.test.ts +0 -135
  38. package/src/tests/for.test.ts +0 -117
  39. package/src/tests/h.test.ts +0 -221
  40. package/src/tests/jsx-compat.test.tsx +0 -86
  41. package/src/tests/lazy.test.ts +0 -100
  42. package/src/tests/lifecycle.test.ts +0 -350
  43. package/src/tests/manifest-snapshot.test.ts +0 -100
  44. package/src/tests/map-array.test.ts +0 -313
  45. package/src/tests/native-marker-error-boundary.test.ts +0 -12
  46. package/src/tests/portal.test.ts +0 -48
  47. package/src/tests/props-extended.test.ts +0 -157
  48. package/src/tests/props.test.ts +0 -250
  49. package/src/tests/reactive-context.test.ts +0 -69
  50. package/src/tests/reactive-props.test.ts +0 -157
  51. package/src/tests/ref.test.ts +0 -70
  52. package/src/tests/show.test.ts +0 -314
  53. package/src/tests/style.test.ts +0 -157
  54. package/src/tests/suspense.test.ts +0 -139
  55. package/src/tests/telemetry.test.ts +0 -297
  56. package/src/types.ts +0 -116
@@ -1,90 +0,0 @@
1
- import { signal } from '@pyreon/reactivity'
2
- import { nativeCompat } from './compat-marker'
3
- import { popErrorBoundary, pushErrorBoundary } from './component'
4
- import { onUnmount } from './lifecycle'
5
- import { reportError } from './telemetry'
6
- import type { VNodeChild, VNodeChildAtom } from './types'
7
-
8
- // Dev-mode gate: see `pyreon/no-process-dev-gate` lint rule for why this
9
- // uses `import.meta.env.DEV` instead of `typeof process !== 'undefined'`.
10
- const __DEV__ = process.env.NODE_ENV !== 'production'
11
-
12
- /**
13
- * ErrorBoundary — catches errors thrown by child components and renders a
14
- * fallback UI instead of crashing the whole tree.
15
- *
16
- * Also reports caught errors to any registered telemetry handlers.
17
- *
18
- * How error propagation works:
19
- * ErrorBoundary pushes a handler onto the module-level boundary stack
20
- * synchronously during its own setup (before children are mounted).
21
- * When mountComponent catches a child error, it calls dispatchToErrorBoundary()
22
- * which invokes the innermost boundary's handler.
23
- *
24
- * Usage:
25
- * h(ErrorBoundary, {
26
- * fallback: (err) => h("p", null, `Error: ${err}`),
27
- * children: h(MyComponent, null),
28
- * })
29
- *
30
- * // or with JSX:
31
- * <ErrorBoundary fallback={(err) => <p>Error: {String(err)}</p>}>
32
- * <MyComponent />
33
- * </ErrorBoundary>
34
- */
35
- export function ErrorBoundary(props: {
36
- /**
37
- * Rendered when a child throws. Receives the caught error and a `reset`
38
- * function — calling `reset()` clears the error and re-renders children.
39
- */
40
- fallback: (err: unknown, reset: () => void) => VNodeChild
41
- children?: VNodeChild
42
- }): VNodeChild {
43
- if (__DEV__ && typeof props.fallback !== 'function') {
44
- // oxlint-disable-next-line no-console
45
- console.warn(
46
- '[Pyreon] <ErrorBoundary> expects `fallback` to be a function: (err, reset) => VNode. ' +
47
- `Received ${typeof props.fallback}.`,
48
- )
49
- }
50
-
51
- const error = signal<unknown>(null)
52
- const reset = () => error.set(null)
53
-
54
- const handler = (err: unknown): boolean => {
55
- if (error.peek() !== null) return false // already in error state — let outer boundary catch it
56
- // Synchronous signal write. The handler fires from inside mountComponent's
57
- // catch, which is itself inside the boundary's own mountReactive effect
58
- // run (the run that mounted the throwing child). The batch system's
59
- // two-tier flush handles this correctly: this `error.set(err)` enqueues
60
- // the boundary's run into the effects queue's nextPass (since the run is
61
- // currently being visited), and the next pass fires it to swap to the
62
- // fallback subtree. See packages/core/reactivity/src/batch.ts for the
63
- // multi-pass effect drain contract.
64
- error.set(err)
65
- reportError({ component: 'ErrorBoundary', phase: 'render', error: err, timestamp: Date.now() })
66
- return true
67
- }
68
-
69
- // Push synchronously — before children are mounted — so child errors see this boundary
70
- pushErrorBoundary(handler)
71
- // Identity-based pop: pass our own handler reference. Sibling boundaries
72
- // can unmount in any order driven by the renderer (keyed `<For>` removal
73
- // of a non-last item, `<Show>` flipping on the FIRST of N siblings, route
74
- // nav, etc.) — without passing the handler reference, the position-based
75
- // `pop()` would remove the WRONG boundary's handler. Same bug class as
76
- // #725 (`popContext()` orphaning provider frames under reactive remount).
77
- onUnmount(() => popErrorBoundary(handler))
78
-
79
- return (): VNodeChildAtom => {
80
- const err = error()
81
- if (err != null) return props.fallback(err, reset) as VNodeChildAtom
82
- const ch = props.children
83
- return (typeof ch === 'function' ? ch() : ch) as VNodeChildAtom
84
- }
85
- }
86
-
87
- // Mark as native so compat-mode jsx() runtimes (react/preact/vue/solid-compat)
88
- // skip wrapCompatComponent — ErrorBoundary uses pushErrorBoundary/onUnmount,
89
- // which need Pyreon's setup frame (compat wrapping breaks dispatchToErrorBoundary).
90
- nativeCompat(ErrorBoundary)
package/src/for.ts DELETED
@@ -1,51 +0,0 @@
1
- import type { NativeItem, Props, VNode } from './types'
2
-
3
- /**
4
- * Symbol used as the VNode type for a For list — runtime-dom handles it
5
- * via mountFor, bypassing the generic VNode reconciler.
6
- */
7
- export const ForSymbol: unique symbol = Symbol('pyreon.For')
8
-
9
- export interface ForProps<T> {
10
- /**
11
- * The list to iterate. Accepts EITHER a function returning the array
12
- * (preferred — keeps reactivity intact when the array comes from a
13
- * signal accessor) OR the array directly (convenient for static lists
14
- * or already-resolved arrays). The runtime in `runtime-dom/src/mount.ts`
15
- * normalizes both shapes; this type matches the runtime so users aren't
16
- * forced to write `each={() => items}` for a plain array.
17
- *
18
- * @example
19
- * <For each={items}>{r => <li>{r.label}</li>}</For> // static
20
- * <For each={() => store.items()}>{r => <li>...</li>}</For> // reactive
21
- */
22
- each: T[] | (() => T[])
23
- /** Keying function — use `by` not `key` (JSX extracts `key` for VNode reconciliation). */
24
- by: (item: T) => string | number
25
- children: (item: T) => VNode | NativeItem
26
- /**
27
- * @deprecated Use `by` instead of `key`. In Pyreon, `<For>` uses `by` for keying.
28
- * JSX reserves `key` for VNode reconciliation — it won't reach the component.
29
- */
30
- key?: never
31
- }
32
-
33
- /**
34
- * Efficient reactive list rendering.
35
- *
36
- * Unlike a plain `() => items().map(item => h(...))`, For never re-creates
37
- * VNodes for existing keys — only new keys invoke `children()`. Structural
38
- * mutations (swap, sort, filter) are O(n) key scan + O(k) DOM moves where k
39
- * is the number of actually displaced entries.
40
- *
41
- * Usage:
42
- * <For each={items} by={r => r.id}>{r => <li>...</li>}</For>
43
- */
44
- export function For<T>(props: ForProps<T>): VNode {
45
- return {
46
- type: ForSymbol as unknown as string,
47
- props: props as unknown as Props,
48
- children: [],
49
- key: null,
50
- }
51
- }
package/src/h.ts DELETED
@@ -1,80 +0,0 @@
1
- import type { ComponentFn, Props, VNode, VNodeChild } from './types'
2
-
3
- /**
4
- * Marker for fragment nodes — renders children without a wrapper element.
5
- *
6
- * MUST use `Symbol.for(...)` (global registry, keyed by string), NOT
7
- * `Symbol(...)` (fresh per evaluation). `h.ts` is inlined into BOTH the
8
- * main `lib/index.js` and the `lib/jsx-runtime.js` published bundles —
9
- * each bundle's evaluation of a bare `Symbol(...)` would produce a
10
- * DISTINCT Symbol identity. JSX `<>` compiles to `jsx(Fragment, ...)` and
11
- * resolves to jsx-runtime's identity; `runtime-server` checks
12
- * `vnode.type === Fragment` against the main-entry identity. Mismatch
13
- * fell through to `renderElement` and crashed SSG with
14
- * `TypeError: Cannot convert a Symbol value to a string`.
15
- * `Symbol.for()` keys by string in a global registry shared across all
16
- * bundle evaluations — same identity everywhere.
17
- */
18
- export const Fragment: symbol = Symbol.for('Pyreon.Fragment')
19
-
20
- /**
21
- * Hyperscript function — the compiled output of JSX.
22
- * `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
23
- *
24
- * Generic on P so TypeScript validates props match the component's signature
25
- * at the call site, then stores the result in the loosely-typed VNode.
26
- */
27
- /** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */
28
- export const EMPTY_PROPS: Props = {} as Props
29
-
30
- /** Makes `children` optional in P (if present) so it can be passed as rest args to h(). */
31
- type PropsWithOptionalChildren<P extends Props> = Omit<P, 'children'> &
32
- ('children' extends keyof P ? { children?: P['children'] } : unknown)
33
-
34
- // Overload: component with typed props — children is optional in the props object
35
- // because it can be passed as rest args. Extra keys are allowed via `& Props`.
36
- export function h<P extends Props>(
37
- type: ComponentFn<P>,
38
- props: (PropsWithOptionalChildren<P> & Props) | null,
39
- ...children: VNodeChild[]
40
- ): VNode
41
- // Overload: intrinsic element, symbol, generic/dynamic component, or mixed union
42
- export function h(
43
- type: string | ((p: any) => VNodeChild) | symbol,
44
- props: Props | null,
45
- ...children: VNodeChild[]
46
- ): VNode
47
- export function h<P extends Props>(
48
- type: string | ComponentFn<P> | symbol,
49
- props: P | null,
50
- ...children: VNodeChild[]
51
- ): VNode {
52
- return {
53
- type: type as string | ComponentFn | symbol,
54
- props: (props ?? EMPTY_PROPS) as Props,
55
- children: normalizeChildren(children),
56
- key: (props?.key as string | number | null) ?? null,
57
- }
58
- }
59
-
60
- function normalizeChildren(children: VNodeChild[]): VNodeChild[] {
61
- // Fast path: no nested arrays — return as-is without allocating
62
- for (let i = 0; i < children.length; i++) {
63
- if (Array.isArray(children[i])) {
64
- return flattenChildren(children)
65
- }
66
- }
67
- return children
68
- }
69
-
70
- function flattenChildren(children: VNodeChild[]): VNodeChild[] {
71
- const result: VNodeChild[] = []
72
- for (const child of children) {
73
- if (Array.isArray(child)) {
74
- result.push(...flattenChildren(child as VNodeChild[]))
75
- } else {
76
- result.push(child)
77
- }
78
- }
79
- return result
80
- }
package/src/index.ts DELETED
@@ -1,80 +0,0 @@
1
- // @pyreon/core — component model, VNode types, lifecycle hooks
2
-
3
- export { defineComponent, dispatchToErrorBoundary, propagateError, runWithHooks } from './component'
4
- export { isNativeCompat, NATIVE_COMPAT_MARKER, nativeCompat } from './compat-marker'
5
- export { mapCompatDomProps, shallowEqualProps } from './compat-shared'
6
- export type { Context, ContextSnapshot, ReactiveContext } from './context'
7
- export {
8
- captureContextStack,
9
- createContext,
10
- createReactiveContext,
11
- getContextStackLength,
12
- popContext,
13
- provide,
14
- pushContext,
15
- removeContextFrame,
16
- restoreContextStack,
17
- setContextStackProvider,
18
- useContext,
19
- withContext,
20
- } from './context'
21
- export type { DynamicProps } from './dynamic'
22
- export { Dynamic } from './dynamic'
23
- export { ErrorBoundary } from './error-boundary'
24
- export type { ForProps } from './for'
25
- export { For, ForSymbol } from './for'
26
- export { EMPTY_PROPS, Fragment, h } from './h'
27
- export type {
28
- AnchorAttributes,
29
- ButtonAttributes,
30
- CSSProperties,
31
- FormAttributes,
32
- ImgAttributes,
33
- InputAttributes,
34
- PyreonHTMLAttributes,
35
- SelectAttributes,
36
- StyleValue,
37
- SvgAttributes,
38
- TargetedEvent,
39
- TextareaAttributes,
40
- } from './jsx-runtime'
41
- export type { DeferProps } from './defer'
42
- export { Defer } from './defer'
43
- export { lazy } from './lazy'
44
- export { onErrorCaptured, onMount, onUnmount, onUpdate } from './lifecycle'
45
- export { mapArray } from './map-array'
46
- export type { PortalProps } from './portal'
47
- export { Portal, PortalSymbol } from './portal'
48
- export {
49
- _rp,
50
- _wrapSpread,
51
- createUniqueId,
52
- makeReactiveProps,
53
- mergeProps,
54
- REACTIVE_PROP,
55
- splitProps,
56
- } from './props'
57
- export type { Ref, RefCallback, RefProp } from './ref'
58
- export { createRef } from './ref'
59
- export type { MatchProps, ShowProps, SwitchProps } from './show'
60
- export { Match, MatchSymbol, Show, Switch } from './show'
61
- export type { ClassValue } from './style'
62
- export { CSS_UNITLESS, cx, normalizeStyleValue, toKebabCase } from './style'
63
- export type { LazyComponent } from './suspense'
64
- export { Suspense } from './suspense'
65
- export type { ErrorContext, ErrorHandler, ReactiveTraceEntry } from './telemetry'
66
- export { registerErrorHandler, reportError } from './telemetry'
67
- export type {
68
- CleanupFn,
69
- ComponentFn,
70
- ComponentInstance,
71
- ExtractProps,
72
- HigherOrderComponent,
73
- LifecycleHooks,
74
- NativeItem,
75
- Props,
76
- VNode,
77
- VNodeChild,
78
- VNodeChildAccessor,
79
- VNodeChildAtom,
80
- } from './types'
@@ -1,2 +0,0 @@
1
- // Dev runtime — same as production but bundlers may inject extra debug info
2
- export { Fragment, jsx as jsxDEV, jsxs } from './jsx-runtime'