|
9 | 9 |
|
10 | 10 | import { GraphQLError } from '../error';
|
11 | 11 | import find from '../jsutils/find';
|
12 |
| -import isInvalid from '../jsutils/isInvalid'; |
| 12 | +import invariant from '../jsutils/invariant'; |
13 | 13 | import keyMap from '../jsutils/keyMap';
|
14 | 14 | import { coerceValue } from '../utilities/coerceValue';
|
15 | 15 | import { typeFromAST } from '../utilities/typeFromAST';
|
@@ -66,48 +66,44 @@ export function getVariableValues(
|
66 | 66 | );
|
67 | 67 | } else {
|
68 | 68 | const hasValue = hasOwnProperty(inputs, varName);
|
69 |
| - const value = inputs[varName]; |
70 |
| - if (!hasValue || value == null) { |
71 |
| - if (isNonNullType(varType)) { |
72 |
| - // If no value or a nullish value was provided to a variable with a |
73 |
| - // non-null type (required), produce an error. |
74 |
| - errors.push( |
75 |
| - new GraphQLError( |
76 |
| - hasValue |
77 |
| - ? `Variable "$${varName}" of non-null type ` + |
78 |
| - `"${String(varType)}" must not be null.` |
79 |
| - : `Variable "$${varName}" of required type ` + |
80 |
| - `"${String(varType)}" was not provided.`, |
81 |
| - [varDefNode], |
82 |
| - ), |
83 |
| - ); |
84 |
| - } else if (varDefNode.defaultValue) { |
85 |
| - // If no value or a nullish value was provided to a variable with a |
86 |
| - // default value, use the default value. |
87 |
| - coercedValues[varName] = valueFromAST( |
88 |
| - varDefNode.defaultValue, |
89 |
| - varType, |
90 |
| - ); |
91 |
| - } else if (hasValue && value == null) { |
92 |
| - // If the explcit value `null` was provided, an entry in the coerced |
| 69 | + const value = hasValue ? inputs[varName] : undefined; |
| 70 | + if (!hasValue && varDefNode.defaultValue) { |
| 71 | + // If no value was provided to a variable with a default value, |
| 72 | + // use the default value. |
| 73 | + coercedValues[varName] = valueFromAST(varDefNode.defaultValue, varType); |
| 74 | + } else if ((!hasValue || value === null) && isNonNullType(varType)) { |
| 75 | + // If no value or a nullish value was provided to a variable with a |
| 76 | + // non-null type (required), produce an error. |
| 77 | + errors.push( |
| 78 | + new GraphQLError( |
| 79 | + hasValue |
| 80 | + ? `Variable "$${varName}" of non-null type ` + |
| 81 | + `"${String(varType)}" must not be null.` |
| 82 | + : `Variable "$${varName}" of required type ` + |
| 83 | + `"${String(varType)}" was not provided.`, |
| 84 | + [varDefNode], |
| 85 | + ), |
| 86 | + ); |
| 87 | + } else if (hasValue) { |
| 88 | + if (value === null) { |
| 89 | + // If the explicit value `null` was provided, an entry in the coerced |
93 | 90 | // values must exist as the value `null`.
|
94 | 91 | coercedValues[varName] = null;
|
95 |
| - } |
96 |
| - } else { |
97 |
| - // Otherwise, a non-null value was provided, coerce it to the expected |
98 |
| - // type or report an error if coercion fails. |
99 |
| - const coerced = coerceValue(value, varType, varDefNode); |
100 |
| - const coercionErrors = coerced.errors; |
101 |
| - if (coercionErrors) { |
102 |
| - const messagePrelude = `Variable "$${varName}" got invalid value ${JSON.stringify( |
103 |
| - value, |
104 |
| - )}; `; |
105 |
| - coercionErrors.forEach(error => { |
106 |
| - error.message = messagePrelude + error.message; |
107 |
| - }); |
108 |
| - errors.push(...coercionErrors); |
109 | 92 | } else {
|
110 |
| - coercedValues[varName] = coerced.value; |
| 93 | + // Otherwise, a non-null value was provided, coerce it to the expected |
| 94 | + // type or report an error if coercion fails. |
| 95 | + const coerced = coerceValue(value, varType, varDefNode); |
| 96 | + const coercionErrors = coerced.errors; |
| 97 | + if (coercionErrors) { |
| 98 | + coercionErrors.forEach(error => { |
| 99 | + error.message = |
| 100 | + `Variable "$${varName}" got invalid ` + |
| 101 | + `value ${JSON.stringify(value)}; ${error.message}`; |
| 102 | + }); |
| 103 | + errors.push(...coercionErrors); |
| 104 | + } else { |
| 105 | + coercedValues[varName] = coerced.value; |
| 106 | + } |
111 | 107 | }
|
112 | 108 | }
|
113 | 109 | }
|
@@ -142,57 +138,71 @@ export function getArgumentValues(
|
142 | 138 | const name = argDef.name;
|
143 | 139 | const argType = argDef.type;
|
144 | 140 | const argumentNode = argNodeMap[name];
|
145 |
| - const defaultValue = argDef.defaultValue; |
146 |
| - if (!argumentNode || argumentNode.value.kind === Kind.NULL) { |
147 |
| - if (isNonNullType(argType)) { |
148 |
| - if (!argumentNode) { |
149 |
| - throw new GraphQLError( |
150 |
| - `Argument "${name}" of required type "${String(argType)}" ` + |
151 |
| - 'was not provided.', |
152 |
| - [node], |
153 |
| - ); |
154 |
| - } else { |
155 |
| - throw new GraphQLError( |
156 |
| - `Argument "${name}" of non-null type "${String(argType)}" ` + |
157 |
| - 'must not be null.', |
158 |
| - [argumentNode.value], |
159 |
| - ); |
160 |
| - } |
161 |
| - } else if (!isInvalid(defaultValue)) { |
162 |
| - coercedValues[name] = defaultValue; |
163 |
| - } else if (argumentNode && argumentNode.value.kind === Kind.NULL) { |
164 |
| - coercedValues[name] = null; |
165 |
| - } |
166 |
| - } else if (argumentNode.value.kind === Kind.VARIABLE) { |
| 141 | + let hasValue; |
| 142 | + let isNull; |
| 143 | + if (argumentNode && argumentNode.value.kind === Kind.VARIABLE) { |
167 | 144 | const variableName = argumentNode.value.name.value;
|
168 |
| - if (variableValues && hasOwnProperty(variableValues, variableName)) { |
169 |
| - // Note: this does not check that this variable value is correct. |
170 |
| - // This assumes that this query has been validated and the variable |
171 |
| - // usage here is of the correct type. |
172 |
| - coercedValues[name] = variableValues[variableName]; |
173 |
| - } else if (isNonNullType(argType)) { |
| 145 | + hasValue = variableValues && hasOwnProperty(variableValues, variableName); |
| 146 | + isNull = variableValues && variableValues[variableName] === null; |
| 147 | + } else { |
| 148 | + hasValue = argumentNode != null; |
| 149 | + isNull = argumentNode && argumentNode.value.kind === Kind.NULL; |
| 150 | + } |
| 151 | + |
| 152 | + if (!hasValue && argDef.defaultValue !== undefined) { |
| 153 | + // If no argument was provided where the definition has a default value, |
| 154 | + // use the default value. |
| 155 | + coercedValues[name] = argDef.defaultValue; |
| 156 | + } else if ((!hasValue || isNull) && isNonNullType(argType)) { |
| 157 | + // If no argument or a null value was provided to an argument with a |
| 158 | + // non-null type (required), produce a field error. |
| 159 | + if (isNull) { |
174 | 160 | throw new GraphQLError(
|
175 |
| - `Argument "${name}" of required type "${String(argType)}" was ` + |
176 |
| - `provided the variable "$${variableName}" which was not provided ` + |
177 |
| - 'a runtime value.', |
| 161 | + `Argument "${name}" of non-null type "${String(argType)}" ` + |
| 162 | + 'must not be null.', |
178 | 163 | [argumentNode.value],
|
179 | 164 | );
|
180 |
| - } else if (!isInvalid(defaultValue)) { |
181 |
| - coercedValues[name] = defaultValue; |
182 |
| - } |
183 |
| - } else { |
184 |
| - const valueNode = argumentNode.value; |
185 |
| - const coercedValue = valueFromAST(valueNode, argType, variableValues); |
186 |
| - if (isInvalid(coercedValue)) { |
187 |
| - // Note: ValuesOfCorrectType validation should catch this before |
188 |
| - // execution. This is a runtime check to ensure execution does not |
189 |
| - // continue with an invalid argument value. |
| 165 | + } else if (argumentNode && argumentNode.value.kind === Kind.VARIABLE) { |
| 166 | + const variableName = argumentNode.value.name.value; |
190 | 167 | throw new GraphQLError(
|
191 |
| - `Argument "${name}" has invalid value ${print(valueNode)}.`, |
| 168 | + `Argument "${name}" of required type "${String(argType)}" ` + |
| 169 | + `was provided the variable "$${variableName}" ` + |
| 170 | + 'which was not provided a runtime value.', |
192 | 171 | [argumentNode.value],
|
193 | 172 | );
|
| 173 | + } else { |
| 174 | + throw new GraphQLError( |
| 175 | + `Argument "${name}" of required type "${String(argType)}" ` + |
| 176 | + 'was not provided.', |
| 177 | + [node], |
| 178 | + ); |
| 179 | + } |
| 180 | + } else if (hasValue) { |
| 181 | + if (argumentNode.value.kind === Kind.NULL) { |
| 182 | + // If the explicit value `null` was provided, an entry in the coerced |
| 183 | + // values must exist as the value `null`. |
| 184 | + coercedValues[name] = null; |
| 185 | + } else if (argumentNode.value.kind === Kind.VARIABLE) { |
| 186 | + const variableName = argumentNode.value.name.value; |
| 187 | + invariant(variableValues, 'Must exist for hasValue to be true.'); |
| 188 | + // Note: This does no further checking that this variable is correct. |
| 189 | + // This assumes that this query has been validated and the variable |
| 190 | + // usage here is of the correct type. |
| 191 | + coercedValues[name] = variableValues[variableName]; |
| 192 | + } else { |
| 193 | + const valueNode = argumentNode.value; |
| 194 | + const coercedValue = valueFromAST(valueNode, argType, variableValues); |
| 195 | + if (coercedValue === undefined) { |
| 196 | + // Note: ValuesOfCorrectType validation should catch this before |
| 197 | + // execution. This is a runtime check to ensure execution does not |
| 198 | + // continue with an invalid argument value. |
| 199 | + throw new GraphQLError( |
| 200 | + `Argument "${name}" has invalid value ${print(valueNode)}.`, |
| 201 | + [argumentNode.value], |
| 202 | + ); |
| 203 | + } |
| 204 | + coercedValues[name] = coercedValue; |
194 | 205 | }
|
195 |
| - coercedValues[name] = coercedValue; |
196 | 206 | }
|
197 | 207 | }
|
198 | 208 | return coercedValues;
|
|
0 commit comments