Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cd632ee

Browse files
committed
[validation] Fix infinite loop on invalid queries in OverlappingFields
1 parent ed7c8fd commit cd632ee

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

src/validation/__tests__/OverlappingFieldsCanBeMerged-test.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,4 +938,55 @@ describe('Validate: Overlapping fields can be merged', () => {
938938

939939
});
940940

941+
it('does not infinite loop on recursive fragment', () => {
942+
expectPassesRule(OverlappingFieldsCanBeMerged, `
943+
fragment fragA on Human {name relatives { name ...fragA } },
944+
`);
945+
});
946+
947+
it('does not infinite loop on immediately spread fragment', () => {
948+
expectPassesRule(OverlappingFieldsCanBeMerged, `
949+
fragment fragA on Human {name ...fragA },
950+
`);
951+
});
952+
953+
it('finds invalid case even with immediately spread fragment', () => {
954+
// You would not expect this to have three error messages, and you would be
955+
// right. The trickiness here is that we don't detect the immediate spread
956+
// on first spreading, because it's in the context of the selection set. So
957+
// by the time we detect and eliminate it, we've already spread it in once,
958+
// and hence we get multiple error messages. We could change the algorithm
959+
// to track that we're in an immediate fragment spread, but that would add
960+
// complexity that only is needed in this error case.
961+
962+
// Because this is an invalid query by another rule (NoFragmentCycles), I'm
963+
// not too worried about this case... and since we used to infinite loop,
964+
// this is strictly better.
965+
expectFailsRule(OverlappingFieldsCanBeMerged, `
966+
fragment sameAliasesWithDifferentFieldTargets on Dog {
967+
...sameAliasesWithDifferentFieldTargets
968+
fido: name
969+
fido: nickname
970+
}
971+
`, [
972+
{ message: fieldsConflictMessage(
973+
'fido',
974+
'name and nickname are different fields'
975+
),
976+
locations: [ { line: 4, column: 9 }, { line: 5, column: 9 } ],
977+
path: undefined },
978+
{ message: fieldsConflictMessage(
979+
'fido',
980+
'name and nickname are different fields'
981+
),
982+
locations: [ { line: 4, column: 9 }, { line: 5, column: 9 } ],
983+
path: undefined },
984+
{ message: fieldsConflictMessage(
985+
'fido',
986+
'nickname and name are different fields'
987+
),
988+
locations: [ { line: 5, column: 9 }, { line: 4, column: 9 } ],
989+
path: undefined }
990+
]);
991+
});
941992
});

src/validation/rules/OverlappingFieldsCanBeMerged.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,12 @@ function collectConflictsBetweenFieldsAndFragment(
239239
fragment
240240
);
241241

242+
if (fragmentNames2.indexOf(fragmentName) !== -1) {
243+
// This means a fragment spread in itself. We're going to infinite loop
244+
// if we try and collect all fields. Pretend we did not index that fragment
245+
fragmentNames2.splice(fragmentNames2.indexOf(fragmentName));
246+
}
247+
242248
// (D) First collect any conflicts between the provided collection of fields
243249
// and the collection of fields represented by the given fragment.
244250
collectConflictsBetween(

0 commit comments

Comments
 (0)