@@ -1855,6 +1855,26 @@ variable.
1855
1855
1856
1856
### All Variable Usages Are Allowed
1857
1857
1858
+ As GraphQL evolves and issues are spotted and fixed, the specification aims to
1859
+ maintain compatibility with existing GraphQL documents. In rare cases, this
1860
+ requires two versions of an algorithm, a Legacy Algorithm which supports clients
1861
+ with both old and new GraphQL documents, and a Strict Algorithm which only
1862
+ supports new GraphQL documents. It is recommended that you implement the Strict
1863
+ Algorithm unless you have existing GraphQL documents that you need to support
1864
+ which would become invalid under the Strict Algorithm, in which case you should
1865
+ implement the Legacy Algorithm.
1866
+
1867
+ The All Variable Usages Are Allowed validation rule has become stricter since
1868
+ the release of the GraphQL Specification, specifically the Strict Algorithm no
1869
+ longer allows a nullable variable to be used in a non-nullable position even
1870
+ when either or both of the variable definition and the input position have a
1871
+ default value.
1872
+
1873
+ #### Strict All Variable Usages Are Allowed
1874
+
1875
+ Implement this only if you are not implementing
1876
+ [ Legacy All Variable Usages Are Allowed] ( #sec-Legacy-All-Variable-Usages-Are-Allowed ) .
1877
+
1858
1878
** Formal Specification**
1859
1879
1860
1880
- For each {operation} in {document}:
@@ -1868,6 +1888,144 @@ variable.
1868
1888
1869
1889
IsVariableUsageAllowed(variableDefinition, variableUsage):
1870
1890
1891
+ - Let {variableType} be the expected type of {variableDefinition}.
1892
+ - Let {locationType} be the expected type of the {Argument}, {ObjectField}, or
1893
+ {ListValue} entry where {variableUsage} is located.
1894
+ - Return {AreTypesCompatible(variableType, locationType)}.
1895
+
1896
+ ** Explanatory Text**
1897
+
1898
+ Variable usages must be compatible with the arguments they are passed to.
1899
+
1900
+ Validation failures occur when variables are used in the context of types that
1901
+ are complete mismatches, or if a nullable type in a variable is passed to a
1902
+ non-null argument type.
1903
+
1904
+ Types must match:
1905
+
1906
+ ``` graphql counter-example
1907
+ query intCannotGoIntoBoolean ($intArg : Int ) {
1908
+ arguments {
1909
+ booleanArgField (booleanArg : $intArg )
1910
+ }
1911
+ }
1912
+ ```
1913
+
1914
+ ${intArg} typed as {Int} cannot be used as an argument to {booleanArg}, typed as
1915
+ {Boolean}.
1916
+
1917
+ List cardinality must also be the same. For example, lists cannot be passed into
1918
+ singular values.
1919
+
1920
+ ``` graphql counter-example
1921
+ query booleanListCannotGoIntoBoolean ($booleanListArg : [Boolean ]) {
1922
+ arguments {
1923
+ booleanArgField (booleanArg : $booleanListArg )
1924
+ }
1925
+ }
1926
+ ```
1927
+
1928
+ Nullability must also be respected. A nullable variable cannot be passed to a
1929
+ non-null argument.
1930
+
1931
+ ``` graphql counter-example
1932
+ query booleanArgQuery ($booleanArg : Boolean ) {
1933
+ arguments {
1934
+ nonNullBooleanArgField (nonNullBooleanArg : $booleanArg )
1935
+ }
1936
+ }
1937
+ ```
1938
+
1939
+ For list types, the same rules around nullability apply to both outer types and
1940
+ inner types. A nullable list cannot be passed to a non-null list, and a list of
1941
+ nullable values cannot be passed to a list of non-null values. The following is
1942
+ valid:
1943
+
1944
+ ``` graphql example
1945
+ query nonNullListToList ($nonNullBooleanList : [Boolean ]! ) {
1946
+ arguments {
1947
+ booleanListArgField (booleanListArg : $nonNullBooleanList )
1948
+ }
1949
+ }
1950
+ ```
1951
+
1952
+ However, a nullable list cannot be passed to a non-null list:
1953
+
1954
+ ``` graphql counter-example
1955
+ query listToNonNullList ($booleanList : [Boolean ]) {
1956
+ arguments {
1957
+ nonNullBooleanListField (nonNullBooleanListArg : $booleanList )
1958
+ }
1959
+ }
1960
+ ```
1961
+
1962
+ This would fail validation because a ` [T] ` cannot be passed to a ` [T]! ` .
1963
+ Similarly a ` [T] ` cannot be passed to a ` [T!] ` .
1964
+
1965
+ ** Nullability, Optionality, and Default Values**
1966
+
1967
+ The value for a non-nullable variable with a default value may be omitted, or
1968
+ may be set to a non-null value, but it cannot be explicitly {null}. Thus, rather
1969
+ than handling a {null} with a run-time _ field error_ as in Legacy All Variable
1970
+ Usages Are Allowed, in Strict All Variable Usages Are Allowed we can make this
1971
+ situation impossible via validation.
1972
+
1973
+ In the example below, the variable ` $booleanArg ` must be non-null because it is
1974
+ used in the non-null argument (` nonNullBooleanArg ` ); however since it provides a
1975
+ default value the variable need not be defined in the request (it is optional,
1976
+ but non-nullable).
1977
+
1978
+ ``` graphql example
1979
+ query booleanArgQueryWithDefault ($booleanArg : Boolean ! = true ) {
1980
+ arguments {
1981
+ nonNullBooleanArgField (nonNullBooleanArg : $booleanArg )
1982
+ }
1983
+ }
1984
+ ```
1985
+
1986
+ In the example below, the variable ` $booleanArg ` must be non-nullable since it
1987
+ is used in a non-null position, even though the argument ` optionalBooleanArg `
1988
+ has a default value.
1989
+
1990
+ ``` graphql example
1991
+ query booleanArgQueryWithDefault ($booleanArg : Boolean ! ) {
1992
+ arguments {
1993
+ optionalNonNullBooleanArgField (optionalBooleanArg : $booleanArg )
1994
+ }
1995
+ }
1996
+ ```
1997
+
1998
+ The default value of ` optionalBooleanArg ` cannot be used when the argument is
1999
+ specified (either with a literal or a variable). You may choose to copy the
2000
+ argument's default value to the variable definition to make the variable
2001
+ optional (but still non-nullable) as in the example below:
2002
+
2003
+ ``` graphql example
2004
+ query booleanArgQueryWithDefault ($booleanArg : Boolean ! = false ) {
2005
+ arguments {
2006
+ optionalNonNullBooleanArgField (optionalBooleanArg : $booleanArg )
2007
+ }
2008
+ }
2009
+ ```
2010
+
2011
+ #### Legacy All Variable Usages Are Allowed
2012
+
2013
+ Implement this only if you are not implementing
2014
+ [ Strict All Variable Usages Are Allowed] ( #sec-Strict-All-Variable-Usages-Are-Allowed ) .
2015
+
2016
+ ** Formal Specification**
2017
+
2018
+ - For each {operation} in {document}:
2019
+ - Let {variableUsages} be all usages transitively included in the {operation}.
2020
+ - For each {variableUsage} in {variableUsages}:
2021
+ - Let {variableName} be the name of {variableUsage}.
2022
+ - Let {variableDefinition} be the {VariableDefinition} named {variableName}
2023
+ defined within {operation}.
2024
+ - {IsVariableUsageAllowedLegacy(variableDefinition, variableUsage)} must be
2025
+ {true}.
2026
+
2027
+ IsVariableUsageAllowedLegacy(variableDefinition, variableUsage):
2028
+
1871
2029
- Let {variableType} be the expected type of {variableDefinition}.
1872
2030
- Let {locationType} be the expected type of the {Argument}, {ObjectField}, or
1873
2031
{ListValue} entry where {variableUsage} is located.
@@ -1883,25 +2041,6 @@ IsVariableUsageAllowed(variableDefinition, variableUsage):
1883
2041
- Return {AreTypesCompatible(variableType, nullableLocationType)}.
1884
2042
- Return {AreTypesCompatible(variableType, locationType)}.
1885
2043
1886
- AreTypesCompatible(variableType, locationType):
1887
-
1888
- - If {locationType} is a non-null type:
1889
- - If {variableType} is NOT a non-null type, return {false}.
1890
- - Let {nullableLocationType} be the unwrapped nullable type of {locationType}.
1891
- - Let {nullableVariableType} be the unwrapped nullable type of {variableType}.
1892
- - Return {AreTypesCompatible(nullableVariableType, nullableLocationType)}.
1893
- - Otherwise, if {variableType} is a non-null type:
1894
- - Let {nullableVariableType} be the nullable type of {variableType}.
1895
- - Return {AreTypesCompatible(nullableVariableType, locationType)}.
1896
- - Otherwise, if {locationType} is a list type:
1897
- - If {variableType} is NOT a list type, return {false}.
1898
- - Let {itemLocationType} be the unwrapped item type of {locationType}.
1899
- - Let {itemVariableType} be the unwrapped item type of {variableType}.
1900
- - Return {AreTypesCompatible(itemVariableType, itemLocationType)}.
1901
- - Otherwise, if {variableType} is a list type, return {false}.
1902
- - Return {true} if {variableType} and {locationType} are identical, otherwise
1903
- {false}.
1904
-
1905
2044
** Explanatory Text**
1906
2045
1907
2046
Variable usages must be compatible with the arguments they are passed to.
@@ -2006,3 +2145,26 @@ query booleanArgQueryWithDefault($booleanArg: Boolean = true) {
2006
2145
2007
2146
Note: The value {null} could still be provided to such a variable at runtime. A
2008
2147
non-null argument must raise a _ field error_ if provided a {null} value.
2148
+
2149
+ #### Are Types Compatible
2150
+
2151
+ Both versions of the algorithm share the definition of {AreTypesCompatible()}:
2152
+
2153
+ AreTypesCompatible(variableType, locationType):
2154
+
2155
+ - If {locationType} is a non-null type:
2156
+ - If {variableType} is NOT a non-null type, return {false}.
2157
+ - Let {nullableLocationType} be the unwrapped nullable type of {locationType}.
2158
+ - Let {nullableVariableType} be the unwrapped nullable type of {variableType}.
2159
+ - Return {AreTypesCompatible(nullableVariableType, nullableLocationType)}.
2160
+ - Otherwise, if {variableType} is a non-null type:
2161
+ - Let {nullableVariableType} be the nullable type of {variableType}.
2162
+ - Return {AreTypesCompatible(nullableVariableType, locationType)}.
2163
+ - Otherwise, if {locationType} is a list type:
2164
+ - If {variableType} is NOT a list type, return {false}.
2165
+ - Let {itemLocationType} be the unwrapped item type of {locationType}.
2166
+ - Let {itemVariableType} be the unwrapped item type of {variableType}.
2167
+ - Return {AreTypesCompatible(itemVariableType, itemLocationType)}.
2168
+ - Otherwise, if {variableType} is a list type, return {false}.
2169
+ - Return {true} if {variableType} and {locationType} are identical, otherwise
2170
+ {false}.
0 commit comments