You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Treat this as a compatibility correction to the existing renderMode = 'light' SSR/CSR promise, not as a new render mode.
The correction must not add a public option, change the Shadow/DSD default, or introduce a general VDOM reconciler. If implementation requires a new public lifecycle hook, ownership option, runtime default, or other additive semantic, stop and reclassify that part through ADR-0140 as a future-minor change.
Context
ADR-0092 correctly chose an explicit render-root policy:
shadow renders into Shadow DOM and emits DSD on the server;
light renders into the host and does not attach a shadow root.
However, it specified SSR and CSR independently and did not define the transition from server-rendered light DOM to an upgraded interactive element. It also did not define who owns host children during that transition.
The current client runtime therefore routes every light-mode connection through renderIntoLightDom(), which calls clearChildren(host) and mounts fresh DOM. pre-hydration-click.ts explicitly skips light-mode hosts because the recorded target is detached by that replacement.
Amend ADR-0092, or add a successor ADR, with this narrow contract:
renderMode = 'light' means the component owns the host's rendered child subtree.
SSR output for that subtree is the authoritative initial DOM.
On client upgrade, matching SSR DOM is activated in place by binding existing event, signal, attribute, and branch markers.
Matching activation preserves node identity, focus, selection, live form values, nested custom-element instances, and pre-upgrade interaction targets.
A structural or marker mismatch emits the existing structured hydration diagnostic and may degrade to a full client render.
Light mode does not simultaneously promise arbitrary consumer-owned child projection. Use Shadow DOM plus slots for projection, or a separate enhancement/controller pattern for decorating arbitrary existing DOM.
Implementation scope
Generalize the internal binding/hydration target only as far as needed to accept the renderer-owned light host subtree.
Route populated light-mode SSR output through in-place activation.
Keep empty-host CSR behavior unchanged.
Enable pre-hydration click capture/replay for light-mode hosts when the target survives activation.
Preserve current Shadow/DSD behavior and public package surface.
Add one nested light custom-element fixture that proves parent activation does not replace the child instance.
Acceptance
SSR -> delayed upgrade keeps exact node identity for an input, button, and nested custom element.
Focus, selection, and a value typed before upgrade survive matching activation.
A pre-upgrade click is replayed exactly once after light activation.
Event, signal, attribute, Show, and keyed/unkeyed For bindings activate against existing light DOM.
Marker/branch mismatch produces a structured diagnostic and safely degrades.
Empty-host CSR light rendering and explicit update() remain compatible.
Shadow/DSD hydration tests remain unchanged and green.
Chromium, Firefox, and WebKit exercise the real SSR -> delayed-upgrade path.
A nextCrm authoring-fitness slice supplies external application evidence before v0.43.3 publication.
ADR, current version plan, status, roadmap, release notes, and package tests agree on the final compatibility classification.
Category: Framework / Element runtime
Priority: P2
Target: v0.43.3
Release gate: BLOCKING
Maintainer classification
Treat this as a compatibility correction to the existing
renderMode = 'light'SSR/CSR promise, not as a new render mode.The correction must not add a public option, change the Shadow/DSD default, or introduce a general VDOM reconciler. If implementation requires a new public lifecycle hook, ownership option, runtime default, or other additive semantic, stop and reclassify that part through ADR-0140 as a future-minor change.
Context
ADR-0092 correctly chose an explicit render-root policy:
shadowrenders into Shadow DOM and emits DSD on the server;lightrenders into the host and does not attach a shadow root.However, it specified SSR and CSR independently and did not define the transition from server-rendered light DOM to an upgraded interactive element. It also did not define who owns host children during that transition.
The current client runtime therefore routes every light-mode connection through
renderIntoLightDom(), which callsclearChildren(host)and mounts fresh DOM.pre-hydration-click.tsexplicitly skips light-mode hosts because the recorded target is detached by that replacement.Relevant evidence:
docs/adr/ADR-0092-dsdelement-render-mode.mdpackages/element/src/open-element-runtime.tspackages/element/src/open-element-render.tspackages/element/src/internal/core/pre-hydration-click.tspackages/element/__tests__/pre-hydration-click.test.tsRequired contract amendment
Amend ADR-0092, or add a successor ADR, with this narrow contract:
renderMode = 'light'means the component owns the host's rendered child subtree.Implementation scope
Acceptance
Show, and keyed/unkeyedForbindings activate against existing light DOM.update()remain compatible.Non-goals