Anchor-click and form-submit navigations run outside the runtime's interaction frame (observe: NavigationEvent.interaction is undefined)
Mantenedores costumam responder em até 1 dia
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Facilidade para iniciantes
- 52/100
- Tipo de issue
- Bug
- Clareza
- Razoavelmente clara
- Status de atividade
- Ativa
- Stack de tecnologia
- typescript
Direção de pesquisa
Start in src/data/events.ts at setupNativeEvents, then inspect @solidjs/web's internal addEvent and the delegated event path through delegateEvents. Preserve the existing listener order and preload behavior; done means anchor clicks and native form submissions receive interaction attribution, preventDefault still works, and non-observe builds remain unchanged.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Summary
Under Solid's observe tier, a navigation performed by clicking an <a> records no interaction: NavigationEvent.interaction is undefined, and the calls the route's data makes carry a navigation origin with no click behind it. A navigation performed by navigate() from an onClick handler is attributed correctly. The difference is where the handler runs: the router attaches its anchor handler to document directly, outside the web runtime's interaction frame.
Where
src/data/events.ts, setupNativeEvents:
// ensure delegated event run first
delegateEvents(["click", "submit"]);
document.addEventListener("click", handleAnchorClick);
if (preload) {
document.addEventListener("mousemove", handleAnchorMove, { passive: true });
document.addEventListener("focusin", handleAnchorPreload, { passive: true });
document.addEventListener("touchstart", handleAnchorPreload, { passive: true });
}
document.addEventListener("submit", handleFormSubmit);
@solidjs/web wraps every handler it dispatches — delegated events via eventHandler, runtime-attached ones via addEvent — in dispatchAsInteraction, i.e. OBSERVE.attribution.withInteraction({ type, target, at }, fn), so every root write inside the handler (the router's location write included) is attributed to that interaction. A raw document.addEventListener goes around that wrapper. handleAnchorClick then calls navigateFromRoute, whose withOrigin(describeNavigation…) frame opens with no enclosing interaction, so the record is an orphan.
handleFormSubmit has the same shape: an action submitted through a native <form> is unattributed, while one submitted from a handler is not.
Observed
With @sentry/solid-2 consuming the records (e2e app on rc.13 / next.32, / → /users/6):
<button onClick={() => navigate('/users/6')}>:NavigationEvent.interactionis the click; the click span links to the route-named navigation span.<a href="/users/6">:NavigationEvent.interaction === undefined; there is no click span at all, since no interaction frame ever opened. The navigation and its server-function call stand alone. The INP-relevant facts on the interaction record (inputDelayMs,handlerMs,settledMs) are lost for every link click in the app — which is most navigations.
The consumer documents the caveat for now rather than guessing a parent by time.
Cause
The direct document listeners date from the ordering requirement noted in the comment — Solid's delegated click must run first so a component's onClick with preventDefault() can stop the navigation — and predate the runtime having an interaction frame to run under. That ordering still has to hold; the fix is to run the handler inside the frame, not to change when it runs.
Options
- Router wraps its handlers. In
setupNativeEvents, whenOBSERVEis defined, dispatchhandleAnchorClickandhandleFormSubmitthroughOBSERVE.attribution.withInteraction({ type: evt.type, target: …, at: evt.timeStamp }, () => handler(evt)). Smallest change, but it duplicates the web runtime'sdescribeEventTarget(element description, thevaluesprivacy gate for text) andinteractionStart(thetimeStampclock check), which the router should not own. - Web exposes the frame.
@solidjs/webgains a small public entry — a listener attach that wraps under observe and is the identity function otherwise (addEvent(node, name, handler, false)already does exactly this but is marked@internal, compiler-emitted). The router uses it for theclickandsubmitlisteners. Preload listeners (mousemove,focusin,touchstart) stay raw: preloading is not a user interaction and should not open frames. - Web stamps
document-level listeners itself. Not viable without patchingEventTarget.prototype; not proposed.
(2) is the right shape: the web runtime owns interaction description, the router only needs "run this as the event's handler". It is a public-surface addition on @solidjs/web, so it needs a decision there first; (1) can land in the router alone if that is preferred short-term.
Either way the order relative to Solid's delegated handler must not change: attach after delegateEvents(["click", "submit"]) exactly as today, so evt.defaultPrevented still reflects component handlers.
Acceptance
- An anchor click that navigates produces a
NavigationEventwhoseinteractionis the click'sInteractionRef(typeclick, targeta#…), the same object identity anavigate()fromonClickgets today. - A
<form>submitted to an action produces an interaction of typesubmiton the action's records. - A component
onClickcallingpreventDefault()still stops the anchor navigation. - Nothing changes in non-observe builds (the wrapper folds to the plain listener).
Related: solidjs/solid#3683 (route declaration to the observe tier), getsentry/sentry-javascript#24517 (consumer; the caveat is documented in docs/solid-2-observe.md there).
— Claude via Cursor
- Linguagem predominante
- TypeScript
- Estrelas
- 1.3k
- Forks
- 183
- Merge médio
- 14h 35min
- PRs com merge (30d)
- 52
Preparar o ambiente
- Sem Dockerfile nem arquivo Docker Compose
- Sem modelo de pull request
- Ler o guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de solidjs/solid-router
-
Dificuldade 4/5 1-2 dias Facilidade para iniciantes 54/100
solidjs/solid-router#687 ·
Mantenedores costumam responder em até 1 dia
-
<A> costs ~6us of server CPU per instance during SSR (20x a plain <a>), mostly mergeProps/splitPropsTalvez já em andamento @birkskyum assumiu há 70 dias. Aberta1.x
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 55/100
solidjs/solid-router#583 ·
Mantenedores costumam responder em até 1 dia
-
1.x enhancement
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 38/100
solidjs/solid-router#518 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 35/100
solidjs/solid-router#482 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
-
enhancement
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 25/100
solidjs/solid-router#459 · 2 comentários ·
Mantenedores costumam responder em até 1 dia
Todas as issues de solidjs/solid-router
Issues semelhantes
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
radix-ui/primitives#4228 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 66/100
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
SignalK/freeboard-sk#1093 ·
Mantenedores costumam responder em até 1 dia
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
Mantenedores costumam responder em até 1 dia
-
[测试] 等待仓库加载后再记录多仓库排序基线Talvez já em andamento @myot233 assumiu hoje. Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
Mantenedores costumam responder em até 1 dia