Skip to content

Commit 5060f7a

Browse files
committed
Merge conflicts
2 parents 8b2a56d + 01414be commit 5060f7a

File tree

6 files changed

+145
-50
lines changed

6 files changed

+145
-50
lines changed

src/execution/collectFields.ts

+4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import { AccumulatorMap } from '../jsutils/AccumulatorMap';
22
import type { ObjMap } from '../jsutils/ObjMap';
33

44
import type {
5+
ArgumentNode,
56
FieldNode,
67
FragmentDefinitionNode,
78
FragmentSpreadNode,
89
InlineFragmentNode,
910
SelectionSetNode,
11+
ValueNode,
1012
} from '../language/ast';
1113
import { Kind } from '../language/kinds';
1214

@@ -141,6 +143,8 @@ function collectFieldsImpl(
141143
) {
142144
continue;
143145
}
146+
const selectionSetWithArgumentsApplied =
147+
selectionSetWithFragmentArgumentsApplied(fragment, selection);
144148
collectFieldsImpl(
145149
schema,
146150
fragments,

src/language/__tests__/visitor-test.ts

+44-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ describe('Visitor', () => {
455455
]);
456456
});
457457

458-
it('visits variables defined in fragments', () => {
458+
it('visits arguments defined on fragments', () => {
459459
const ast = parse('fragment a($v: Boolean = false) on t { f }', {
460460
noLocation: true,
461461
});
@@ -504,6 +504,49 @@ describe('Visitor', () => {
504504
]);
505505
});
506506

507+
it('visits arguments on fragment spreads', () => {
508+
const ast = parse('fragment a on t { ...s(v: false) }', {
509+
noLocation: true,
510+
});
511+
const visited: Array<any> = [];
512+
513+
visit(ast, {
514+
enter(node) {
515+
checkVisitorFnArgs(ast, arguments);
516+
visited.push(['enter', node.kind, getValue(node)]);
517+
},
518+
leave(node) {
519+
checkVisitorFnArgs(ast, arguments);
520+
visited.push(['leave', node.kind, getValue(node)]);
521+
},
522+
});
523+
524+
expect(visited).to.deep.equal([
525+
['enter', 'Document', undefined],
526+
['enter', 'FragmentDefinition', undefined],
527+
['enter', 'Name', 'a'],
528+
['leave', 'Name', 'a'],
529+
['enter', 'NamedType', undefined],
530+
['enter', 'Name', 't'],
531+
['leave', 'Name', 't'],
532+
['leave', 'NamedType', undefined],
533+
['enter', 'SelectionSet', undefined],
534+
['enter', 'FragmentSpread', undefined],
535+
['enter', 'Name', 's'],
536+
['leave', 'Name', 's'],
537+
['enter', 'Argument', { kind: 'BooleanValue', value: false }],
538+
['enter', 'Name', 'v'],
539+
['leave', 'Name', 'v'],
540+
['enter', 'BooleanValue', false],
541+
['leave', 'BooleanValue', false],
542+
['leave', 'Argument', { kind: 'BooleanValue', value: false }],
543+
['leave', 'FragmentSpread', undefined],
544+
['leave', 'SelectionSet', undefined],
545+
['leave', 'FragmentDefinition', undefined],
546+
['leave', 'Document', undefined],
547+
]);
548+
});
549+
507550
it('n', () => {
508551
const ast = parse(kitchenSinkQuery, {
509552
experimentalClientControlledNullability: true,

src/language/ast.ts

+9
Original file line numberDiff line numberDiff line change
@@ -428,8 +428,13 @@ export interface FragmentSpreadNode {
428428
readonly kind: Kind.FRAGMENT_SPREAD;
429429
readonly loc?: Location | undefined;
430430
readonly name: NameNode;
431+
<<<<<<< HEAD
431432
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
432433
readonly arguments?: ReadonlyArray<ArgumentNode> | undefined;
434+
=======
435+
readonly arguments?: ReadonlyArray<ArgumentNode>;
436+
readonly directives?: ReadonlyArray<DirectiveNode>;
437+
>>>>>>> 01414be319c245415c1c5d4818a4fe9179c2909d
433438
}
434439

435440
export interface InlineFragmentNode {
@@ -444,9 +449,13 @@ export interface FragmentDefinitionNode {
444449
readonly kind: Kind.FRAGMENT_DEFINITION;
445450
readonly loc?: Location | undefined;
446451
readonly name: NameNode;
452+
<<<<<<< HEAD
447453
readonly variableDefinitions?:
448454
| ReadonlyArray<VariableDefinitionNode>
449455
| undefined;
456+
=======
457+
readonly variableDefinitions?: ReadonlyArray<VariableDefinitionNode>;
458+
>>>>>>> 01414be319c245415c1c5d4818a4fe9179c2909d
450459
readonly typeCondition: NamedTypeNode;
451460
readonly directives?: ReadonlyArray<DirectiveNode> | undefined;
452461
readonly selectionSet: SelectionSetNode;

src/language/parser.ts

+2-41
Original file line numberDiff line numberDiff line change
@@ -80,29 +80,8 @@ export interface ParseOptions {
8080
* in the source that they correspond to. This configuration flag
8181
* disables that behavior for performance or testing.
8282
*/
83-
<<<<<<< HEAD
84-
<<<<<<< HEAD
8583
noLocation?: boolean | undefined;
8684

87-
/**
88-
* If enabled, the parser will understand and parse variable definitions
89-
* contained in a fragment definition. They'll be represented in the
90-
* `variableDefinitions` field of the FragmentDefinitionNode.
91-
*
92-
* Additionally, the parser will understand arguments passed to fragment
93-
* spreads. They'll be represented in the `arguments` field of the
94-
* FragmentSpreadNode.
95-
*
96-
* The syntax is identical to normal, query-defined variables. For example:
97-
*
98-
* ```graphql
99-
* fragment A($var: Boolean = false) on T {
100-
* ...
101-
* }
102-
* ```
103-
*/
104-
allowLegacyFragmentVariables?: boolean | undefined;
105-
10685
/**
10786
* EXPERIMENTAL:
10887
*
@@ -125,12 +104,6 @@ export interface ParseOptions {
125104
* future.
126105
*/
127106
experimentalClientControlledNullability?: boolean | undefined;
128-
=======
129-
noLocation?: boolean;
130-
>>>>>>> Remove flag for parsing, but add default validation to indicate fragment args are not yet spec-supported, and may be missing validation.
131-
=======
132-
noLocation?: boolean;
133-
>>>>>>> 01414be319c245415c1c5d4818a4fe9179c2909d
134107
}
135108

136109
/**
@@ -591,22 +564,10 @@ export class Parser {
591564
parseFragmentDefinition(): FragmentDefinitionNode {
592565
const start = this._lexer.token;
593566
this.expectKeyword('fragment');
594-
// Legacy support for defining variables within fragments changes
595-
// the grammar of FragmentDefinition:
596-
// - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
597-
if (this._options.allowLegacyFragmentVariables === true) {
598-
return this.node<FragmentDefinitionNode>(start, {
599-
kind: Kind.FRAGMENT_DEFINITION,
600-
name,
601-
variableDefinitions: this.parseVariableDefinitions(),
602-
typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
603-
directives: this.parseDirectives(false),
604-
selectionSet: this.parseSelectionSet(),
605-
});
606-
}
607567
return this.node<FragmentDefinitionNode>(start, {
608568
kind: Kind.FRAGMENT_DEFINITION,
609-
name,
569+
name: this.parseFragmentName(),
570+
variableDefinitions: this.parseVariableDefinitions(),
610571
typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
611572
directives: this.parseDirectives(false),
612573
selectionSet: this.parseSelectionSet(),

src/language/visitor.ts

+86
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,97 @@ type ReducedField<T, R> = T extends null | undefined
7777
? ReadonlyArray<R>
7878
: R;
7979

80+
<<<<<<< HEAD
8081
/**
8182
* A KeyMap describes each the traversable properties of each kind of node.
8283
*/
8384
export type ASTVisitorKeyMap = {
8485
[NodeT in ASTNode as NodeT['kind']]?: ReadonlyArray<keyof NodeT>;
86+
=======
87+
const QueryDocumentKeys = {
88+
Name: [],
89+
90+
Document: ['definitions'],
91+
OperationDefinition: [
92+
'name',
93+
'variableDefinitions',
94+
'directives',
95+
'selectionSet',
96+
],
97+
VariableDefinition: ['variable', 'type', 'defaultValue', 'directives'],
98+
Variable: ['name'],
99+
SelectionSet: ['selections'],
100+
Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
101+
Argument: ['name', 'value'],
102+
103+
FragmentSpread: ['name', 'arguments', 'directives'],
104+
InlineFragment: ['typeCondition', 'directives', 'selectionSet'],
105+
FragmentDefinition: [
106+
'name',
107+
'variableDefinitions',
108+
'typeCondition',
109+
'directives',
110+
'selectionSet',
111+
],
112+
113+
IntValue: [],
114+
FloatValue: [],
115+
StringValue: [],
116+
BooleanValue: [],
117+
NullValue: [],
118+
EnumValue: [],
119+
ListValue: ['values'],
120+
ObjectValue: ['fields'],
121+
ObjectField: ['name', 'value'],
122+
123+
Directive: ['name', 'arguments'],
124+
125+
NamedType: ['name'],
126+
ListType: ['type'],
127+
NonNullType: ['type'],
128+
129+
SchemaDefinition: ['description', 'directives', 'operationTypes'],
130+
OperationTypeDefinition: ['type'],
131+
132+
ScalarTypeDefinition: ['description', 'name', 'directives'],
133+
ObjectTypeDefinition: [
134+
'description',
135+
'name',
136+
'interfaces',
137+
'directives',
138+
'fields',
139+
],
140+
FieldDefinition: ['description', 'name', 'arguments', 'type', 'directives'],
141+
InputValueDefinition: [
142+
'description',
143+
'name',
144+
'type',
145+
'defaultValue',
146+
'directives',
147+
],
148+
InterfaceTypeDefinition: [
149+
'description',
150+
'name',
151+
'interfaces',
152+
'directives',
153+
'fields',
154+
],
155+
UnionTypeDefinition: ['description', 'name', 'directives', 'types'],
156+
EnumTypeDefinition: ['description', 'name', 'directives', 'values'],
157+
EnumValueDefinition: ['description', 'name', 'directives'],
158+
InputObjectTypeDefinition: ['description', 'name', 'directives', 'fields'],
159+
160+
DirectiveDefinition: ['description', 'name', 'arguments', 'locations'],
161+
162+
SchemaExtension: ['directives', 'operationTypes'],
163+
164+
ScalarTypeExtension: ['name', 'directives'],
165+
ObjectTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
166+
InterfaceTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
167+
UnionTypeExtension: ['name', 'directives', 'types'],
168+
EnumTypeExtension: ['name', 'directives', 'values'],
169+
InputObjectTypeExtension: ['name', 'directives', 'fields'],
170+
>>>>>>> 01414be319c245415c1c5d4818a4fe9179c2909d
85171
};
86172

87173
export const BREAK: unknown = Object.freeze({});

src/validation/specifiedRules.ts

-8
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,6 @@ import { VariablesAreInputTypesRule } from './rules/VariablesAreInputTypesRule';
6666
// Spec Section: "All Variable Usages Are Allowed"
6767
import { VariablesInAllowedPositionRule } from './rules/VariablesInAllowedPositionRule';
6868
import type { SDLValidationRule, ValidationRule } from './ValidationContext';
69-
70-
// Prevent not-yet-in-spec usage of Fragment Arguments by default
71-
import { NoFragmentArgumentUsageRule } from './rules/custom/NoFragmentArgumentUsageRule';
72-
73-
// Prevent not-yet-in-spec usage of Fragment Arguments by default
74-
import { NoFragmentArgumentUsageRule } from './rules/custom/NoFragmentArgumentUsageRule';
75-
7669
/**
7770
* This set includes all validation rules defined by the GraphQL spec.
7871
*
@@ -94,7 +87,6 @@ export const specifiedRules: ReadonlyArray<ValidationRule> = Object.freeze([
9487
NoUnusedFragmentsRule,
9588
PossibleFragmentSpreadsRule,
9689
NoFragmentCyclesRule,
97-
NoFragmentArgumentUsageRule,
9890
UniqueVariableNamesRule,
9991
NoUndefinedVariablesRule,
10092
NoUnusedVariablesRule,

0 commit comments

Comments
 (0)