-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
[WIP] Fix various apollo-cache-inmemory 1.3.x bugs. #3964
[WIP] Fix various apollo-cache-inmemory 1.3.x bugs. #3964
Conversation
This is important because cache.readFragment passes a rootId to readQueryFromStore that is not always "ROOT_QUERY". cc @carllippert
Using a different fragmentMatcher function may produce different results, so it should factor into the StoreReader cache keys. This still assumes any given fragment matcher function is pure, in the sense that it will always return the same result given the same inputs. Also reverted 1acbef6 so that the defaultFragmentMatcher function is always the same function object in case no custom fragment matcher function is provided. @carllippert This may help with your fragment matching issues.
I'm experiencing exact the same problem. The first time it reads the correct fragment but the next time it will always return the first fragment even if the id is different. Updating the package (reverts to 1.2.10) did resolve the problem for now. |
@jelteliekens Can you confirm you were using |
So, I thought I had a reproduction, but I was mistakenly still using |
Before this change, we were retrieving an object from the cache every time we wanted to look up a single property of that object.
This should help with github.com/apollographql/react-apollo/issues/2442, as long as the known properties of query document nodes do not participate in cycles.
If npm install [email protected] |
@benjamn Apparently I also was using version 1.3.0. After updating to 1.3.3 this morning the problem went away so I think it's fixed now. Thanks! |
As explained here, with astonishing honesty: https://github.com/facebook/react-native/blob/98a6f19d7c41e1d4fd3c04d07bb2c4e627f21724/Libraries/vendor/core/Map.js#L44-L50 As reported most recently here: apollographql/react-apollo#2442 (comment) For the record, I have previously complained that these polyfills are simply buggy and should be replaced: #3394 (comment) While that is still true, this workaround should moot the debate. 🐮
69c678b
to
07f3f47
Compare
DUDE. It worked! Fragment match bug is fixed in 1.3.3 🎉 Pushing fix to our alpha channel right now to really see how the performance improvements are with 1.3 ( since this all started trying to improve performance ). Thanks so much for the fix! |
Awesome! By the way, the |
@benjamn -- Please let me know if you need any changes from apollo-link-rest or apollo-link-state to be more "spec-friendly" for these performance changes! |
Fixes apollographql/react-apollo#2442. This temporarily mitigates the prototype chain bug that will be permanently fixed by this React Native PR that I submitted yesterday: facebook/react-native#21492 I would like to find a way to bundle a different Map polyfill in React Native apps, without increasing bundle sizes for non-RN apps, but that has proven tricky so far. For future reference, this seems to be the way to do it (thanks to @peggyrayzis for the tip): https://facebook.github.io/react-native/docs/platform-specific-code#platform-specific-extensions Until a new version of React Native is released with these changes included, the simplest way to fix the problem is simply to avoid storing any prototype objects in a Map, so that's what I've done in this commit. We are already wrapping Object.freeze and friends in src/fixPolyfills.ts, which should make it possible to use frozen objects as Map keys (the other bug that I addressed in the React Native PR linked above).
1fe97f9
to
cbd0314
Compare
@fbartho I don't think I have any warnings or suggestions for you right now. The problems with the |
@benjamn Speaking as a user & contributor to apollo / apollo-link-rest / apollo-link-state on react-native, I'm invested 😉 -- My question was actually also more about if you need help testing any of these changes with apollo-link-rest. |
React Native used to have Map and Set polyfills that relied on tagging objects with a special __MAP_POLYFILL_INTERNAL_HASH__ property, which breaks down when the object to be tagged happens to be frozen. In 833072e (#3964) I introduced a workaround to make sure objects got tagged before becoming non-extensible, which robustly solved the problem for any Map and Set polyfills that rely on an object tagging strategy. Note that Apollo Client freezes objects only in development (using maybeDeepFreeze), so the problem fixPolyfills.ts was intended to solve was only ever a problem in development. I also submitted a PR to React Native that make their Map and Set polyfills store non-extensible objects in an array, rather than attempting to tag them: facebook/react-native#21492. Those changes were first released in React Native 0.59.0, so technically the fixPolyfills.ts logic should not be necessary for anyone using that version or later. Since then, React Native has stopped using any polyfills for Map and Set (yay!), so the need for the workaround has been even further reduced: facebook/react-native@93b9ac7 Those changes were first released in React Native 0.61.0, which is still the latest minor version (0.61.5 is latest). I'm not sure how many people are still using older versions of React Native, or what sort of LTS policies they have. Expo SDK 36 uses 0.61.4, for what it's worth: https://docs.expo.io/versions/latest/sdk/overview/ In any case, I think we can eliminate these polyfills from the default bundle, as long as we take some care to include them when bundling for React Native. This strategy uses a combination of techniques for selective bundling in React Native: https://facebook.github.io/react-native/docs/platform-specific-code#platform-specific-extensions facebook/react-native#2208
React Native used to have Map and Set polyfills that relied on tagging objects with a special __MAP_POLYFILL_INTERNAL_HASH__ property, which breaks down when the object to be tagged happens to be frozen. In 833072e (#3964) I introduced a workaround to make sure objects got tagged before becoming non-extensible, which robustly solved the problem for any Map and Set polyfills that rely on an object tagging strategy. Note that Apollo Client freezes objects only in development (using maybeDeepFreeze), so the problem fixPolyfills.ts was intended to solve was only ever a problem in development. I also submitted a PR to React Native that make their Map and Set polyfills store non-extensible objects in an array, rather than attempting to tag them: facebook/react-native#21492. Those changes were first released in React Native 0.59.0, so technically the fixPolyfills.ts logic should not be necessary for anyone using that version or later. Since then, React Native has stopped using any polyfills for Map and Set (yay!), so the need for the workaround has been even further reduced: facebook/react-native@93b9ac7 Those changes were first released in React Native 0.61.0, which is still the latest minor version (0.61.5 is latest). I'm not sure how many people are still using older versions of React Native, or what sort of LTS policies they have. Expo SDK 36 uses 0.61.4, for what it's worth: https://docs.expo.io/versions/latest/sdk/overview/ In any case, I think we can eliminate these polyfills from the default bundle, as long as we take some care to include them when bundling for React Native. This strategy uses a combination of techniques for selective bundling in React Native: https://facebook.github.io/react-native/docs/platform-specific-code#platform-specific-extensions facebook/react-native#2208
Since publishing
[email protected]
officially, several bugs have been reported, so we have removed thelatest
tag from 1.3.0 and restored the old 1.2.10 version aslatest
. The most recent 1.3.x release is now tagged asnext
, so you can install it by runningThe more information we include in the cache keys used by the
InMemoryCache
, the more different cached results can be distinguished from one another. It's a bug if a change in some input value can change the result without also producing a different cache key. The typical solution is to include the relevant input data in the cache key returned bymakeCacheKey
. Note that not all input data needs to be included explicitly in the cache key, since some inputs are simply derived from other inputs.Related bugs, possibly also fixed by this PR: