Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Anchor-click and form-submit navigations run outside the runtime's interaction frame (observe: NavigationEvent.interaction is undefined)

Aperta
#643 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
52/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
typescript
Ambito
frontend, web-dev

Direzione di ricerca

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.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug

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.interaction is 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

  1. Router wraps its handlers. In setupNativeEvents, when OBSERVE is defined, dispatch handleAnchorClick and handleFormSubmit through OBSERVE.attribution.withInteraction({ type: evt.type, target: …, at: evt.timeStamp }, () => handler(evt)). Smallest change, but it duplicates the web runtime's describeEventTarget (element description, the values privacy gate for text) and interactionStart (the timeStamp clock check), which the router should not own.
  2. Web exposes the frame. @solidjs/web gains 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 the click and submit listeners. Preload listeners (mousemove, focusin, touchstart) stay raw: preloading is not a user interaction and should not open frames.
  3. Web stamps document-level listeners itself. Not viable without patching EventTarget.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 NavigationEvent whose interaction is the click's InteractionRef (type click, target a#…), the same object identity a navigate() from onClick gets today.
  • A <form> submitted to an action produces an interaction of type submit on the action's records.
  • A component onClick calling preventDefault() 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

Lingua principale
TypeScript
Stelle
1.3k
Fork
182
Merge medio
22h 57m
PR unite (30g)
37

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di solidjs/solid-router

Tutte le issue di solidjs/solid-router

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.