sveltejs / svelte

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

Default values for array-like props breaks rendering #11647

Closed bertmad3400 closed 2 weeks ago

bertmad3400 commented 2 weeks ago

Describe the bug

This specific bug has been reported multiple times before (both here and in the language-tools repo - see https://github.com/sveltejs/svelte/issues/5673, https://github.com/sveltejs/language-tools/issues/1167 and https://github.com/sveltejs/language-tools/issues/2236), but I have dared to re-report it, both because I believe the following is a new perspective, and because it's a major, unaddressed bug currently completely breaking otherwise stable production applications for us.

The core of the issue is the fact that if the value of a prop with a default value changes to undefined, the prop doesn't take on the default value, but rather becomes undefined. Not only does this invalidate the types present (with no errors from the compiler), but this has the potential to completely break the app, should the prop be array like and be used in an each block. Even worse, arrays with undefined in props with default values works initially, but expanding or changing the array will mean that the undefined value will get re-passed to the component (even with keyed each blocks), this time removing the default value.

From our experience, this doesn't only throw an error, but completely breaks the rendering engine making the whole app fall apart and become completely unresponsive to the user. For us this is a really severe issue, currently breaking important, production apps, and without the proper typing, it is really, really tough to ensure that we catch all the places where this could happen. As this seems to have been resolved for Svelte 5, I would assume that a fix isn't going to get back-ported, but if anyone has any input on how to gracefully handle this, that would be massively appreciated

Reproduction

https://svelte.dev/repl/8e7f6c46501c49bca84afcc58bbcc82e?version=4.2.17

Click the "add list-element" button to make the array update, passing the undefined "tags" value of the second list item to the ListElement component for the second time, removing the default value and breaking the app (see console for error)

Logs

No response

System Info

Not relevant

Severity

blocking all usage of svelte

dummdidumm commented 2 weeks ago

Svelte 5 fixes this specific bug, and in runes mode, the behavior is changed to that of what you expect. We're not backporting this because it's a breaking change. As for how gracefully handle it: You can use a reactive statement to ensure the fallback is always applied like this:

    export let tags = []
    $: tags = tags ?? [];