pmndrs / valtio

🧙 Valtio makes proxy-state simple for React and Vanilla
https://valtio.dev
MIT License
9.02k stars 251 forks source link

fix(vanilla): Prevent adding new property on snapshot #752

Closed pastelmind closed 1 year ago

pastelmind commented 1 year ago

Related Issues or Discussions

Partially deals with #749 by disallowing property addition (but does not completely fix it, since we still allow property removal)

Summary

As a performance optimization, we currently mark properties of snapshots as configurable. This allows users to inadvertently add or remove properties on a snapshot object with no warning. Although TypeScript typings do prevent this to a degree, it is not foolproof.

While we currently do not have a robust solution that disallows property removal while maintaining the current level of performance, we can prevent addition of new properties on the snapshot by calling Object.preventExtensions() on it.

Check List

vercel[bot] commented 1 year ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
valtio ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 10, 2023 2:12pm
codesandbox-ci[bot] commented 1 year ago

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 135fdf0dc56892ada6c8701fea663a331a8b2a1c:

Sandbox Source
React Configuration
React Typescript Configuration
React Browserify Configuration
React Snowpack Configuration
React Parcel Configuration
dai-shi commented 1 year ago

Seems like #519 codesandbox works well too.

dai-shi commented 1 year ago

I'll make this to mark #749 as closed as nothing else is actionable. Please open a new discussion for more implementation ideas.

lovetingyuan commented 1 year ago

this change cause an error, call ownKeys in Proxy object, ownKeys target is non-extensible but key is missing from trap result

pastelmind commented 1 year ago

Could you elaborate? Please provide some sample code so we can understand it.

lovetingyuan commented 1 year ago

Could you elaborate? Please provide some sample code so we can understand it.

I use valtio in expo project, I think the problem may be related to [Hermes](https://reactnative.dev/docs/hermes) engine? I am not sure. Here is example repo: https://github.com/lovetingyuan/expo-example

setup development environment for expo, then run npm run android, click the detail button

lovetingyuan commented 1 year ago

when I add "jsEngine": "jsc", in app.json, there is no error. So this issue is highly possible related to hermes engine.

lovetingyuan commented 1 year ago

I create an issue in hermes repo https://github.com/facebook/hermes/issues/1063, you can take a look.

pastelmind commented 1 year ago

If this is an engine bug in Hermes, I'm OK with reverting the change for now while we investigate the issue.

pastelmind commented 1 year ago

From https://github.com/pmndrs/valtio/discussions/764 reported by @afkcodes, I hypothesize that Hermes may be implementing Object.preventExtensions() in such a way that it also makes existing properties non-writable and non-configurable, a la Object.freeze(). This could be wrong ofc. But if true, then we may have no choice but to remove Object.preventExtensions().

My investigations in https://github.com/pmndrs/valtio/discussions/764#discussioncomment-6517634 https://github.com/pmndrs/valtio/discussions/764#discussioncomment-6521744 indicate that the actual culprit may be a defineProperty proxy trap bug in Hermes. I suggest we continue this discussion in #765 as it is more visible than a closed pull request.

afkcodes commented 1 year ago

This i have validated and have found that this is true, i have my state typed, thanks @pastelmind