Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: create <svelte:element> instances with the correct namespace #10006

Merged
merged 19 commits into from
Jan 29, 2024

Conversation

eEQK
Copy link
Contributor

@eEQK eEQK commented Dec 27, 2023

A continuation of #9647 that closes #9645

my commit adds checking whether an element or its parent is an SVG element, and if so - sets the namespace to namespace_svg

Before submitting the PR, please make sure you do the following

  • ✅ It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • ✅ Prefix your PR title with feat:, fix:, chore:, or docs:.
  • ✅ This message body should clearly illustrate what problems it solves.
  • ✅ Ideally, include a test that fails without this PR but passes with it.

Tests and linting

  • ✅ Run the tests with pnpm test and lint the project with pnpm lint

Copy link

changeset-bot bot commented Dec 27, 2023

⚠️ No Changeset found

Latest commit: 77e763c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

vercel bot commented Dec 27, 2023

@eEQK is attempting to deploy a commit to the Svelte Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Member

@dummdidumm dummdidumm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I left a few comments that need to be addressed. Also, could you add a changeset?

packages/svelte/src/compiler/phases/2-analyze/index.js Outdated Show resolved Hide resolved
context.state.analysis.elements.push(node);

const is_svg_element =
(node.tag.type === 'Identifier' && node.tag.name && SVGElements.includes(node.tag.name)) ||
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong - the name of the identifier shouldn't be used to infer whether or not this is an SVG element

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I thought it was the evaluated name, but it's just the variable name

however, how would you determine the tag value in this case? don't we have to do it at runtime?

<script>
	export let a = 'svg';
	export let b = 'path';
</script>

<svelte:element this={a}>
	<svelte:element this={b}></svelte:element>
</svelte:element>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't determine it statically in this case, and determining it at runtime would mean loading a long list of tags into the runtime, which I'm not sure if it's worth it. I'm ok with this not working for now, AFAIK this also doesn't work in Svelte 4.

Copy link
Contributor Author

@eEQK eEQK Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it does not work in Svelte 4. Should I also add other tests that will be failing? using slots/snippets is not working either (both in svelte 4 and 5)

as for doing this at runtime - don't we only have to check if one of the parents is an svg without custom namespace?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs to be determined at runtime, yeah, but I'm pretty sure we only need to check two cases:

  • value is "svg" — it's an SVG element
  • value is "foreignObject" — it's an HTML element
  • otherwise inherit namespace from parent element

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a go at this and it's unfortantely not possible to determine in some cases:
If this is client-side only (i.e. no hydration) and the first run, then the anchor from which we'll get the parent element will not be attached to its parent yet, so the parent element is null and we can't know.

packages/svelte/src/internal/client/render.js Outdated Show resolved Hide resolved
packages/svelte/src/compiler/phases/2-analyze/index.js Outdated Show resolved Hide resolved
context.state.analysis.elements.push(node);

const is_svg_element =
(node.tag.type === 'Identifier' && node.tag.name && SVGElements.includes(node.tag.name)) ||
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I thought it was the evaluated name, but it's just the variable name

however, how would you determine the tag value in this case? don't we have to do it at runtime?

<script>
	export let a = 'svg';
	export let b = 'path';
</script>

<svelte:element this={a}>
	<svelte:element this={b}></svelte:element>
</svelte:element>

@zhihengGet
Copy link

just wondering if theres any progress on this :( , my lucide -svelte icons looks blank for couple months now xd

@dummdidumm dummdidumm merged commit 77b4c4b into sveltejs:main Jan 29, 2024
6 of 8 checks passed
trueadm pushed a commit that referenced this pull request Jan 31, 2024
…10006)

Infer namespace from parents where possible, and do a runtime-best-effort where it's not statically known
fixes #9645

---------

Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
dummdidumm added a commit that referenced this pull request Apr 18, 2024
In #10006 we added more elaborate mechanisms to determine which namespace a given element is in. For `<svelte:element>` we added a "can't know at compile time" case and introduced a limited heuristic into the runtime.
This doesn't work for a few reasons:
- we're checking the parent's namespace to determine the current namespace, but the element itself could be the one that _changes_ the namespace
- as mentioned in the previous comment already, on the first render we can't do any parent analysis
- it does not take into account the static component namespace

The last point is the crucial one: In Svelte 4, we're falling back to the component namespace if we can't know statically - e.g. if someone added `<svelte:options namespace="svg">` then `<svelte:element>` should fall back to that namespace instead.
We were not doing that up until now, which introduced a regression. Fixing this also means getting rid of the (flawed) "can't know statically" heuristic.

Fixes #10858, though for a complete solution we likely need some way to tell `<svelte:element>` the namespace at runtime through a special attribute. Maybe we can use `xmlns` for that like we do in the static case
Rich-Harris pushed a commit that referenced this pull request Apr 18, 2024
* fix: fall back to component namespace when not statically determinable

In #10006 we added more elaborate mechanisms to determine which namespace a given element is in. For `<svelte:element>` we added a "can't know at compile time" case and introduced a limited heuristic into the runtime.
This doesn't work for a few reasons:
- we're checking the parent's namespace to determine the current namespace, but the element itself could be the one that _changes_ the namespace
- as mentioned in the previous comment already, on the first render we can't do any parent analysis
- it does not take into account the static component namespace

The last point is the crucial one: In Svelte 4, we're falling back to the component namespace if we can't know statically - e.g. if someone added `<svelte:options namespace="svg">` then `<svelte:element>` should fall back to that namespace instead.
We were not doing that up until now, which introduced a regression. Fixing this also means getting rid of the (flawed) "can't know statically" heuristic.

Fixes #10858, though for a complete solution we likely need some way to tell `<svelte:element>` the namespace at runtime through a special attribute. Maybe we can use `xmlns` for that like we do in the static case

* support dynamic svelte:element namespace through xmlns attribute

* fix
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Svelte 5: svg not visible when using lucide-svelte
4 participants