graphql-jit 0.8.9 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +25 -0
  2. package/dist/cjs/ast.d.ts +89 -0
  3. package/dist/cjs/ast.js +766 -0
  4. package/dist/cjs/ast.js.map +1 -0
  5. package/dist/cjs/compat.d.ts +70 -0
  6. package/dist/cjs/compat.js +144 -0
  7. package/dist/cjs/compat.js.map +1 -0
  8. package/dist/cjs/debug.d.ts +29 -0
  9. package/dist/cjs/debug.js +46 -0
  10. package/dist/cjs/debug.js.map +1 -0
  11. package/dist/cjs/error.d.ts +7 -0
  12. package/dist/cjs/error.js +58 -0
  13. package/dist/cjs/error.js.map +1 -0
  14. package/dist/cjs/execution.d.ts +154 -0
  15. package/dist/cjs/execution.js +1240 -0
  16. package/dist/cjs/execution.js.map +1 -0
  17. package/dist/cjs/generate.d.ts +4 -0
  18. package/dist/cjs/generate.js +13 -0
  19. package/dist/cjs/generate.js.map +1 -0
  20. package/dist/cjs/index.d.ts +3 -0
  21. package/dist/cjs/index.js +10 -0
  22. package/dist/cjs/index.js.map +1 -0
  23. package/dist/cjs/inspect.d.ts +5 -0
  24. package/dist/cjs/inspect.js +110 -0
  25. package/dist/cjs/inspect.js.map +1 -0
  26. package/dist/cjs/json.d.ts +9 -0
  27. package/dist/cjs/json.js +144 -0
  28. package/dist/cjs/json.js.map +1 -0
  29. package/dist/cjs/memoize.d.ts +5 -0
  30. package/dist/cjs/memoize.js +28 -0
  31. package/dist/cjs/memoize.js.map +1 -0
  32. package/dist/cjs/non-null.d.ts +9 -0
  33. package/dist/cjs/non-null.js +205 -0
  34. package/dist/cjs/non-null.js.map +1 -0
  35. package/dist/cjs/package.json +3 -0
  36. package/dist/{resolve-info.d.ts → cjs/resolve-info.d.ts} +10 -12
  37. package/dist/cjs/resolve-info.js +232 -0
  38. package/dist/cjs/resolve-info.js.map +1 -0
  39. package/dist/cjs/runtime.d.ts +14 -0
  40. package/dist/cjs/runtime.js +92 -0
  41. package/dist/cjs/runtime.js.map +1 -0
  42. package/dist/cjs/types.d.ts +1 -0
  43. package/dist/cjs/types.js +3 -0
  44. package/dist/cjs/types.js.map +1 -0
  45. package/dist/cjs/variables.d.ts +20 -0
  46. package/dist/cjs/variables.js +357 -0
  47. package/dist/cjs/variables.js.map +1 -0
  48. package/dist/esm/ast.d.ts +89 -0
  49. package/dist/esm/ast.js +751 -0
  50. package/dist/esm/ast.js.map +1 -0
  51. package/dist/esm/compat.d.ts +70 -0
  52. package/dist/esm/compat.js +102 -0
  53. package/dist/esm/compat.js.map +1 -0
  54. package/dist/esm/debug.d.ts +29 -0
  55. package/dist/esm/debug.js +40 -0
  56. package/dist/esm/debug.js.map +1 -0
  57. package/dist/esm/error.d.ts +7 -0
  58. package/dist/esm/error.js +55 -0
  59. package/dist/esm/error.js.map +1 -0
  60. package/dist/esm/execution.d.ts +154 -0
  61. package/dist/esm/execution.js +1227 -0
  62. package/dist/esm/execution.js.map +1 -0
  63. package/dist/esm/generate.d.ts +4 -0
  64. package/dist/esm/generate.js +10 -0
  65. package/dist/esm/generate.js.map +1 -0
  66. package/dist/esm/index.d.ts +3 -0
  67. package/dist/esm/index.js +3 -0
  68. package/dist/esm/index.js.map +1 -0
  69. package/dist/esm/inspect.d.ts +5 -0
  70. package/dist/esm/inspect.js +106 -0
  71. package/dist/esm/inspect.js.map +1 -0
  72. package/dist/esm/json.d.ts +9 -0
  73. package/dist/esm/json.js +141 -0
  74. package/dist/esm/json.js.map +1 -0
  75. package/dist/esm/memoize.d.ts +5 -0
  76. package/dist/esm/memoize.js +20 -0
  77. package/dist/esm/memoize.js.map +1 -0
  78. package/dist/esm/non-null.d.ts +9 -0
  79. package/dist/esm/non-null.js +199 -0
  80. package/dist/esm/non-null.js.map +1 -0
  81. package/dist/esm/package.json +3 -0
  82. package/dist/{resolve-info.d.mts → esm/resolve-info.d.ts} +10 -12
  83. package/dist/esm/resolve-info.js +224 -0
  84. package/dist/esm/resolve-info.js.map +1 -0
  85. package/dist/esm/runtime.d.ts +14 -0
  86. package/dist/esm/runtime.js +89 -0
  87. package/dist/esm/runtime.js.map +1 -0
  88. package/dist/esm/types.d.ts +1 -0
  89. package/dist/esm/types.js +2 -0
  90. package/dist/esm/types.js.map +1 -0
  91. package/dist/esm/variables.d.ts +20 -0
  92. package/dist/esm/variables.js +350 -0
  93. package/dist/esm/variables.js.map +1 -0
  94. package/package.json +39 -35
  95. package/dist/ast.d.mts +0 -7
  96. package/dist/ast.d.ts +0 -7
  97. package/dist/ast.js +0 -635
  98. package/dist/ast.js.map +0 -1
  99. package/dist/ast.mjs +0 -612
  100. package/dist/ast.mjs.map +0 -1
  101. package/dist/compat.d.mts +0 -7
  102. package/dist/compat.d.ts +0 -7
  103. package/dist/compat.js +0 -113
  104. package/dist/compat.js.map +0 -1
  105. package/dist/compat.mjs +0 -75
  106. package/dist/compat.mjs.map +0 -1
  107. package/dist/error.d.mts +0 -11
  108. package/dist/error.d.ts +0 -11
  109. package/dist/error.js +0 -79
  110. package/dist/error.js.map +0 -1
  111. package/dist/error.mjs +0 -57
  112. package/dist/error.mjs.map +0 -1
  113. package/dist/execution.d.mts +0 -7
  114. package/dist/execution.d.ts +0 -7
  115. package/dist/execution.js +0 -1262
  116. package/dist/execution.js.map +0 -1
  117. package/dist/execution.mjs +0 -1248
  118. package/dist/execution.mjs.map +0 -1
  119. package/dist/generate.d.mts +0 -6
  120. package/dist/generate.d.ts +0 -6
  121. package/dist/generate.js +0 -37
  122. package/dist/generate.js.map +0 -1
  123. package/dist/generate.mjs +0 -13
  124. package/dist/generate.mjs.map +0 -1
  125. package/dist/index-CeluTkd4.d.mts +0 -329
  126. package/dist/index-mKv2zpdA.d.ts +0 -329
  127. package/dist/index.d.mts +0 -7
  128. package/dist/index.d.ts +0 -7
  129. package/dist/index.js +0 -36
  130. package/dist/index.js.map +0 -1
  131. package/dist/index.mjs +0 -15
  132. package/dist/index.mjs.map +0 -1
  133. package/dist/inspect.d.mts +0 -7
  134. package/dist/inspect.d.ts +0 -7
  135. package/dist/inspect.js +0 -121
  136. package/dist/inspect.js.map +0 -1
  137. package/dist/inspect.mjs +0 -97
  138. package/dist/inspect.mjs.map +0 -1
  139. package/dist/json.d.mts +0 -18
  140. package/dist/json.d.ts +0 -18
  141. package/dist/json.js +0 -181
  142. package/dist/json.js.map +0 -1
  143. package/dist/json.mjs +0 -164
  144. package/dist/json.mjs.map +0 -1
  145. package/dist/memoize.d.mts +0 -6
  146. package/dist/memoize.d.ts +0 -6
  147. package/dist/memoize.js +0 -67
  148. package/dist/memoize.js.map +0 -1
  149. package/dist/memoize.mjs +0 -31
  150. package/dist/memoize.mjs.map +0 -1
  151. package/dist/non-null.d.mts +0 -7
  152. package/dist/non-null.d.ts +0 -7
  153. package/dist/non-null.js +0 -196
  154. package/dist/non-null.js.map +0 -1
  155. package/dist/non-null.mjs +0 -167
  156. package/dist/non-null.mjs.map +0 -1
  157. package/dist/resolve-info.js +0 -245
  158. package/dist/resolve-info.js.map +0 -1
  159. package/dist/resolve-info.mjs +0 -219
  160. package/dist/resolve-info.mjs.map +0 -1
  161. package/dist/runtime.d.mts +0 -7
  162. package/dist/runtime.d.ts +0 -7
  163. package/dist/runtime.js +0 -115
  164. package/dist/runtime.js.map +0 -1
  165. package/dist/runtime.mjs +0 -91
  166. package/dist/runtime.mjs.map +0 -1
  167. package/dist/types.d.mts +0 -3
  168. package/dist/types.d.ts +0 -3
  169. package/dist/types.js +0 -17
  170. package/dist/types.js.map +0 -1
  171. package/dist/types.mjs +0 -1
  172. package/dist/types.mjs.map +0 -1
  173. package/dist/variables.d.mts +0 -17
  174. package/dist/variables.d.ts +0 -17
  175. package/dist/variables.js +0 -412
  176. package/dist/variables.js.map +0 -1
  177. package/dist/variables.mjs +0 -391
  178. package/dist/variables.mjs.map +0 -1
