@graphql-tools/executor
Version:
Fork of GraphQL.js' execute function
81 lines (80 loc) • 2.79 kB
JavaScript
/** @internal */
export class DeferredFragmentRecord {
path;
label;
id;
parentDeferUsage;
pendingExecutionGroups;
successfulExecutionGroups;
children;
pending;
fns;
constructor(path, label, parentDeferUsage) {
this.path = path;
this.label = label;
this.parentDeferUsage = parentDeferUsage;
this.pendingExecutionGroups = new Set();
this.successfulExecutionGroups = new Set();
this.children = new Set();
this.pending = false;
this.fns = [];
}
onPending(fn) {
this.fns.push(fn);
}
setAsPending() {
this.pending = true;
for (const fn of this.fns) {
fn();
}
}
}
export function isDeferredFragmentRecord(deliveryGroup) {
return deliveryGroup instanceof DeferredFragmentRecord;
}
/**
* @internal
*/
export class DeferredFragmentFactory {
_rootDeferredFragments = new Map();
get(deferUsage, path) {
const deferUsagePath = this._pathAtDepth(path, deferUsage.depth);
let deferredFragmentRecords;
if (deferUsagePath === undefined) {
deferredFragmentRecords = this._rootDeferredFragments;
}
else {
// A doubly nested Map<Path, Map<DeferUsage, DeferredFragmentRecord>>
// could be used, but could leak memory in long running operations.
// A WeakMap could be used instead. The below implementation is
// WeakMap-Like, saving the Map on the Path object directly.
// Alternatively, memory could be reclaimed manually, taking care to
// also reclaim memory for nested DeferredFragmentRecords if the parent
// is removed secondary to an error.
deferredFragmentRecords = deferUsagePath.deferredFragmentRecords;
if (deferredFragmentRecords === undefined) {
deferredFragmentRecords = new Map();
deferUsagePath.deferredFragmentRecords = deferredFragmentRecords;
}
}
let deferredFragmentRecord = deferredFragmentRecords.get(deferUsage);
if (deferredFragmentRecord === undefined) {
const { label, parentDeferUsage } = deferUsage;
deferredFragmentRecord = new DeferredFragmentRecord(deferUsagePath, label, parentDeferUsage);
deferredFragmentRecords.set(deferUsage, deferredFragmentRecord);
}
return deferredFragmentRecord;
}
_pathAtDepth(path, depth) {
if (depth === 0) {
return;
}
const stack = [];
let currentPath = path;
while (currentPath !== undefined) {
stack.unshift(currentPath);
currentPath = currentPath.prev;
}
return stack[depth - 1];
}
}