@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.
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +53 -31
- package/package.json +2 -6
- package/src/compat-marker.ts +0 -79
- package/src/compat-shared.ts +0 -80
- package/src/component.ts +0 -98
- package/src/context.ts +0 -349
- package/src/defer.ts +0 -279
- package/src/dynamic.ts +0 -32
- package/src/env.d.ts +0 -6
- package/src/error-boundary.ts +0 -90
- package/src/for.ts +0 -51
- package/src/h.ts +0 -80
- package/src/index.ts +0 -80
- package/src/jsx-dev-runtime.ts +0 -2
- package/src/jsx-runtime.ts +0 -747
- package/src/lazy.ts +0 -25
- package/src/lifecycle.ts +0 -152
- package/src/manifest.ts +0 -579
- package/src/map-array.ts +0 -42
- package/src/portal.ts +0 -39
- package/src/props.ts +0 -269
- package/src/ref.ts +0 -32
- package/src/show.ts +0 -121
- package/src/style.ts +0 -102
- package/src/suspense.ts +0 -52
- package/src/telemetry.ts +0 -120
- package/src/tests/compat-marker.test.ts +0 -96
- package/src/tests/compat-shared.test.ts +0 -99
- package/src/tests/component.test.ts +0 -281
- package/src/tests/context.test.ts +0 -629
- package/src/tests/core.test.ts +0 -1290
- package/src/tests/cx.test.ts +0 -70
- package/src/tests/defer.test.ts +0 -359
- package/src/tests/dynamic.test.ts +0 -87
- package/src/tests/error-boundary.test.ts +0 -181
- package/src/tests/extract-props-overloads.types.test.ts +0 -135
- package/src/tests/for.test.ts +0 -117
- package/src/tests/h.test.ts +0 -221
- package/src/tests/jsx-compat.test.tsx +0 -86
- package/src/tests/lazy.test.ts +0 -100
- package/src/tests/lifecycle.test.ts +0 -350
- package/src/tests/manifest-snapshot.test.ts +0 -100
- package/src/tests/map-array.test.ts +0 -313
- package/src/tests/native-marker-error-boundary.test.ts +0 -12
- package/src/tests/portal.test.ts +0 -48
- package/src/tests/props-extended.test.ts +0 -157
- package/src/tests/props.test.ts +0 -250
- package/src/tests/reactive-context.test.ts +0 -69
- package/src/tests/reactive-props.test.ts +0 -157
- package/src/tests/ref.test.ts +0 -70
- package/src/tests/show.test.ts +0 -314
- package/src/tests/style.test.ts +0 -157
- package/src/tests/suspense.test.ts +0 -139
- package/src/tests/telemetry.test.ts +0 -297
- package/src/types.ts +0 -116
package/src/error-boundary.ts
DELETED
|
@@ -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'
|
package/src/jsx-dev-runtime.ts
DELETED