graphql-js icon indicating copy to clipboard operation
graphql-js copied to clipboard

`RangeError` for combination of recursive input and default value

Open mat-sop opened this issue 2 years ago • 1 comments

Hi, I was working with input fields' default values in graphql-core and I encountered a problem with a combination of recursive inputs and default values which also occurs in graphql-js. Let's take this SDL as an example:

"""Example 1"""
type Query { field(recursiveInput: RecursiveInput): String }

input RecursiveInput {
  self: RecursiveInput = {value: "foo"}
  value: String 
}

If I understand correctly that example is invalid, because {value: "foo"} is lacking the self field, then the default value for self is looked up, which leads to a recursion error - RangeError: Maximum call stack size exceeded.

When the default value is removed, everything works fine:

"""Example 2"""
type Query { field(recursiveInput: RecursiveInput): String }

input RecursiveInput {
  self: RecursiveInput
  value: String 
}

However, the following also looks fine, because self doesn't need to be looked up, but it still causes a recursion error:

"""Example 3"""
type Query { field(recursiveInput: RecursiveInput): String }

input RecursiveInput {
  self: RecursiveInput = {value: "foo", self: null}
  value: String 
}

On the other hand, the following actually invalid example does not give an error:

"""Example 4"""
type Query { field(recursiveInput: RecursiveInput): String }

input RecursiveInput {
  self: RecursiveInput!
  value: String 
}

If I'm not mistaken:

  • Example 1 should produce a proper error instead of creating a stack overflow
  • Example 3 should not produce an error
  • Example 4 should produce an error showing that this is an invalid definition

To test all examples I used [email protected] and following code:

const { buildSchema } = require('graphql');
const schemaString = `...`;
const schema = buildSchema(schemaString);

mat-sop avatar Mar 31 '23 10:03 mat-sop

Ses also the section on Circular References in the GraphQL spec which explicitly states that example 2 is valid, while example 4 is invalid. From the section I would also conclude that example 3 is valid, while example 1 is invalid, though the documentation is less clear about it, and does not contain examples with default values.

Cito avatar Mar 31 '23 10:03 Cito