grafast 0.1.1-beta.11 → 0.1.1-beta.13

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 (41) hide show
  1. package/README.md +0 -3
  2. package/dist/args.js +8 -2
  3. package/dist/constraints.d.ts +15 -1
  4. package/dist/constraints.js +40 -1
  5. package/dist/engine/LayerPlan.d.ts +1 -0
  6. package/dist/engine/LayerPlan.js +62 -9
  7. package/dist/engine/OperationPlan.js +372 -274
  8. package/dist/engine/OutputPlan.d.ts +6 -5
  9. package/dist/engine/OutputPlan.js +423 -444
  10. package/dist/engine/executeBucket.js +36 -77
  11. package/dist/error.d.ts +13 -0
  12. package/dist/grafastGraphql.d.ts +5 -5
  13. package/dist/graphqlCollectFields.d.ts +6 -0
  14. package/dist/graphqlCollectFields.js +14 -8
  15. package/dist/interfaces.d.ts +18 -0
  16. package/dist/interfaces.js +0 -2
  17. package/dist/mermaid.js +20 -11
  18. package/dist/operationPlan-input.js +8 -1
  19. package/dist/planJSONInterfaces.d.ts +2 -0
  20. package/dist/prepare.js +3 -3
  21. package/dist/step.d.ts +5 -5
  22. package/dist/step.js +53 -2
  23. package/dist/steps/__flag.d.ts +3 -2
  24. package/dist/steps/__inputObject.d.ts +1 -0
  25. package/dist/steps/__inputObject.js +36 -0
  26. package/dist/steps/__item.d.ts +3 -3
  27. package/dist/steps/__trackedValue.d.ts +8 -0
  28. package/dist/steps/__trackedValue.js +40 -0
  29. package/dist/steps/__value.d.ts +2 -1
  30. package/dist/steps/constant.d.ts +2 -0
  31. package/dist/steps/constant.js +12 -0
  32. package/dist/steps/graphqlResolver.js +8 -5
  33. package/dist/steps/listen.d.ts +2 -2
  34. package/dist/steps/object.d.ts +1 -1
  35. package/dist/steps/sideEffect.d.ts +0 -1
  36. package/dist/thereCanBeOnlyOne.js +1 -1
  37. package/dist/utils.d.ts +4 -0
  38. package/dist/utils.js +7 -0
  39. package/dist/version.d.ts +1 -1
  40. package/dist/version.js +1 -1
  41. package/package.json +1 -1
@@ -13,66 +13,6 @@ const interfaces_js_1 = require("../interfaces.js");
13
13
  const polymorphic_js_1 = require("../polymorphic.js");
14
14
  const access_js_1 = require("../steps/access.js");
15
15
  const { executeSync, GraphQLBoolean, GraphQLError, GraphQLFloat, GraphQLID, GraphQLInt, GraphQLString, isObjectType, Kind, OperationTypeNode, } = graphql;
16
- const ref_FLAG_ERROR = tamedevil_1.default.ref(interfaces_js_1.FLAG_ERROR, "FLAG_ERROR");
17
- const ref_coerceError = tamedevil_1.default.ref(coerceError, "coerceError");
18
- const ref_nonNullError = tamedevil_1.default.ref(nonNullError, "nonNullError");
19
- const ref_stringifyString = tamedevil_1.default.ref(tamedevil_1.stringifyString, "stringifyString");
20
- const ref_stringifyJSON = tamedevil_1.default.ref(tamedevil_1.stringifyJSON, "stringifyJSON");
21
- const ref_isPolymorphicData = tamedevil_1.default.ref(polymorphic_js_1.isPolymorphicData, "isPolymorphicData");
22
- const ref_$$concreteType = tamedevil_1.default.ref(interfaces_js_1.$$concreteType, "$$concreteType");
23
- const ref_assert = tamedevil_1.default.ref(assert, "assert");
24
- const ref_getChildBucketAndIndex = tamedevil_1.default.ref(getChildBucketAndIndex, "getChildBucketAndIndex");
25
- const ref_inspect = tamedevil_1.default.ref(inspect_js_1.inspect, "inspect");
26
- const ref_$$streamMore = tamedevil_1.default.ref(interfaces_js_1.$$streamMore, "$$streamMore");
27
- const te_String = (0, tamedevil_1.default) `String`;
28
- const te_nullIsFineComment = (0, tamedevil_1.default) `// root/introspection, null is fine`;
29
- const te_nullString = (0, tamedevil_1.default) `"null"`;
30
- const te_null = (0, tamedevil_1.default) `null`;
31
- const te_childBucket = (0, tamedevil_1.default) `childBucket`;
32
- const te_childBucketIndex = (0, tamedevil_1.default) `childBucketIndex`;
33
- const te_executeString = (0, tamedevil_1.default) `executeString`;
34
- const te_execute = (0, tamedevil_1.default) `execute`;
35
- const te_polymorphic = (0, tamedevil_1.default) `polymorphic`;
36
- const te_letStringLbrace = (0, tamedevil_1.default) `let string = "{";`;
37
- const te_stringPlusEquals = (0, tamedevil_1.default) `string +=`;
38
- const te_stringPlusEqualsRbrace = (0, tamedevil_1.default) ` string += "}";\n`;
39
- const te_stringPlusEqualsRbracket = (0, tamedevil_1.default) ` string += "]";\n`;
40
- const te_constObjEqualsObjectCreateNull = (0, tamedevil_1.default) `const obj = Object.create(null);`;
41
- const te_comma = (0, tamedevil_1.default) `,`;
42
- const te_specDotLocationDetails = (0, tamedevil_1.default) `spec.locationDetails`;
43
- const te_thisDotLocationDetails = (0, tamedevil_1.default) `this.locationDetails`;
44
- const te_specDotOutputPlan = (0, tamedevil_1.default) `spec.outputPlan`;
45
- const te_bucket = (0, tamedevil_1.default) `bucket`;
46
- const te_bucketIndex = (0, tamedevil_1.default) `bucketIndex`;
47
- const te_handleDeferred = (0, tamedevil_1.default) `
48
- // Everything seems okay; queue any deferred payloads
49
- for (const defer of this.deferredOutputPlans) {
50
- root.queue.push({
51
- root,
52
- path: mutablePath.slice(1),
53
- bucket,
54
- bucketIndex,
55
- outputPlan: defer,
56
- label: defer.type.deferLabel,
57
- });
58
- }
59
- `;
60
- const te_string = (0, tamedevil_1.default) `string`;
61
- const te_object = (0, tamedevil_1.default) `object`;
62
- const te_obj = (0, tamedevil_1.default) `obj`;
63
- const te_data = (0, tamedevil_1.default) `data`;
64
- const te_commonErrorHandler = tamedevil_1.default.ref(commonErrorHandler, "handleError");
65
- const te_childBucketCBIDC = (0, tamedevil_1.default) `, childBucket, childBucketIndex, directChild`;
66
- const te_letString = (0, tamedevil_1.default) `let string;`;
67
- const te_constDataEqualsEmptyArray = (0, tamedevil_1.default) `const data = [];`;
68
- const te_stringEqualsEmptyArrayString = (0, tamedevil_1.default) ` string = "[]";`;
69
- const te_stringEqualsLeftSquareBraceString = (0, tamedevil_1.default) ` string = "[";\n`;
70
- const te_noopComment = (0, tamedevil_1.default) ` /* noop */`;
71
- const te_ifIGt0StrPlusEqualComma = (0, tamedevil_1.default) `\n if (i > 0) { string += ","; }\n`;
72
- const te_dataIEquals = (0, tamedevil_1.default) `data[i] =`;
73
- const te_childOutputPlan = (0, tamedevil_1.default) `childOutputPlan`;
74
- const te_underscoreNonNull = (0, tamedevil_1.default) `_nonNull`;
75
- const te_underscoreStream = (0, tamedevil_1.default) `_stream`;
76
16
  /**
77
17
  * Defines a way of taking a layerPlan and converting it into an output value.
78
18
  *
@@ -102,6 +42,8 @@ class OutputPlan {
102
42
  this.type = type;
103
43
  /**
104
44
  * Appended to the root step when accessed to avoid the need for AccessSteps
45
+ *
46
+ * @internal
105
47
  */
106
48
  this.processRoot = null;
107
49
  /**
@@ -126,6 +68,8 @@ class OutputPlan {
126
68
  layerPlan.operationPlan.stepTracker.addOutputPlan(this);
127
69
  this.childByTypeName =
128
70
  this.type.mode === "polymorphic" ? Object.create(null) : undefined;
71
+ // NOTE: this may be cleared during `this.finalize()`
72
+ this.sideEffectStep = layerPlan.latestSideEffectStep;
129
73
  }
130
74
  print() {
131
75
  const type = this.type;
@@ -158,7 +102,7 @@ class OutputPlan {
158
102
  }
159
103
  }
160
104
  toString() {
161
- return `OutputPlan<${this.type.mode}∈${this.layerPlan.id}!${this.rootStep.id}>`;
105
+ return `OutputPlan<${this.type.mode}${this.sideEffectStep ? `^${this.sideEffectStep.id}` : ""}∈${this.layerPlan.id}!${this.rootStep.id}>`;
162
106
  }
163
107
  addChild(type, key, child) {
164
108
  if (this.type.mode === "root" || this.type.mode === "object") {
@@ -251,7 +195,7 @@ class OutputPlan {
251
195
  // By just reusing the same path over and over we don't need to allocate
252
196
  // more memory for more arrays; but we must be _incredibly_ careful to
253
197
  // ensure any changes to it are reversed.
254
- _mutablePath, _bucket, _bucketIndex) {
198
+ _mutablePath, _bucket, _bucketIndex, _rawBucketRootValue, _bucketRootFlags) {
255
199
  throw new Error(`OutputPlan.execute has yet to be built!`);
256
200
  }
257
201
  // This gets replaced with a mode-specific executor
@@ -259,12 +203,21 @@ class OutputPlan {
259
203
  // By just reusing the same path over and over we don't need to allocate
260
204
  // more memory for more arrays; but we must be _incredibly_ careful to
261
205
  // ensure any changes to it are reversed.
262
- _mutablePath, _bucket, _bucketIndex) {
206
+ _mutablePath, _bucket, _bucketIndex, _rawBucketRootValue, _bucketRootFlags) {
263
207
  throw new Error(`OutputPlan.executeString has yet to be built!`);
264
208
  }
265
209
  optimize() {
210
+ // This optimization works by ridding us of access steps at the very end of
211
+ // paths and just accessing properties directly. In rare circumstances
212
+ // involving untethered side effects in earlier versions this could lead to
213
+ // errors being skipped and data generated previous to the error being
214
+ // returned; but OutputPlans now check the latestSideEffectStep so this
215
+ // should be safe aga.
266
216
  const $root = this.layerPlan.operationPlan.dangerouslyGetStep(this.rootStep.id);
267
- if ($root instanceof index_js_1.AccessStep && $root.fallback === undefined) {
217
+ if ($root instanceof index_js_1.AccessStep &&
218
+ $root.fallback === undefined &&
219
+ $root.implicitSideEffectStep === null &&
220
+ (!this.sideEffectStep || !(0, index_js_1.stepADependsOnStepB)($root, this.sideEffectStep))) {
268
221
  const expressionDetails = $root.unbatchedExecute[access_js_1.expressionSymbol];
269
222
  if (expressionDetails !== undefined) {
270
223
  // @ts-ignore
@@ -278,6 +231,19 @@ class OutputPlan {
278
231
  }
279
232
  }
280
233
  finalize() {
234
+ // Clear the sideEffectStep if the rootStep explicitly depends on it.
235
+ // NOTE: this occurs here since more dependencies could have been added to
236
+ // $root after `this` was created.
237
+ const $sideEffect = this.sideEffectStep;
238
+ if ($sideEffect) {
239
+ const $root = this.rootStep;
240
+ if ($root === $sideEffect ||
241
+ $root.implicitSideEffectStep === $sideEffect ||
242
+ (0, index_js_1.stepADependsOnStepB)($root, $sideEffect)) {
243
+ // It's marked readonly, but we override it anyway
244
+ this.sideEffectStep = null;
245
+ }
246
+ }
281
247
  // Build the executor
282
248
  switch (this.type.mode) {
283
249
  case "null": {
@@ -370,12 +336,8 @@ class OutputPlan {
370
336
  spec.outputPlan.layerPlan.id === this.layerPlan.id,
371
337
  };
372
338
  }
373
- makeObjectExecutor(type.typeName, digestFieldTypes, this.deferredOutputPlans.length > 0, type.mode === "root", false, (fn) => {
374
- this.execute = fn;
375
- });
376
- makeObjectExecutor(type.typeName, digestFieldTypes, this.deferredOutputPlans.length > 0, type.mode === "root", true, (fn) => {
377
- this.executeString = fn;
378
- });
339
+ this.execute = makeObjectExecutor(type.typeName, digestFieldTypes, this.deferredOutputPlans.length > 0, type.mode === "root", false);
340
+ this.executeString = makeObjectExecutor(type.typeName, digestFieldTypes, this.deferredOutputPlans.length > 0, type.mode === "root", true);
379
341
  break;
380
342
  }
381
343
  default: {
@@ -420,17 +382,20 @@ exports.nonNullError = nonNullError;
420
382
  *
421
383
  * @internal
422
384
  */
423
- function getChildBucketAndIndex(childOutputPlan, outputPlan, bucket, bucketIndex, arrayIndex = null) {
385
+ function getChildBucketAndIndex(layerPlan, outputPlan, bucket, bucketIndex, arrayIndex = null) {
386
+ if (bucket.layerPlan === layerPlan) {
387
+ return [bucket, bucketIndex];
388
+ }
424
389
  if ((arrayIndex == null) ===
425
390
  (outputPlan != null && outputPlan.type.mode === "array")) {
426
391
  throw new Error("GrafastInternalError<83d0e3cc-7eec-4185-85b4-846540288162>: arrayIndex must be supplied iff outputPlan is an array");
427
392
  }
428
- if (outputPlan != null && childOutputPlan.layerPlan === bucket.layerPlan) {
393
+ if (outputPlan != null && layerPlan === bucket.layerPlan) {
429
394
  // Same layer; straightforward
430
395
  return [bucket, bucketIndex];
431
396
  }
432
- const reversePath = [childOutputPlan.layerPlan];
433
- let current = childOutputPlan.layerPlan;
397
+ const reversePath = [layerPlan];
398
+ let current = layerPlan;
434
399
  while (!bucket.children[current.id]) {
435
400
  current = current.parentLayerPlan;
436
401
  if (!current) {
@@ -484,78 +449,112 @@ function getChildBucketAndIndex(childOutputPlan, outputPlan, bucket, bucketIndex
484
449
  return [currentBucket, currentIndex];
485
450
  }
486
451
  exports.getChildBucketAndIndex = getChildBucketAndIndex;
487
- function makeExecutorExpression(options) {
488
- const { inner, nameExtra, asString, skipNullHandling = false, preamble = tamedevil_1.default.blank, } = options;
489
- return (0, tamedevil_1.default) `\
490
- (function compiledOutputPlan${asString ? te_String : tamedevil_1.default.blank}_${nameExtra}(
491
- root,
492
- mutablePath,
493
- bucket,
494
- bucketIndex,
495
- rawBucketRootValue = bucket.store.get(this.rootStep.id).at(bucketIndex),
496
- bucketRootFlags = bucket.store.get(this.rootStep.id)._flagsAt(bucketIndex)
497
- ) {
498
- const bucketRootValue = this.processRoot !== null ? this.processRoot(rawBucketRootValue, bucketRootFlags) : rawBucketRootValue;
499
- ${preamble}\
500
- ${skipNullHandling
501
- ? dev_js_1.isDev
502
- ? te_nullIsFineComment
503
- : tamedevil_1.default.blank
504
- : (0, tamedevil_1.default) `if (bucketRootValue == null) return ${asString ? te_nullString : te_null};`}
505
- if (bucketRootFlags & ${ref_FLAG_ERROR}) {
506
- throw ${ref_coerceError}(bucketRootValue, this.locationDetails, mutablePath.slice(1));
507
- }
508
- ${inner}
509
- })`;
452
+ function makeExecutor(config) {
453
+ const { preamble = null, inner, asString, nameExtra, skipNullHandling = false, } = config;
454
+ const fn = function (root, mutablePath, bucket, bucketIndex, rawBucketRootValue = bucket.store.get(this.rootStep.id).at(bucketIndex), bucketRootFlags = bucket.store.get(this.rootStep.id)._flagsAt(bucketIndex)) {
455
+ if (this.sideEffectStep !== null) {
456
+ const sideEffectBucketDetails = getChildBucketAndIndex(this.sideEffectStep.layerPlan, null, bucket, bucketIndex);
457
+ if (sideEffectBucketDetails) {
458
+ const [sideEffectBucket, sideEffectBucketIndex] = sideEffectBucketDetails;
459
+ const ev = sideEffectBucket.store.get(this.sideEffectStep.id);
460
+ if (!ev) {
461
+ throw new Error(`GrafastInternalError<da9cc5a0-23bf-4af8-a103-92f995795398>: ${(0, index_js_1.stripAnsi)(String(this.sideEffectStep))} has no entry in ${bucket}`);
462
+ }
463
+ const seFlags = ev._flagsAt(sideEffectBucketIndex);
464
+ if (seFlags & interfaces_js_1.FLAG_ERROR) {
465
+ const seVal = ev.at(sideEffectBucketIndex);
466
+ throw coerceError(seVal, this.locationDetails, mutablePath.slice(1));
467
+ }
468
+ }
469
+ }
470
+ const bucketRootValue = this.processRoot !== null
471
+ ? this.processRoot(rawBucketRootValue, bucketRootFlags)
472
+ : rawBucketRootValue;
473
+ const earlyReturn = preamble?.call(this, bucketRootValue);
474
+ if (earlyReturn !== undefined) {
475
+ return earlyReturn;
476
+ }
477
+ if (bucketRootFlags & interfaces_js_1.FLAG_ERROR) {
478
+ throw coerceError(bucketRootValue, this.locationDetails, mutablePath.slice(1));
479
+ }
480
+ if (!skipNullHandling) {
481
+ if (bucketRootValue == null)
482
+ return (asString ? "null" : null);
483
+ }
484
+ return inner.call(this, bucketRootValue, root, mutablePath, bucket, bucketIndex, rawBucketRootValue, bucketRootFlags);
485
+ };
486
+ fn.displayName = `outputPlan${asString ? "String" : ""}_${nameExtra}`;
487
+ return fn;
510
488
  }
511
- function makeExecutor(options, callback) {
512
- const expression = makeExecutorExpression(options);
513
- if (callback !== undefined) {
514
- tamedevil_1.default.runInBatch(expression, callback);
515
- }
516
- else {
517
- return tamedevil_1.default.run((0, tamedevil_1.default) `return ${expression}`);
489
+ function executeChildPlan(that, locationDetails, childOutputPlan, isNonNull, asString, childBucket, childBucketIndex, bucket, bucketIndex, mutablePath, mutablePathIndex, root, rawBucketRootValue, bucketRootFlags) {
490
+ const $sideEffect = childOutputPlan.layerPlan.parentSideEffectStep;
491
+ if ($sideEffect !== null) {
492
+ // Check if there's an error
493
+ const sideEffectBucketDetails = getChildBucketAndIndex($sideEffect.layerPlan, null, bucket, bucketIndex);
494
+ if (sideEffectBucketDetails) {
495
+ const [sideEffectBucket, sideEffectBucketIndex] = sideEffectBucketDetails;
496
+ const ev = sideEffectBucket.store.get($sideEffect.id);
497
+ if (!ev) {
498
+ throw new Error(`GrafastInternalError<d18d52b5-f5bf-42df-a2dd-80e522310b8e>: ${(0, index_js_1.stripAnsi)(String($sideEffect))} has no entry in ${bucket}`);
499
+ }
500
+ const flags = ev._flagsAt(sideEffectBucketIndex);
501
+ if (flags & interfaces_js_1.FLAG_ERROR) {
502
+ const e = coerceError(ev.at(sideEffectBucketIndex), locationDetails, mutablePath.slice(1));
503
+ if (isNonNull) {
504
+ throw e;
505
+ }
506
+ else {
507
+ const streamCount = root.streams.length;
508
+ const queueCount = root.queue.length;
509
+ commonErrorHandler(e, locationDetails, mutablePath, mutablePathIndex, root, streamCount, queueCount);
510
+ return asString ? "null" : null;
511
+ }
512
+ }
513
+ }
518
514
  }
519
- }
520
- function makeExecuteChildPlanCode(setTargetOrReturn, locationDetails, childOutputPlan, isNonNull, asString, childBucket = te_childBucket, childBucketIndex = te_childBucketIndex) {
521
- const te_childOutputPlanExecute = (0, tamedevil_1.default) `${childOutputPlan}.${asString ? te_executeString : te_execute}(
522
- root,
523
- mutablePath,
524
- ${childBucket},
525
- ${childBucketIndex},
526
- ${childBucket}.rootStep === this.rootStep ? rawBucketRootValue : undefined,
527
- ${childBucket}.rootStep === this.rootStep ? bucketRootFlags : undefined
528
- )`;
529
515
  // This is the code that changes based on if the field is nullable or not
530
516
  if (isNonNull) {
531
517
  // No need to catch error
532
- return (0, tamedevil_1.default) `\
533
- ${childBucket === te_bucket
534
- ? tamedevil_1.default.blank
535
- : (0, tamedevil_1.default) `if (${childBucket} == null) {
536
- throw ${ref_nonNullError}(${locationDetails}, mutablePath.slice(1));
537
- }
538
- `}fieldResult = ${te_childOutputPlanExecute};
539
- if (fieldResult == ${asString ? te_nullString : te_null}) {
540
- throw ${ref_nonNullError}(${locationDetails}, mutablePath.slice(1));
541
- }
542
- ${setTargetOrReturn} fieldResult;`;
518
+ if (childBucket === bucket) {
519
+ //noop
520
+ }
521
+ else {
522
+ if (childBucket == null) {
523
+ throw nonNullError(locationDetails, mutablePath.slice(1));
524
+ }
525
+ }
526
+ const fieldResult = childOutputPlan[asString ? "executeString" : "execute"](root, mutablePath, childBucket, childBucketIndex,
527
+ // NOTE: the previous code may have had a bug here, it referenced childBucket.rootStep
528
+ childOutputPlan.rootStep === that.rootStep
529
+ ? rawBucketRootValue
530
+ : undefined, childOutputPlan.rootStep === that.rootStep ? bucketRootFlags : undefined);
531
+ if (fieldResult == (asString ? "null" : null)) {
532
+ throw nonNullError(locationDetails, mutablePath.slice(1));
533
+ }
534
+ return fieldResult;
543
535
  }
544
536
  else {
545
537
  // Need to catch error and set null
546
- return (0, tamedevil_1.default) `\
547
- {
548
- const streamCount = root.streams.length;
549
- const queueCount = root.queue.length;
550
- try {
551
- ${setTargetOrReturn} ${childBucket === te_bucket
552
- ? tamedevil_1.default.blank
553
- : (0, tamedevil_1.default) `${childBucket} == null ? ${asString ? te_nullString : te_null} : `}${te_childOutputPlanExecute};
554
- } catch (e) {
555
- ${te_commonErrorHandler}(e, ${locationDetails}, mutablePath, mutablePathIndex, root, streamCount, queueCount);
556
- ${setTargetOrReturn} ${asString ? te_nullString : te_null};
557
- }
558
- }`;
538
+ const streamCount = root.streams.length;
539
+ const queueCount = root.queue.length;
540
+ try {
541
+ if (childBucket !== bucket && childBucket == null) {
542
+ return asString ? "null" : null;
543
+ }
544
+ else {
545
+ return childOutputPlan[asString ? "executeString" : "execute"](root, mutablePath, childBucket, childBucketIndex,
546
+ // NOTE: the previous code may have had a bug here, it referenced childBucket.rootStep
547
+ childOutputPlan.rootStep === that.rootStep
548
+ ? rawBucketRootValue
549
+ : undefined, childOutputPlan.rootStep === that.rootStep
550
+ ? bucketRootFlags
551
+ : undefined);
552
+ }
553
+ }
554
+ catch (e) {
555
+ commonErrorHandler(e, locationDetails, mutablePath, mutablePathIndex, root, streamCount, queueCount);
556
+ return asString ? "null" : null;
557
+ }
559
558
  }
560
559
  }
561
560
  function commonErrorHandler(e, locationDetails, mutablePath, mutablePathIndex, root, streamCount, queueCount) {
@@ -573,97 +572,94 @@ function commonErrorHandler(e, locationDetails, mutablePath, mutablePathIndex, r
573
572
  }
574
573
  root.errors.push(error);
575
574
  }
576
- /*
577
- * Below here we create the executors that can be shared across many different
578
- * OutputPlans without having to be recreated (thus saving significant memory,
579
- * and increasing the probability of optimization).
580
- */
581
575
  const nullExecutor = makeExecutor({
582
- inner: tamedevil_1.default.cache ` return null;`,
583
- nameExtra: tamedevil_1.default.cache `null`,
576
+ inner: () => null,
577
+ nameExtra: "null",
584
578
  asString: false,
585
579
  });
586
580
  const nullExecutorString = makeExecutor({
587
- inner: tamedevil_1.default.cache ` return "null";`,
588
- nameExtra: tamedevil_1.default.cache `null`,
581
+ inner: () => "null",
582
+ nameExtra: `null`,
589
583
  asString: true,
590
584
  });
591
585
  /* This is what leafExecutor should use if insideGraphQL (which isn't currently
592
- * supported)
593
- `\
594
- if (root.insideGraphQL) {
595
- // Don't serialize to avoid the double serialization problem
596
- return bucketRootValue;
597
- } else {
598
- return this.type.graphqlType.serialize(bucketRootValue);
599
- }
600
- ` */
586
+ * supported)
587
+ `\
588
+ if (root.insideGraphQL) {
589
+ // Don't serialize to avoid the double serialization problem
590
+ return bucketRootValue;
591
+ } else {
592
+ return this.type.graphqlType.serialize(bucketRootValue);
593
+ }
594
+ ` */
601
595
  const leafExecutor = makeExecutor({
602
- inner: (0, tamedevil_1.default) `\
603
- return this.type.graphqlType.serialize(bucketRootValue);
604
- `,
605
- nameExtra: tamedevil_1.default.cache `leaf`,
596
+ inner(bucketRootValue) {
597
+ return this.type.graphqlType.serialize(bucketRootValue);
598
+ },
599
+ nameExtra: `leaf`,
606
600
  asString: false,
607
601
  });
608
602
  const leafExecutorString = makeExecutor({
609
- inner: (0, tamedevil_1.default) `\
610
- return ${ref_stringifyJSON}(this.type.graphqlType.serialize(bucketRootValue));
611
- `,
612
- nameExtra: tamedevil_1.default.cache `leaf`,
603
+ inner(bucketRootValue) {
604
+ return (0, tamedevil_1.stringifyJSON)(this.type.graphqlType.serialize(bucketRootValue));
605
+ },
606
+ nameExtra: `leaf`,
613
607
  asString: true,
614
608
  });
615
609
  const booleanLeafExecutorString = makeExecutor({
616
- inner: (0, tamedevil_1.default) `\
617
- const val = this.type.graphqlType.serialize(bucketRootValue);
618
- return val === true ? 'true' : 'false';
619
- `,
620
- nameExtra: tamedevil_1.default.cache `booleanLeaf`,
610
+ inner(bucketRootValue) {
611
+ const val = this.type.graphqlType.serialize(bucketRootValue);
612
+ return val === true ? "true" : "false";
613
+ },
614
+ nameExtra: `booleanLeaf`,
621
615
  asString: true,
622
616
  skipNullHandling: false,
623
- preamble: (0, tamedevil_1.default) `\
624
- if (bucketRootValue === true) return 'true';
625
- if (bucketRootValue === false) return 'false';
626
- `,
617
+ preamble(bucketRootValue) {
618
+ if (bucketRootValue === true)
619
+ return "true";
620
+ if (bucketRootValue === false)
621
+ return "false";
622
+ },
627
623
  });
628
624
  const intLeafExecutorString = makeExecutor({
629
- inner: (0, tamedevil_1.default) `\
630
- return '' + this.type.graphqlType.serialize(bucketRootValue);
631
- `,
632
- nameExtra: tamedevil_1.default.cache `intLeaf`,
625
+ inner(bucketRootValue) {
626
+ return "" + this.type.graphqlType.serialize(bucketRootValue);
627
+ },
628
+ nameExtra: `intLeaf`,
633
629
  asString: true,
634
630
  skipNullHandling: false,
635
631
  // Fast check to see if number is 32 bit integer
636
- preamble: (0, tamedevil_1.default) `\
637
- if ((bucketRootValue | 0) === bucketRootValue) {
638
- return '' + bucketRootValue;
639
- }
640
- `,
632
+ preamble(bucketRootValue) {
633
+ if ((bucketRootValue | 0) === bucketRootValue) {
634
+ return "" + bucketRootValue;
635
+ }
636
+ },
641
637
  });
642
638
  const floatLeafExecutorString = makeExecutor({
643
- inner: (0, tamedevil_1.default) `\
644
- return String(this.type.graphqlType.serialize(bucketRootValue));
645
- `,
646
- nameExtra: tamedevil_1.default.cache `floatLeaf`,
639
+ inner(bucketRootValue) {
640
+ return String(this.type.graphqlType.serialize(bucketRootValue));
641
+ },
642
+ nameExtra: `floatLeaf`,
647
643
  asString: true,
648
644
  skipNullHandling: false,
649
- preamble: (0, tamedevil_1.default) `\
650
- if (Number.isFinite(bucketRootValue)) {
651
- return '' + bucketRootValue;
652
- }
653
- `,
645
+ preamble(bucketRootValue) {
646
+ if (Number.isFinite(bucketRootValue)) {
647
+ return "" + bucketRootValue;
648
+ }
649
+ },
654
650
  });
655
651
  const stringLeafExecutorString = makeExecutor({
656
- inner: (0, tamedevil_1.default) `\
657
- return ${ref_stringifyString}(this.type.graphqlType.serialize(bucketRootValue));
658
- `,
659
- nameExtra: tamedevil_1.default.cache `stringLeaf`,
652
+ inner(bucketRootValue) {
653
+ return (0, tamedevil_1.stringifyString)(this.type.graphqlType.serialize(bucketRootValue));
654
+ },
655
+ nameExtra: `stringLeaf`,
660
656
  asString: true,
661
657
  skipNullHandling: false,
662
- preamble: (0, tamedevil_1.default) `\
663
- if (typeof bucketRootValue === 'string') {
664
- return ${ref_stringifyString}(bucketRootValue);
665
- }
666
- `,
658
+ preamble(bucketRootValue) {
659
+ if (typeof bucketRootValue === "string") {
660
+ return (0, tamedevil_1.stringifyString)(bucketRootValue);
661
+ }
662
+ },
667
663
  });
668
664
  // NOTE: the reference to $$concreteType here is a (temporary) optimization; it
669
665
  // should be `resolveType(bucketRootValue)` but it's not worth the function
@@ -671,53 +667,32 @@ const stringLeafExecutorString = makeExecutor({
671
667
  // store.
672
668
  function makePolymorphicExecutor(asString) {
673
669
  return makeExecutor({
674
- inner: (0, tamedevil_1.default) `\
675
- ${dev_js_1.isDev
676
- ? (0, tamedevil_1.default) `\
677
- if (!${ref_isPolymorphicData}(bucketRootValue)) {
678
- throw ${ref_coerceError}(
679
- new Error(
680
- "GrafastInternalError<db7fcda5-dc39-4568-a7ce-ee8acb88806b>: Expected polymorphic data",
681
- ),
682
- this.locationDetails,
683
- mutablePath.slice(1),
684
- );
685
- }
686
- `
687
- : tamedevil_1.default.blank}\
688
- const typeName = bucketRootValue[${ref_$$concreteType}];
689
- const childOutputPlan = this.childByTypeName[typeName];
690
- ${dev_js_1.isDev
691
- ? (0, tamedevil_1.default) `{
692
- ${ref_assert}.ok(
693
- typeName,
694
- "GrafastInternalError<fd3f3cf0-0789-4c74-a6cd-839c808896ed>: Could not determine concreteType for object",
695
- );
696
- ${ref_assert}.ok(
697
- childOutputPlan,
698
- \`GrafastInternalError<a46999ef-41ff-4a22-bae9-fa37ff6e5f7f>: Could not determine the OutputPlan to use for '\${typeName}' from '\${bucket.layerPlan}'\`,
699
- );
700
- }`
701
- : tamedevil_1.default.blank}
702
-
703
- const directChild = bucket.children[childOutputPlan.layerPlan.id];
704
- if (directChild !== undefined) {
705
- return childOutputPlan.${asString ? te_executeString : te_execute}(root, mutablePath, directChild.bucket, directChild.map.get(bucketIndex));
706
- } else {
707
- const c = ${ref_getChildBucketAndIndex}(
708
- childOutputPlan,
709
- this,
710
- bucket,
711
- bucketIndex,
712
- );
713
- if (!c) {
714
- throw new Error("GrafastInternalError<691509d8-31fa-4cfe-a6df-dcba21bd521f>: polymorphic executor couldn't determine child bucket");
715
- }
716
- const [childBucket, childBucketIndex] = c;
717
- return childOutputPlan.${asString ? te_executeString : te_execute}(root, mutablePath, childBucket, childBucketIndex);
718
- }
719
- `,
720
- nameExtra: te_polymorphic,
670
+ inner(bucketRootValue, root, mutablePath, bucket, bucketIndex) {
671
+ if (dev_js_1.isDev) {
672
+ if (!(0, polymorphic_js_1.isPolymorphicData)(bucketRootValue)) {
673
+ throw coerceError(new Error("GrafastInternalError<db7fcda5-dc39-4568-a7ce-ee8acb88806b>: Expected polymorphic data"), this.locationDetails, mutablePath.slice(1));
674
+ }
675
+ }
676
+ const typeName = bucketRootValue[interfaces_js_1.$$concreteType];
677
+ const childOutputPlan = this.childByTypeName[typeName];
678
+ if (dev_js_1.isDev) {
679
+ assert.ok(typeName, "GrafastInternalError<fd3f3cf0-0789-4c74-a6cd-839c808896ed>: Could not determine concreteType for object");
680
+ assert.ok(childOutputPlan, `GrafastInternalError<a46999ef-41ff-4a22-bae9-fa37ff6e5f7f>: Could not determine the OutputPlan to use for '${typeName}' from '${bucket.layerPlan}'`);
681
+ }
682
+ const directChild = bucket.children[childOutputPlan.layerPlan.id];
683
+ if (directChild !== undefined) {
684
+ return childOutputPlan[asString ? "executeString" : "execute"](root, mutablePath, directChild.bucket, directChild.map.get(bucketIndex));
685
+ }
686
+ else {
687
+ const c = getChildBucketAndIndex(childOutputPlan.layerPlan, this, bucket, bucketIndex);
688
+ if (!c) {
689
+ throw new Error("GrafastInternalError<691509d8-31fa-4cfe-a6df-dcba21bd521f>: polymorphic executor couldn't determine child bucket");
690
+ }
691
+ const [childBucket, childBucketIndex] = c;
692
+ return childOutputPlan[asString ? "executeString" : "execute"](root, mutablePath, childBucket, childBucketIndex);
693
+ }
694
+ },
695
+ nameExtra: "polymorphic",
721
696
  asString,
722
697
  });
723
698
  }
@@ -725,75 +700,91 @@ const polymorphicExecutor = makePolymorphicExecutor(false);
725
700
  const polymorphicExecutorString = makePolymorphicExecutor(true);
726
701
  function makeArrayExecutor(childIsNonNull, canStream, asString) {
727
702
  return makeExecutor({
728
- inner: (0, tamedevil_1.default) `\
729
- if (!Array.isArray(bucketRootValue)) {
730
- console.warn(\`Hit fallback for value \${${ref_inspect}(bucketRootValue)} coercion to mode 'array'\`);
731
- return ${asString ? te_nullString : te_null};
732
- }
733
-
734
- const childOutputPlan = this.child;
735
- const l = bucketRootValue.length;
736
- let fieldResult;
737
- ${asString ? te_letString : te_constDataEqualsEmptyArray}
738
- if (l === 0) {
739
- ${asString ? te_stringEqualsEmptyArrayString : te_noopComment}
740
- } else {
741
- ${asString ? te_stringEqualsLeftSquareBraceString : tamedevil_1.default.blank}\
742
- const mutablePathIndex = mutablePath.push(-1) - 1;
743
-
744
- // Now to populate the children...
745
- const directChild = bucket.children[childOutputPlan.layerPlan.id];
746
- let childBucket, childBucketIndex, lookup;
747
- if (directChild !== undefined) {
748
- childBucket = directChild.bucket;
749
- lookup = directChild.map.get(bucketIndex)
750
- }
751
- for (let i = 0; i < l; i++) {
752
- if (directChild !== undefined) {
753
- childBucketIndex = lookup[i];
754
- } else {
755
- const c = ${ref_getChildBucketAndIndex}(
756
- childOutputPlan,
757
- this,
758
- bucket,
759
- bucketIndex,
760
- i,
761
- );
762
- if (c !== null) {
763
- ([childBucket, childBucketIndex] = c);
764
- } else {
765
- childBucket = childBucketIndex = null;
766
- }
767
- }
768
-
769
- mutablePath[mutablePathIndex] = i;
770
- ${asString ? te_ifIGt0StrPlusEqualComma : tamedevil_1.default.blank}
771
- ${makeExecuteChildPlanCode(asString ? te_stringPlusEquals : te_dataIEquals, te_thisDotLocationDetails, te_childOutputPlan, childIsNonNull, asString)}
772
- }
773
-
774
- mutablePath.length = mutablePathIndex;
775
- ${asString ? te_stringPlusEqualsRbracket : tamedevil_1.default.blank}
776
- }
777
- ${canStream
778
- ? (0, tamedevil_1.default) `\
779
- const stream = bucketRootValue[${ref_$$streamMore}] /* as | AsyncIterableIterator<any> | undefined*/;
780
- if (stream !== undefined) {
781
- root.streams.push({
782
- root,
783
- path: mutablePath.slice(1),
784
- bucket,
785
- bucketIndex,
786
- outputPlan: childOutputPlan,
787
- label: childOutputPlan.layerPlan.reason.stream?.label,
788
- stream,
789
- startIndex: bucketRootValue.length,
790
- });
791
- }`
792
- : tamedevil_1.default.blank}
793
-
794
- return ${asString ? te_string : te_data};
795
- `,
796
- nameExtra: (0, tamedevil_1.default) `array${childIsNonNull ? te_underscoreNonNull : tamedevil_1.default.blank}${canStream ? te_underscoreStream : tamedevil_1.default.blank}`,
703
+ inner(bucketRootValue, root, mutablePath, bucket, bucketIndex, rawBucketRootValue, bucketRootFlags) {
704
+ if (!Array.isArray(bucketRootValue)) {
705
+ console.warn(`Hit fallback for value ${(0, inspect_js_1.inspect)(bucketRootValue)} coercion to mode 'array'`);
706
+ return (asString ? "null" : null);
707
+ }
708
+ if (this.child === null) {
709
+ throw new Error(`GrafastInternalError<365fd45e-2939-411b-92a6-4f6875d8fbd3>: ${this} has no child output plan?!`);
710
+ }
711
+ const childOutputPlan = this.child;
712
+ const l = bucketRootValue.length;
713
+ let string;
714
+ let data;
715
+ if (l === 0) {
716
+ if (asString) {
717
+ string = "[]";
718
+ }
719
+ else {
720
+ data = [];
721
+ }
722
+ }
723
+ else {
724
+ if (asString) {
725
+ string = "[";
726
+ }
727
+ else {
728
+ data = [];
729
+ }
730
+ const mutablePathIndex = mutablePath.push(-1) - 1;
731
+ // Now to populate the children...
732
+ const directChild = bucket.children[childOutputPlan.layerPlan.id];
733
+ let childBucket, childBucketIndex, lookup;
734
+ if (directChild !== undefined) {
735
+ childBucket = directChild.bucket;
736
+ lookup = directChild.map.get(bucketIndex);
737
+ }
738
+ for (let i = 0; i < l; i++) {
739
+ if (directChild !== undefined) {
740
+ childBucketIndex = lookup[i];
741
+ }
742
+ else {
743
+ const c = getChildBucketAndIndex(childOutputPlan.layerPlan, this, bucket, bucketIndex, i);
744
+ if (c !== null) {
745
+ [childBucket, childBucketIndex] = c;
746
+ }
747
+ else {
748
+ childBucket = childBucketIndex = null;
749
+ }
750
+ }
751
+ mutablePath[mutablePathIndex] = i;
752
+ if (asString) {
753
+ if (i > 0) {
754
+ string += ",";
755
+ }
756
+ }
757
+ const val = executeChildPlan(this, this.locationDetails, childOutputPlan, childIsNonNull, asString, childBucket, childBucketIndex, bucket, bucketIndex, mutablePath, mutablePathIndex, root, rawBucketRootValue, bucketRootFlags);
758
+ if (asString) {
759
+ string += val;
760
+ }
761
+ else {
762
+ data[i] = val;
763
+ }
764
+ }
765
+ mutablePath.length = mutablePathIndex;
766
+ if (asString) {
767
+ string += "]";
768
+ }
769
+ }
770
+ if (canStream) {
771
+ const stream = bucketRootValue[interfaces_js_1.$$streamMore];
772
+ if (stream !== undefined) {
773
+ root.streams.push({
774
+ root,
775
+ path: mutablePath.slice(1),
776
+ bucket,
777
+ bucketIndex,
778
+ outputPlan: childOutputPlan,
779
+ label: childOutputPlan.layerPlan.reason.stream?.label,
780
+ stream,
781
+ startIndex: bucketRootValue.length,
782
+ });
783
+ }
784
+ }
785
+ return (asString ? string : data);
786
+ },
787
+ nameExtra: `array${childIsNonNull ? "_nonNull" : ""}${canStream ? "_stream" : ""}`,
797
788
  asString,
798
789
  });
799
790
  }
@@ -813,7 +804,7 @@ const arrayExecutorString_nonNullable_streaming = makeArrayExecutor(true, true,
813
804
  *
814
805
  * ENHANCE: write our own introspection execution!
815
806
  */
816
- const introspect = (root, outputPlan, mutablePath, asString) => {
807
+ function introspect(root, outputPlan, mutablePath, asString) {
817
808
  const { locationDetails } = outputPlan;
818
809
  const { field: rawField, introspectionCacheByVariableValues, variableNames, } = outputPlan.type;
819
810
  const field = {
@@ -846,7 +837,7 @@ const introspect = (root, outputPlan, mutablePath, asString) => {
846
837
  const canonical = JSON.stringify(variableValues);
847
838
  const cached = introspectionCacheByVariableValues.get(canonical);
848
839
  if (cached !== undefined) {
849
- return asString ? JSON.stringify(cached) : cached;
840
+ return (asString ? JSON.stringify(cached) : cached);
850
841
  }
851
842
  const graphqlResult = executeSync({
852
843
  schema: outputPlan.layerPlan.operationPlan.schema,
@@ -867,167 +858,155 @@ const introspect = (root, outputPlan, mutablePath, asString) => {
867
858
  }
868
859
  const result = graphqlResult.data.a;
869
860
  introspectionCacheByVariableValues.set(canonical, result);
870
- return asString ? JSON.stringify(result) : result;
871
- };
872
- const ref_introspect = tamedevil_1.default.ref(introspect, "introspect");
861
+ return (asString ? JSON.stringify(result) : result);
862
+ }
873
863
  const introspectionExecutor = makeExecutor({
874
- inner: (0, tamedevil_1.default) ` return ${ref_introspect}(root, this, mutablePath, false)`,
875
- nameExtra: tamedevil_1.default.cache `introspection`,
864
+ inner(_bucketRootValue, root, mutablePath) {
865
+ return introspect(root, this, mutablePath, false);
866
+ },
867
+ nameExtra: `introspection`,
876
868
  asString: false,
877
869
  skipNullHandling: true,
878
870
  });
879
871
  const introspectionExecutorString = makeExecutor({
880
- inner: (0, tamedevil_1.default) ` return ${ref_introspect}(root, this, mutablePath, true)`,
881
- nameExtra: tamedevil_1.default.cache `introspection`,
872
+ inner(_bucketRootValue, root, mutablePath) {
873
+ return introspect(root, this, mutablePath, true);
874
+ },
875
+ nameExtra: `introspection`,
882
876
  asString: true,
883
877
  skipNullHandling: true,
884
878
  });
885
879
  const SAFE_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
886
880
  function makeObjectExecutor(typeName, fieldTypes, hasDeferredOutputPlans,
887
881
  // this.type.mode === "root",
888
- isRoot, asString, callback) {
882
+ isRoot, asString) {
889
883
  if (!SAFE_NAME.test(typeName)) {
890
884
  throw new Error(`Unsafe type name: ${typeName}; doesn't conform to 'Name' in the GraphQL spec`);
891
885
  }
892
- const keys = [];
893
- const fieldSpecs = [];
894
- let signature = (asString ? "s" : "o") +
895
- (isRoot ? "r" : "") +
896
- (hasDeferredOutputPlans ? "d" : "");
897
- let hasChildBucketReference = false;
898
- for (const [key, fieldSpec] of Object.entries(fieldTypes)) {
899
- if (!SAFE_NAME.test(key)) {
886
+ if (dev_js_1.isDev) {
887
+ if (Object.getPrototypeOf(fieldTypes) !== null) {
888
+ throw new Error(`GrafastInternalError<3d8e3547-d818-44e1-a076-16b828e3a34d>: fieldTypes must have a null prototype`);
889
+ }
890
+ }
891
+ const fieldDigests = Object.entries(fieldTypes).map(([responseKey, fieldSpec], i) => {
892
+ // NOTE: this code relies on the fact that fieldName and typeName do
893
+ // not require any quoting in JSON/JS - they must conform to GraphQL
894
+ // `Name`.
895
+ if (!SAFE_NAME.test(responseKey)) {
900
896
  // This should not be able to happen if the GraphQL operation is valid
901
- throw new Error(`Unsafe key: ${key}; doesn't conform to 'Name' in the GraphQL spec`);
897
+ throw new Error(`Unsafe key: ${responseKey}; doesn't conform to 'Name' in the GraphQL spec`);
902
898
  }
903
- keys.push(key);
904
- fieldSpecs.push(fieldSpec);
905
899
  const { fieldType, sameBucket } = fieldSpec;
900
+ const addComma = asString && i > 0;
906
901
  switch (fieldType) {
907
902
  case "__typename": {
908
- signature += "_";
909
- break;
903
+ return {
904
+ isTypeName: true,
905
+ addComma,
906
+ responseKey,
907
+ stringValue: asString ? `"${responseKey}":"${typeName}"` : null,
908
+ };
910
909
  }
910
+ case "outputPlan!":
911
911
  case "outputPlan?": {
912
- signature += "?";
913
- break;
914
- }
915
- case "outputPlan!": {
916
- signature += "!";
917
- break;
912
+ return {
913
+ isTypeName: false,
914
+ addComma,
915
+ responseKey,
916
+ stringPrefix: asString ? `"${responseKey}":` : null,
917
+ sameBucket,
918
+ isNonNull: fieldType === "outputPlan!",
919
+ };
918
920
  }
919
921
  default: {
920
922
  const never = fieldType;
921
- throw new Error(`Unsupported field type '${never}'`);
923
+ throw new Error(`GrafastInternalError<879082f4-fe6f-4112-814f-852b9932ca83>: unsupported key type ${never}`);
922
924
  }
923
925
  }
924
- if (!sameBucket) {
925
- hasChildBucketReference = true;
926
- signature += "~";
927
- }
928
- }
929
- withObjectExecutorFactory(signature, fieldSpecs, hasDeferredOutputPlans, isRoot, asString, hasChildBucketReference, (factory) => {
930
- const fn = factory(typeName, ...keys);
931
- callback(fn);
932
926
  });
933
- }
934
- const makeObjectExecutorCache = new lru_1.default({
935
- maxLength: 1000,
936
- });
937
- const makingObjectExecutorCallbacks = new Map();
938
- function withObjectExecutorFactory(signature, fieldSpecs, hasDeferredOutputPlans, isRoot, asString, hasChildBucketReference, callback) {
939
- const fn = makeObjectExecutorCache.get(signature);
940
- if (fn !== undefined) {
941
- return callback(fn);
942
- }
943
- const building = makingObjectExecutorCallbacks.get(signature);
944
- if (building !== undefined) {
945
- building.push(callback);
946
- return;
947
- }
948
- const callbacks = [callback];
949
- makingObjectExecutorCallbacks.set(signature, callbacks);
950
- const inner = (0, tamedevil_1.default) `\
951
- ${asString ? te_letStringLbrace : te_constObjEqualsObjectCreateNull}
952
- const { keys } = this;
953
- const mutablePathIndex = mutablePath.push("!") - 1;
954
- let spec${hasChildBucketReference ? te_childBucketCBIDC : tamedevil_1.default.blank}, fieldResult;
955
-
956
- ${tamedevil_1.default.join(fieldSpecs.map(({ fieldType, sameBucket }, i) => {
957
- const te_fieldNameI = tamedevil_1.default.identifier(`fieldName_${i}`);
958
- switch (fieldType) {
959
- case "__typename": {
960
- if (asString) {
961
- // NOTE: this code relies on the fact that fieldName and typeName do
962
- // not require any quoting in JSON/JS - they must conform to GraphQL
963
- // `Name`.
964
- return (0, tamedevil_1.default) ` string += \`${i === 0 ? tamedevil_1.default.blank : te_comma}"\${${te_fieldNameI}}":"\${typeName}"\`;\n`;
927
+ return makeExecutor({
928
+ inner(bucketRootValue, root, mutablePath, bucket, bucketIndex, rawBucketRootValue, bucketRootFlags) {
929
+ let string = asString ? "{" : undefined;
930
+ const obj = asString
931
+ ? undefined
932
+ : Object.create(null);
933
+ const keys = this.keys;
934
+ const mutablePathIndex = mutablePath.push("!") - 1;
935
+ for (const digest of fieldDigests) {
936
+ if (digest.addComma) {
937
+ string += ",";
938
+ }
939
+ const responseKey = digest.responseKey;
940
+ if (digest.isTypeName) {
941
+ if (asString) {
942
+ string += digest.stringValue;
943
+ }
944
+ else {
945
+ obj[responseKey] = typeName;
946
+ }
965
947
  }
966
948
  else {
967
- return (0, tamedevil_1.default) ` obj[${te_fieldNameI}] = typeName;\n`;
949
+ mutablePath[mutablePathIndex] = responseKey;
950
+ const spec = keys[responseKey];
951
+ if (digest.sameBucket) {
952
+ const val = executeChildPlan(this, spec.locationDetails, spec.outputPlan, digest.isNonNull, asString, bucket, bucketIndex, bucket, bucketIndex, mutablePath, mutablePathIndex, root, rawBucketRootValue, bucketRootFlags);
953
+ if (asString) {
954
+ string += digest.stringPrefix;
955
+ string += val;
956
+ }
957
+ else {
958
+ obj[responseKey] = val;
959
+ }
960
+ }
961
+ else {
962
+ const directChild = bucket.children[spec.outputPlan.layerPlan.id];
963
+ let childBucket, childBucketIndex;
964
+ if (directChild !== undefined) {
965
+ childBucket = directChild.bucket;
966
+ childBucketIndex = directChild.map.get(bucketIndex);
967
+ }
968
+ else {
969
+ const c = getChildBucketAndIndex(spec.outputPlan.layerPlan, this, bucket, bucketIndex);
970
+ if (c !== null) {
971
+ [childBucket, childBucketIndex] = c;
972
+ }
973
+ else {
974
+ childBucket = childBucketIndex = null;
975
+ }
976
+ }
977
+ const val = executeChildPlan(this, spec.locationDetails, spec.outputPlan, digest.isNonNull, asString, childBucket, childBucketIndex, bucket, bucketIndex, mutablePath, mutablePathIndex, root, rawBucketRootValue, bucketRootFlags);
978
+ if (asString) {
979
+ string += digest.stringPrefix;
980
+ string += val;
981
+ }
982
+ else {
983
+ obj[responseKey] = val;
984
+ }
985
+ }
968
986
  }
969
987
  }
970
- case "outputPlan!":
971
- case "outputPlan?": {
972
- return (0, tamedevil_1.default) `\
973
- mutablePath[mutablePathIndex] = ${te_fieldNameI};
974
- spec = keys[${te_fieldNameI}];
975
- ${asString
976
- ? (0, tamedevil_1.default) ` string += \`${i === 0 ? tamedevil_1.default.blank : te_comma}"\${${te_fieldNameI}}":\`;
977
- `
978
- : tamedevil_1.default.blank}\
979
- ${sameBucket
980
- ? (0, tamedevil_1.default) `\
981
- ${makeExecuteChildPlanCode(asString ? te_stringPlusEquals : (0, tamedevil_1.default) `obj[${te_fieldNameI}] =`, te_specDotLocationDetails, te_specDotOutputPlan, fieldType === "outputPlan!", asString, te_bucket, te_bucketIndex)}`
982
- : (0, tamedevil_1.default) `\
983
- directChild = bucket.children[spec.outputPlan.layerPlanId];
984
- if (directChild !== undefined) {
985
- childBucket = directChild.bucket;
986
- childBucketIndex = directChild.map.get(bucketIndex);
987
- } else {
988
- const c = ${ref_getChildBucketAndIndex}(
989
- spec.outputPlan,
990
- this,
991
- bucket,
992
- bucketIndex,
993
- );
994
- if (c !== null) {
995
- ([childBucket, childBucketIndex] = c);
996
- } else {
997
- childBucket = childBucketIndex = null;
998
- }
999
- }
1000
- ${makeExecuteChildPlanCode(asString ? te_stringPlusEquals : (0, tamedevil_1.default) `obj[${te_fieldNameI}] =`, te_specDotLocationDetails, te_specDotOutputPlan, fieldType === "outputPlan!", asString)}`}
1001
- `;
988
+ mutablePath.length = mutablePathIndex;
989
+ if (asString) {
990
+ string += "}";
1002
991
  }
1003
- default: {
1004
- const never = fieldType;
1005
- throw new Error(`GrafastInternalError<879082f4-fe6f-4112-814f-852b9932ca83>: unsupported key type ${never}`);
992
+ if (hasDeferredOutputPlans) {
993
+ // Everything seems okay; queue any deferred payloads
994
+ for (const defer of this.deferredOutputPlans) {
995
+ root.queue.push({
996
+ root,
997
+ path: mutablePath.slice(1),
998
+ bucket,
999
+ bucketIndex,
1000
+ outputPlan: defer,
1001
+ label: defer.type.deferLabel,
1002
+ });
1003
+ }
1006
1004
  }
1007
- }
1008
- }), "\n")}
1009
-
1010
- mutablePath.length = mutablePathIndex;
1011
- ${asString ? te_stringPlusEqualsRbrace : tamedevil_1.default.blank}\
1012
- ${hasDeferredOutputPlans ? te_handleDeferred : tamedevil_1.default.blank}
1013
- return ${asString ? te_string : te_obj};`;
1014
- const executorExpression = makeExecutorExpression({
1015
- inner: inner,
1016
- nameExtra: te_object,
1005
+ return (asString ? string : obj);
1006
+ },
1007
+ nameExtra: "object",
1017
1008
  asString,
1018
1009
  skipNullHandling: isRoot,
1019
- preamble: tamedevil_1.default.blank,
1020
- });
1021
- const factoryExpression = (0, tamedevil_1.default) `\
1022
- function objectExecutorFactory(typeName${tamedevil_1.default.join(fieldSpecs.map((_, i) => (0, tamedevil_1.default) `, ${tamedevil_1.default.identifier(`fieldName_${i}`)}`), "")}) {
1023
- return ${executorExpression};
1024
- }`;
1025
- tamedevil_1.default.runInBatch(factoryExpression, (factory) => {
1026
- makeObjectExecutorCache.set(signature, factory);
1027
- makingObjectExecutorCallbacks.delete(signature);
1028
- for (const callback of callbacks) {
1029
- callback(factory);
1030
- }
1031
1010
  });
1032
1011
  }
1033
1012
  const makeCache = new lru_1.default({