Skip to content

Commit

Permalink
fix: replace JSON.stringify with replaceDeepEqual in structural s…
Browse files Browse the repository at this point in the history
…haring integrity check (#8030)

* feat: throw when `replaceDeepEqual` contains circular references

* ci: apply automated fixes

* chore: up test

* chore: review changes

* ci: apply automated fixes

* chore: add return

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Dominik Dorfmeister <office@dorfmeister.cc>
  • Loading branch information
3 people authored Sep 9, 2024
1 parent d58cf08 commit 1bffc78
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 24 deletions.
50 changes: 30 additions & 20 deletions packages/query-core/src/__tests__/query.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -975,36 +975,46 @@ describe('query', () => {

const queryFn = vi.fn()

const data: Array<{
id: number
name: string
link: null | { id: number; name: string; link: unknown }
}> = Array.from({ length: 5 })
.fill(null)
.map((_, index) => ({
id: index,
name: `name-${index}`,
link: null,
}))

if (data[0] && data[1]) {
data[0].link = data[1]
data[1].link = data[0]
}

queryFn.mockImplementation(async () => {
await sleep(10)

const data: Array<{
id: number
name: string
link: null | { id: number; name: string; link: unknown }
}> = Array.from({ length: 5 })
.fill(null)
.map((_, index) => ({
id: index,
name: `name-${index}`,
link: null,
}))

if (data[0] && data[1]) {
data[0].link = data[1]
data[1].link = data[0]
}

return data
})

await queryClient.prefetchQuery({ queryKey: key, queryFn })
await queryClient.prefetchQuery({
queryKey: key,
queryFn,
initialData: structuredClone(data),
})

const query = queryCache.find({ queryKey: key })!

expect(queryFn).toHaveBeenCalledTimes(1)

expect(query.state.status).toBe('error')
expect(
query.state.error?.message.includes('Maximum call stack size exceeded'),
).toBeTruthy()

expect(consoleMock).toHaveBeenCalledWith(
expect.stringContaining(
'StructuralSharing requires data to be JSON serializable',
'Structural sharing requires data to be JSON serializable',
),
)

Expand Down
6 changes: 2 additions & 4 deletions packages/query-core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,15 +356,13 @@ export function replaceData<
} else if (options.structuralSharing !== false) {
if (process.env.NODE_ENV !== 'production') {
try {
JSON.stringify(prevData)
JSON.stringify(data)
return replaceEqualDeep(prevData, data)
} catch (error) {
console.error(
`StructuralSharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${options.queryHash}]: ${error}`,
`Structural sharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${options.queryHash}]: ${error}`,
)
}
}

// Structurally share data between prev and new data if needed
return replaceEqualDeep(prevData, data)
}
Expand Down

0 comments on commit 1bffc78

Please sign in to comment.