-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Svelte 5: $state rune on classes breaks enumeration #9699
Comments
Runes in classes get transformed into get/set properties which live on the class prototype, the observed behavior is just a result of that as that applies to all classes. In the final release it probably should be documented that these side effects are to be expected. (You should not try to spread class instances anyway, you lose the prototype.) |
@brunnerh The transformation of runes into getters/setters on the prototype makes it extremely difficult to write generalised code using classes that include runes. Adding getters and setters to a class does not mark the property as enumerable on the class as well as the object. It does not only break spreading, but Since it changes the behaviour greatly and there is no trivial workaround, I don't think this problem just needs to be documented. |
That is not really an option. The whole point of the classes approach is to provide raw performance and this would put a large dent in that. Runes are still in flux, in the end you might not need to use class syntax unless for very specific cases where the performance is more important than the ergonomics. |
Making runes directly usable in objects would be a great solution. If this is not possible the compiler could also mark the properties as enumerable on the class prototype. This would at least allow class Test{
get prop1(){ ...}
set prop1(){ ...}
get prop2(){ ...}
set prop2(){ ...}
}
Object.defineProperties(Test.prototype, {
"prop1": {
enumerable: true
},
"prop2": {
enumerable: true
}
}) While this is a pretty ugly solution, I don't think this would have any performance implications except making the bundle slightly larger. |
@JanNitschke Unfortunately, due to how we implement this on classes (we use private fields) the Personally, I'm of the opinion that maybe this is best solved using class Text extends Record { } Where |
What's the use case behind this that can't be solved with a POJO (i.e. |
Closing this, as I suspect |
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.
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
The text was updated successfully, but these errors were encountered: