Skip to content

Commit 1740c8a

Browse files
Implements variable null literal detection
1 parent ebc5ed4 commit 1740c8a

File tree

2 files changed

+48
-48
lines changed

2 files changed

+48
-48
lines changed

Sources/GraphQL/Execution/Values.swift

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -64,62 +64,56 @@ func getVariableValue(schema: GraphQLSchema, definitionAST: VariableDefinition,
6464
let type = typeFromAST(schema: schema, inputTypeAST: definitionAST.type)
6565
let variable = definitionAST.variable
6666

67-
if type == nil || !isInputType(type: type) {
67+
guard let inputType = type as? GraphQLInputType else {
6868
throw GraphQLError(
6969
message:
7070
"Variable \"$\(variable.name.value)\" expected value of type " +
7171
"\"\(definitionAST.type)\" which cannot be used as an input type.",
7272
nodes: [definitionAST]
7373
)
7474
}
75-
76-
let inputType = type as! GraphQLInputType
77-
let errors = try isValidValue(value: input, type: inputType)
78-
79-
if errors.isEmpty {
80-
if input == .null {
81-
if let defaultValue = definitionAST.defaultValue {
82-
return try valueFromAST(valueAST: defaultValue, type: inputType)
83-
}
84-
else if !(inputType is GraphQLNonNull) {
85-
return .null
75+
76+
if input == .undefined {
77+
if let defaultValue = definitionAST.defaultValue {
78+
return try valueFromAST(valueAST: defaultValue, type: inputType)
79+
} else {
80+
if inputType is GraphQLNonNull {
81+
throw GraphQLError(message: "Non-nullable type \(inputType) must be provided.")
82+
} else {
83+
return .undefined
8684
}
8785
}
88-
89-
return try coerceValue(type: inputType, value: input)!
9086
}
91-
92-
guard input != .null else {
87+
88+
let errors = try isValidValue(value: input, type: inputType)
89+
guard errors.isEmpty else {
90+
let message = !errors.isEmpty ? "\n" + errors.joined(separator: "\n") : ""
9391
throw GraphQLError(
9492
message:
95-
"Variable \"$\(variable.name.value)\" of required type " +
96-
"\"\(definitionAST.type)\" was not provided.",
93+
"Variable \"$\(variable.name.value)\" got invalid value " +
94+
"\(input).\(message)", // TODO: "\(JSON.stringify(input)).\(message)",
9795
nodes: [definitionAST]
9896
)
9997
}
100-
101-
let message = !errors.isEmpty ? "\n" + errors.joined(separator: "\n") : ""
102-
103-
throw GraphQLError(
104-
message:
105-
"Variable \"$\(variable.name.value)\" got invalid value " +
106-
"\(input).\(message)", // TODO: "\(JSON.stringify(input)).\(message)",
107-
nodes: [definitionAST]
108-
)
98+
99+
return try coerceValue(type: inputType, value: input)
109100
}
110101

111102
/**
112103
* Given a type and any value, return a runtime value coerced to match the type.
113104
*/
114-
func coerceValue(type: GraphQLInputType, value: Map) throws -> Map? {
105+
func coerceValue(type: GraphQLInputType, value: Map) throws -> Map {
115106
if let nonNull = type as? GraphQLNonNull {
116107
// Note: we're not checking that the result of coerceValue is non-null.
117108
// We only call this function after calling isValidValue.
118-
return try coerceValue(type: nonNull.ofType as! GraphQLInputType, value: value)!
109+
return try coerceValue(type: nonNull.ofType as! GraphQLInputType, value: value)
110+
}
111+
112+
guard value != .undefined else {
113+
return .undefined
119114
}
120-
121115
guard value != .null else {
122-
return nil
116+
return .null
123117
}
124118

125119
if let list = type as? GraphQLList {
@@ -129,35 +123,41 @@ func coerceValue(type: GraphQLInputType, value: Map) throws -> Map? {
129123
var coercedValues: [Map] = []
130124

131125
for item in value {
132-
coercedValues.append(try coerceValue(type: itemType as! GraphQLInputType, value: item)!)
126+
coercedValues.append(try coerceValue(type: itemType as! GraphQLInputType, value: item))
133127
}
134128

135129
return .array(coercedValues)
136130
}
137131

138-
return .array([try coerceValue(type: itemType as! GraphQLInputType, value: value)!])
132+
return .array([try coerceValue(type: itemType as! GraphQLInputType, value: value)])
139133
}
140134

141-
if let type = type as? GraphQLInputObjectType {
135+
if let objectType = type as? GraphQLInputObjectType {
142136
guard case .dictionary(let value) = value else {
143-
return nil
137+
throw GraphQLError(message: "Must be dictionary to extract to an input type")
144138
}
145139

146-
let fields = type.fields
140+
let fields = objectType.fields
147141

148142
return try .dictionary(fields.keys.reduce([:]) { obj, fieldName in
149-
var objCopy = obj
150-
let field = fields[fieldName]
151-
152-
var fieldValue = try coerceValue(type: field!.type, value: value[fieldName] ?? .null)
153-
154-
if fieldValue == .null {
155-
fieldValue = field.flatMap({ $0.defaultValue })
143+
var obj = obj
144+
let field = fields[fieldName]!
145+
if let fieldValueMap = value[fieldName] {
146+
let fieldValue = try coerceValue(
147+
type: field.type,
148+
value: fieldValueMap
149+
)
150+
obj[fieldName] = fieldValue
156151
} else {
157-
objCopy[fieldName] = fieldValue
152+
// If AST doesn't contain field, it is undefined
153+
if let defaultValue = field.defaultValue {
154+
obj[fieldName] = defaultValue
155+
} else {
156+
obj[fieldName] = .undefined
157+
}
158158
}
159-
160-
return objCopy
159+
160+
return obj
161161
})
162162
}
163163

Sources/GraphQL/Utilities/ValueFromAST.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ func valueFromAST(valueAST: Value, type: GraphQLInputType, variables: [String: M
3737
if let variable = variables[variableName] {
3838
return variable
3939
} else {
40-
return .null
40+
return .undefined
4141
}
4242
}
4343

@@ -92,6 +92,6 @@ func valueFromAST(valueAST: Value, type: GraphQLInputType, variables: [String: M
9292
throw GraphQLError(message: "Must be leaf type")
9393
}
9494

95-
// If we've made it this far, it should be a literal
95+
// If we've made it this far, it should be a scalar
9696
return try type.parseLiteral(valueAST: valueAST)
9797
}

0 commit comments

Comments
 (0)