@@ -0,0 +1,1227 @@
1
+ import fastJson from "fast-json-stringify";
2
+ import { genFn } from "./generate.js";
3
+ import { jitRuntime } from "./runtime.js";
4
+ import { appendSourceURL, createGeneratedSourceName, formatDebugSource, normalizeDebugOptions } from "./debug.js";
5
+ const GLOBAL_RUNTIME_NAME = "__context.rt";
6
+ import { GraphQLEnumType, GraphQLError, isAbstractType, isLeafType, isListType, isNonNullType, isObjectType, isSpecifiedScalarType, Kind, locatedError, responsePathAsArray, TypeNameMetaFieldDef } from "graphql";
7
+ import { addPath, collectFields, collectSubfields, computeLocations, flattenPath, getArgumentDefs, joinSkipIncludePath, resolveFieldDef, serializeObjectPathForSkipInclude } from "./ast.js";
8
+ import { GraphQLError as GraphqlJitError } from "./error.js";
9
+ import createInspect from "./inspect.js";
10
+ import { queryToJSONSchema } from "./json.js";
11
+ import { createNullTrimmer } from "./non-null.js";
12
+ import { createResolveInfoThunk } from "./resolve-info.js";
13
+ import { compileVariableParsing, failToParseVariables } from "./variables.js";
14
+ import { getGraphQLErrorOptions, getOperationRootType } from "./compat.js";
15
+ const inspect = createInspect();
16
+ // prefix for the variable used ot cache validation results
17
+ const SAFETY_CHECK_PREFIX = "__validNode";
18
+ const GLOBAL_DATA_NAME = "__context.data";
19
+ const GLOBAL_ERRORS_NAME = "__context.errors";
20
+ const GLOBAL_NULL_ERRORS_NAME = "__context.nullErrors";
21
+ const GLOBAL_ROOT_NAME = "__context.rootValue";
22
+ export const GLOBAL_VARIABLES_NAME = "__context.variables";
23
+ const GLOBAL_CONTEXT_NAME = "__context.context";
24
+ const GLOBAL_EXECUTION_CONTEXT = "__context";
25
+ const GLOBAL_PROMISE_COUNTER = "__context.promiseCounter";
26
+ const GLOBAL_INSPECT_NAME = "__context.inspect";
27
+ const GLOBAL_SAFE_MAP_NAME = `${GLOBAL_RUNTIME_NAME}.safeMap`;
28
+ const GRAPHQL_ERROR = "__context.GraphQLError";
29
+ const GLOBAL_RESOLVE = "__context.resolve";
30
+ const GLOBAL_PARENT_NAME = "__parent";
31
+ const LOCAL_JS_FIELD_NAME_PREFIX = "__field";
32
+ /**
33
+ * It compiles a GraphQL query to an executable function
34
+ * @param {GraphQLSchema} schema GraphQL schema
35
+ * @param {DocumentNode} document Query being submitted
36
+ * @param {string} operationName name of the operation
37
+ * @param partialOptions compilation options to tune the compiler features
38
+ * @returns {CompiledQuery} the cacheable result
39
+ */
40
+ export function compileQuery(schema, document, operationName, partialOptions) {
41
+ if (!schema) {
42
+ throw new Error(`Expected ${schema} to be a GraphQL schema.`);
43
+ }
44
+ if (!document) {
45
+ throw new Error("Must provide document.");
46
+ }
47
+ if (partialOptions &&
48
+ partialOptions.resolverInfoEnricher &&
49
+ typeof partialOptions.resolverInfoEnricher !== "function") {
50
+ throw new Error("resolverInfoEnricher must be a function");
51
+ }
52
+ try {
53
+ const options = {
54
+ disablingCapturingStackErrors: false,
55
+ customJSONSerializer: false,
56
+ disableLeafSerialization: false,
57
+ customSerializers: {},
58
+ useExperimentalPathBasedSkipInclude: false,
59
+ ...partialOptions
60
+ };
61
+ // If a valid context cannot be created due to incorrect arguments,
62
+ // a "Response" with only errors is returned.
63
+ const context = buildCompilationContext(schema, document, options, operationName);
64
+ const debugOptions = normalizeDebugOptions(options.debug);
65
+ let stringify;
66
+ if (options.customJSONSerializer) {
67
+ const jsonSchema = queryToJSONSchema(context);
68
+ stringify = fastJson(jsonSchema);
69
+ }
70
+ else {
71
+ stringify = JSON.stringify;
72
+ }
73
+ const getVariables = compileVariableParsing(schema, context.operation.variableDefinitions || [], debugOptions
74
+ ? {
75
+ compilerOptions: debugOptions,
76
+ operation: context.operation
77
+ }
78
+ : undefined);
79
+ const type = getOperationRootType(context.schema, context.operation);
80
+ const fieldMap = collectFields(context, type, context.operation.selectionSet, Object.create(null), Object.create(null));
81
+ const functionBody = compileOperation(context, type, fieldMap);
82
+ const generatedSource = debugOptions
83
+ ? appendSourceURL(formatDebugSource(functionBody, debugOptions.formatSourceCode), createGeneratedSourceName(context.operation.name?.value, debugOptions, "query"))
84
+ : functionBody;
85
+ const compiledQuery = {
86
+ query: createBoundQuery(context, document,
87
+ // eslint-disable-next-line no-new-func
88
+ new Function("return " + generatedSource)(), getVariables, context.operation.name != null
89
+ ? context.operation.name.value
90
+ : undefined),
91
+ stringify
92
+ };
93
+ if (context.operation.operation === "subscription") {
94
+ compiledQuery.subscribe = createBoundSubscribe(context, document, compileSubscriptionOperation(context, type, fieldMap, compiledQuery.query), getVariables, context.operation.name != null
95
+ ? context.operation.name.value
96
+ : undefined);
97
+ }
98
+ if (debugOptions) {
99
+ // result of the compilation useful for debugging issues
100
+ // and visualization tools like try-jit.
101
+ compiledQuery.__DO_NOT_USE_THIS_OR_YOU_WILL_BE_FIRED_compilation =
102
+ generatedSource;
103
+ }
104
+ return compiledQuery;
105
+ }
106
+ catch (err) {
107
+ return {
108
+ errors: normalizeErrors(err)
109
+ };
110
+ }
111
+ }
112
+ export function isCompiledQuery(query) {
113
+ return "query" in query && typeof query.query === "function";
114
+ }
115
+ // Exported only for an error test
116
+ export function createBoundQuery(compilationContext, document, func, getVariableValues, operationName) {
117
+ const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos } = compilationContext;
118
+ const trimmer = createNullTrimmer(compilationContext);
119
+ const fnName = operationName || "query";
120
+ /**
121
+ * In-order to assign a debuggable name to the bound query function,
122
+ * we create an intermediate object with a method named as the
123
+ * intended function name. This is because Function.prototype.name
124
+ * is not writeable.
125
+ *
126
+ * http://www.ecma-international.org/ecma-262/6.0/#sec-method-definitions-runtime-semantics-propertydefinitionevaluation
127
+ *
128
+ * section: 14.3.9.3 - calls SetFunctionName
129
+ */
130
+ const ret = {
131
+ [fnName](rootValue, context, variables) {
132
+ // this can be shared across in a batch request
133
+ const parsedVariables = getVariableValues(variables || {});
134
+ // Return early errors if variable coercing failed.
135
+ if (failToParseVariables(parsedVariables)) {
136
+ return { errors: parsedVariables.errors };
137
+ }
138
+ const executionContext = {
139
+ rootValue,
140
+ context,
141
+ variables: parsedVariables.coerced,
142
+ inspect,
143
+ GraphQLError: GraphqlJitError,
144
+ resolvers,
145
+ typeResolvers,
146
+ isTypeOfs,
147
+ serializers,
148
+ resolveInfos,
149
+ trimmer,
150
+ rt: jitRuntime,
151
+ promiseCounter: 0,
152
+ data: {},
153
+ nullErrors: [],
154
+ errors: []
155
+ };
156
+ // eslint-disable-next-line no-useless-call
157
+ const result = func.call(null, executionContext);
158
+ if (isPromise(result)) {
159
+ return result.then(postProcessResult);
160
+ }
161
+ return postProcessResult(executionContext);
162
+ }
163
+ };
164
+ return ret[fnName];
165
+ }
166
+ function postProcessResult({ data, nullErrors, errors, trimmer }) {
167
+ if (nullErrors.length > 0) {
168
+ const trimmed = trimmer(data, nullErrors);
169
+ return {
170
+ data: trimmed.data,
171
+ errors: errors.concat(trimmed.errors)
172
+ };
173
+ }
174
+ else if (errors.length > 0) {
175
+ return {
176
+ data,
177
+ errors
178
+ };
179
+ }
180
+ return { data };
181
+ }
182
+ /**
183
+ * Create the main function body.
184
+ *
185
+ * Implements the "Evaluating operations" section of the spec.
186
+ *
187
+ * It defers all top level field for consistency and protection for null root values,
188
+ * all the fields are deferred regardless of presence of resolver or not.
189
+ *
190
+ * @param {CompilationContext} context compilation context with the execution context
191
+ * @returns {string} a function body to be instantiated together with the header, footer
192
+ */
193
+ function compileOperation(context, type, fieldMap) {
194
+ const serialExecution = context.operation.operation === "mutation";
195
+ const topLevel = compileObjectType(context, type, [], [GLOBAL_ROOT_NAME], [GLOBAL_DATA_NAME], undefined, GLOBAL_ERRORS_NAME, fieldMap, true);
196
+ let body = `function query (${GLOBAL_EXECUTION_CONTEXT}) {
197
+ "use strict";
198
+ `;
199
+ if (serialExecution) {
200
+ body += `${GLOBAL_EXECUTION_CONTEXT}.queue = [];`;
201
+ }
202
+ body += generateUniqueDeclarations(context, true);
203
+ body += `${GLOBAL_DATA_NAME} = ${topLevel}\n`;
204
+ if (serialExecution) {
205
+ body += compileDeferredFieldsSerially(context);
206
+ body += `
207
+ ${GLOBAL_EXECUTION_CONTEXT}.finalResolve = () => {};
208
+ ${GLOBAL_RESOLVE} = (context) => {
209
+ if (context.jobCounter >= context.queue.length) {
210
+ // All mutations have finished
211
+ context.finalResolve(context);
212
+ return;
213
+ }
214
+ context.queue[context.jobCounter++](context);
215
+ };
216
+ // There might not be a job to run due to invalid queries
217
+ if (${GLOBAL_EXECUTION_CONTEXT}.queue.length > 0) {
218
+ ${GLOBAL_EXECUTION_CONTEXT}.jobCounter = 1; // since the first one will be run manually
219
+ ${GLOBAL_EXECUTION_CONTEXT}.queue[0](${GLOBAL_EXECUTION_CONTEXT});
220
+ }
221
+ if (${GLOBAL_PROMISE_COUNTER} > 0) {
222
+ return new Promise(resolve => ${GLOBAL_EXECUTION_CONTEXT}.finalResolve = resolve);
223
+ }
224
+ `;
225
+ }
226
+ else {
227
+ body += compileDeferredFields(context);
228
+ body += `
229
+ return ${GLOBAL_RUNTIME_NAME}.finalizeResult(${GLOBAL_EXECUTION_CONTEXT});`;
230
+ }
231
+ body += `
232
+ // sync execution, the results are ready
233
+ return undefined;
234
+ }`;
235
+ body += context.hoistedFunctions.join("\n");
236
+ return body;
237
+ }
238
+ /**
239
+ * Processes the deferred node list in the compilation context.
240
+ *
241
+ * Each deferred node get a copy of the compilation context with
242
+ * a new empty list for deferred nodes to properly scope the nodes.
243
+ * @param {CompilationContext} context compilation context
244
+ * @returns {string} compiled transformations all of deferred nodes
245
+ */
246
+ function compileDeferredFields(context) {
247
+ let body = "";
248
+ context.deferred.forEach((deferredField, index) => {
249
+ body += `
250
+ if (${SAFETY_CHECK_PREFIX}${index}) {
251
+ ${compileDeferredField(context, deferredField)}
252
+ }`;
253
+ });
254
+ return body;
255
+ }
256
+ function compileDeferredField(context, deferredField, appendix) {
257
+ const { name, originPathsFormatted, destinationPaths, fieldNodes, fieldType, fieldName, jsFieldName, responsePath, parentType, args } = deferredField;
258
+ const subContext = createSubCompilationContext(context);
259
+ const nodeBody = compileType(subContext, parentType, fieldType, fieldNodes, [jsFieldName], [`${GLOBAL_PARENT_NAME}.${name}`], responsePath);
260
+ const parentIndexes = getParentArgIndexes(context);
261
+ const resolverName = getResolverName(parentType.name, fieldName);
262
+ const resolverHandler = getHoistedFunctionName(context, `${name}${resolverName}Handler`);
263
+ const topLevelArgs = getArgumentsName(resolverName);
264
+ const validArgs = getValidArgumentsVarName(resolverName);
265
+ const executionError = createErrorObject(context, fieldNodes, responsePath, "err.message != null ? err.message : err", "err");
266
+ const executionInfo = getExecutionInfo(subContext, parentType, fieldType, fieldName, fieldNodes, responsePath);
267
+ const emptyError = createErrorObject(context, fieldNodes, responsePath, '""');
268
+ const resolverParentPath = originPathsFormatted;
269
+ const resolverCall = `${GLOBAL_EXECUTION_CONTEXT}.resolvers.${resolverName}(
270
+ ${resolverParentPath},${topLevelArgs},${GLOBAL_CONTEXT_NAME}, ${executionInfo})`;
271
+ const resultParentPath = destinationPaths.join(".");
272
+ const compiledArgs = compileArguments(subContext, args, topLevelArgs, validArgs, fieldType, responsePath);
273
+ const body = `
274
+ ${compiledArgs}
275
+ if (${validArgs} === true) {
276
+ ${GLOBAL_RUNTIME_NAME}.callResolver(${GLOBAL_EXECUTION_CONTEXT},
277
+ () => ${resolverCall},
278
+ result => {
279
+ ${resolverHandler}(${GLOBAL_EXECUTION_CONTEXT}, ${resultParentPath}, result, ${parentIndexes});
280
+ },
281
+ err => {
282
+ if (err) {
283
+ ${getErrorDestination(fieldType)}.push(${executionError});
284
+ } else {
285
+ ${getErrorDestination(fieldType)}.push(${emptyError});
286
+ }
287
+ }
288
+ );
289
+ }`;
290
+ context.hoistedFunctions.push(`
291
+ function ${resolverHandler}(${GLOBAL_EXECUTION_CONTEXT}, ${GLOBAL_PARENT_NAME}, ${jsFieldName}, ${parentIndexes}) {
292
+ ${generateUniqueDeclarations(subContext)}
293
+ ${GLOBAL_PARENT_NAME}.${name} = ${nodeBody};
294
+ ${compileDeferredFields(subContext)}
295
+ ${appendix || ""}
296
+ }
297
+ `);
298
+ return body;
299
+ }
300
+ function compileDeferredFieldsSerially(context) {
301
+ let body = "";
302
+ context.deferred.forEach((deferredField, index) => {
303
+ const { name, fieldName, parentType } = deferredField;
304
+ const resolverName = getResolverName(parentType.name, fieldName);
305
+ const mutationHandler = getHoistedFunctionName(context, `${name}${resolverName}Mutation`);
306
+ body += `
307
+ if (${SAFETY_CHECK_PREFIX}${index}) {
308
+ ${GLOBAL_EXECUTION_CONTEXT}.queue.push(${mutationHandler});
309
+ }
310
+ `;
311
+ const appendix = `
312
+ if (${GLOBAL_PROMISE_COUNTER} === 0) {
313
+ ${GLOBAL_RESOLVE}(${GLOBAL_EXECUTION_CONTEXT});
314
+ }
315
+ `;
316
+ context.hoistedFunctions.push(`
317
+ function ${mutationHandler}(${GLOBAL_EXECUTION_CONTEXT}) {
318
+ ${compileDeferredField(context, deferredField, appendix)}
319
+ }
320
+ `);
321
+ });
322
+ return body;
323
+ }
324
+ /**
325
+ * Processes a generic node.
326
+ *
327
+ * The type is analysed and later reprocessed in dedicated functions.
328
+ * @param {CompilationContext} context compilation context to hold deferred nodes
329
+ * @param parentType
330
+ * @param {GraphQLType} type type of current parent node
331
+ * @param {FieldNode[]} fieldNodes array of the field nodes
332
+ * @param originPaths originPaths path in the parent object from where to fetch results
333
+ * @param destinationPaths path in the where to write the result
334
+ * @param previousPath response path until this node
335
+ * @returns {string} body of the resolvable fieldNodes
336
+ */
337
+ function compileType(context, parentType, type, fieldNodes, originPaths, destinationPaths, previousPath) {
338
+ const sourcePath = joinOriginPaths(originPaths);
339
+ const isNonNull = isNonNullType(type);
340
+ const innerType = isNonNull ? type.ofType : type;
341
+ // Optimization: replace the null→instanceof cascade with a single monomorphic
342
+ // runtime call for leaf types. Avoids N separate GraphQLError call sites per
343
+ // query and lets V8 optimize a single IC instead of one per field.
344
+ if (isLeafType(innerType) &&
345
+ !(context.options.disableLeafSerialization &&
346
+ (innerType instanceof GraphQLEnumType || isSpecifiedScalarType(innerType)))) {
347
+ const dest = isNonNull ? GLOBAL_NULL_ERRORS_NAME : GLOBAL_ERRORS_NAME;
348
+ const serializerName = getSerializerName(innerType.name);
349
+ context.serializers[serializerName] = getSerializer(innerType, context.options.customSerializers[innerType.name]);
350
+ const parentIndexes = getParentArgIndexes(context);
351
+ const handlerBody = `${dest}.push(${createErrorObject(context, fieldNodes, previousPath, "message")});`;
352
+ const cachedHandler = context.leafErrHandlerCache.get(handlerBody);
353
+ let errHandler;
354
+ if (cachedHandler) {
355
+ errHandler = cachedHandler;
356
+ }
357
+ else {
358
+ errHandler = getHoistedFunctionName(context, `${innerType.name}${originPaths.join("")}SerializerErrorHandler`);
359
+ context.hoistedFunctions.push(`
360
+ function ${errHandler}(${GLOBAL_EXECUTION_CONTEXT}, message, ${parentIndexes}) {
361
+ ${handlerBody}}
362
+ `);
363
+ context.leafErrHandlerCache.set(handlerBody, errHandler);
364
+ }
365
+ const locs = JSON.stringify(computeLocations(fieldNodes));
366
+ const path = serializeResponsePathAsArray(previousPath);
367
+ const capStack = context.options.disablingCapturingStackErrors
368
+ ? "true"
369
+ : "false";
370
+ const serializerRef = `${GLOBAL_EXECUTION_CONTEXT}.serializers.${serializerName}`;
371
+ const extraIndexes = parentIndexes ? `, ${parentIndexes}` : "";
372
+ if (isNonNull) {
373
+ const nullMsg = `"Cannot return null for non-nullable field ${parentType.name}.${getFieldNodesName(fieldNodes)}."`;
374
+ return `${GLOBAL_RUNTIME_NAME}.checkNonNullLeaf(${GLOBAL_EXECUTION_CONTEXT}, ${sourcePath}, ${dest}, ${nullMsg}, ${locs}, ${path}, ${capStack}, ${serializerRef}, ${errHandler}${extraIndexes})`;
375
+ }
376
+ else {
377
+ return `${GLOBAL_RUNTIME_NAME}.checkNullableLeaf(${GLOBAL_EXECUTION_CONTEXT}, ${sourcePath}, ${dest}, ${locs}, ${path}, ${capStack}, ${serializerRef}, ${errHandler}${extraIndexes})`;
378
+ }
379
+ }
380
+ let body = `${sourcePath} == null ? `;
381
+ let errorDestination;
382
+ if (isNonNullType(type)) {
383
+ type = type.ofType;
384
+ const nullErrorStr = `"Cannot return null for non-nullable field ${parentType.name}.${getFieldNodesName(fieldNodes)}."`;
385
+ body += `(${GLOBAL_NULL_ERRORS_NAME}.push(${createErrorObject(context, fieldNodes, previousPath, nullErrorStr)}), null) :`;
386
+ errorDestination = GLOBAL_NULL_ERRORS_NAME;
387
+ }
388
+ else {
389
+ body += "null : ";
390
+ errorDestination = GLOBAL_ERRORS_NAME;
391
+ }
392
+ body += "(";
393
+ // value can be an error obj
394
+ const errorPath = `${sourcePath}.message != null ? ${sourcePath}.message : ${sourcePath}`;
395
+ body += `${sourcePath} instanceof Error ? (${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, errorPath, sourcePath)}), null) : `;
396
+ if (isLeafType(type)) {
397
+ body += compileLeafType(context, type, originPaths, fieldNodes, previousPath, errorDestination);
398
+ }
399
+ else if (isObjectType(type)) {
400
+ const fieldMap = collectSubfields(context, type, fieldNodes, previousPath);
401
+ body += compileObjectType(context, type, fieldNodes, originPaths, destinationPaths, previousPath, errorDestination, fieldMap, false);
402
+ }
403
+ else if (isAbstractType(type)) {
404
+ body += compileAbstractType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination);
405
+ }
406
+ else if (isListType(type)) {
407
+ body += compileListType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination);
408
+ }
409
+ else {
410
+ /* istanbul ignore next */
411
+ throw new Error(`unsupported type: ${type.toString()}`);
412
+ }
413
+ body += ")";
414
+ return body;
415
+ }
416
+ function compileLeafType(context, type, originPaths, fieldNodes, previousPath, errorDestination) {
417
+ let body = "";
418
+ if (context.options.disableLeafSerialization &&
419
+ (type instanceof GraphQLEnumType || isSpecifiedScalarType(type))) {
420
+ body += `${joinOriginPaths(originPaths)}`;
421
+ }
422
+ else {
423
+ const serializerName = getSerializerName(type.name);
424
+ context.serializers[serializerName] = getSerializer(type, context.options.customSerializers[type.name]);
425
+ const parentIndexes = getParentArgIndexes(context);
426
+ const serializerErrorHandler = getHoistedFunctionName(context, `${type.name}${originPaths.join("")}SerializerErrorHandler`);
427
+ context.hoistedFunctions.push(`
428
+ function ${serializerErrorHandler}(${GLOBAL_EXECUTION_CONTEXT}, message, ${parentIndexes}) {
429
+ ${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, "message")});}
430
+ `);
431
+ body += `${GLOBAL_EXECUTION_CONTEXT}.serializers.${serializerName}(${GLOBAL_EXECUTION_CONTEXT}, ${joinOriginPaths(originPaths)}, ${serializerErrorHandler}, ${parentIndexes})`;
432
+ }
433
+ return body;
434
+ }
435
+ /**
436
+ * Compile a node of object type.
437
+ * @param {CompilationContext} context
438
+ * @param {GraphQLObjectType} type type of the node
439
+ * @param fieldNodes fieldNodes array with the nodes references
440
+ * @param originPaths originPaths path in the parent object from where to fetch results
441
+ * @param destinationPaths path in the where to write the result
442
+ * @param responsePath response path until this node
443
+ * @param errorDestination Path for error array
444
+ * @param fieldMap map of fields to fieldNodes array with the nodes references
445
+ * @param alwaysDefer used to force the field to be resolved with a resolver ala graphql-js
446
+ * @returns {string}
447
+ */
448
+ function compileObjectType(context, type, fieldNodes, originPaths, destinationPaths, responsePath, errorDestination, fieldMap, alwaysDefer) {
449
+ // trivialTypeNameVar applies only to __typename of this (current) type.
450
+ // Clear it on context so nested field compilations and deferred resolver
451
+ // handler sub-contexts don't reference finalType outside its switch scope.
452
+ const trivialTypeNameVar = context.trivialTypeNameVar;
453
+ context.trivialTypeNameVar = undefined;
454
+ const body = genFn();
455
+ // Begin object compilation paren
456
+ body("(");
457
+ if (typeof type.isTypeOf === "function" && !alwaysDefer) {
458
+ context.isTypeOfs[type.name + "IsTypeOf"] = type.isTypeOf;
459
+ body(`!${GLOBAL_EXECUTION_CONTEXT}.isTypeOfs["${type.name}IsTypeOf"](${joinOriginPaths(originPaths)}) ? (${errorDestination}.push(${createErrorObject(context, fieldNodes, responsePath, `\`Expected value of type "${type.name}" but got: $\{${GLOBAL_INSPECT_NAME}(${joinOriginPaths(originPaths)})}.\``)}), null) :`);
460
+ }
461
+ // object start
462
+ body("{");
463
+ for (const name of Object.keys(fieldMap)) {
464
+ const fieldNodes = fieldMap[name];
465
+ const field = resolveFieldDef(context, type, fieldNodes);
466
+ if (!field) {
467
+ // Field is invalid, should have been caught in validation
468
+ // but the error is swallowed for compatibility reasons.
469
+ continue;
470
+ }
471
+ // Key of the object
472
+ // `name` is the field name or an alias supplied by the user
473
+ body(`"${name}": `);
474
+ /**
475
+ * Value of the object
476
+ *
477
+ * The combined condition for whether a field should be included
478
+ * in the object.
479
+ *
480
+ * Here, the logical operation is `||` because every fieldNode
481
+ * is at the same level in the tree, if at least "one of" the nodes
482
+ * is included, then the field is included.
483
+ *
484
+ * For example,
485
+ *
486
+ * ```graphql
487
+ * {
488
+ * foo @skip(if: $c1)
489
+ * ... { foo @skip(if: $c2) }
490
+ * }
491
+ * ```
492
+ *
493
+ * The logic for `foo` becomes -
494
+ *
495
+ * `compilationFor($c1) || compilationFor($c2)`
496
+ */
497
+ const serializedResponsePath = joinSkipIncludePath(serializeObjectPathForSkipInclude(responsePath), name);
498
+ const fieldConditionsList = (context.options.useExperimentalPathBasedSkipInclude
499
+ ? fieldNodes.map((it) => it.__internalShouldIncludePath?.[serializedResponsePath])
500
+ : fieldNodes.map((it) => it.__internalShouldInclude)).filter(isNotNull);
501
+ let fieldCondition = fieldConditionsList
502
+ .map((it) => {
503
+ if (it.length > 0) {
504
+ return `(${it.join(" && ")})`;
505
+ }
506
+ // default: if there are no conditions, it means that the field
507
+ // is always included in the path
508
+ return "true";
509
+ })
510
+ .filter(isNotNull)
511
+ .join(" || ");
512
+ // if it's an empty string, it means that the field is always included
513
+ if (!fieldCondition) {
514
+ // if there are no conditions, it means that the field
515
+ // is always included in the path
516
+ fieldCondition = "true";
517
+ }
518
+ const alwaysIncluded = fieldCondition
519
+ .split(" || ")
520
+ .every((p) => p === "true");
521
+ if (!alwaysIncluded) {
522
+ body(`(${fieldCondition})`);
523
+ }
524
+ // Inline __typename
525
+ // No need to call a resolver for typename
526
+ if (field === TypeNameMetaFieldDef) {
527
+ const typenameValue = trivialTypeNameVar ?? `"${type.name}"`;
528
+ body(alwaysIncluded ? `${typenameValue},` : `? ${typenameValue} : undefined,`);
529
+ continue;
530
+ }
531
+ let resolver = field.resolve;
532
+ if (!resolver && alwaysDefer) {
533
+ const fieldName = field.name;
534
+ resolver = (parent) => parent && parent[fieldName];
535
+ }
536
+ if (resolver) {
537
+ context.deferred.push({
538
+ name,
539
+ responsePath: addPath(responsePath, name),
540
+ originPaths,
541
+ originPathsFormatted: joinOriginPaths(originPaths),
542
+ destinationPaths,
543
+ parentType: type,
544
+ fieldName: field.name,
545
+ jsFieldName: getJsFieldName(field.name),
546
+ fieldType: field.type,
547
+ fieldNodes,
548
+ args: getArgumentDefs(field, fieldNodes[0])
549
+ });
550
+ context.resolvers[getResolverName(type.name, field.name)] = resolver;
551
+ const idx = context.deferred.length - 1;
552
+ if (alwaysIncluded) {
553
+ body(`(${SAFETY_CHECK_PREFIX}${idx} = true, null)`);
554
+ }
555
+ else {
556
+ body(`? (${SAFETY_CHECK_PREFIX}${idx} = true, null) : (${SAFETY_CHECK_PREFIX}${idx} = false, undefined)`);
557
+ }
558
+ }
559
+ else {
560
+ const compiledFieldType = compileType(context, type, field.type, fieldNodes, originPaths.concat(field.name), destinationPaths.concat(name), addPath(responsePath, name));
561
+ if (alwaysIncluded) {
562
+ body(compiledFieldType);
563
+ }
564
+ else {
565
+ body(`? ${compiledFieldType} : undefined`);
566
+ }
567
+ }
568
+ // End object property
569
+ body(",");
570
+ }
571
+ // End object
572
+ body("}");
573
+ // End object compilation paren
574
+ body(")");
575
+ return body.toString();
576
+ }
577
+ function compileAbstractType(context, parentType, type, fieldNodes, originPaths, previousPath, errorDestination) {
578
+ let resolveType;
579
+ if (type.resolveType) {
580
+ resolveType = type.resolveType;
581
+ }
582
+ else {
583
+ resolveType = (value, context, info) => defaultResolveTypeFn(value, context, info, type);
584
+ }
585
+ const typeResolverName = getTypeResolverName(type.name);
586
+ context.typeResolvers[typeResolverName] = resolveType;
587
+ const finalTypeName = "finalType";
588
+ // Trivial types (no deferred resolvers) whose case bodies differ only in
589
+ // the __typename literal are grouped into a single shared case that uses
590
+ // the already computed finalType variable instead of a hardcoded string.
591
+ const trivialGroups = new Map();
592
+ const nonTrivialCases = [];
593
+ for (const objectType of context.schema.getPossibleTypes(type)) {
594
+ const subContext = createSubCompilationContext(context);
595
+ subContext.trivialTypeNameVar = finalTypeName;
596
+ const object = compileType(subContext, parentType, objectType, fieldNodes, originPaths, ["__concrete"], addPath(previousPath, objectType.name, "meta"));
597
+ if (subContext.deferred.length === 0) {
598
+ // object was compiled with trivialTypeNameVar
599
+ // group identical bodies to share a single case
600
+ const group = trivialGroups.get(object) ?? [];
601
+ group.push(objectType.name);
602
+ trivialGroups.set(object, group);
603
+ }
604
+ else {
605
+ nonTrivialCases.push(`case "${objectType.name}": {
606
+ ${generateUniqueDeclarations(subContext)}
607
+ const __concrete = ${object};
608
+ ${compileDeferredFields(subContext)}
609
+ return __concrete;
610
+ }`);
611
+ }
612
+ }
613
+ const trivialCases = Array.from(trivialGroups.entries()).map(([sharedObj, typeNames]) => {
614
+ const caseLabels = typeNames.map((n) => `case "${n}"`).join(": ");
615
+ return `${caseLabels}: {
616
+ const __concrete = ${sharedObj};
617
+ return __concrete;
618
+ }`;
619
+ });
620
+ const collectedTypes = [...nonTrivialCases, ...trivialCases].join("\n");
621
+ const nullTypeError = `"Runtime Object type is not a possible type for \\"${type.name}\\"."`;
622
+ const notPossibleTypeError =
623
+ // eslint-disable-next-line no-template-curly-in-string
624
+ '`Runtime Object type "${nodeType}" is not a possible type for "' +
625
+ type.name +
626
+ '".`';
627
+ const noTypeError = `${finalTypeName} ? ${notPossibleTypeError} : "Abstract type ${type.name} must resolve to an Object type at runtime for field ${parentType.name}.${getFieldNodesName(fieldNodes)}. Either the ${type.name} type should provide a \\"resolveType\\" function or each possible types should provide an \\"isTypeOf\\" function."`;
628
+ return `((nodeType, err) =>
629
+ {
630
+ if (err != null) {
631
+ ${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, "err.message != null ? err.message : err", "err")});
632
+ return null;
633
+ }
634
+ if (nodeType == null) {
635
+ ${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, nullTypeError)})
636
+ return null;
637
+ }
638
+ const ${finalTypeName} = typeof nodeType === "string" ? nodeType : nodeType.name;
639
+ switch(${finalTypeName}) {
640
+ ${collectedTypes}
641
+ default:
642
+ ${errorDestination}.push(${createErrorObject(context, fieldNodes, previousPath, noTypeError)})
643
+ return null;
644
+ }
645
+ })(
646
+ ${GLOBAL_EXECUTION_CONTEXT}.typeResolvers.${typeResolverName}(${joinOriginPaths(originPaths)},
647
+ ${GLOBAL_CONTEXT_NAME},
648
+ ${getExecutionInfo(context, parentType, type, type.name, fieldNodes, previousPath)}))`;
649
+ }
650
+ /**
651
+ * Compile a list transformation.
652
+ *
653
+ * @param {CompilationContext} context
654
+ * @param {GraphQLObjectType} parentType type of the parent of object which contained this type
655
+ * @param {GraphQLList<GraphQLType>} type list type being compiled
656
+ * @param {FieldNode[]} fieldNodes
657
+ * @param originalObjectPaths
658
+ * @param {ObjectPath} responsePath
659
+ * @param errorDestination
660
+ * @returns {string} compiled list transformation
661
+ */
662
+ function compileListType(context, parentType, type, fieldNodes, originalObjectPaths, responsePath, errorDestination) {
663
+ const name = originalObjectPaths.join(".");
664
+ const listContext = createSubCompilationContext(context);
665
+ // context depth will be mutated, so we cache the current value.
666
+ const newDepth = ++listContext.depth;
667
+ const fieldType = type.ofType;
668
+ const dataBody = compileType(listContext, parentType, fieldType, fieldNodes, ["__currentItem"], [`${GLOBAL_PARENT_NAME}[idx${newDepth}]`], addPath(responsePath, "idx" + newDepth, "variable"));
669
+ const errorMessage = `"Expected Iterable, but did not find one for field ${parentType.name}.${getFieldNodesName(fieldNodes)}."`;
670
+ const errorCase = `(${errorDestination}.push(${createErrorObject(context, fieldNodes, responsePath, errorMessage)}), null)`;
671
+ const executionError = createErrorObject(context, fieldNodes, addPath(responsePath, "idx" + newDepth, "variable"), "err.message != null ? err.message : err", "err");
672
+ const emptyError = createErrorObject(context, fieldNodes, responsePath, '""');
673
+ const uniqueDeclarations = generateUniqueDeclarations(listContext);
674
+ const deferredFields = compileDeferredFields(listContext);
675
+ const itemHandler = getHoistedFunctionName(context, `${parentType.name}${originalObjectPaths.join("")}MapItemHandler`);
676
+ const childIndexes = getParentArgIndexes(listContext);
677
+ listContext.hoistedFunctions.push(`
678
+ function ${itemHandler}(${GLOBAL_EXECUTION_CONTEXT}, ${GLOBAL_PARENT_NAME}, __currentItem, ${childIndexes}) {
679
+ ${uniqueDeclarations}
680
+ ${GLOBAL_PARENT_NAME}[idx${newDepth}] = ${dataBody};
681
+ ${deferredFields}
682
+ }
683
+ `);
684
+ const safeMapHandler = getHoistedFunctionName(context, `${parentType.name}${originalObjectPaths.join("")}MapHandler`);
685
+ const parentIndexes = getParentArgIndexes(context);
686
+ listContext.hoistedFunctions.push(`
687
+ function ${safeMapHandler}(${GLOBAL_EXECUTION_CONTEXT}, __currentItem, idx${newDepth}, resultArray, ${parentIndexes}) {
688
+ ${GLOBAL_RUNTIME_NAME}.handleListItemResult(${GLOBAL_EXECUTION_CONTEXT}, __currentItem,
689
+ result => {
690
+ ${itemHandler}(${GLOBAL_EXECUTION_CONTEXT}, resultArray, result, ${childIndexes});
691
+ },
692
+ err => {
693
+ resultArray.push(null);
694
+ if (err) {
695
+ ${getErrorDestination(fieldType)}.push(${executionError});
696
+ } else {
697
+ ${getErrorDestination(fieldType)}.push(${emptyError});
698
+ }
699
+ }
700
+ );
701
+ }
702
+ `);
703
+ return `(typeof ${name} === "string" || typeof ${name}[Symbol.iterator] !== "function") ? ${errorCase} :
704
+ ${GLOBAL_SAFE_MAP_NAME}(${GLOBAL_EXECUTION_CONTEXT}, ${name}, ${safeMapHandler}, ${parentIndexes})`;
705
+ }
706
+ const MAGIC_MINUS_INFINITY = "__MAGIC_MINUS_INFINITY__71d4310a_d4a3_4a05_b1fe_e60779d24998";
707
+ const MAGIC_PLUS_INFINITY = "__MAGIC_PLUS_INFINITY__bb201c39_3333_4695_b4ad_7f1722e7aa7a";
708
+ const MAGIC_NAN = "__MAGIC_NAN__57f286b9_4c20_487f_b409_79804ddcb4f8";
709
+ const MAGIC_DATE = "__MAGIC_DATE__33a9e76d_02e0_4128_8e92_3530ad3da74d";
710
+ function specialValueReplacer(key, value) {
711
+ if (Number.isNaN(value)) {
712
+ return MAGIC_NAN;
713
+ }
714
+ if (value === Infinity) {
715
+ return MAGIC_PLUS_INFINITY;
716
+ }
717
+ if (value === -Infinity) {
718
+ return MAGIC_MINUS_INFINITY;
719
+ }
720
+ if (this[key] instanceof Date) {
721
+ return MAGIC_DATE + this[key].getTime();
722
+ }
723
+ return value;
724
+ }
725
+ function objectStringify(val) {
726
+ return JSON.stringify(val, specialValueReplacer)
727
+ .replace(new RegExp(`"${MAGIC_NAN}"`, "g"), "NaN")
728
+ .replace(new RegExp(`"${MAGIC_PLUS_INFINITY}"`, "g"), "Infinity")
729
+ .replace(new RegExp(`"${MAGIC_MINUS_INFINITY}"`, "g"), "-Infinity")
730
+ .replace(new RegExp(`"${MAGIC_DATE}([^"]+)"`, "g"), "new Date($1)");
731
+ }
732
+ /**
733
+ * Calculates a GraphQLResolveInfo object for the resolver calls.
734
+ *
735
+ * if the resolver does not use, it returns null.
736
+ * @param {CompilationContext} context compilation context to submit the resolveInfoResolver
737
+ * @param parentType
738
+ * @param fieldType
739
+ * @param fieldName
740
+ * @param fieldNodes
741
+ * @param responsePath
742
+ * @returns {string} a call to the resolve info creator or "{}" if unused
743
+ */
744
+ function getExecutionInfo(context, parentType, fieldType, fieldName, fieldNodes, responsePath) {
745
+ const resolveInfoName = createResolveInfoName(responsePath);
746
+ const { schema, fragments, operation } = context;
747
+ context.resolveInfos[resolveInfoName] = createResolveInfoThunk({
748
+ schema,
749
+ fragments,
750
+ operation,
751
+ parentType,
752
+ fieldName,
753
+ fieldType,
754
+ fieldNodes
755
+ }, context.options.resolverInfoEnricher);
756
+ return `${GLOBAL_EXECUTION_CONTEXT}.resolveInfos.${resolveInfoName}(${GLOBAL_ROOT_NAME}, ${GLOBAL_VARIABLES_NAME}, ${serializeResponsePath(responsePath)})`;
757
+ }
758
+ function getArgumentsName(prefixName) {
759
+ return `${prefixName}Args`;
760
+ }
761
+ function getValidArgumentsVarName(prefixName) {
762
+ return `${prefixName}ValidArgs`;
763
+ }
764
+ function objectPath(topLevel, path) {
765
+ if (!path) {
766
+ return topLevel;
767
+ }
768
+ let objectPath = topLevel;
769
+ const flattened = flattenPath(path);
770
+ for (const section of flattened) {
771
+ if (section.type === "literal") {
772
+ objectPath += `["${section.key}"]`;
773
+ }
774
+ else {
775
+ /* istanbul ignore next */
776
+ throw new Error("should only have received literal paths");
777
+ }
778
+ }
779
+ return objectPath;
780
+ }
781
+ /**
782
+ * Returns a static object with the all the arguments needed for the resolver
783
+ * @param context
784
+ * @param {Arguments} args
785
+ * @param topLevelArg name of the toplevel
786
+ * @param validArgs
787
+ * @param returnType
788
+ * @param path
789
+ * @returns {string}
790
+ */
791
+ function compileArguments(context, args, topLevelArg, validArgs, returnType, path) {
792
+ // default to assuming arguments are valid
793
+ let body = `
794
+ let ${validArgs} = true;
795
+ const ${topLevelArg} = ${objectStringify(args.values)};
796
+ `;
797
+ const errorDestination = getErrorDestination(returnType);
798
+ for (const variable of args.missing) {
799
+ const varName = variable.valueNode.name.value;
800
+ body += `if (Object.prototype.hasOwnProperty.call(${GLOBAL_VARIABLES_NAME}, "${varName}")) {`;
801
+ if (variable.argument && isNonNullType(variable.argument.definition.type)) {
802
+ const message = `'Argument "${variable.argument.definition.name}" of non-null type "${variable.argument.definition.type.toString()}" must not be null.'`;
803
+ body += `if (${GLOBAL_VARIABLES_NAME}['${variable.valueNode.name.value}'] == null) {
804
+ ${errorDestination}.push(${createErrorObject(context, [variable.argument.node.value], path, message)});
805
+ ${validArgs} = false;
806
+ }`;
807
+ }
808
+ body += `
809
+ ${objectPath(topLevelArg, variable.path)} = ${GLOBAL_VARIABLES_NAME}['${variable.valueNode.name.value}'];
810
+ }`;
811
+ // If there is no default value and no variable input
812
+ // throw a field error
813
+ if (variable.argument &&
814
+ isNonNullType(variable.argument.definition.type) &&
815
+ variable.argument.definition.defaultValue === undefined) {
816
+ const message = `'Argument "${variable.argument.definition.name}" of required type "${variable.argument.definition.type.toString()}" was provided the variable "$${varName}" which was not provided a runtime value.'`;
817
+ body += ` else {
818
+ ${errorDestination}.push(${createErrorObject(context, [variable.argument.node.value], path, message)});
819
+ ${validArgs} = false;
820
+ }`;
821
+ }
822
+ }
823
+ return body;
824
+ }
825
+ /**
826
+ * Safety checks for resolver execution is done via side effects every time a resolver function
827
+ * is encountered.
828
+ *
829
+ * This function generates the declarations, so the side effect is valid code.
830
+ *
831
+ * @param {CompilationContext} context compilation context
832
+ * @param {boolean} defaultValue usually false, meant to be true at the top level
833
+ * @returns {string} a list of declarations eg: var __validNode0 = false;\nvar __validNode1 = false;
834
+ */
835
+ function generateUniqueDeclarations(context, defaultValue = false) {
836
+ return context.deferred
837
+ .map((_, idx) => `
838
+ let ${SAFETY_CHECK_PREFIX}${idx} = ${defaultValue};
839
+ `)
840
+ .join("\n");
841
+ }
842
+ function createSubCompilationContext(context) {
843
+ return { ...context, deferred: [] };
844
+ }
845
+ export function isPromise(value) {
846
+ return (value != null &&
847
+ typeof value === "object" &&
848
+ typeof value.then === "function");
849
+ }
850
+ export function isPromiseInliner(value) {
851
+ return `${GLOBAL_RUNTIME_NAME}.isPromise(${value})`;
852
+ }
853
+ /**
854
+ * Serializes the response path for an error response.
855
+ *
856
+ * @param {ObjectPath | undefined} path response path of a field
857
+ * @returns {string} filtered serialization of the response path
858
+ */
859
+ function serializeResponsePathAsArray(path) {
860
+ const flattened = flattenPath(path);
861
+ let src = "[";
862
+ for (let i = flattened.length - 1; i >= 0; i--) {
863
+ // meta is only used for the function name
864
+ if (flattened[i].type === "meta") {
865
+ continue;
866
+ }
867
+ src +=
868
+ flattened[i].type === "literal"
869
+ ? `"${flattened[i].key}",`
870
+ : `${flattened[i].key},`;
871
+ }
872
+ return src + "]";
873
+ }
874
+ function getErrorDestination(type) {
875
+ return isNonNullType(type) ? GLOBAL_NULL_ERRORS_NAME : GLOBAL_ERRORS_NAME;
876
+ }
877
+ function createResolveInfoName(path) {
878
+ return (flattenPath(path)
879
+ .map((p) => p.key)
880
+ .join("_") + "Info");
881
+ }
882
+ /**
883
+ * Serializes the response path for the resolve info function
884
+ * @param {ObjectPath | undefined} path response path of a field
885
+ * @returns {string} filtered serialization of the response path
886
+ */
887
+ function serializeResponsePath(path) {
888
+ if (!path) {
889
+ return "undefined";
890
+ }
891
+ if (path.type === "meta") {
892
+ // meta is ignored while serializing for the resolve info functions
893
+ return serializeResponsePath(path.prev);
894
+ }
895
+ const literalValue = `"${path.key}"`;
896
+ return `{
897
+ key: ${path.type === "literal" ? literalValue : path.key},
898
+ prev: ${serializeResponsePath(path.prev)}
899
+ }`;
900
+ }
901
+ /**
902
+ * Returned a bound serialization function of a scalar or enum
903
+ * @param {GraphQLScalarType | GraphQLEnumType} scalar
904
+ * @param customSerializer custom serializer
905
+ * @returns {(v: any) => any} bound serializationFunction
906
+ */
907
+ function getSerializer(scalar, customSerializer) {
908
+ const { name } = scalar;
909
+ const serialize = customSerializer || ((val) => scalar.serialize(val));
910
+ return function leafSerializer(context, v, onError, ...idx) {
911
+ try {
912
+ const value = serialize(v);
913
+ if (isInvalid(value)) {
914
+ onError(context, `Expected a value of type "${name}" but received: ${v}`, ...idx);
915
+ return null;
916
+ }
917
+ return value;
918
+ }
919
+ catch (e) {
920
+ onError(context, (e && e.message) ||
921
+ `Expected a value of type "${name}" but received an Error`, ...idx);
922
+ return null;
923
+ }
924
+ };
925
+ }
926
+ /**
927
+ * Default abstract type resolver.
928
+ *
929
+ * It only handle sync type resolving.
930
+ * @param value
931
+ * @param contextValue
932
+ * @param {GraphQLResolveInfo} info
933
+ * @param {GraphQLAbstractType} abstractType
934
+ * @returns {string}
935
+ */
936
+ function defaultResolveTypeFn(value, contextValue, info, abstractType) {
937
+ // First, look for `__typename`.
938
+ if (value != null &&
939
+ typeof value === "object" &&
940
+ typeof value.__typename === "string") {
941
+ return value.__typename;
942
+ }
943
+ // Otherwise, test each possible type.
944
+ const possibleTypes = info.schema.getPossibleTypes(abstractType);
945
+ for (const type of possibleTypes) {
946
+ if (type.isTypeOf) {
947
+ const isTypeOfResult = type.isTypeOf(value, contextValue, info);
948
+ if (isPromise(isTypeOfResult)) {
949
+ throw new Error(`Promises are not supported for resolving type of ${value}`);
950
+ }
951
+ else if (isTypeOfResult) {
952
+ return type.name;
953
+ }
954
+ }
955
+ }
956
+ throw new Error(`Could not resolve the object type in possible types of ${abstractType.name} for the value: ` +
957
+ inspect(value));
958
+ }
959
+ /**
960
+ * Constructs a ExecutionContext object from the arguments passed to
961
+ * execute, which we will pass throughout the other execution methods.
962
+ *
963
+ * Throws a GraphQLError if a valid execution context cannot be created.
964
+ */
965
+ export function buildCompilationContext(schema, document, options, operationName) {
966
+ const errors = [];
967
+ let operation = undefined;
968
+ let hasMultipleAssumedOperations = false;
969
+ const fragments = Object.create(null);
970
+ for (const definition of document.definitions) {
971
+ switch (definition.kind) {
972
+ case Kind.OPERATION_DEFINITION:
973
+ if (!operationName && operation) {
974
+ hasMultipleAssumedOperations = true;
975
+ }
976
+ else if (!operationName ||
977
+ (definition.name && definition.name.value === operationName)) {
978
+ operation = definition;
979
+ }
980
+ break;
981
+ case Kind.FRAGMENT_DEFINITION:
982
+ fragments[definition.name.value] = definition;
983
+ break;
984
+ }
985
+ }
986
+ if (!operation) {
987
+ if (operationName) {
988
+ throw new GraphQLError(`Unknown operation named "${operationName}".`);
989
+ }
990
+ else {
991
+ throw new GraphQLError("Must provide an operation.");
992
+ }
993
+ }
994
+ else if (hasMultipleAssumedOperations) {
995
+ throw new GraphQLError("Must provide operation name if query contains multiple operations.");
996
+ }
997
+ return {
998
+ schema,
999
+ fragments,
1000
+ rootValue: null,
1001
+ contextValue: null,
1002
+ operation,
1003
+ options,
1004
+ resolvers: {},
1005
+ serializers: {},
1006
+ typeResolvers: {},
1007
+ isTypeOfs: {},
1008
+ resolveInfos: {},
1009
+ hoistedFunctions: [],
1010
+ hoistedFunctionNames: new Map(),
1011
+ leafErrHandlerCache: new Map(),
1012
+ deferred: [],
1013
+ depth: -1,
1014
+ variableValues: {},
1015
+ errors
1016
+ };
1017
+ }
1018
+ function getFieldNodesName(nodes) {
1019
+ return nodes.length > 1
1020
+ ? "(" + nodes.map(({ name }) => name.value).join(",") + ")"
1021
+ : nodes[0].name.value;
1022
+ }
1023
+ function getHoistedFunctionName(context, name) {
1024
+ const count = context.hoistedFunctionNames.get(name);
1025
+ if (count === undefined) {
1026
+ context.hoistedFunctionNames.set(name, 0);
1027
+ return name;
1028
+ }
1029
+ context.hoistedFunctionNames.set(name, count + 1);
1030
+ return `${name}${count + 1}`;
1031
+ }
1032
+ function createErrorObject(context, nodes, path, message, originalError) {
1033
+ return `new ${GRAPHQL_ERROR}(${message},
1034
+ ${JSON.stringify(computeLocations(nodes))},
1035
+ ${serializeResponsePathAsArray(path)},
1036
+ ${originalError || "undefined"},
1037
+ ${context.options.disablingCapturingStackErrors ? "true" : "false"})`;
1038
+ }
1039
+ function getResolverName(parentName, name) {
1040
+ return parentName + name + "Resolver";
1041
+ }
1042
+ function getTypeResolverName(name) {
1043
+ return name + "TypeResolver";
1044
+ }
1045
+ function getSerializerName(name) {
1046
+ return name + "Serializer";
1047
+ }
1048
+ function normalizeErrors(err) {
1049
+ if (Array.isArray(err)) {
1050
+ return err.map((e) => normalizeError(e));
1051
+ }
1052
+ return [normalizeError(err)];
1053
+ }
1054
+ function normalizeError(err) {
1055
+ return err instanceof GraphQLError
1056
+ ? err
1057
+ : new GraphqlJitError(err.message, err.locations, err.path, err);
1058
+ }
1059
+ /**
1060
+ * Returns true if a value is undefined, or NaN.
1061
+ */
1062
+ function isInvalid(value) {
1063
+ // eslint-disable-next-line no-self-compare
1064
+ return value === undefined || value !== value;
1065
+ }
1066
+ function getParentArgIndexes(context) {
1067
+ let args = "";
1068
+ for (let i = 0; i <= context.depth; ++i) {
1069
+ if (i > 0) {
1070
+ args += ", ";
1071
+ }
1072
+ args += `idx${i}`;
1073
+ }
1074
+ return args;
1075
+ }
1076
+ function getJsFieldName(fieldName) {
1077
+ return `${LOCAL_JS_FIELD_NAME_PREFIX}${fieldName}`;
1078
+ }
1079
+ export function isAsyncIterable(val) {
1080
+ return typeof Object(val)[Symbol.asyncIterator] === "function";
1081
+ }
1082
+ function compileSubscriptionOperation(context, type, fieldMap, queryFn) {
1083
+ const fieldNodes = Object.values(fieldMap)[0];
1084
+ const fieldNode = fieldNodes[0];
1085
+ const fieldName = fieldNode.name.value;
1086
+ const field = resolveFieldDef(context, type, fieldNodes);
1087
+ if (!field) {
1088
+ throw new GraphQLError(`The subscription field "${fieldName}" is not defined.`, getGraphQLErrorOptions(fieldNodes));
1089
+ }
1090
+ const responsePath = addPath(undefined, fieldName);
1091
+ const resolveInfoName = createResolveInfoName(responsePath);
1092
+ const subscriber = field.subscribe;
1093
+ async function executeSubscription(executionContext) {
1094
+ const resolveInfo = executionContext.resolveInfos[resolveInfoName](executionContext.rootValue, executionContext.variables, responsePath);
1095
+ try {
1096
+ const eventStream = await subscriber?.(executionContext.rootValue, executionContext.variables, executionContext.context, resolveInfo);
1097
+ if (eventStream instanceof Error) {
1098
+ throw eventStream;
1099
+ }
1100
+ return eventStream;
1101
+ }
1102
+ catch (error) {
1103
+ throw locatedError(error, resolveInfo.fieldNodes, responsePathAsArray(resolveInfo.path));
1104
+ }
1105
+ }
1106
+ async function createSourceEventStream(executionContext) {
1107
+ try {
1108
+ const eventStream = await executeSubscription(executionContext);
1109
+ // Assert field returned an event stream, otherwise yield an error.
1110
+ if (!isAsyncIterable(eventStream)) {
1111
+ throw new Error("Subscription field must return Async Iterable. " +
1112
+ `Received: ${inspect(eventStream)}.`);
1113
+ }
1114
+ return eventStream;
1115
+ }
1116
+ catch (error) {
1117
+ // If it is a GraphQLError, report it as an ExecutionResult, containing only errors and no data.
1118
+ // Otherwise treat the error as a system-class error and re-throw it.
1119
+ if (error instanceof GraphQLError) {
1120
+ return { errors: [error] };
1121
+ }
1122
+ throw error;
1123
+ }
1124
+ }
1125
+ return async function subscribe(executionContext) {
1126
+ const resultOrStream = await createSourceEventStream(executionContext);
1127
+ if (!isAsyncIterable(resultOrStream)) {
1128
+ return resultOrStream;
1129
+ }
1130
+ // For each payload yielded from a subscription, map it over the normal
1131
+ // GraphQL `execute` function, with `payload` as the rootValue.
1132
+ // This implements the "MapSourceToResponseEvent" algorithm described in
1133
+ // the GraphQL specification. The `execute` function provides the
1134
+ // "ExecuteSubscriptionEvent" algorithm, as it is nearly identical to the
1135
+ // "ExecuteQuery" algorithm, for which `execute` is also used.
1136
+ // We use our `query` function in place of `execute`
1137
+ const mapSourceToResponse = (payload) => queryFn(payload, executionContext.context, executionContext.variables);
1138
+ return mapAsyncIterator(resultOrStream, mapSourceToResponse);
1139
+ };
1140
+ }
1141
+ function createBoundSubscribe(compilationContext, document, func, getVariableValues, operationName) {
1142
+ const { resolvers, typeResolvers, isTypeOfs, serializers, resolveInfos } = compilationContext;
1143
+ const trimmer = createNullTrimmer(compilationContext);
1144
+ const fnName = operationName || "subscribe";
1145
+ const ret = {
1146
+ async [fnName](rootValue, context, variables) {
1147
+ // this can be shared across in a batch request
1148
+ const parsedVariables = getVariableValues(variables || {});
1149
+ // Return early errors if variable coercing failed.
1150
+ if (failToParseVariables(parsedVariables)) {
1151
+ return { errors: parsedVariables.errors };
1152
+ }
1153
+ const executionContext = {
1154
+ rootValue,
1155
+ context,
1156
+ variables: parsedVariables.coerced,
1157
+ inspect,
1158
+ GraphQLError: GraphqlJitError,
1159
+ resolvers,
1160
+ typeResolvers,
1161
+ isTypeOfs,
1162
+ serializers,
1163
+ resolveInfos,
1164
+ trimmer,
1165
+ rt: jitRuntime,
1166
+ promiseCounter: 0,
1167
+ nullErrors: [],
1168
+ errors: [],
1169
+ data: {}
1170
+ };
1171
+ // eslint-disable-next-line no-useless-call
1172
+ return func.call(null, executionContext);
1173
+ }
1174
+ };
1175
+ return ret[fnName];
1176
+ }
1177
+ /**
1178
+ * Given an AsyncIterable and a callback function, return an AsyncIterator
1179
+ * which produces values mapped via calling the callback function.
1180
+ */
1181
+ function mapAsyncIterator(iterable, callback) {
1182
+ const iterator = iterable[Symbol.asyncIterator]();
1183
+ async function mapResult(result) {
1184
+ if (result.done) {
1185
+ return result;
1186
+ }
1187
+ try {
1188
+ return { value: await callback(result.value), done: false };
1189
+ }
1190
+ catch (error) {
1191
+ if (typeof iterator.return === "function") {
1192
+ try {
1193
+ await iterator.return();
1194
+ }
1195
+ catch (e) {
1196
+ /* ignore error */
1197
+ }
1198
+ }
1199
+ throw error;
1200
+ }
1201
+ }
1202
+ return {
1203
+ async next() {
1204
+ return mapResult(await iterator.next());
1205
+ },
1206
+ async return() {
1207
+ return typeof iterator.return === "function"
1208
+ ? mapResult(await iterator.return())
1209
+ : { value: undefined, done: true };
1210
+ },
1211
+ async throw(error) {
1212
+ return typeof iterator.throw === "function"
1213
+ ? mapResult(await iterator.throw(error))
1214
+ : Promise.reject(error);
1215
+ },
1216
+ [Symbol.asyncIterator]() {
1217
+ return this;
1218
+ }
1219
+ };
1220
+ }
1221
+ function joinOriginPaths(originPaths) {
1222
+ return originPaths.join(".");
1223
+ }
1224
+ function isNotNull(it) {
1225
+ return it != null;
1226
+ }
1227
+ //# sourceMappingURL=execution.js.map