Describe the bug
In Solid 2.0.0-beta.14, reconciling a tracked nested store value from an array to a plain object can corrupt the store proxy shape.
After replacing an array value with an object, the value can still behave like an array proxy. Array.isArray(store.value) stays true, and Object.keys(store.value) can throw a proxy invariant error.
Your Example Website or App
https://stackblitz.com/edit/solidjs-templates-xviezrmj?file=src%2FApp.tsx
import { createRenderEffect, createStore, reconcile } from 'solid-js';
export default function App() {
const [store, setStore] = createStore<any>({ value: [1, 2] });
createRenderEffect(
() => store.value,
() => {}
);
return (
<main>
<button
onClick={() => {
setStore(reconcile({ value: { a: 1 } }, 'id'));
console.log('isArray:', Array.isArray(store.value));
console.log('keys:', Object.keys(store.value));
console.log('value.a:', store.value.a);
}}
>
replace array with object
</button>
</main>
);
}
Steps to Reproduce the Bug or Issue
- Open the repro.
- Open the browser console.
- Click
replace array with object.
- Observe the console output.
isArray: true
TypeError: 'ownKeys' on proxy: trap result did not include 'length'
Expected behavior
After reconciling { value: [1, 2] } to { value: { a: 1 } }, the nested value should behave like a plain object:
isArray: false
keys: ["a"]
value.a: 1
Screenshots or Videos
No response
Platform
- OS: macOS
- Browser: Chrome
- Version: current stable
Additional context
This appears related to packages/solid-signals/src/store/reconcile.ts. When a nested value has already been tracked and then changes from array to object, reconcile appears to reuse/mutate the existing array-shaped proxy target instead of replacing it with an object-shaped value.
If Array.isArray(previousValue) !== Array.isArray(nextValue), reconcile likely needs to treat the nested value as a replacement rather than a same-shape merge.
Describe the bug
In Solid 2.0.0-beta.14, reconciling a tracked nested store value from an array to a plain object can corrupt the store proxy shape.
After replacing an array value with an object, the value can still behave like an array proxy.
Array.isArray(store.value)staystrue, andObject.keys(store.value)can throw a proxy invariant error.Your Example Website or App
https://stackblitz.com/edit/solidjs-templates-xviezrmj?file=src%2FApp.tsx
Steps to Reproduce the Bug or Issue
replace array with object.Expected behavior
After reconciling
{ value: [1, 2] }to{ value: { a: 1 } }, the nested value should behave like a plain object:Screenshots or Videos
No response
Platform
Additional context
This appears related to
packages/solid-signals/src/store/reconcile.ts. When a nested value has already been tracked and then changes from array to object, reconcile appears to reuse/mutate the existing array-shaped proxy target instead of replacing it with an object-shaped value.If
Array.isArray(previousValue) !== Array.isArray(nextValue), reconcile likely needs to treat the nested value as a replacement rather than a same-shape merge.