Skip to content

Commit 11954af

Browse files
author
Sylvain Lebresne
committed
Additional review feedback
Outside of minor typos/updates, the bulk of this change is switching how we collect used variables to be more efficient/avoid generating useless garbage.
1 parent aad3648 commit 11954af

6 files changed

Lines changed: 173 additions & 158 deletions

File tree

composition-js/src/validate.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import {
3131
selectionSetOf,
3232
typenameFieldName,
3333
validateSupergraph,
34-
VariableDefinitions
34+
VariableDefinitions,
35+
isOutputType
3536
} from "@apollo/federation-internals";
3637
import {
3738
Edge,
@@ -210,7 +211,8 @@ function buildWitnessNextStep(edges: Edge[], index: number): SelectionSet | unde
210211
// ellipsis instead make it immediately clear after which part of the query there is an issue.
211212
const lastType = edges[edges.length -1].tail.type;
212213
// Note that vertex types are named type and output ones, so if it's not a leaf it is guaranteed to be selectable.
213-
return isLeafType(lastType) ? undefined : new SelectionSet(lastType as CompositeType);
214+
assert(isOutputType(lastType), 'Should not have input types as vertex types');
215+
return isLeafType(lastType) ? undefined : new SelectionSet(lastType);
214216
}
215217

216218
const edge = edges[index];
@@ -240,11 +242,15 @@ function buildWitnessNextStep(edges: Edge[], index: number): SelectionSet | unde
240242
}
241243

242244
function buildWitnessField(definition: FieldDefinition<any>): Field {
245+
if (definition.arguments().length === 0) {
246+
return new Field(definition);
247+
}
248+
243249
const args = Object.create(null);
244250
for (const argDef of definition.arguments()) {
245251
args[argDef.name] = generateWitnessValue(argDef.type!);
246252
}
247-
return new Field(definition, args, new VariableDefinitions());
253+
return new Field(definition, args);
248254
}
249255

250256
function generateWitnessValue(type: InputType): any {

internals-js/src/definitions.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,16 @@ import {
3232
removeAllCoreFeatures,
3333
} from "./coreSpec";
3434
import { assert, mapValues, MapWithCachedArrays, removeArrayElement } from "./utils";
35-
import { withDefaultValues, valueEquals, valueToString, valueToAST, variablesInValue, valueFromAST, valueNodeToConstValueNode, argumentsEquals } from "./values";
35+
import {
36+
withDefaultValues,
37+
valueEquals,
38+
valueToString,
39+
valueToAST,
40+
valueFromAST,
41+
valueNodeToConstValueNode,
42+
argumentsEquals,
43+
collectVariablesInValue
44+
} from "./values";
3645
import { removeInaccessibleElements } from "./inaccessibleSpec";
3746
import { printDirectiveDefinition, printSchema } from './print';
3847
import { sameType } from './types';
@@ -399,8 +408,10 @@ export class DirectiveTargetElement<T extends DirectiveTargetElement<T>> {
399408
: ' ' + this.appliedDirectives.join(' ');
400409
}
401410

402-
variablesInAppliedDirectives(): Variables {
403-
return this.appliedDirectives.reduce((acc: Variables, d) => mergeVariables(acc, variablesInArguments(d.arguments())), []);
411+
collectVariablesInAppliedDirectives(collector: VariableCollector) {
412+
for (const applied of this.appliedDirectives) {
413+
collector.collectInArguments(applied.arguments());
414+
}
404415
}
405416
}
406417

@@ -3054,7 +3065,7 @@ export class Directive<
30543065
// applied to a field that is part of an extension, the field will have its extension set, but not the underlying directive.
30553066
private _extension?: Extension<any>;
30563067

3057-
constructor(readonly name: string, private _args: TArgs) {
3068+
constructor(readonly name: string, private _args: TArgs = Object.create(null)) {
30583069
super();
30593070
}
30603071

@@ -3299,38 +3310,38 @@ export class Variable {
32993310

33003311
export type Variables = readonly Variable[];
33013312

3302-
export function mergeVariables(v1s: Variables, v2s: Variables): Variables {
3303-
if (v1s.length == 0) {
3304-
return v2s;
3313+
export class VariableCollector {
3314+
private readonly _variables = new Map<string, Variable>();
3315+
3316+
add(variable: Variable) {
3317+
this._variables.set(variable.name, variable);
33053318
}
3306-
if (v2s.length == 0) {
3307-
return v1s;
3319+
3320+
addAll(variables: Variables) {
3321+
for (const variable of variables) {
3322+
this.add(variable);
3323+
}
33083324
}
3309-
const res: Variable[] = v1s.concat();
3310-
for (const v of v2s) {
3311-
if (!containsVariable(v1s, v)) {
3312-
res.push(v);
3325+
3326+
collectInArguments(args: {[key: string]: any}) {
3327+
for (const value of Object.values(args)) {
3328+
collectVariablesInValue(value, this);
33133329
}
33143330
}
3315-
return res;
3316-
}
33173331

3318-
export function containsVariable(variables: Variables, toCheck: Variable): boolean {
3319-
return variables.some(v => v.name == toCheck.name);
3332+
variables() {
3333+
return mapValues(this._variables);
3334+
}
3335+
3336+
toString(): string {
3337+
return this.variables().toString();
3338+
}
33203339
}
33213340

33223341
export function isVariable(v: any): v is Variable {
33233342
return v instanceof Variable;
33243343
}
33253344

3326-
export function variablesInArguments(args: {[key: string]: any}): Variables {
3327-
let variables: Variables = [];
3328-
for (const value of Object.values(args)) {
3329-
variables = mergeVariables(variables, variablesInValue(value));
3330-
}
3331-
return variables;
3332-
}
3333-
33343345
export class VariableDefinition extends DirectiveTargetElement<VariableDefinition> {
33353346
constructor(
33363347
schema: Schema,

0 commit comments

Comments
 (0)