Skip to content
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

Maximum call stack size exceeded possible in query with object queried at multiple graphql paths #4081

Closed
abergenw opened this issue Oct 31, 2018 · 5 comments
Assignees

Comments

@abergenw
Copy link
Contributor

I have a query somewhat with the following structure:

query TestQuery {
  authenticatedUser {
    ...UserFragment
      
    company {
      users {
        ...UserFragment
      }
    }
  }
}

fragment UserFragment on User {
  firstName
  company {
    id
  }
}

If the same company (same id) is returned both under authenticatedUser > company and authenticatedUser > company > users > company, it seems like the same object instance is returned from apollo-cache-inmemory. This has all sorts of implications, not least as it can lead to the resulting object having a cyclic nature making Apollo cause a RangeError when using isEqual.

I suspect this is because in the above example the company selection set is cached (with users) and thus not evaluated correctly for authenticatedUser > company > users > company (without users). Maybe @benjamn can confirm this?

Versions

System:
OS: macOS High Sierra 10.13.6
Binaries:
Node: 8.11.4 - /usr/local/bin/node
Yarn: 1.10.1 - /usr/local/bin/yarn
npm: 5.6.0 - /usr/local/bin/npm
Browsers:
Chrome: 70.0.3538.77
Safari: 12.0
npmPackages:
apollo-cache-inmemory: 1.3.7 => 1.3.7
apollo-client: 2.4.5 => 2.4.5
apollo-link-batch-http: 1.2.3 => 1.2.3
react-apollo: 2.2.4 => 2.2.4
npmGlobalPackages:
apollo-codegen: 0.10.5

@abergenw abergenw changed the title Range error: Maximum call stack size exceeded possible in query with object queried at multiple graphql paths Maximum call stack size exceeded possible in query with object queried at multiple graphql paths Oct 31, 2018
@benjamn
Copy link
Member

benjamn commented Oct 31, 2018

Can you put together a CodeSandbox reproduction? We shouldn't be returning the same company object for authenticatedUser > company as we're returning for the ... users > company objects, since the selection sets have a different structure. However, the same company object could appear multiple times for different users. That by itself shouldn't create cycles, but maybe there's something else happening.

@abergenw
Copy link
Contributor Author

abergenw commented Nov 1, 2018

Here's a simple reproduction:

https://codesandbox.io/s/94w34wx1ow

I also quickly tried creating a test only for apollo-cache-inmemory but for some reason I couldn't get the problem to occur while only testing readQueryFromStore.

@benjamn benjamn self-assigned this Nov 2, 2018
benjamn added a commit that referenced this issue Nov 2, 2018
As #4081 demonstrates, if there are key collisions during result merging,
it's possible for source objects that were previously merged by reference
into the target object (finalResult.result) to be modified destructively
by later merges, which in some cases can lead to cycles in the results
returned by the cache.

This version of the merge function uses a copy-on-first-write strategy to
ensure we never modify target objects that might once have been source
objects. The code could have been considerably simpler if I didn't try to
track pastCopies, but performance and memory usage are very important for
this code, which is why I went to the trouble of limiting the number of
shallow copies made during a single merge.
@benjamn
Copy link
Member

benjamn commented Nov 2, 2018

@abergenw I believe I've tracked this bug down to the merge function in readFromStore.ts, and I've submitted a PR to be extra careful never to modify cached result objects. I'm still very much planning to add a regression test, though that's been a bit tricky (as you noticed above). In the meantime, I've published a beta version to npm. Please try updating to apollo-cache-inmemory@1.3.9-beta.1 when you have the chance!

@abergenw
Copy link
Contributor Author

abergenw commented Nov 2, 2018

I can confirm that apollo-cache-inmemory@1.3.9-beta.1 works like a charm. Good work @benjamn!

benjamn added a commit that referenced this issue Nov 2, 2018
@benjamn
Copy link
Member

benjamn commented Nov 3, 2018

Since apollo-cache-inmemory@1.3.9 has been published, I think this is fixed. Thanks for reporting this issue, @abergenw!

@benjamn benjamn closed this as completed Nov 3, 2018
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants