@@ -135,17 +135,34 @@ extension GraphQLNonNull: GraphQLWrapperType {}
135135/// try $0.map.asBool(converting: true)
136136/// }
137137/// )
138- public final class GraphQLScalarType : Sendable {
138+ public final class GraphQLScalarType : @ unchecked Sendable {
139139 public let name : String
140140 public let description : String ?
141141 public let specifiedByURL : String ?
142142 public let astNode : ScalarTypeDefinition ?
143143 public let extensionASTNodes : [ ScalarExtensionDefinition ]
144144 public let kind : TypeKind = . scalar
145145
146- let serialize : @Sendable ( Any ) throws -> Map
147- let parseValue : @Sendable ( Map ) throws -> Map
148- let parseLiteral : @Sendable ( Value ) throws -> Map
146+ // Callbacks may be configured after building an SDL schema, before it is used for execution.
147+ // Synchronize access so reading a callback cannot race with its replacement.
148+ private var _serialize : @Sendable ( Any ) throws -> Map
149+ private var _parseValue : @Sendable ( Map ) throws -> Map
150+ private var _parseLiteral : @Sendable ( Value ) throws -> Map
151+
152+ public var serialize : @Sendable ( Any ) throws -> Map {
153+ get { scalarPropertyQueue . sync { _serialize } }
154+ set { scalarPropertyQueue . sync ( flags : . barrier ) { _serialize = newValue } }
155+ }
156+
157+ public var parseValue : @Sendable ( Map ) throws -> Map {
158+ get { scalarPropertyQueue . sync { _parseValue } }
159+ set { scalarPropertyQueue . sync ( flags : . barrier ) { _parseValue = newValue } }
160+ }
161+
162+ public var parseLiteral : @Sendable ( Value ) throws -> Map {
163+ get { scalarPropertyQueue . sync { _parseLiteral } }
164+ set { scalarPropertyQueue . sync ( flags : . barrier ) { _parseLiteral = newValue } }
165+ }
149166
150167 public init (
151168 name : String ,
@@ -163,9 +180,9 @@ public final class GraphQLScalarType: Sendable {
163180 self . specifiedByURL = specifiedByURL
164181 self . astNode = astNode
165182 self . extensionASTNodes = extensionASTNodes
166- self . serialize = serialize
167- self . parseValue = parseValue ?? defaultParseValue
168- self . parseLiteral = parseLiteral ?? defaultParseLiteral
183+ _serialize = serialize
184+ _parseValue = parseValue ?? defaultParseValue
185+ _parseLiteral = parseLiteral ?? defaultParseLiteral
169186 }
170187
171188 /// Serializes an internal value to include in a response.
@@ -1421,3 +1438,9 @@ private let fieldPropertyQueue = DispatchQueue(
14211438 label : " graphql.field.properties " ,
14221439 attributes : . concurrent
14231440)
1441+
1442+ /// Shared reader/writer queue for scalar callbacks.
1443+ private let scalarPropertyQueue = DispatchQueue (
1444+ label : " graphql.scalar.properties " ,
1445+ attributes : . concurrent
1446+ )
0 commit comments