@elurjs/core 3.6.1 → 3.7.0-beta.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/lib/async.cjs +1 -1
- package/dist/lib/async.js +1 -1
- package/dist/lib/component.cjs +1 -2
- package/dist/lib/component.js +2 -66
- package/dist/lib/context.cjs +1 -1
- package/dist/lib/context.js +35 -23
- package/dist/lib/devtools.cjs +1 -1
- package/dist/lib/devtools.js +1 -1
- package/dist/lib/elur/async.cjs +1 -1
- package/dist/lib/elur/async.cjs.map +1 -1
- package/dist/lib/elur/async.js +1 -1
- package/dist/lib/elur/component.cjs +1 -2
- package/dist/lib/elur/component.d.cts +1 -17
- package/dist/lib/elur/component.d.ts +1 -17
- package/dist/lib/elur/component.js +2 -66
- package/dist/lib/elur/context.cjs +1 -1
- package/dist/lib/elur/context.cjs.map +1 -1
- package/dist/lib/elur/context.d.cts +5 -0
- package/dist/lib/elur/context.d.ts +5 -0
- package/dist/lib/elur/context.js +35 -23
- package/dist/lib/elur/context.js.map +1 -1
- package/dist/lib/elur/devtools.cjs +1 -1
- package/dist/lib/elur/devtools.cjs.map +1 -1
- package/dist/lib/elur/devtools.js +1 -1
- package/dist/lib/elur/form.cjs +1 -1
- package/dist/lib/elur/form.cjs.map +1 -1
- package/dist/lib/elur/form.js +1 -1
- package/dist/lib/elur/hydrate/index.cjs +1 -2
- package/dist/lib/elur/hydrate/index.d.cts +1 -13
- package/dist/lib/elur/hydrate/index.d.ts +1 -13
- package/dist/lib/elur/hydrate/index.js +2 -410
- package/dist/lib/elur/lifecycle.cjs +1 -1
- package/dist/lib/elur/lifecycle.cjs.map +1 -1
- package/dist/lib/elur/lifecycle.d.cts +27 -0
- package/dist/lib/elur/lifecycle.d.ts +27 -0
- package/dist/lib/elur/lifecycle.js +4 -0
- package/dist/lib/elur/lifecycle.js.map +1 -1
- package/dist/lib/elur/next/component.d.cts +281 -0
- package/dist/lib/elur/next/component.d.ts +281 -0
- package/dist/lib/elur/next/dom-write.d.cts +18 -0
- package/dist/lib/elur/next/dom-write.d.ts +18 -0
- package/dist/lib/elur/next/hydrate.d.cts +14 -0
- package/dist/lib/elur/next/hydrate.d.ts +14 -0
- package/dist/lib/elur/next/keyed-diff.d.cts +46 -0
- package/dist/lib/elur/next/keyed-diff.d.ts +46 -0
- package/dist/lib/elur/next/mount-helpers.d.cts +25 -0
- package/dist/lib/elur/next/mount-helpers.d.ts +25 -0
- package/dist/lib/elur/next/mount.d.cts +29 -0
- package/dist/lib/elur/next/mount.d.ts +29 -0
- package/dist/lib/elur/next/node-binding.d.cts +6 -0
- package/dist/lib/elur/next/node-binding.d.ts +6 -0
- package/dist/lib/elur/next/reactivity.d.cts +193 -0
- package/dist/lib/elur/next/reactivity.d.ts +193 -0
- package/dist/lib/elur/next-2/component.cjs +2 -0
- package/dist/lib/elur/next-2/component.cjs.map +1 -0
- package/dist/lib/elur/next-2/component.d.cts +283 -0
- package/dist/lib/elur/next-2/component.d.ts +283 -0
- package/dist/lib/elur/next-2/component.js +340 -0
- package/dist/lib/elur/next-2/component.js.map +1 -0
- package/dist/lib/elur/next-2/dom-write.cjs +2 -0
- package/dist/lib/elur/next-2/dom-write.cjs.map +1 -0
- package/dist/lib/elur/next-2/dom-write.d.cts +18 -0
- package/dist/lib/elur/next-2/dom-write.d.ts +18 -0
- package/dist/lib/elur/next-2/dom-write.js +31 -0
- package/dist/lib/elur/next-2/dom-write.js.map +1 -0
- package/dist/lib/elur/next-2/hydrate.cjs +2 -0
- package/dist/lib/elur/next-2/hydrate.cjs.map +1 -0
- package/dist/lib/elur/next-2/hydrate.d.cts +30 -0
- package/dist/lib/elur/next-2/hydrate.d.ts +30 -0
- package/dist/lib/elur/next-2/hydrate.js +449 -0
- package/dist/lib/elur/next-2/hydrate.js.map +1 -0
- package/dist/lib/elur/next-2/keyed-diff.cjs +2 -0
- package/dist/lib/elur/next-2/keyed-diff.cjs.map +1 -0
- package/dist/lib/elur/next-2/keyed-diff.d.cts +79 -0
- package/dist/lib/elur/next-2/keyed-diff.d.ts +79 -0
- package/dist/lib/elur/next-2/keyed-diff.js +208 -0
- package/dist/lib/elur/next-2/keyed-diff.js.map +1 -0
- package/dist/lib/elur/next-2/mount-helpers.cjs +2 -0
- package/dist/lib/elur/next-2/mount-helpers.cjs.map +1 -0
- package/dist/lib/elur/next-2/mount-helpers.d.cts +25 -0
- package/dist/lib/elur/next-2/mount-helpers.d.ts +25 -0
- package/dist/lib/elur/next-2/mount-helpers.js +87 -0
- package/dist/lib/elur/next-2/mount-helpers.js.map +1 -0
- package/dist/lib/elur/next-2/mount.cjs +2 -0
- package/dist/lib/elur/next-2/mount.cjs.map +1 -0
- package/dist/lib/elur/next-2/mount.d.cts +29 -0
- package/dist/lib/elur/next-2/mount.d.ts +29 -0
- package/dist/lib/elur/next-2/mount.js +34 -0
- package/dist/lib/elur/next-2/mount.js.map +1 -0
- package/dist/lib/elur/next-2/node-binding.cjs +2 -0
- package/dist/lib/elur/next-2/node-binding.cjs.map +1 -0
- package/dist/lib/elur/next-2/node-binding.d.cts +6 -0
- package/dist/lib/elur/next-2/node-binding.d.ts +6 -0
- package/dist/lib/elur/next-2/node-binding.js +130 -0
- package/dist/lib/elur/next-2/node-binding.js.map +1 -0
- package/dist/lib/elur/next-2/reactivity.cjs +2 -0
- package/dist/lib/elur/next-2/reactivity.cjs.map +1 -0
- package/dist/lib/elur/next-2/reactivity.d.cts +220 -0
- package/dist/lib/elur/next-2/reactivity.d.ts +220 -0
- package/dist/lib/elur/next-2/reactivity.js +614 -0
- package/dist/lib/elur/next-2/reactivity.js.map +1 -0
- package/dist/lib/elur/next-2/scheduler.cjs +2 -0
- package/dist/lib/elur/next-2/scheduler.cjs.map +1 -0
- package/dist/lib/elur/next-2/scheduler.d.cts +23 -0
- package/dist/lib/elur/next-2/scheduler.d.ts +23 -0
- package/dist/lib/elur/next-2/scheduler.js +26 -0
- package/dist/lib/elur/next-2/scheduler.js.map +1 -0
- package/dist/lib/elur/plugins.cjs +1 -1
- package/dist/lib/elur/plugins.cjs.map +1 -1
- package/dist/lib/elur/plugins.js +1 -1
- package/dist/lib/elur/reactivity.cjs +1 -2
- package/dist/lib/elur/reactivity.d.cts +1 -67
- package/dist/lib/elur/reactivity.d.ts +1 -67
- package/dist/lib/elur/reactivity.js +2 -218
- package/dist/lib/elur/router.cjs +2 -2
- package/dist/lib/elur/router.cjs.map +1 -1
- package/dist/lib/elur/router.js +2 -2
- package/dist/lib/elur/router.js.map +1 -1
- package/dist/lib/elur/server/index.cjs +1 -1
- package/dist/lib/elur/server/index.cjs.map +1 -1
- package/dist/lib/elur/server/index.js +180 -108
- package/dist/lib/elur/server/index.js.map +1 -1
- package/dist/lib/elur/store.cjs +1 -1
- package/dist/lib/elur/store.cjs.map +1 -1
- package/dist/lib/elur/store.js +10 -4
- package/dist/lib/elur/store.js.map +1 -1
- package/dist/lib/elur/template/bindings.cjs +1 -1
- package/dist/lib/elur/template/bindings.cjs.map +1 -1
- package/dist/lib/elur/template/bindings.js +98 -84
- package/dist/lib/elur/template/bindings.js.map +1 -1
- package/dist/lib/elur/template/dom-write.d.cts +1 -5
- package/dist/lib/elur/template/dom-write.d.ts +1 -5
- package/dist/lib/elur/template/error-boundary.cjs +1 -1
- package/dist/lib/elur/template/error-boundary.cjs.map +1 -1
- package/dist/lib/elur/template/error-boundary.js +56 -50
- package/dist/lib/elur/template/error-boundary.js.map +1 -1
- package/dist/lib/elur/template/html.cjs +1 -1
- package/dist/lib/elur/template/html.cjs.map +1 -1
- package/dist/lib/elur/template/html.js +40 -37
- package/dist/lib/elur/template/html.js.map +1 -1
- package/dist/lib/elur/template/index.cjs +1 -1
- package/dist/lib/elur/template/index.d.cts +2 -1
- package/dist/lib/elur/template/index.d.ts +2 -1
- package/dist/lib/elur/template/index.js +13 -12
- package/dist/lib/elur/template/keyed-diff.d.cts +1 -32
- package/dist/lib/elur/template/keyed-diff.d.ts +1 -32
- package/dist/lib/elur/template/keyed.cjs +1 -1
- package/dist/lib/elur/template/keyed.cjs.map +1 -1
- package/dist/lib/elur/template/keyed.d.cts +10 -2
- package/dist/lib/elur/template/keyed.d.ts +10 -2
- package/dist/lib/elur/template/keyed.js +12 -1
- package/dist/lib/elur/template/keyed.js.map +1 -1
- package/dist/lib/elur/template/mount-helpers.d.cts +1 -29
- package/dist/lib/elur/template/mount-helpers.d.ts +1 -29
- package/dist/lib/elur/template/node-binding.d.cts +1 -6
- package/dist/lib/elur/template/node-binding.d.ts +1 -6
- package/dist/lib/elur/template/portal.cjs +1 -1
- package/dist/lib/elur/template/portal.cjs.map +1 -1
- package/dist/lib/elur/template/portal.js +1 -1
- package/dist/lib/elur/template/transitions.cjs +1 -1
- package/dist/lib/elur/template/transitions.cjs.map +1 -1
- package/dist/lib/elur/template/transitions.js +2 -2
- package/dist/lib/elur/template/types.cjs +1 -1
- package/dist/lib/elur/template/types.cjs.map +1 -1
- package/dist/lib/elur/template/types.d.cts +55 -0
- package/dist/lib/elur/template/types.d.ts +55 -0
- package/dist/lib/elur/template/types.js +5 -1
- package/dist/lib/elur/template/types.js.map +1 -1
- package/dist/lib/elur.cjs +1 -1
- package/dist/lib/elur.js +2 -2
- package/dist/lib/form.cjs +1 -1
- package/dist/lib/form.js +1 -1
- package/dist/lib/hydrate.cjs +1 -2
- package/dist/lib/hydrate.js +2 -410
- package/dist/lib/index.cjs +1 -1
- package/dist/lib/index.js +2 -2
- package/dist/lib/lifecycle.cjs +1 -1
- package/dist/lib/lifecycle.js +4 -0
- package/dist/lib/plugins.cjs +1 -1
- package/dist/lib/plugins.js +1 -1
- package/dist/lib/router.cjs +2 -2
- package/dist/lib/router.js +2 -2
- package/dist/lib/server.cjs +1 -1
- package/dist/lib/server.js +180 -108
- package/dist/lib/signals.cjs +1 -2
- package/dist/lib/signals.js +2 -218
- package/dist/lib/store.cjs +1 -1
- package/dist/lib/store.js +10 -4
- package/dist/lib/template.cjs +1 -1
- package/dist/lib/template.js +13 -12
- package/package.json +7 -9
- package/dist/lib/elur/component.cjs.map +0 -1
- package/dist/lib/elur/component.js.map +0 -1
- package/dist/lib/elur/hydrate/index.cjs.map +0 -1
- package/dist/lib/elur/hydrate/index.js.map +0 -1
- package/dist/lib/elur/reactivity.cjs.map +0 -1
- package/dist/lib/elur/reactivity.js.map +0 -1
- package/dist/lib/elur/template/dom-write.cjs +0 -2
- package/dist/lib/elur/template/dom-write.cjs.map +0 -1
- package/dist/lib/elur/template/dom-write.js +0 -16
- package/dist/lib/elur/template/dom-write.js.map +0 -1
- package/dist/lib/elur/template/keyed-diff.cjs +0 -2
- package/dist/lib/elur/template/keyed-diff.cjs.map +0 -1
- package/dist/lib/elur/template/keyed-diff.js +0 -100
- package/dist/lib/elur/template/keyed-diff.js.map +0 -1
- package/dist/lib/elur/template/mount-helpers.cjs +0 -2
- package/dist/lib/elur/template/mount-helpers.cjs.map +0 -1
- package/dist/lib/elur/template/mount-helpers.js +0 -132
- package/dist/lib/elur/template/mount-helpers.js.map +0 -1
- package/dist/lib/elur/template/node-binding.cjs +0 -2
- package/dist/lib/elur/template/node-binding.cjs.map +0 -1
- package/dist/lib/elur/template/node-binding.js +0 -95
- package/dist/lib/elur/template/node-binding.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component.cjs","names":[],"sources":["../../../../src/elur/next-2/component.ts"],"sourcesContent":["/**\n * Elur \"next\" — kernel unificado de componentes (experimental).\n *\n * Implementa A.6–A.9 del PLAN_TECNICO_ELUR_NEXT sobre el ownership de\n * `./reactivity.ts`:\n * - Una sola `ComponentInstance` para clases y funciones (adaptadores).\n * - Máquina de estados (A.7): created → initializing → rendering →\n * pending-mount → mounted → disposing → disposed (o failed).\n * - Mount transaccional (A.9): cualquier fallo dispara rollback —\n * cleanups registrados, owner reactivo disposed, DOM insertado removido.\n * - `unmount()` idempotente (A.2.10).\n * - `onMount` corre DESPUÉS del commit DOM (A.2.9).\n * - Todo lo creado en setup/render pertenece al owner de la instancia y\n * muere con unmount (A.2.1 — no más effects huérfanos).\n *\n * Las invocaciones implementan `ELUR_RENDER_PROTOCOL.mountDom`, así el\n * renderer existente las monta sin saber que son componentes.\n */\n\nimport {\n getOwner,\n runWithOwner,\n signal,\n Owner,\n Signal,\n type Disposable,\n type OwnerLike,\n} from \"./reactivity.js\";\nimport {\n isElurComponent,\n _debugComponentMountStart,\n _debugComponentMountEnd,\n _debugComponentUnmount,\n type ElurComponent,\n type ComponentController,\n} from \"../lifecycle.js\";\nimport {\n ELUR_RENDER_PROTOCOL,\n isElurTemplate,\n type DomProtocolContext,\n} from \"../template/types.js\";\nimport {\n _pushComponentContext,\n _popComponentContext,\n _withComponentContext,\n _pushContextScopeResolver,\n} from \"../context.js\";\n\n// --- Máquina de estados (A.7) -------------------------------------------------\n\nexport type ComponentState =\n | \"created\"\n | \"initializing\"\n | \"rendering\"\n | \"pending-mount\"\n | \"mounted\"\n | \"deactivated\"\n | \"disposing\"\n | \"disposed\"\n | \"failed\";\n\n// --- Hooks --------------------------------------------------------------------\n\n// --- A.16: error boundaries ----------------------------------------------------\n\n/** Fase del lifecycle donde ocurrió el error. */\nexport type ErrorPhase =\n | \"setup\"\n | \"init\"\n | \"render\"\n | \"hydrate\"\n | \"mount\"\n | \"effect\"\n | \"activate\"\n | \"deactivate\"\n | \"cleanup\"\n | \"unmount\";\n\n/** Información estructurada del error (A.16). */\nexport interface ComponentErrorInfo {\n phase: ErrorPhase;\n /** Instancia donde ocurrió el error (no la boundary que lo maneja). */\n component: ComponentInstance;\n cause: unknown;\n}\n\n/** Resolución de una boundary (A.16). */\nexport type ErrorResolution =\n | { handled: false }\n | { handled: true; fallback?: Renderable }\n | { handled: true; retry: true };\n\nexport interface ComponentHooks {\n /** Tras el commit DOM. Puede devolver cleanup (corre en unmount). */\n onMount?: () => (() => void) | void;\n /** Antes de remover el DOM. */\n onUnmount?: () => void;\n /**\n * Boundary de errores (A.16): recibe info estructurada; el error burbujea\n * por la cadena de instancias hasta una boundary que devuelva handled.\n * `void` = manejado sin más.\n */\n onError?: (info: ComponentErrorInfo) => ErrorResolution | void;\n /** A.17: tras setup durante SSR — nunca en cliente. */\n onServerRender?: () => void;\n}\n\n/** Contexto que recibe el setup de un componente funcional. */\nexport interface SetupCtx {\n onMount(fn: () => (() => void) | void): void;\n onUnmount(fn: () => void): void;\n onError(fn: (info: ComponentErrorInfo) => ErrorResolution | void): void;\n /** A.17: hook server-side — corre tras setup durante SSR, nunca en cliente. */\n onServerRender(fn: () => void): void;\n /** Owner de la instancia — para runWithOwner/getOwner manual. */\n readonly owner: OwnerLike;\n /** Señal interna de una prop (A.13) — para acceso reactivo explícito. */\n propSignal<K extends string>(key: K): Signal<unknown> | undefined;\n /**\n * A.14: renderiza el contenido de un slot (lazy — corre el render del\n * slot bajo el owner del padre que lo declaró). `\"default\"` por defecto.\n */\n slot(name?: string): unknown;\n /** A.14: slots declarados en la invocación. */\n readonly slots: Record<string, Slot> | undefined;\n}\n\n// --- Renderable ---------------------------------------------------------------\n\ninterface RenderableValue {\n _render(parent: Node, before: Node | null): () => void;\n}\n\nfunction asRenderable(v: unknown): RenderableValue | null {\n if (isElurTemplate(v)) return v as unknown as RenderableValue;\n return null;\n}\n\n// --- A.14: Slots (lazy, marcados) --------------------------------------------------\n\n/** Renderable común: cualquier cosa montable en un binding. */\nexport type Renderable =\n | ElurComponent\n | ComponentInvocation<unknown>\n | Slot\n | { _render(parent: Node, before: Node | null): () => void }\n | string\n | number\n | bigint\n | false\n | null\n | undefined\n | Renderable[];\n\n/**\n * Slot lazy y marcado (A.14): el contenido se renderiza bajo el owner del\n * padre que LO DECLARÓ (contexto léxico), aunque se monte dentro del\n * componente consumidor.\n */\nexport interface Slot {\n readonly __isElurSlot: true;\n /** Owner capturado en el punto de declaración (contexto léxico). */\n readonly owner: OwnerLike | null;\n render(): unknown;\n}\n\nexport function slot(render: () => unknown): Slot {\n return { __isElurSlot: true, owner: getOwner(), render };\n}\n\nexport function isElurSlot(v: unknown): v is Slot {\n return (\n v != null &&\n typeof v === \"object\" &&\n (v as { __isElurSlot?: boolean }).__isElurSlot === true\n );\n}\n\n// --- ComponentInstance ----------------------------------------------------------\n\nlet nextInstanceId = 1;\n\nexport class ComponentInstance implements Disposable {\n readonly id = nextInstanceId++;\n readonly kind: \"class\" | \"function\";\n state: ComponentState = \"created\";\n /** Owner reactivo de la instancia — todo lo creado dentro muere con él. */\n readonly owner = new Owner();\n /** Instancia padre (owner activo cuando se creó esta instancia). */\n parent: ComponentInstance | null = null;\n hooks: ComponentHooks = {};\n renderable: RenderableValue | null = null;\n /** A.12: frame de provide/inject propio de la instancia — permanente. */\n readonly context = new Map<unknown, unknown>();\n\n private _inst: ElurComponent | null = null;\n private _invocation: ComponentInvocation<any> | null = null;\n private _renderCleanup: (() => void) | null = null;\n private _mountCleanups: (() => void)[] | null = null;\n /** A.13: señales internas por prop + objeto live pasado al setup. */\n private _propSignals: Map<string, Signal<unknown>> | null = null;\n private _liveProps: Record<string, unknown> | null = null;\n /** A.16: fase actual del lifecycle — para el ComponentErrorInfo. */\n private _phase: ErrorPhase = \"setup\";\n /** A.16: posición de montaje — para renderizar fallback de boundary. */\n private _mountParent: Node | null = null;\n private _mountBefore: Node | null = null;\n /** A.3.8: nodos DOM de la instancia — para detach/attach. */\n private _domNodes: Node[] | null = null;\n /** A.21: controllers de ciclo de vida (Lit-style). */\n private _controllers: ComponentController[] | null = null;\n\n constructor(source: ElurComponent | ComponentInvocation<any>) {\n if (isElurComponent(source)) {\n this.kind = \"class\";\n this._inst = source;\n } else {\n this.kind = \"function\";\n this._invocation = source;\n }\n // A.16: errores de effects/computeds de la instancia burbujean aquí.\n this.owner.onOwnerError = (err) =>\n reportError(this, { phase: \"effect\", component: this, cause: err })\n .handled;\n }\n\n /**\n * Mount transaccional (A.9). Cualquier fase que falle → rollback completo:\n * owner disposed, cleanups corridos, DOM insertado removido, state=failed.\n *\n * Opciones:\n * - `ctxSnapshot`: contexto capturado en el punto de declaración\n * (mounts dentro de effects dinámicos heredan provide/inject).\n * - `deferOnMount`: recibe una función `fire()` que corre onMount; el\n * caller decide cuándo invocarla (fragments aún no insertados).\n */\n mount(\n parent: Node,\n before: Node | null,\n opts?: {\n ctxSnapshot?: Map<unknown, unknown>[];\n deferOnMount?: (fire: () => void) => void;\n /** Valores a proveer en el frame de contexto de la instancia (A.12). */\n provides?: Iterable<readonly [unknown, unknown]>;\n /**\n * A.14: owner del declarante — para contenido de slots, el owner padre\n * es el del padre que declaró el contenido, no el del punto de montaje.\n */\n declOwner?: OwnerLike | null;\n },\n ): void {\n if (this.state !== \"created\") {\n throw new Error(\n `[elur-next] ComponentInstance.mount(): estado inválido \"${this.state}\" (una instancia montada no puede montarse otra vez).`,\n );\n }\n ownerToInstance.set(this.owner, this);\n ownerToContext.set(this.owner, this.context);\n this._resolveParent();\n // A.12: el owner de la instancia se cuelga del owner activo en el punto\n // de declaración — así la cadena de owners reproduce el árbol de\n // componentes y provide/inject resuelven por instancias.\n this.owner.parent = opts?.declOwner !== undefined ? opts.declOwner : getOwner();\n if (opts?.provides) {\n for (const [k, v] of opts.provides) this.context.set(k, v);\n }\n this._mountParent = parent;\n this._mountBefore = before;\n\n // A.2.4: debug events sólo para funcionales — las clases ya emiten por\n // mount-helpers; emitir aquí duplicaría. El payload es la\n // ComponentInstance (id/kind/state/parent en el árbol).\n const isFunctional = !isElurComponent(this._inst);\n const dbg = this as unknown as ElurComponent;\n if (isFunctional) _debugComponentMountStart(dbg);\n\n // A.3.8: índice donde empieza el DOM de la instancia — para capturar el\n // rango de nodos tras _render y poder detach/attach después.\n const startIndex = before\n ? Array.prototype.indexOf.call(parent.childNodes, before)\n : parent.childNodes.length;\n\n try {\n // --- initializing + rendering + pending-mount, TODO bajo el mismo\n // frame de contexto: los hijos montados durante _render heredan el\n // provide de esta instancia (como en la impl actual).\n this.state = \"initializing\";\n runWithOwner(this.owner, () =>\n this._withScope(opts?.ctxSnapshot, () => {\n this._initBody();\n // A.21: controllers de la clase + programáticos — hostInit dentro\n // del frame para que lo que creen quede poseído por la instancia.\n if (this._inst?._controllers) {\n for (const c of this._inst._controllers) this.addController(c);\n }\n if (this._controllers) {\n for (const c of this._controllers) c.hostInit?.();\n }\n // pending-mount: activar bindings + insertar DOM, aún dentro del\n // frame de contexto para que los hijos hereden provide/inject.\n this._phase = \"mount\";\n this.state = \"pending-mount\";\n this._renderCleanup = this.renderable!._render(parent, before);\n // A.3.8: capturar los nodos insertados entre startIndex y `before`.\n const endIndex = before\n ? Array.prototype.indexOf.call(parent.childNodes, before)\n : parent.childNodes.length;\n this._domNodes = Array.prototype.slice.call(\n parent.childNodes,\n startIndex,\n endIndex,\n ) as Node[];\n }),\n );\n\n // --- commit ---\n this.state = \"mounted\";\n\n // onMount DESPUÉS del commit DOM (A.2.9) — inmediato o diferido por\n // el caller (fragments que aún no están en el documento).\n const fire = () => this._runOnMount();\n if (opts?.deferOnMount) opts.deferOnMount(fire);\n else fire();\n } catch (err) {\n this._rollback();\n const res = reportError(this, {\n phase: this._phase,\n component: this,\n cause: err,\n });\n if (!res.handled) throw err;\n if (\"retry\" in res && res.retry) {\n // Una sola reintento — instancia fresca (el owner viejo está\n // disposed); un segundo fallo se propaga igual.\n new ComponentInstance(this._inst ?? this._invocation!).mount(\n parent,\n before,\n opts,\n );\n } else if (\"fallback\" in res && res.fallback !== undefined) {\n this._renderFallback(res.fallback, parent, before);\n }\n } finally {\n // A.3.3/A.2.4: mountEnd balanceado — se emite haya éxito, rollback,\n // retry o fallback, para que el tooling pueda emparejar start/end.\n if (isFunctional) _debugComponentMountEnd(dbg);\n }\n }\n\n /** A.21: registra un controller — sus hooks corren bajo este owner. */\n addController(c: ComponentController): void {\n (this._controllers ??= []).push(c);\n }\n\n /**\n * A.3.8: saca el DOM de la instancia SIN disponer nada — effects, signals\n * y contexto siguen vivos (página cached, Suspense, transición). No-op si\n * no está montado.\n */\n detach(): void {\n if (this.state !== \"mounted\" || !this._domNodes) return;\n const frag = document.createDocumentFragment();\n for (const n of this._domNodes) frag.appendChild(n);\n this.state = \"deactivated\";\n // A.21: hostDeactivate — signals/effects del controller siguen vivos.\n if (this._controllers) {\n runWithOwner(this.owner, () => {\n for (const c of this._controllers!) c.hostDeactivate?.();\n });\n }\n }\n\n /**\n * A.3.8: reinserta el DOM de una instancia detached en la posición original\n * (o en parent/before dados). No-op si no está deactivated.\n */\n attach(parent?: Node, before?: Node | null): void {\n if (this.state !== \"deactivated\" || !this._domNodes) return;\n const p = parent ?? this._mountParent;\n const b = before !== undefined ? before : this._mountBefore;\n if (!p) return;\n for (const n of this._domNodes) p.insertBefore(n, b);\n this.state = \"mounted\";\n // A.21: hostActivate — la instancia volvió al DOM.\n if (this._controllers) {\n runWithOwner(this.owner, () => {\n for (const c of this._controllers!) c.hostActivate?.();\n });\n }\n }\n\n /** Idempotente (A.2.10): disponer dos veces es seguro. */\n unmount(): void {\n if (this.state === \"created\") return; // nunca montado\n if (this.state === \"disposing\" || this.state === \"disposed\") return;\n if (this.state === \"failed\") {\n this.state = \"disposed\";\n return;\n }\n // A.3.8: unmount de una instancia detached dispone igual — el cleanup\n // del renderable remueve los nodos de su padre actual (el fragment).\n if (this.state === \"deactivated\") this._domNodes = null;\n this.state = \"disposing\";\n // A.2.4: mismo criterio — sólo funcionales (las clases emiten por\n // mount-helpers).\n if (!isElurComponent(this._inst)) {\n _debugComponentUnmount(this as unknown as ElurComponent);\n }\n try {\n // A.12: bajo el owner → inject() resuelve dentro de onUnmount también.\n runWithOwner(this.owner, () => {\n this.hooks.onUnmount?.call(this._inst ?? undefined);\n this._inst?.onUnmount?.();\n // A.21: hostUnmount antes del disposal del owner.\n if (this._controllers) {\n for (const c of this._controllers) c.hostUnmount?.();\n }\n });\n } catch (err) {\n // A.16: errores de unmount no abortan el disposal pero se reportan.\n this._reportSwallowed(err, \"unmount\");\n }\n if (this._mountCleanups) {\n for (const fn of this._mountCleanups) {\n try {\n fn();\n } catch (err) {\n // A.3.4/A.16: cleanup errors continúan el teardown, pero se reportan.\n this._reportSwallowed(err, \"cleanup\");\n }\n }\n this._mountCleanups = null;\n }\n // Owner primero (mata effects/computeds/cleanups de la instancia),\n // luego el cleanup del renderable (remueve DOM + cleanup propio).\n this.owner.dispose();\n try {\n this._renderCleanup?.();\n } finally {\n this._renderCleanup = null;\n this.state = \"disposed\";\n }\n }\n\n dispose(): void {\n this.unmount();\n }\n\n /** @internal — corre onMount una vez; no-op si ya no está montado. */\n _runOnMount(): void {\n if (this.state !== \"mounted\") return;\n try {\n // A.12: bajo el owner → inject() dentro de onMount resuelve por la\n // cadena de instancias (contexto permanente, no sólo durante render).\n const mountRet = runWithOwner(this.owner, () => {\n const r =\n this.kind === \"class\" ? this._inst!.onMount?.() : this.hooks.onMount?.();\n // A.21\n if (this._controllers) {\n for (const c of this._controllers) c.hostMounted?.();\n }\n return r;\n });\n if (typeof mountRet === \"function\") {\n (this._mountCleanups ??= []).push(mountRet);\n }\n } catch (err) {\n // A.16: onMount falla → rollback completo + boundary (+fallback).\n this._rollback();\n const res = reportError(this, {\n phase: \"mount\",\n component: this,\n cause: err,\n });\n if (!res.handled) throw err;\n if (\"fallback\" in res && res.fallback !== undefined) {\n this._renderFallback(res.fallback, this._mountParent!, this._mountBefore);\n }\n }\n }\n\n /**\n * @internal A.16: intenta manejar el error con el boundary propio.\n * `null` = este nodo no tiene boundary — seguir subiendo.\n */\n _handleError(info: ComponentErrorInfo): ErrorResolution | null {\n if (this.kind === \"function\" && this.hooks.onError) {\n const r = this.hooks.onError(info);\n if (r === undefined) return { handled: true };\n return r;\n }\n if (this.kind === \"class\" && this._inst?.onError) {\n this._inst.onError(info.cause);\n return { handled: true };\n }\n return null;\n }\n\n /** A.16: errores de teardown — se reportan a la cadena; si nadie los maneja quedan registrados. */\n private _reportSwallowed(err: unknown, phase: ErrorPhase): void {\n const res = reportError(this, { phase, component: this, cause: err });\n if (!res.handled) console.error(\"[elur-next] error en \" + phase + \":\", err);\n }\n\n /** A.16: renderiza el fallback de una boundary en la posición del componente. */\n private _renderFallback(\n fallback: Renderable,\n parent: Node,\n before: Node | null,\n ): void {\n const r = asRenderable(fallback);\n if (r) r._render(parent, before);\n else if (typeof fallback === \"string\" || typeof fallback === \"number\") {\n parent.insertBefore(document.createTextNode(String(fallback)), before);\n } else if (Array.isArray(fallback)) {\n for (const f of fallback) this._renderFallback(f, parent, before);\n }\n // ComponentInvocation / ElurComponent se montan por el camino normal.\n else if (fallback) {\n new ComponentInstance(fallback as ComponentInvocation<unknown>).mount(\n parent,\n before,\n );\n }\n }\n\n /** Camina la cadena de owners hasta la instancia registrada más cercana. */\n private _resolveParent(): void {\n let o = getOwner();\n while (o) {\n const inst = ownerToInstance.get(o);\n if (inst) {\n this.parent = inst;\n return;\n }\n o = o.parent;\n }\n }\n\n private _rollback(): void {\n // Cancelar hooks pendientes + cleanups + owner + hijos + DOM insertado.\n this.owner.dispose();\n try {\n this._renderCleanup?.();\n } finally {\n this._renderCleanup = null;\n this.state = \"failed\";\n }\n }\n\n private _makeSetupCtx(): SetupCtx {\n const inst = this;\n return {\n owner: this.owner,\n onMount(fn) {\n inst.hooks.onMount = fn;\n },\n onUnmount(fn) {\n inst.hooks.onUnmount = fn;\n },\n onError(fn) {\n inst.hooks.onError = fn;\n },\n onServerRender(fn) {\n inst.hooks.onServerRender = fn;\n },\n propSignal(key) {\n return inst._propSignals?.get(key);\n },\n slots: this._invocation?.slots,\n // Devuelve el Slot marcado — el renderer lo desenvuelve bajo el owner\n // del declarante (contexto léxico, A.14).\n slot(name = \"default\") {\n return inst._invocation?.slots?.[name];\n },\n };\n }\n\n /** Fases initializing+rendering: setup/onInit + render → this.renderable. */\n private _initBody(): void {\n if (this.kind === \"class\") {\n const inst = this._inst!;\n this._phase = \"init\";\n inst.onInit?.();\n this._phase = \"render\";\n this.state = \"rendering\";\n this.renderable = asRenderable(inst.render());\n } else {\n const inv = this._invocation!;\n const ctx = this._makeSetupCtx();\n this._phase = \"setup\";\n this.state = \"rendering\";\n // A.13: LiveProps — getters readonly sobre signals internas.\n // Leer props.x dentro de un binding/effect registra dependencia.\n this.renderable = asRenderable(\n inv.definition.setup(this._initProps(inv.props), ctx),\n );\n }\n if (!this.renderable) {\n throw new Error(\n `[elur-next] El componente #${this.id} no produjo un template renderizable.`,\n );\n }\n }\n\n /** Corre `body` dentro del frame de contexto (snapshot o frame nuevo). */\n private _withScope(\n ctxSnapshot: Map<unknown, unknown>[] | undefined,\n body: () => void,\n ): void {\n if (ctxSnapshot) {\n _withComponentContext(ctxSnapshot, body);\n } else {\n _pushComponentContext();\n try {\n body();\n } finally {\n _popComponentContext();\n }\n }\n }\n\n /**\n * A.18 — hidratación: setup/onInit + render una sola vez, luego adopta el\n * DOM SSR via ctx.render (que activa bindings dentro del owner de la\n * instancia). En mismatch: rollback de la activación + remount por el mismo\n * kernel REUSANDO el renderable — setup/onInit no se duplica.\n */\n _hydrate(ctx: {\n parent: Node;\n bounds: { start: Comment; end: Comment } | null;\n render(value: unknown): unknown;\n /** \"throw\" propaga el mismatch en vez de remontar (HydrateOptions). */\n mismatch?: \"throw\" | \"warn-remount\" | \"remount\";\n }): void {\n if (this.state !== \"created\") {\n throw new Error(`[elur-next] _hydrate(): estado inválido \"${this.state}\".`);\n }\n ownerToInstance.set(this.owner, this);\n ownerToContext.set(this.owner, this.context);\n this._resolveParent();\n this.owner.parent = getOwner();\n try {\n this.state = \"initializing\";\n let hydrateCleanup: unknown;\n runWithOwner(this.owner, () =>\n this._withScope(undefined, () => {\n this._initBody();\n this.state = \"pending-mount\";\n hydrateCleanup = ctx.render(this.renderable);\n }),\n );\n this._renderCleanup =\n typeof hydrateCleanup === \"function\" ? (hydrateCleanup as () => void) : null;\n this.state = \"mounted\";\n this._runOnMount();\n } catch (error) {\n if (ctx.mismatch === \"throw\") throw error;\n if (ctx.mismatch !== \"remount\") {\n console.warn(\"[elur] Hydration mismatch en componente; remounting:\", error);\n }\n // Mismatch SSR → rollback de la activación y remount por el kernel,\n // reutilizando this.renderable (onInit/setup ya corrieron — A.18).\n this.owner.dispose();\n const retry = this.renderable;\n this.state = \"initializing\";\n runWithOwner(this.owner, () =>\n this._withScope(undefined, () => {\n if (!retry) this._initBody();\n this.state = \"pending-mount\";\n this._renderCleanup = this.renderable!._render(\n ctx.parent,\n ctx.bounds?.end ?? null,\n );\n }),\n );\n this.state = \"mounted\";\n this._runOnMount();\n }\n }\n\n /**\n * A.17 — SSR: setup/onInit + onServerRender + serializar el renderable.\n * NO corre onMount/onUnmount; el owner server-side se dispone al final\n * (mata effects/computeds creados en setup).\n */\n async _renderServer(sctx: {\n markers?: boolean;\n render(value: unknown, options?: { markers?: boolean }): string | Promise<string>;\n }): Promise<string> {\n this.state = \"initializing\";\n ownerToInstance.set(this.owner, this);\n ownerToContext.set(this.owner, this.context);\n this._resolveParent();\n this.owner.parent = getOwner();\n runWithOwner(this.owner, () =>\n this._withScope(undefined, () => {\n this._initBody();\n if (this.kind === \"class\") this._inst!.onServerRender?.();\n else this.hooks.onServerRender?.();\n }),\n );\n try {\n return await sctx.render(this.renderable, { markers: sctx.markers });\n } finally {\n // Disposal server-side: cleanups + hijos reactivos, sin lifecycle DOM.\n this.owner.dispose();\n this.state = \"disposed\";\n }\n }\n\n /**\n * A.13 — crea el objeto LiveProps: propiedades readonly respaldadas por\n * signals. OJO: destructurar props en setup crea snapshots no reactivos.\n */\n private _initProps(props: unknown): Record<string, unknown> {\n this._propSignals = new Map();\n this._liveProps = {};\n if (props != null && typeof props === \"object\") {\n for (const [key, value] of Object.entries(props)) {\n if (key === \"key\") continue; // la key es identidad, no prop reactiva\n const sig = signal(value);\n this._propSignals.set(key, sig);\n Object.defineProperty(this._liveProps, key, {\n enumerable: true,\n get: () => sig.value,\n });\n }\n }\n return this._liveProps;\n }\n\n /**\n * A.13/A.15 — true si `inv` es la misma definición con la misma key:\n * entonces el runtime debe actualizar props, no recrear el setup.\n */\n matches(inv: ComponentInvocation<any>): boolean {\n if (this.kind !== \"function\" || !this._invocation) return false;\n const keyOf = (p: unknown) =>\n p != null && typeof p === \"object\"\n ? (p as Record<string, unknown>).key\n : undefined;\n return (\n inv.definition === this._invocation.definition &&\n keyOf(inv.props) === keyOf(this._invocation.props)\n );\n }\n\n /**\n * A.13 — actualiza props sin recrear setup: escribe cada signal de prop.\n * Props nuevas se añaden; props desaparecidas quedan en undefined.\n */\n updateProps(props: unknown): void {\n if (!this._propSignals || !this._liveProps) return;\n const seen = new Set<string>();\n if (props != null && typeof props === \"object\") {\n for (const [key, value] of Object.entries(props)) {\n if (key === \"key\") continue;\n seen.add(key);\n const sig = this._propSignals.get(key);\n if (sig) {\n sig.value = value;\n } else {\n const s = signal(value);\n this._propSignals.set(key, s);\n Object.defineProperty(this._liveProps, key, {\n enumerable: true,\n get: () => s.value,\n });\n }\n }\n }\n for (const key of this._propSignals.keys()) {\n if (!seen.has(key)) this._propSignals.get(key)!.value = undefined;\n }\n }\n}\n\n/**\n * A.16: burbujeo de errores por la cadena de instancias (padres reales del\n * árbol de componentes). Devuelve la primera resolución manejada; si nadie\n * maneja el error, `{ handled: false }` y el caller decide (re-lanzar o\n * registrar).\n */\nexport function reportError(\n from: ComponentInstance,\n info: ComponentErrorInfo,\n): ErrorResolution {\n let cur: ComponentInstance | null = from;\n while (cur) {\n const r = cur._handleError(info);\n if (r !== null) return r;\n cur = cur.parent;\n }\n return { handled: false };\n}\n\n// --- Adaptador de clase ---------------------------------------------------------\n\n/** Envuelve un ElurComponent de clase en el kernel unificado. */\nexport function adaptClassComponent(inst: ElurComponent): ComponentInstance {\n const ci = new ComponentInstance(inst);\n // Los hooks de clase se leen de la instancia en mount/unmount directamente\n // (onInit/onMount/onUnmount/onError) — no necesitan registro por ctx.\n return ci;\n}\n\n// --- Componentes funcionales (A.5) ------------------------------------------------\n\nexport interface ComponentDefinition<P> {\n (props?: P, slots?: Record<string, Slot>): ComponentInvocation<P>;\n readonly setup: (props: P | undefined, ctx: SetupCtx) => unknown;\n readonly _isComponentDefinition: true;\n}\n\n/** Invocación marcada: `Counter({ initial: 10 })` NO ejecuta setup — monta después. */\nexport class ComponentInvocation<P> {\n readonly [ELUR_RENDER_PROTOCOL] = {\n mountDom: (ctx: DomProtocolContext): (() => void) => {\n const inst = new ComponentInstance(this as ComponentInvocation<any>);\n // mount() resuelve `parent` caminando la cadena de owners — bajo el\n // swap, el caller corre dentro del owner del componente padre.\n inst.mount(ctx.parent, ctx.before);\n return () => inst.unmount();\n },\n // A.17 — SSR: setup + onServerRender + serialización; sin lifecycle DOM.\n renderServer: (sctx: {\n markers?: boolean;\n render(value: unknown, options?: { markers?: boolean }): string | Promise<string>;\n }): Promise<string> => {\n const inst = new ComponentInstance(this as ComponentInvocation<any>);\n return inst._renderServer(sctx);\n },\n // A.18 — hidratación: setup una vez + adopta DOM SSR; mismatch → remount\n // por el kernel reusando el renderable.\n hydrateDom: (ctx: {\n parent: Node;\n bounds: { start: Comment; end: Comment } | null;\n render(value: unknown): unknown;\n }): (() => void) => {\n const inst = new ComponentInstance(this as ComponentInvocation<any>);\n inst._hydrate(ctx);\n return () => inst.unmount();\n },\n };\n\n readonly definition: ComponentDefinition<P>;\n readonly props: P | undefined;\n /** A.14: slots declarados en la llamada — `Card(props, { default: slot(...) })`. */\n readonly slots: Record<string, Slot> | undefined;\n\n constructor(\n definition: ComponentDefinition<P>,\n props: P | undefined,\n slots?: Record<string, Slot>,\n ) {\n this.definition = definition;\n this.props = props;\n this.slots = slots;\n }\n}\n\nexport function isComponentInvocation(v: unknown): v is ComponentInvocation<any> {\n return v instanceof ComponentInvocation;\n}\n\n/** Owner → instancia, para localizar el padre al montar una invocación. */\nconst ownerToInstance = new WeakMap<OwnerLike, ComponentInstance>();\n/** Owner → frame de contexto (instancias o roots de mount con provides). */\nconst ownerToContext = new WeakMap<OwnerLike, Map<unknown, unknown>>();\n\n/**\n * @internal — registra un frame de contexto para un owner raíz (mount de\n * template con router, roots de app, etc).\n */\nexport function _registerContextOwner(\n owner: OwnerLike,\n context: Map<unknown, unknown>,\n): void {\n ownerToContext.set(owner, context);\n}\n\n// --- A.12: contexto permanente por instancia -----------------------------------\n//\n// El modelo actual usa un stack global empujado durante init/render — por eso\n// provide/inject fallan fuera de esas fases (A.3.6). Aquí el contexto ES de la\n// instancia: un Map propio por ComponentInstance, resuelto caminando la cadena\n// de owners activa. inject() funciona en setup, effects, onMount y callbacks —\n// el árbol de owners reproduce el árbol de componentes permanentemente.\n// Si no hay instancia en la cadena → undefined → el resolver cae al stack\n// global (misma semántica: provide fuera de componente lanza error).\n\n// Resolver secundario: el primario (server/index, ALS) gana durante SSR;\n// éste se consulta cuando aquél devuelve undefined (lado cliente).\n_pushContextScopeResolver(() => {\n const frames: Map<unknown, unknown>[] = [];\n let o: OwnerLike | null = getOwner();\n while (o) {\n const ctx = ownerToContext.get(o);\n if (ctx) frames.push(ctx);\n o = o.parent;\n }\n if (frames.length === 0) return undefined;\n frames.reverse(); // cadena innermost→outermost → stack outermost→innermost\n return frames;\n});\n\n/**\n * Define un componente funcional de primera clase (A.5):\n * `Counter(props)` retorna una invocación marcada; el runtime ejecuta el\n * setup cuando monta la invocación.\n */\nexport function defineComponent<P = Record<string, never>>(\n setup: (props: P | undefined, ctx: SetupCtx) => unknown,\n): ComponentDefinition<P> {\n const def = ((props?: P, slots?: Record<string, Slot>) =>\n new ComponentInvocation<P>(\n def as ComponentDefinition<P>,\n props,\n slots,\n )) as ComponentDefinition<P>;\n (def as { setup: unknown }).setup = setup;\n (def as { _isComponentDefinition: boolean })._isComponentDefinition = true;\n return def;\n}\n\n// --- Mount de alto nivel ------------------------------------------------------------\n\n/**\n * Monta un componente (clase o invocación funcional) en `container` y\n * devuelve el handle con `unmount()`. Todo el árbol reactivo muere con el\n * unmount — sin fugas de effects/computeds.\n */\nexport function mountComponent(\n value: ElurComponent | ComponentInvocation<any>,\n container: Element,\n): { unmount(): void; instance: ComponentInstance } {\n const inst = new ComponentInstance(value);\n inst.mount(container, null);\n return { unmount: () => inst.unmount(), instance: inst };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Elur "next" — kernel unificado de componentes (experimental).
|
|
3
|
+
*
|
|
4
|
+
* Implementa A.6–A.9 del PLAN_TECNICO_ELUR_NEXT sobre el ownership de
|
|
5
|
+
* `./reactivity.ts`:
|
|
6
|
+
* - Una sola `ComponentInstance` para clases y funciones (adaptadores).
|
|
7
|
+
* - Máquina de estados (A.7): created → initializing → rendering →
|
|
8
|
+
* pending-mount → mounted → disposing → disposed (o failed).
|
|
9
|
+
* - Mount transaccional (A.9): cualquier fallo dispara rollback —
|
|
10
|
+
* cleanups registrados, owner reactivo disposed, DOM insertado removido.
|
|
11
|
+
* - `unmount()` idempotente (A.2.10).
|
|
12
|
+
* - `onMount` corre DESPUÉS del commit DOM (A.2.9).
|
|
13
|
+
* - Todo lo creado en setup/render pertenece al owner de la instancia y
|
|
14
|
+
* muere con unmount (A.2.1 — no más effects huérfanos).
|
|
15
|
+
*
|
|
16
|
+
* Las invocaciones implementan `ELUR_RENDER_PROTOCOL.mountDom`, así el
|
|
17
|
+
* renderer existente las monta sin saber que son componentes.
|
|
18
|
+
*/
|
|
19
|
+
import { Owner, Signal, type Disposable, type OwnerLike } from "./reactivity.js";
|
|
20
|
+
import { type ElurComponent, type ComponentController } from "../lifecycle.js";
|
|
21
|
+
import { ELUR_RENDER_PROTOCOL, type DomProtocolContext } from "../template/types.js";
|
|
22
|
+
export type ComponentState = "created" | "initializing" | "rendering" | "pending-mount" | "mounted" | "deactivated" | "disposing" | "disposed" | "failed";
|
|
23
|
+
/** Fase del lifecycle donde ocurrió el error. */
|
|
24
|
+
export type ErrorPhase = "setup" | "init" | "render" | "hydrate" | "mount" | "effect" | "activate" | "deactivate" | "cleanup" | "unmount";
|
|
25
|
+
/** Información estructurada del error (A.16). */
|
|
26
|
+
export interface ComponentErrorInfo {
|
|
27
|
+
phase: ErrorPhase;
|
|
28
|
+
/** Instancia donde ocurrió el error (no la boundary que lo maneja). */
|
|
29
|
+
component: ComponentInstance;
|
|
30
|
+
cause: unknown;
|
|
31
|
+
}
|
|
32
|
+
/** Resolución de una boundary (A.16). */
|
|
33
|
+
export type ErrorResolution = {
|
|
34
|
+
handled: false;
|
|
35
|
+
} | {
|
|
36
|
+
handled: true;
|
|
37
|
+
fallback?: Renderable;
|
|
38
|
+
} | {
|
|
39
|
+
handled: true;
|
|
40
|
+
retry: true;
|
|
41
|
+
};
|
|
42
|
+
export interface ComponentHooks {
|
|
43
|
+
/** Tras el commit DOM. Puede devolver cleanup (corre en unmount). */
|
|
44
|
+
onMount?: () => (() => void) | void;
|
|
45
|
+
/** Antes de remover el DOM. */
|
|
46
|
+
onUnmount?: () => void;
|
|
47
|
+
/**
|
|
48
|
+
* Boundary de errores (A.16): recibe info estructurada; el error burbujea
|
|
49
|
+
* por la cadena de instancias hasta una boundary que devuelva handled.
|
|
50
|
+
* `void` = manejado sin más.
|
|
51
|
+
*/
|
|
52
|
+
onError?: (info: ComponentErrorInfo) => ErrorResolution | void;
|
|
53
|
+
/** A.17: tras setup durante SSR — nunca en cliente. */
|
|
54
|
+
onServerRender?: () => void;
|
|
55
|
+
}
|
|
56
|
+
/** Contexto que recibe el setup de un componente funcional. */
|
|
57
|
+
export interface SetupCtx {
|
|
58
|
+
onMount(fn: () => (() => void) | void): void;
|
|
59
|
+
onUnmount(fn: () => void): void;
|
|
60
|
+
onError(fn: (info: ComponentErrorInfo) => ErrorResolution | void): void;
|
|
61
|
+
/** A.17: hook server-side — corre tras setup durante SSR, nunca en cliente. */
|
|
62
|
+
onServerRender(fn: () => void): void;
|
|
63
|
+
/** Owner de la instancia — para runWithOwner/getOwner manual. */
|
|
64
|
+
readonly owner: OwnerLike;
|
|
65
|
+
/** Señal interna de una prop (A.13) — para acceso reactivo explícito. */
|
|
66
|
+
propSignal<K extends string>(key: K): Signal<unknown> | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* A.14: renderiza el contenido de un slot (lazy — corre el render del
|
|
69
|
+
* slot bajo el owner del padre que lo declaró). `"default"` por defecto.
|
|
70
|
+
*/
|
|
71
|
+
slot(name?: string): unknown;
|
|
72
|
+
/** A.14: slots declarados en la invocación. */
|
|
73
|
+
readonly slots: Record<string, Slot> | undefined;
|
|
74
|
+
}
|
|
75
|
+
interface RenderableValue {
|
|
76
|
+
_render(parent: Node, before: Node | null): () => void;
|
|
77
|
+
}
|
|
78
|
+
/** Renderable común: cualquier cosa montable en un binding. */
|
|
79
|
+
export type Renderable = ElurComponent | ComponentInvocation<unknown> | Slot | {
|
|
80
|
+
_render(parent: Node, before: Node | null): () => void;
|
|
81
|
+
} | string | number | bigint | false | null | undefined | Renderable[];
|
|
82
|
+
/**
|
|
83
|
+
* Slot lazy y marcado (A.14): el contenido se renderiza bajo el owner del
|
|
84
|
+
* padre que LO DECLARÓ (contexto léxico), aunque se monte dentro del
|
|
85
|
+
* componente consumidor.
|
|
86
|
+
*/
|
|
87
|
+
export interface Slot {
|
|
88
|
+
readonly __isElurSlot: true;
|
|
89
|
+
/** Owner capturado en el punto de declaración (contexto léxico). */
|
|
90
|
+
readonly owner: OwnerLike | null;
|
|
91
|
+
render(): unknown;
|
|
92
|
+
}
|
|
93
|
+
export declare function slot(render: () => unknown): Slot;
|
|
94
|
+
export declare function isElurSlot(v: unknown): v is Slot;
|
|
95
|
+
export declare class ComponentInstance implements Disposable {
|
|
96
|
+
readonly id: number;
|
|
97
|
+
readonly kind: "class" | "function";
|
|
98
|
+
state: ComponentState;
|
|
99
|
+
/** Owner reactivo de la instancia — todo lo creado dentro muere con él. */
|
|
100
|
+
readonly owner: Owner;
|
|
101
|
+
/** Instancia padre (owner activo cuando se creó esta instancia). */
|
|
102
|
+
parent: ComponentInstance | null;
|
|
103
|
+
hooks: ComponentHooks;
|
|
104
|
+
renderable: RenderableValue | null;
|
|
105
|
+
/** A.12: frame de provide/inject propio de la instancia — permanente. */
|
|
106
|
+
readonly context: Map<unknown, unknown>;
|
|
107
|
+
private _inst;
|
|
108
|
+
private _invocation;
|
|
109
|
+
private _renderCleanup;
|
|
110
|
+
private _mountCleanups;
|
|
111
|
+
/** A.13: señales internas por prop + objeto live pasado al setup. */
|
|
112
|
+
private _propSignals;
|
|
113
|
+
private _liveProps;
|
|
114
|
+
/** A.16: fase actual del lifecycle — para el ComponentErrorInfo. */
|
|
115
|
+
private _phase;
|
|
116
|
+
/** A.16: posición de montaje — para renderizar fallback de boundary. */
|
|
117
|
+
private _mountParent;
|
|
118
|
+
private _mountBefore;
|
|
119
|
+
/** A.3.8: nodos DOM de la instancia — para detach/attach. */
|
|
120
|
+
private _domNodes;
|
|
121
|
+
/** A.21: controllers de ciclo de vida (Lit-style). */
|
|
122
|
+
private _controllers;
|
|
123
|
+
constructor(source: ElurComponent | ComponentInvocation<any>);
|
|
124
|
+
/**
|
|
125
|
+
* Mount transaccional (A.9). Cualquier fase que falle → rollback completo:
|
|
126
|
+
* owner disposed, cleanups corridos, DOM insertado removido, state=failed.
|
|
127
|
+
*
|
|
128
|
+
* Opciones:
|
|
129
|
+
* - `ctxSnapshot`: contexto capturado en el punto de declaración
|
|
130
|
+
* (mounts dentro de effects dinámicos heredan provide/inject).
|
|
131
|
+
* - `deferOnMount`: recibe una función `fire()` que corre onMount; el
|
|
132
|
+
* caller decide cuándo invocarla (fragments aún no insertados).
|
|
133
|
+
*/
|
|
134
|
+
mount(parent: Node, before: Node | null, opts?: {
|
|
135
|
+
ctxSnapshot?: Map<unknown, unknown>[];
|
|
136
|
+
deferOnMount?: (fire: () => void) => void;
|
|
137
|
+
/** Valores a proveer en el frame de contexto de la instancia (A.12). */
|
|
138
|
+
provides?: Iterable<readonly [unknown, unknown]>;
|
|
139
|
+
/**
|
|
140
|
+
* A.14: owner del declarante — para contenido de slots, el owner padre
|
|
141
|
+
* es el del padre que declaró el contenido, no el del punto de montaje.
|
|
142
|
+
*/
|
|
143
|
+
declOwner?: OwnerLike | null;
|
|
144
|
+
}): void;
|
|
145
|
+
/** A.21: registra un controller — sus hooks corren bajo este owner. */
|
|
146
|
+
addController(c: ComponentController): void;
|
|
147
|
+
/**
|
|
148
|
+
* A.3.8: saca el DOM de la instancia SIN disponer nada — effects, signals
|
|
149
|
+
* y contexto siguen vivos (página cached, Suspense, transición). No-op si
|
|
150
|
+
* no está montado.
|
|
151
|
+
*/
|
|
152
|
+
detach(): void;
|
|
153
|
+
/**
|
|
154
|
+
* A.3.8: reinserta el DOM de una instancia detached en la posición original
|
|
155
|
+
* (o en parent/before dados). No-op si no está deactivated.
|
|
156
|
+
*/
|
|
157
|
+
attach(parent?: Node, before?: Node | null): void;
|
|
158
|
+
/** Idempotente (A.2.10): disponer dos veces es seguro. */
|
|
159
|
+
unmount(): void;
|
|
160
|
+
dispose(): void;
|
|
161
|
+
/** @internal — corre onMount una vez; no-op si ya no está montado. */
|
|
162
|
+
_runOnMount(): void;
|
|
163
|
+
/**
|
|
164
|
+
* @internal A.16: intenta manejar el error con el boundary propio.
|
|
165
|
+
* `null` = este nodo no tiene boundary — seguir subiendo.
|
|
166
|
+
*/
|
|
167
|
+
_handleError(info: ComponentErrorInfo): ErrorResolution | null;
|
|
168
|
+
/** A.16: errores de teardown — se reportan a la cadena; si nadie los maneja quedan registrados. */
|
|
169
|
+
private _reportSwallowed;
|
|
170
|
+
/** A.16: renderiza el fallback de una boundary en la posición del componente. */
|
|
171
|
+
private _renderFallback;
|
|
172
|
+
/** Camina la cadena de owners hasta la instancia registrada más cercana. */
|
|
173
|
+
private _resolveParent;
|
|
174
|
+
private _rollback;
|
|
175
|
+
private _makeSetupCtx;
|
|
176
|
+
/** Fases initializing+rendering: setup/onInit + render → this.renderable. */
|
|
177
|
+
private _initBody;
|
|
178
|
+
/** Corre `body` dentro del frame de contexto (snapshot o frame nuevo). */
|
|
179
|
+
private _withScope;
|
|
180
|
+
/**
|
|
181
|
+
* A.18 — hidratación: setup/onInit + render una sola vez, luego adopta el
|
|
182
|
+
* DOM SSR via ctx.render (que activa bindings dentro del owner de la
|
|
183
|
+
* instancia). En mismatch: rollback de la activación + remount por el mismo
|
|
184
|
+
* kernel REUSANDO el renderable — setup/onInit no se duplica.
|
|
185
|
+
*/
|
|
186
|
+
_hydrate(ctx: {
|
|
187
|
+
parent: Node;
|
|
188
|
+
bounds: {
|
|
189
|
+
start: Comment;
|
|
190
|
+
end: Comment;
|
|
191
|
+
} | null;
|
|
192
|
+
render(value: unknown): unknown;
|
|
193
|
+
/** "throw" propaga el mismatch en vez de remontar (HydrateOptions). */
|
|
194
|
+
mismatch?: "throw" | "warn-remount" | "remount";
|
|
195
|
+
}): void;
|
|
196
|
+
/**
|
|
197
|
+
* A.17 — SSR: setup/onInit + onServerRender + serializar el renderable.
|
|
198
|
+
* NO corre onMount/onUnmount; el owner server-side se dispone al final
|
|
199
|
+
* (mata effects/computeds creados en setup).
|
|
200
|
+
*/
|
|
201
|
+
_renderServer(sctx: {
|
|
202
|
+
markers?: boolean;
|
|
203
|
+
render(value: unknown, options?: {
|
|
204
|
+
markers?: boolean;
|
|
205
|
+
}): string | Promise<string>;
|
|
206
|
+
}): Promise<string>;
|
|
207
|
+
/**
|
|
208
|
+
* A.13 — crea el objeto LiveProps: propiedades readonly respaldadas por
|
|
209
|
+
* signals. OJO: destructurar props en setup crea snapshots no reactivos.
|
|
210
|
+
*/
|
|
211
|
+
private _initProps;
|
|
212
|
+
/**
|
|
213
|
+
* A.13/A.15 — true si `inv` es la misma definición con la misma key:
|
|
214
|
+
* entonces el runtime debe actualizar props, no recrear el setup.
|
|
215
|
+
*/
|
|
216
|
+
matches(inv: ComponentInvocation<any>): boolean;
|
|
217
|
+
/**
|
|
218
|
+
* A.13 — actualiza props sin recrear setup: escribe cada signal de prop.
|
|
219
|
+
* Props nuevas se añaden; props desaparecidas quedan en undefined.
|
|
220
|
+
*/
|
|
221
|
+
updateProps(props: unknown): void;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* A.16: burbujeo de errores por la cadena de instancias (padres reales del
|
|
225
|
+
* árbol de componentes). Devuelve la primera resolución manejada; si nadie
|
|
226
|
+
* maneja el error, `{ handled: false }` y el caller decide (re-lanzar o
|
|
227
|
+
* registrar).
|
|
228
|
+
*/
|
|
229
|
+
export declare function reportError(from: ComponentInstance, info: ComponentErrorInfo): ErrorResolution;
|
|
230
|
+
/** Envuelve un ElurComponent de clase en el kernel unificado. */
|
|
231
|
+
export declare function adaptClassComponent(inst: ElurComponent): ComponentInstance;
|
|
232
|
+
export interface ComponentDefinition<P> {
|
|
233
|
+
(props?: P, slots?: Record<string, Slot>): ComponentInvocation<P>;
|
|
234
|
+
readonly setup: (props: P | undefined, ctx: SetupCtx) => unknown;
|
|
235
|
+
readonly _isComponentDefinition: true;
|
|
236
|
+
}
|
|
237
|
+
/** Invocación marcada: `Counter({ initial: 10 })` NO ejecuta setup — monta después. */
|
|
238
|
+
export declare class ComponentInvocation<P> {
|
|
239
|
+
readonly [ELUR_RENDER_PROTOCOL]: {
|
|
240
|
+
mountDom: (ctx: DomProtocolContext) => (() => void);
|
|
241
|
+
renderServer: (sctx: {
|
|
242
|
+
markers?: boolean;
|
|
243
|
+
render(value: unknown, options?: {
|
|
244
|
+
markers?: boolean;
|
|
245
|
+
}): string | Promise<string>;
|
|
246
|
+
}) => Promise<string>;
|
|
247
|
+
hydrateDom: (ctx: {
|
|
248
|
+
parent: Node;
|
|
249
|
+
bounds: {
|
|
250
|
+
start: Comment;
|
|
251
|
+
end: Comment;
|
|
252
|
+
} | null;
|
|
253
|
+
render(value: unknown): unknown;
|
|
254
|
+
}) => (() => void);
|
|
255
|
+
};
|
|
256
|
+
readonly definition: ComponentDefinition<P>;
|
|
257
|
+
readonly props: P | undefined;
|
|
258
|
+
/** A.14: slots declarados en la llamada — `Card(props, { default: slot(...) })`. */
|
|
259
|
+
readonly slots: Record<string, Slot> | undefined;
|
|
260
|
+
constructor(definition: ComponentDefinition<P>, props: P | undefined, slots?: Record<string, Slot>);
|
|
261
|
+
}
|
|
262
|
+
export declare function isComponentInvocation(v: unknown): v is ComponentInvocation<any>;
|
|
263
|
+
/**
|
|
264
|
+
* @internal — registra un frame de contexto para un owner raíz (mount de
|
|
265
|
+
* template con router, roots de app, etc).
|
|
266
|
+
*/
|
|
267
|
+
export declare function _registerContextOwner(owner: OwnerLike, context: Map<unknown, unknown>): void;
|
|
268
|
+
/**
|
|
269
|
+
* Define un componente funcional de primera clase (A.5):
|
|
270
|
+
* `Counter(props)` retorna una invocación marcada; el runtime ejecuta el
|
|
271
|
+
* setup cuando monta la invocación.
|
|
272
|
+
*/
|
|
273
|
+
export declare function defineComponent<P = Record<string, never>>(setup: (props: P | undefined, ctx: SetupCtx) => unknown): ComponentDefinition<P>;
|
|
274
|
+
/**
|
|
275
|
+
* Monta un componente (clase o invocación funcional) en `container` y
|
|
276
|
+
* devuelve el handle con `unmount()`. Todo el árbol reactivo muere con el
|
|
277
|
+
* unmount — sin fugas de effects/computeds.
|
|
278
|
+
*/
|
|
279
|
+
export declare function mountComponent(value: ElurComponent | ComponentInvocation<any>, container: Element): {
|
|
280
|
+
unmount(): void;
|
|
281
|
+
instance: ComponentInstance;
|
|
282
|
+
};
|
|
283
|
+
export {};
|