Various improvements around previousResult/newData change detection. #4032
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #3992, along with a few other miscellaneous improvements.
As #3992 (and specifically the reproduction that @OurMajesty provided) demonstrates, now that the
InMemoryCache
may return the same object for multiple reads (when the data have not changed), thepreviousResult
is often exactly (===
) the same object asnewData.result
, which was causing the code removed by this commit to return early instead of broadcasting the watch.This early return was unsafe, because the contents of the object may have changed since they were previously broadcast, so we actually do need to report those modifications, even though the object reference is the same.
In other words,
previousResult === newData.result
does not imply "nothing has changed," as I mistakenly assumed in this discussion: #3394 (comment)In the longer term, I would like to eliminate the
previousResult
logic entirely, since it seems redundant now that we can precisely track changes to the store, but for now it's important for backwards compatibility. Specifically,previousResult
still provides a way to prefer the previous object if it is structurally identical to the new object, though of course that preference is moot whenpreviousResult === newData.result
.The
previousResult
object should never be used as a basis for skipping broadcasts. Only the application developer can decide whether===
object identity means it's safe to skip rendering, likely in the context of a larger design which treats cache results as immutable data. The job of theInMemoryCache
is to make no unsound assumptions, and to broadcast results whenever they may have changed.