-
-
Notifications
You must be signed in to change notification settings - Fork 852
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
Map & Set support (v5) #354
Conversation
Might be nice to have the additional tests from #353 in this branch, in case we missed something? |
@mweststrate I wish you had told me you wouldn't let the PR for ES6 only maps to pass through in that thread. Though, yeah, it all happened really fast :) |
Do we want to have ES5 support or do we want to have IE11 support? I believe it's not the same thing. IE11 doesn't support iterators and lots of other methods according to MDN. |
quick update: I'll hope to get back to it next week, travelling this week,
so might not have time to look into it / answer the questions :)
…On Thu, Apr 18, 2019 at 6:12 PM Andrey Goncharov ***@***.***> wrote:
Do we want to have ES5 support or do we want to have IE11 support? I
believe it's not the same thing. IE11 doesn't support iterators and lots of
other methods according to MDN
<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Browser_compatibility>
.
This would still require to run some tests conditionally. It still would
be an issue if a project, successfully using Maps, all of a sudden has to
start supporting IE11. That kind of project still would have to be
refactored.
@mweststrate <https://github.com/mweststrate> are you firm on not letting
ES6 only implementation pass through? Since it's gonna be a major release
anyway, I guess it's ok to break things. Though IE11 folks wouldn't even be
broken, they'll just have to stick to the old way of working with Maps
manually. What we could do in this case is to add tests that the old way
still works as expected.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#354 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAN4NBHAAUNYDKWVL5PVWTTPRCMVDANCNFSM4HG5JYMQ>
.
|
Includes support for: - mutable drafts in `produce` callbacks - patch listeners BREAKING CHANGE: `Map` objects are now drafted
Support for patch listeners included BREAKING CHANGE: `Set` objects are now drafted
These traps ensure the underlying state is never touched by the user.
5e6dcf8
to
c90cd57
Compare
Added patch-related functionality for ES6 Sets. Items to discuss:
TODOs:
@aleclarson if you merge it to v4 branch, I'd be happy to carry on this discussion there, since it really does belong there. Originally posted by @keenondrums in #358 (comment) |
No, we should make sure changes to object keys have patches created for them, since Immer patches can be useful even when not serialized to JSON. Note: Immer prefers working with tree-like data structures, and I'm not sure what the bugs are when relational data is used.
To be clear, Immer patches aren't strictly JSON patches, but you must use JSON-only keys/values if you ever need to serialize the patches.
To not support ES5 would add unwanted complexity to the API for ES5 users. :( Originally posted by @aleclarson in #358 (comment) |
@aleclarson do we want to support ES5 (read it as environments that lack Proxy support) or IE11? It's not the same thing. As MDN states IE11 doesn't support |
Some random thoughts: I think it is fine to limit maps to only allow strings / numbers as keys. I think having objects as keys, which can then be updated in a producer as well, will get confusing very quickly, and just bailing out is probably better until we encounter a good RL use case The goal is to make sure devs can use immer safely inside consumer facing applications, without sudden suprises. In practice that means that we need to support ES5, or at least, things that can be polyfilled to ES 5. So in this specific case, whether The risky semantic difference here is that sets and maps would be treated totally different as soon as they are considered draftable. So it could be an option to only support sets and maps in a next major, but I think it would be a significant maintenance burden. Mostly being helping people out that, ignorantly, npm installed the latest version, work a while with that, use maps / sets (probably without checking the docs on that at all seemed to works ootb), and then discover that they have to rewrite a lot of code after a first round of QA on IE11... |
I don't think there's much valid use-cases outside of strings/numbers anyway. I think the main benefit of using a |
It's actually a very important use-case for Sets and Maps. Most of the time I reach for them it's for this property. |
@shabbyrobe I have to correct my statement. I think any valid key (including objects, symbols and etc.) is going to work with Maps. I just doubt if it's going to work with patches enabled. |
I resolved the merge conflicts. There might be some mistakes in there, as it was quite tricky. Some tests related to
Coming days I won't have time to further investigate, so I'll continue after that, or if anyone beats me to it, welcome :). Sorry, this got a lot more complicated than it ought to be as there were significant changes on master as well, but it is tricky to find them one by one due to the whitespace changes. I think it should be possible to build the traps up a bit more efficiently, but let's get the tests passing first. |
@mweststrate Git has options for merging without whitespace conflicts (see here). Maybe you should rebase and keep the tabs in place? |
Good one, gonna try that as well.
…On Wed, Oct 23, 2019 at 2:44 PM Alec Larson ***@***.***> wrote:
@mweststrate <https://github.com/mweststrate> Git has options for merging
without whitespace conflicts (see here
<https://stackoverflow.com/questions/9776527/merging-without-whitespace-conflicts>).
Maybe you should rebase and keep the tabs in place?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#354?email_source=notifications&email_token=AAN4NBBM7MKV2ICWGNQ32OTQQBILJA5CNFSM4HG5JYM2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECBOWTY#issuecomment-545450831>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBHZHHYDJ2QU7DLXFA3QQBILJANCNFSM4HG5JYMQ>
.
|
@mweststrate I've found a place where logic is broken. If we move back an old function, it will fail but only one test. I'll try to fix it tomorrow Line 141 in ae80361
|
@mweststrate I've fixed tests, but I've got doubts about expected behaviour on this line ff25a83#diff-b40ab5eb20dfada012e789db3e9780bbR142 |
@mweststrate I've fixed errors in ie11, but you may revert it if need ffd8769 |
@runnez thanks for investigating! Sorry for messing up that if-else logic while merging 😅 |
No I mean it is actually safe and a good idea to set is to a property
called "@@iterator" as fallback, as there are a couple of utility libraries
that actually look for that in the absence of a proper Symbol.iterator
…On Mon, Oct 28, 2019 at 1:41 PM Andrey Boldyrev ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/proxy.js
<#354 (comment)>:
> @@ -258,7 +259,7 @@ const mapTraps = makeTrapsForGetters({
keys: state => () => latest(state).keys(),
values: iterateMapValues,
entries: iterateMapValues,
- [Symbol.iterator]: iterateMapValues
+ [hasSymbol && Symbol.iterator]: iterateMapValues
I agree, it looks cleaner. But if env doesn't have Symbol, these code
won't fire. Or Did you mean only readability?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#354?email_source=notifications&email_token=AAN4NBDOA65PVS5WSLY735LQQ3TYRA5CNFSM4HG5JYM2YY3PNVWWK3TUL52HS4DFWFIHK3DMKJSXC5LFON2FEZLWNFSXPKTDN5WW2ZLOORPWSZGOCJMXPIA#discussion_r339567389>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBFP4V3YJYBC7VGI7RDQQ3TYRANCNFSM4HG5JYMQ>
.
|
@mweststrate did I understand you correctly? 24658bc |
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.
@runnez cool, thanks for the changes, that was what I was looking for indeed!
Did an in-depth review / test, and I think this is starting to look really solid now! Left a bunch of comments, but I think all the hard stuff is done :) Just pushed a few commits as well, so feel free to review them.
obj2.val = "you" | ||
}, | ||
[ | ||
{op: "remove", path: [0], value: {id: 1, val: "We"}}, |
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'd expect patches here that capture that the modification was only the object inside the sets, rather than patches on the set itself, like:
op: "replace", path: [1, "val"], value: "will"
Is there a special reason the entire set entry gets reconstructed? (I agree that the concept of indices in a set can be challenged, and maybe your approach is more correct, but sets guarantee insertion order, so I think it should be ok rely on paths in sets?)
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 think this quite an edge case anyway, so we could also open it as a fresh follow up issue, and see if anybody runs into the difference, before doing anything.
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.
Ambiguity of indices in Sets was the primary reason. As you said, you can iterate over them, however, you cannot get an item at index.
Love the idea of leaving this edge case out of the PR.
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.
See #450
* Map drafts | ||
*/ | ||
|
||
const mapTraps = makeTrapsForGetters({ |
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.
Random thought: could we use the ES5 implementation, and not use Proxies for maps and sets at all? If that would simplify the implementation that would be cool. If "ES5" administration doesn't play nicely inside a proxy draft tree, than lets leave it as is. But proxies themself don't add much for maps and sets, since all object interactions are through functions anyway.
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.
Could also be opened as follow up optimization issue, to reduce the package size
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 think it's possible to use one codebase for Map and Set and use both Proxy and ES5 mechanics. Let's do it as a follow up issue
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.
See #449
Perfect, I'll try to wrap up remaining things and cut a release tonight :)
…On Wed, Oct 30, 2019 at 3:35 PM Andrey Boldyrev ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/proxy.js
<#354 (comment)>:
> + "ownKeys",
+ "has",
+ "set",
+ "deleteProperty",
+ "defineProperty",
+ "getOwnPropertyDescriptor",
+ "preventExtensions",
+ "isExtensible",
+ "getPrototypeOf"
+])
+
+/**
+ * Map drafts
+ */
+
+const mapTraps = makeTrapsForGetters({
I think it's possible to use one codebase for Map and Set and use both
Proxy and ES5 mechanics. Let's do it as a follow up issue
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#354?email_source=notifications&email_token=AAN4NBCTZ5EMAOAT3D65XNTQRGSVTA5CNFSM4HG5JYM2YY3PNVWWK3TUL52HS4DFWFIHK3DMKJSXC5LFON2FEZLWNFSXPKTDN5WW2ZLOORPWSZGOCJXZP6Q#discussion_r340691973>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAN4NBC3PVUD372EOBGKH4LQRGSVTANCNFSM4HG5JYMQ>
.
|
🎉 This PR is included in version 5.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Try v5.0.0 today!
Tasks
Map
/Set
support withsetUseProxies(true)
onDelete
/onAssign
hooks work with ES6 maps/sets (and write tests)Map
/Set
support in ES5 mode4.59 -> 6.28
gzipped, minified