Skip to content

dynamic() / Dynamic with a string tag: no runHydrationEvents(), namespace ignores parent #3386

Description

@ryansolid

Version: 2.0.0-rc.8 (@solidjs/web)

Two correctness gaps in the string-tag branch of dynamic() (packages/web/src/index.ts ~366–374), which Dynamic uses:

case "string":
  const el = sharedConfig.hydrating
    ? getNextElement()
    : createElement(component as string, untrack(() => (props as any).is));
  spread(el, props);
  return el;

1. Hydration event replay never runs

Compiled JSX emits _$runHydrationEvents() after any element with event handlers (babel-plugin/src/dom/element.ts ~323). dynamic() binds handlers through spread(el, props) and never calls it. Events queued by the hydration header script for a <Dynamic component="button" onClick=…> are replayed only if some other compiled element on the page happens to call runHydrationEvents() after it hydrates; if the interactive elements are all Dynamic, queued clicks are dropped until _$HY.done. @yak/solid had to add the call in its own element renderer.

Fix: call runHydrationEvents() after spread when hydrating (cheap — it's a no-op when nothing is queued).

2. Namespace is chosen from the tag alone

createElement(tag) picks the namespace via SVGElements.has(tag) / MathMLElements.has(tag). Tags that exist in both HTML and SVG — a, script, style, title — are always created as HTML, so <svg><Dynamic component="a"> produces an HTML anchor inside an SVG tree. The compiler resolves this from the parent at build time; the runtime path has no parent context. This is why @yak/solid carries an ambiguousSvgTags set and routes those four tags differently.

Fix options: (a) accept the namespace from the mount context — insert/the parent element is known at spread time (el.parentNode after insertion is too late; a context or an explicit ns option would work); (b) at minimum document the limitation and expose the set so libraries don't hard-code it.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions