Description
Describe the bug
<!-- Child.svelte -->
<script>
let { toString } = $props()
console.log(toString)
</script>
<!-- Parent.svelte -->
<script>
import Component from "./Component.svelte"
</script>
<Component {...{}} />
Expected output: undefined
Actual output: function toString()
From the docs on the spread operator:
A single spread creates a shallow copy of the original object (but without non-enumerable properties and without copying the prototype)
In regular JS the object prototype (or any prototype for that matter) is never spread:
console.log({ toString: 123, ...{} })
// output: Object { toString: 123 }
The issue comes from this line:
However this is not an isolated case, the in
operator is used throughout the file above another 20+ times and is likely used many times in other places as well, causing similar issues.
In general, the in
operator is bad and 99% of the times you don't want to check the prototype, so Object.hasOwn
or Object.prototype.hasOwnProperty.call
should always be preferred. Maybe even ban in
using eslint.
Note this issue also causes legit props to be overridden/not accessible:
{@const obj= { somethingElse: 123 }}
<Component toString="legit" {...obj} />
<!-- In component, reading `toString` returns the function rather than "legit", even when it's typed as string -->
Reproduction
https://svelte.dev/playground/8d30600fe1c54c69a76146c602cd977d?version=5.34.1
Severity
serious