sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.63k stars 4.13k forks source link

Svelte component nested inside a <svelte:element> with dynamic 'this' breaks attribute reactivity #9742

Open ranjan-purbey opened 10 months ago

ranjan-purbey commented 10 months ago

Describe the bug

Nesting a svelte component inside a with dynamic this like this:

<svelte:element this={"div"}>
  <MyComponent />
</svelte:element>

breaks attribute reactivity for the entire svelte block. Though content reactivity is not affected.

This issue doesn't pop up when either the this attr is static (like this="div" instead of this={"div"}) or, when the svelte:element doesn't have any other svelte components as children.

The bug affects all svelte versions that support svelte:element including v3.47.0 (except svelte 5 preview).

Reproduction

  1. Go to example repl.
  2. Try toggling the checkbox and notice the border style of the following div change.
  3. Uncomment line 12 (<MyComponent/> inside <svelte:element>)
  4. Repeat step 2 but border style doesn't change now.
  5. Make the this attribute of svelte:element static by removing the curly braces.
  6. Repeat step 2 and this time border style does change.

Logs

No response

System Info

Svelte repl

Severity

blocking all usage of svelte

ranjan-purbey commented 10 months ago

Idk if this change makes sense, but it seems to solve the issue as well as passes all existing tests

diff --git a/packages/svelte/src/compiler/compile/render_dom/Block.js b/packages/svelte/src/compiler/compile/render_dom/Block.js
index 7f0f37aa7..ed076ea42 100644
--- a/packages/svelte/src/compiler/compile/render_dom/Block.js
+++ b/packages/svelte/src/compiler/compile/render_dom/Block.js
@@ -265,6 +265,8 @@ export default class Block {
       this.add_variable({ type: 'Identifier', name: '#current' });
       if (this.chunks.intro.length > 0) {
         this.chunks.intro.push(b`#current = true;`);
+      }
+      if (this.chunks.mount.length > 0) {
         this.chunks.mount.push(b`#current = true;`);
       }
       if (this.chunks.outro.length > 0) {
jweston491 commented 5 months ago

Ran into this issue as well, using svelte@4.2.9