Skip to content

Svelte 5: $state rune on classes breaks enumeration  #9699

@JanNitschke

Description

@JanNitschke

Describe the bug

using the $state rune on class properties hides them from Object enumeration.
Object.keys(), for in, spreading to clone do not work as I would expect.

<script>
class ToDo{
  id = 0
  name = $state(name)
  constructor(name){ 
    this.name = name;
  }
}
Objects.keys(new ToDo("test")) // ["id"]
for(let prop in new ToDo("test")){
  console.log(prop) // "id"
} 
console.log({...(new ToDo("test"))}.name) // undefined
</script>

Cause

The compiler changes the name field on the instance to private (#name) removing it from enumeration. The getters and setters are created attached to the class/prototype instead of the instance. The way they are set also hides them from direct enumeration on the prototype.
The behaviour of enumeration in JS in combination with prototype chains leads to the rune having a bigger effect than most developers would expect.

This could be fixed by injecting Object.defineProperties(...) into the constructor instead of getters and setters on the class.

Reproduction

https://svelte-5-preview.vercel.app/#H4sIAAAAAAAAE21TyY7bMAz9FVadg40JnJ6zDFB0-YLe4hw0Eu0IVSRDotMWhv-9oqxkkk4vlri8x0eRnkRnLEaxOUzCyTOKjfg8DGIl6M_ARrygJUx29GNQ7NlFFcxAL61rySJBbzTs4dOWbWVljPDDf_UTmy3lWMp4ft4uDq6RXE-RJGHVilbUJaK8ixRGRT5UnFUXipboZGJTgHwUwMwHf4oQ8trHlHJw-CtrSPTj0AepEZY2UrEV3EW_m9_wOvYx-eG4EGUVQEGqn19O0vXIjBVaPKOjGvYvUGRxRW-5valpmpIwF2lvHXmLjfV9lVJXULJWDMwN1VtYr3NPYCI4TzAE4wg1SKezrax3qO9Zn7DrUFFV3atpqfMBKhY1BD-AcXDTfEu5MvyrjRE1C9EeFxWGMKT5gL9gyPL-R2G667scmOEIH_Z77myx6vuyD-VaofLL6las4FbbIddS0tpbu9cZP1zev3nZhnrRls28Ck16km9SnarqYXD3s02RPLEE5pjbrd-W200fMaHLWsmYL5l9Z9wwErwapzcXaUfcTxzLE51hncDTmqFz-m3OXpvOoBabtNs4H-e_3BKzFnEDAAA=

Logs

No response

System Info

Tested in Chrome and Safari on macOS

Severity

blocking an upgrade

Metadata

Metadata

Assignees

No one assigned

    Labels

    awaiting submitterneeds a reproduction, or clarification

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions