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

Top level {@html ...} not working if component rendered to ShadowRoot #8038

Closed
jhony1104 opened this issue Nov 18, 2022 · 2 comments
Closed

Comments

@jhony1104
Copy link

jhony1104 commented Nov 18, 2022

Describe the bug

If a Svelte component is rendered to a ShadowRoot, it is not possible to create a top level {@html ...} tag.

The element creation fails with:

DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('#document-fragment') is not a valid name.

It works if {@html ...} is wrapped by another element.

Reproduction

https://stackblitz.com/edit/vitejs-vite-wc4uwt?file=src/App.svelte

Logs

DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('#document-fragment') is not a valid name.
    at element (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/.vite/deps/chunk-BJ76AV5Z.js?v=921e7c36:333:19)
    at HtmlTag.m (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/.vite/deps/chunk-BJ76AV5Z.js?v=921e7c36:700:18)
    at Object.mount [as m] (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/src/App.svelte?t=1668790976113:43:13)
    at mount_component (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/.vite/deps/chunk-BJ76AV5Z.js?v=921e7c36:1686:24)
    at init (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/.vite/deps/chunk-BJ76AV5Z.js?v=921e7c36:1765:5)
    at new App (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/src/App.svelte?t=1668790976113:83:3)
    at createComponent (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/svelte-hmr/runtime/svelte-hooks.js?v=921e7c36:206:20)
    at targetCmp.$replace (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/svelte-hmr/runtime/svelte-hooks.js?v=921e7c36:269:15)
    at refreshComponent (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/svelte-hmr/runtime/proxy.js?v=921e7c36:171:15)
    at ProxyAdapterDom.rerender (https://vitejs-vite-wc4uwt--5173.local-credentialless.webcontainer.io/node_modules/svelte-hmr/runtime/proxy-adapter-dom.js?v=921e7c36:77:5)

System Info

System:
    OS: Linux 5.10 Debian GNU/Linux 11 (bullseye) 11 (bullseye)
    Container: Yes
    Shell: 5.1.4 - /bin/bash
  Binaries:
    Node: 16.18.1 - /usr/bin/node
    npm: 8.19.2 - /usr/bin/npm
  Browsers:
    Vivaldi: 5.5.2805.44 (blink/chromium based)
  npmPackages:
    svelte: ^3.52.0 => 3.53.1 
    vite: ^3.2.3 => 3.2.4
@jhony1104
Copy link
Author

jhony1104 commented Nov 22, 2022

The reason fo this seems to be, that HtmlTag internally creates an element of the same type as its target element. (L705)

m(
html: string,
target: HTMLElement | SVGElement,
anchor: HTMLElement | SVGElement = null
) {
if (!this.e) {
if (this.is_svg) this.e = svg_element(target.nodeName as keyof SVGElementTagNameMap);
else this.e = element(target.nodeName as keyof HTMLElementTagNameMap);
this.t = target;
this.c(html);
}
this.i(anchor);
}

But the shadowRoot element is special and has only #document-fragment as its nodeName. And it is impossible to create a #document-fragment element with document.createElement(), which is used by element() .

If one wants to create a element of the same type as the target, an alternative would be to use the host type.

Possibely something like this:

m(
    html: string,
    target: HTMLElement | SVGElement | ShadowRoot,
    anchor: HTMLElement | SVGElement = null
) {
    if (!this.e) {
        if (this.is_svg) this.e = svg_element(target.nodeName as keyof SVGElementTagNameMap);
        else if ("host" in target) this.e = element(target.host.nodeName as keyof HTMLElementTagNameMap);
        else this.e = element(target.nodeName as keyof HTMLElementTagNameMap);
        this.t = target;
        this.c(html);
    }

    this.i(anchor);
}

@jhony1104
Copy link
Author

related to #7319 and fixed by #7364

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

No branches or pull requests

1 participant