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
Fix/es5 array delete error #173
Conversation
src/es5.js
Outdated
each(proxy, (index, child) => { | ||
if (!state.assigned[index]) markChangesRecursively(child) | ||
const {added, removed} = diffKeys(base, proxy) | ||
if (added.length > 0 || removed.length > 0) markChanged(state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is markChanged
called here again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah... sorry, it's a mistake.
@@ -125,15 +141,7 @@ export function applyPatches(draft, patches) { | |||
base[key] = patch.value | |||
break | |||
case "remove": | |||
if (Array.isArray(base)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine by just explicitly forbidding it (I mean, it is pretty weird to call delete
on an array, as splice
is the idiomatic way to remove entries in the middle). That als simplifies the rest of the implementation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In both proxy and es5 mode, when delete an array item wont't cause any error, unless calling applyPatches with the patches. I think it's better to use the patches to replay the actions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for example
let anArray = [1,2,3];
let changes = [];
produce(anArray, d => {
delete d[1];
}, (p, i) => {
changes = [...p];
})
let arr1 = applyPatches([1, 2], changes)
console.log(arr1) // [1]
let arr2 = applyPatches([1, 2, 3, 4], changes)
console.log(arr2) // throw "Remove can only remove the last key of an array"
the same patches apply on some data will lead to different result. It's so confused for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would simplify the entire solution to have the proxy trap throw on delete if the target is an array. delete
should not be used on arrays in producers period. It will keep the implementation of immer faster as well, compared to the current changes in the PR. If it was super easy it would be fine to support, but there is no real value in supporting it imho, so no reason to jump through hoops to get it working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that's may be a good idea.
Thanks for catching this error! I think it should be fine to just throw an error when |
I hope that the code can get the same behavior in both proxy and es5 mode, this is why I open this pr. |
I also find other two questions in the process. In this PR, I think I've resolved them.
2、
I'm not sure if I should open an issue or another PR , but I wish to get some suggestions from @mweststrate , expect for your replies. |
when delete array items in using es5 mode, the produce doesn't work.
for example:
finally,we get that fork is the same reference with base, the same time we get that the length of patches and inversePatches is zero.