mirror of https://github.com/sveltejs/svelte
The plain-object branch of clone copies keys onto a fresh `{}` with
`copy[key] = ...`. For the key `__proto__` that runs the setter inherited
from Object.prototype instead of creating a property, so the key is dropped
from the snapshot and, when its value is an object, becomes the snapshot's
prototype. The copy then answers for fields that were data:
const state = $state(JSON.parse('{"__proto__":{"admin":true},"b":2}'))
const snap = $state.snapshot(state)
Object.keys(snap) // ['b']
snap.admin // true
An own __proto__ key does not come from an object literal, it comes from
JSON, which is where state hydrated from a response, from storage, or from
a query string comes from.
structuredClone, which this same function falls back to for everything it
does not walk itself, keeps the key as an own property. Define the slot so
the walked path answers the same way.
pull/18629/head
parent
26786e9298
commit
82fc329384
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: keep an own `__proto__` key in `$state.snapshot`
|
||||
@ -0,0 +1,5 @@
|
||||
import { test } from '../../test';
|
||||
|
||||
export default test({
|
||||
html: `<div>["__proto__","b"]</div><div>true</div><div></div>`
|
||||
});
|
||||
@ -0,0 +1,11 @@
|
||||
<script>
|
||||
// An own `__proto__` key comes from JSON, which is where state hydrated
|
||||
// from a response, from storage, or from a query string comes from.
|
||||
let state = $state(JSON.parse('{"__proto__":{"admin":true},"b":2}'));
|
||||
|
||||
const snapshot = $state.snapshot(state);
|
||||
</script>
|
||||
|
||||
<div>{JSON.stringify(Object.keys(snapshot))}</div>
|
||||
<div>{Object.getPrototypeOf(snapshot) === Object.prototype}</div>
|
||||
<div>{snapshot.admin}</div>
|
||||
Loading…
Reference in new issue