Skip to content

Commit c9ef407

Browse files
gh-action-runnergh-action-runner
authored andcommitted
Squashed 'apollo-ios/' changes from 23904fc26..bf71e9c73
bf71e9c73 V1 selectionset equality merged fragment child fix (#833) 59319e8ab Merge branch 'v1' of https://github.com/apollographql/apollo-ios-dev into v1 4a0f032a8 Release 1.25.2 (#809) git-subtree-dir: apollo-ios git-subtree-split: bf71e9c7373f68b9f5b8d1b9cdf810ebb4e0bf68
1 parent d7ea19b commit c9ef407

File tree

2 files changed

+69
-35
lines changed

2 files changed

+69
-35
lines changed

Sources/ApolloAPI/SelectionSet+Equatable.swift

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -55,40 +55,69 @@ public extension SelectionSet {
5555

5656
private func fieldsForEquality() -> [String: FieldValue] {
5757
var fields: [String: FieldValue] = [:]
58-
if let asTypeCase = self as? any InlineFragment {
59-
self.addFulfilledSelections(of: type(of: asTypeCase.asRootEntityType), to: &fields)
58+
var addedFragments: Set<ObjectIdentifier> = []
6059

61-
} else {
62-
self.addFulfilledSelections(of: type(of: self), to: &fields)
60+
for fragment in type(of: self).__fulfilledFragments {
61+
self.addFulfilledSelections(of: fragment, to: &fields, addedFragments: &addedFragments)
6362
}
6463

6564
return fields
6665
}
6766

6867
private func addFulfilledSelections(
6968
of selectionSetType: any SelectionSet.Type,
70-
to fields: inout [String: FieldValue]
69+
to fields: inout [String: FieldValue],
70+
addedFragments: inout Set<ObjectIdentifier>
7171
) {
72-
guard self.__data.fragmentIsFulfilled(selectionSetType) else {
72+
let selectionSetTypeId = ObjectIdentifier(selectionSetType)
73+
guard !addedFragments.contains(selectionSetTypeId),
74+
self.__data.fragmentIsFulfilled(selectionSetType) else {
7375
return
7476
}
7577

78+
addedFragments.insert(selectionSetTypeId)
79+
7680
for selection in selectionSetType.__selections {
7781
switch selection {
7882
case let .field(field):
7983
add(field: field, to: &fields)
8084

8185
case let .inlineFragment(typeCase):
82-
self.addFulfilledSelections(of: typeCase, to: &fields)
86+
self.addFulfilledSelections(of: typeCase, to: &fields, addedFragments: &addedFragments)
8387

8488
case let .conditional(_, selections):
85-
self.addConditionalSelections(selections, to: &fields)
89+
self.addConditionalSelections(selections, to: &fields, addedFragments: &addedFragments)
8690

8791
case let .fragment(fragmentType):
88-
self.addFulfilledSelections(of: fragmentType, to: &fields)
92+
self.addFulfilledSelections(of: fragmentType, to: &fields, addedFragments: &addedFragments)
8993

9094
case let .deferred(_, fragmentType, _):
91-
self.addFulfilledSelections(of: fragmentType, to: &fields)
95+
self.addFulfilledSelections(of: fragmentType, to: &fields, addedFragments: &addedFragments)
96+
}
97+
}
98+
}
99+
100+
private func addConditionalSelections(
101+
_ selections: [Selection],
102+
to fields: inout [String: FieldValue],
103+
addedFragments: inout Set<ObjectIdentifier>
104+
) {
105+
for selection in selections {
106+
switch selection {
107+
case let .inlineFragment(typeCase):
108+
self.addFulfilledSelections(of: typeCase, to: &fields, addedFragments: &addedFragments)
109+
110+
case let .fragment(fragment):
111+
self.addFulfilledSelections(of: fragment, to: &fields, addedFragments: &addedFragments)
112+
113+
case let .deferred(_, fragment, _):
114+
self.addFulfilledSelections(of: fragment, to: &fields, addedFragments: &addedFragments)
115+
116+
case let .conditional(_, selections):
117+
addConditionalSelections(selections, to: &fields, addedFragments: &addedFragments)
118+
119+
case let .field(field):
120+
add(field: field, to: &fields)
92121
}
93122
}
94123
}
@@ -177,30 +206,6 @@ public extension SelectionSet {
177206

178207
}
179208

180-
private func addConditionalSelections(
181-
_ selections: [Selection],
182-
to fields: inout [String: FieldValue]
183-
) {
184-
for selection in selections {
185-
switch selection {
186-
case let .inlineFragment(typeCase):
187-
self.addFulfilledSelections(of: typeCase, to: &fields)
188-
189-
case let .fragment(fragment):
190-
self.addFulfilledSelections(of: fragment, to: &fields)
191-
192-
case let .deferred(_, fragment, _):
193-
self.addFulfilledSelections(of: fragment, to: &fields)
194-
195-
case let .conditional(_, selections):
196-
addConditionalSelections(selections, to: &fields)
197-
198-
case let .field(field):
199-
add(field: field, to: &fields)
200-
}
201-
}
202-
}
203-
204209
}
205210

206211
extension Hasher {

Sources/ApolloAPI/SelectionSet.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public protocol CompositeInlineFragment: CompositeSelectionSet, InlineFragment {
4949
public protocol SelectionSet: Hashable, CustomDebugStringConvertible {
5050
associatedtype Schema: SchemaMetadata
5151

52-
/// A type representing all of the fragments the `SelectionSet` can be converted to.
52+
/// A type representing all of the named fragments the `SelectionSet` can be converted to.
5353
/// Defaults to a stub type with no fragments.
5454
/// A `SelectionSet` with fragments should provide a type that conforms to `FragmentContainer`
5555
associatedtype Fragments = NoFragments
@@ -61,6 +61,12 @@ public protocol SelectionSet: Hashable, CustomDebugStringConvertible {
6161
/// This may be a concrete type (`Object`) or an abstract type (`Interface`, or `Union`).
6262
static var __parentType: any ParentType { get }
6363

64+
/// The fragments whose selections are always fulfilled on a valid instance of the `SelectionSet`.
65+
static var __fulfilledFragments: [any SelectionSet.Type] { get }
66+
67+
/// The deferred fragments that may be fulfilled on a valid instance of the `SelectionSet`.
68+
static var __deferredFragments: [any Deferrable.Type] { get }
69+
6470
/// The data of the underlying GraphQL object represented by the generated selection set.
6571
var __data: DataDict { get }
6672

@@ -86,6 +92,8 @@ extension SelectionSet {
8692

8793
@inlinable public static var __selections: [Selection] { [] }
8894

95+
@inlinable public static var __deferredFragments: [any Deferrable.Type] { [] }
96+
8997
@inlinable public var __objectType: Object? {
9098
guard let __typename else { return nil }
9199
return Schema.objectType(forTypename: __typename)
@@ -113,6 +121,27 @@ extension SelectionSet {
113121
public var debugDescription: String {
114122
return "\(self.__data._data as AnyObject)"
115123
}
124+
125+
// MARK: - Internal
126+
127+
@_spi(Internal)
128+
@inlinable public static var __fulfilledFragmentIds: Set<ObjectIdentifier> {
129+
Set(Self.__fulfilledFragments.map(ObjectIdentifier.init))
130+
}
131+
132+
@_spi(Internal)
133+
@inlinable public static var __deferredFragmentIds: Set<ObjectIdentifier> {
134+
Set(Self.__fulfilledFragments.map(ObjectIdentifier.init))
135+
}
136+
137+
public init(unsafelyWithData data: [String: JSONValue]) {
138+
self.init(_dataDict: DataDict(
139+
data: data,
140+
fulfilledFragments: Self.__fulfilledFragmentIds,
141+
deferredFragments: Self.__deferredFragmentIds
142+
))
143+
}
144+
116145
}
117146

118147
extension SelectionSet where Fragments: FragmentContainer {

0 commit comments

Comments
 (0)