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

Support non-list variables for list arguments #1043

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

Shane32
Copy link

@Shane32 Shane32 commented Aug 29, 2023

@netlify
Copy link

netlify bot commented Aug 29, 2023

Deploy Preview for graphql-spec-draft ready!

Name Link
🔨 Latest commit 3dfc15c
🔍 Latest deploy log https://app.netlify.com/sites/graphql-spec-draft/deploys/64ee5a0232c6af000800db13
😎 Deploy Preview https://deploy-preview-1043--graphql-spec-draft.netlify.app/draft
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@Shane32
Copy link
Author

Shane32 commented Aug 29, 2023

Example stepping through logic for AreTypesCompatible with new steps when comparing list-type locations with non-list type variables:

Step Scenario 1 Scenario 2 Scenario 3 Scenario 4 Scenario 5
variableType String String! String String! String
locationType [String!] [String!] [String] [String] [String]!
1 Is locationType is non-null type false false false false true
1a If variableType is NOT a non-null type true - return false
2 if variableType is a non-null type false true false true
2a let nullableVariableType... String String
2b AreTypesCompatible String, [String!] String, [String]
3 if locationType is a list type true true
3a let itemLocationType String! String
3b If variableType is NOT a list type true true
3b1 If itemLocationType is a non-null type true false
3b1a Let nullableItemLocationType... String
3b1b AreTypesCompatible String, String
3b2 AreTypesCompatible String, String

@Shane32
Copy link
Author

Shane32 commented Aug 29, 2023

Note that no rules have changed for how default values for variables work. Since all existing nullability checks apply to the outermost layer, all are still valid with these new rules, in line with 'option 5' outlined in #1033.

Comment on lines +1899 to +1902
- If {itemLocationType} is a non-null type:
- Let {nullableItemLocationType} be the unwrapped nullable type of {itemLocationType}.
- Return {AreTypesCompatible(variableType, nullableItemLocationType)}.
- Otherwise, return {AreTypesCompatible(variableType, itemLocationType)}.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this is simpler to write and equally as effective (and potentially more understandable):

Suggested change
- If {itemLocationType} is a non-null type:
- Let {nullableItemLocationType} be the unwrapped nullable type of {itemLocationType}.
- Return {AreTypesCompatible(variableType, nullableItemLocationType)}.
- Otherwise, return {AreTypesCompatible(variableType, itemLocationType)}.
- If {itemLocationType} is a non-null type:
- Let {nonNullVariableType} be the non-null type of {variableType}.
- Return AreTypesCompatible(nonNullVariableType, itemLocationType).

However, all the rest of the logic favors unwrapping types, rather than wrapping types. So with a single extra line in the logic here, we are only unwrapping types, and never wrapping types.

@Shane32
Copy link
Author

Shane32 commented Oct 16, 2023

GraphQL.NET's implementation of this is here, locked behind an experimental option flag:

@benjie
Copy link
Member

benjie commented Oct 16, 2023

If you haven't already, please consider adding this to an upcoming GraphQL Working Group. Let me know if you need any guidance.

https://github.com/graphql/graphql-wg/tree/main/agendas/2023

@benjie
Copy link
Member

benjie commented Oct 16, 2023

Oops, just saw #1033 (comment)

Copy link
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change alone is not sufficient; the behavior must also be adopted in CoerceArgumentValues:

https://spec.graphql.org/draft/#sec-Coercing-Field-Arguments

Specifically 5.f.iii.

  1. Let value be the value provided in variableValues for the name variableName.

Would need to become something like:

  1. Let {variableValue} be the value provided in {variableValues} for the name {variableName}.
  2. If {hasValue} is {false}, or {variableValue} is {null}, or {variableValue} is a list, or {argumentType} is neither a list type nor a non-null list type, or {variableType} is either a list type or a non-null list type, then:
    1. Let {value} be {variableValue}.
  3. Otherwise:
    1. Let {value} be a list containing the single value {variableValue}.

Further we'd need to change logic in coercion too, for which it would be wise to land #1058 first.

@benjie
Copy link
Member

benjie commented Nov 10, 2023

I think we'd wrap all of that above in its own algorithm, something like:

  1. Let {value} be {CoerceVariableValue(variableName, argumentType)}.

@benjie
Copy link
Member

benjie commented Nov 10, 2023

Before working any more on this, I recommend that we land:

I then have edits in mind that I think would make this a clearer win.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants