Skip to content

Commit

Permalink
Correctly Count Object References (vercel#10903)
Browse files Browse the repository at this point in the history
* Correctly Count Object References

* Make error message better

* add more tests
  • Loading branch information
Timer authored and ScriptedAlchemy committed Mar 17, 2020
1 parent d97739c commit ab7416d
Showing 1 changed file with 18 additions and 11 deletions.
29 changes: 18 additions & 11 deletions packages/next/lib/is-serializable-props.ts
Expand Up @@ -23,22 +23,26 @@ export function isSerializableProps(
)
}

const visited = new WeakSet()

function visit(value: any, path: string) {
function visit(visited: Map<any, string>, value: any, path: string) {
if (visited.has(value)) {
throw new SerializableError(
page,
method,
path,
'Circular references cannot be expressed in JSON.'
`Circular references cannot be expressed in JSON (references: \`${visited.get(
value
) || '(self)'}\`).`
)
}

visited.add(value)
visited.set(value, path)
}

function isSerializable(value: any, path: string): true {
function isSerializable(
refs: Map<any, string>,
value: any,
path: string
): true {
const type = typeof value
if (
// `null` can be serialized, but not `undefined`.
Expand All @@ -65,16 +69,18 @@ export function isSerializableProps(
}

if (isPlainObject(value)) {
visit(value, path)
visit(refs, value, path)

if (
Object.entries(value).every(([key, value]) => {
const nextPath = regexpPlainIdentifier.test(key)
? `${path}.${key}`
: `${path}[${JSON.stringify(key)}]`

const newRefs = new Map(refs)
return (
isSerializable(key, nextPath) && isSerializable(value, nextPath)
isSerializable(newRefs, key, nextPath) &&
isSerializable(newRefs, value, nextPath)
)
})
) {
Expand All @@ -90,11 +96,12 @@ export function isSerializableProps(
}

if (Array.isArray(value)) {
visit(value, path)
visit(refs, value, path)

const newRefs = new Map(refs)
if (
value.every((value, index) =>
isSerializable(value, `${path}[${index}]`)
isSerializable(newRefs, value, `${path}[${index}]`)
)
) {
return true
Expand Down Expand Up @@ -124,7 +131,7 @@ export function isSerializableProps(
)
}

return isSerializable(input, '')
return isSerializable(new Map(), input, '')
}

export class SerializableError extends Error {
Expand Down

0 comments on commit ab7416d

Please sign in to comment.