grafast 0.1.1-beta.21 → 0.1.1-beta.22

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 (94) hide show
  1. package/README.md +0 -4
  2. package/dist/args.js +3 -3
  3. package/dist/constants.d.ts +79 -0
  4. package/dist/constants.js +79 -0
  5. package/dist/engine/LayerPlan.d.ts +71 -8
  6. package/dist/engine/LayerPlan.js +375 -265
  7. package/dist/engine/OperationPlan.d.ts +77 -14
  8. package/dist/engine/OperationPlan.js +1508 -382
  9. package/dist/engine/OperationPlanTypes.d.ts +66 -0
  10. package/dist/engine/OperationPlanTypes.js +3 -0
  11. package/dist/engine/OutputPlan.d.ts +6 -0
  12. package/dist/engine/OutputPlan.js +138 -82
  13. package/dist/engine/StepTracker.js +76 -17
  14. package/dist/engine/executeBucket.js +327 -166
  15. package/dist/engine/lib/defaultPlanResolver.d.ts +1 -4
  16. package/dist/engine/lib/defaultPlanResolver.js +1 -5
  17. package/dist/engine/lib/withGlobalLayerPlan.d.ts +3 -1
  18. package/dist/engine/lib/withGlobalLayerPlan.js +19 -1
  19. package/dist/envelop.js +14 -3
  20. package/dist/error.d.ts +1 -1
  21. package/dist/error.js +9 -9
  22. package/dist/establishOperationPlan.d.ts +2 -1
  23. package/dist/establishOperationPlan.js +10 -10
  24. package/dist/execute.js +7 -5
  25. package/dist/global.d.ts +10 -0
  26. package/dist/global.js +25 -0
  27. package/dist/grafastGraphql.js +4 -3
  28. package/dist/grafastPrint.js +36 -4
  29. package/dist/index.d.ts +76 -8
  30. package/dist/index.js +37 -33
  31. package/dist/input.js +20 -1
  32. package/dist/inspect.js +1 -0
  33. package/dist/interfaces.d.ts +80 -122
  34. package/dist/interfaces.js +0 -77
  35. package/dist/makeGrafastSchema.d.ts +118 -35
  36. package/dist/makeGrafastSchema.js +197 -29
  37. package/dist/mermaid.js +198 -97
  38. package/dist/operationPlan-input.d.ts +1 -1
  39. package/dist/operationPlan-input.js +15 -5
  40. package/dist/planJSONInterfaces.d.ts +24 -5
  41. package/dist/prepare.d.ts +16 -9
  42. package/dist/prepare.js +54 -51
  43. package/dist/step.d.ts +45 -9
  44. package/dist/step.js +139 -22
  45. package/dist/steps/__flag.d.ts +3 -2
  46. package/dist/steps/__flag.js +31 -29
  47. package/dist/steps/__inputObject.d.ts +1 -1
  48. package/dist/steps/__inputStaticLeaf.d.ts +3 -2
  49. package/dist/steps/__inputStaticLeaf.js +13 -7
  50. package/dist/steps/__item.d.ts +1 -1
  51. package/dist/steps/__item.js +3 -3
  52. package/dist/steps/__trackedValue.d.ts +6 -3
  53. package/dist/steps/__trackedValue.js +25 -9
  54. package/dist/steps/__value.d.ts +2 -1
  55. package/dist/steps/__value.js +5 -0
  56. package/dist/steps/access.d.ts +17 -1
  57. package/dist/steps/access.js +14 -1
  58. package/dist/steps/applyInput.d.ts +1 -1
  59. package/dist/steps/applyInput.js +7 -6
  60. package/dist/steps/applyTransforms.js +9 -7
  61. package/dist/steps/bakedInput.js +2 -2
  62. package/dist/steps/coalesce.d.ts +15 -0
  63. package/dist/steps/coalesce.js +36 -0
  64. package/dist/steps/constant.js +16 -14
  65. package/dist/steps/each.d.ts +2 -2
  66. package/dist/steps/first.d.ts +2 -0
  67. package/dist/steps/first.js +5 -1
  68. package/dist/steps/graphqlResolver.d.ts +2 -2
  69. package/dist/steps/graphqlResolver.js +63 -161
  70. package/dist/steps/index.d.ts +3 -15
  71. package/dist/steps/index.js +6 -41
  72. package/dist/steps/lambda.js +1 -1
  73. package/dist/steps/last.d.ts +2 -0
  74. package/dist/steps/last.js +4 -0
  75. package/dist/steps/listTransform.d.ts +2 -2
  76. package/dist/steps/listTransform.js +11 -13
  77. package/dist/steps/load.d.ts +28 -22
  78. package/dist/steps/load.js +47 -1
  79. package/dist/steps/node.d.ts +10 -7
  80. package/dist/steps/node.js +5 -19
  81. package/dist/steps/object.js +6 -1
  82. package/dist/steps/proxy.d.ts +0 -6
  83. package/dist/steps/proxy.js +3 -3
  84. package/dist/steps/remapKeys.d.ts +1 -1
  85. package/dist/steps/remapKeys.js +0 -1
  86. package/dist/utils.d.ts +27 -5
  87. package/dist/utils.js +235 -15
  88. package/dist/version.d.ts +1 -1
  89. package/dist/version.js +1 -1
  90. package/package.json +6 -6
  91. package/dist/polymorphic.d.ts +0 -14
  92. package/dist/polymorphic.js +0 -72
  93. package/dist/steps/polymorphicBranch.d.ts +0 -27
  94. package/dist/steps/polymorphicBranch.js +0 -62
@@ -1,19 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LayerPlan = void 0;
4
- exports.isBranchingLayerPlan = isBranchingLayerPlan;
4
+ exports.hasParentLayerPlan = hasParentLayerPlan;
5
5
  exports.isDeferredLayerPlan = isDeferredLayerPlan;
6
- exports.isPolymorphicLayerPlan = isPolymorphicLayerPlan;
7
6
  const tslib_1 = require("tslib");
8
- const lru_1 = tslib_1.__importDefault(require("@graphile/lru"));
9
- const tamedevil_1 = tslib_1.__importDefault(require("tamedevil"));
10
7
  const assert = tslib_1.__importStar(require("../assert.js"));
8
+ const constants_js_1 = require("../constants.js");
9
+ const error_js_1 = require("../error.js");
11
10
  const inspect_js_1 = require("../inspect.js");
12
- const interfaces_js_1 = require("../interfaces.js");
13
- const polymorphic_js_1 = require("../polymorphic.js");
11
+ const utils_js_1 = require("../utils.js");
14
12
  const executeBucket_js_1 = require("./executeBucket.js");
15
- function isBranchingLayerPlan(layerPlan) {
16
- return layerPlan.reason.type === "polymorphic";
13
+ /**
14
+ * If any of these flags exist on a value then it isn't the value we want to
15
+ * include for the combo step.
16
+ */
17
+ const SKIP_FLAGS = constants_js_1.FLAG_ERROR | constants_js_1.FLAG_STOPPED | constants_js_1.FLAG_POLY_SKIPPED | constants_js_1.FLAG_INHIBITED;
18
+ /**
19
+ * If any of these flags exist on the "$__typename" step, then the value
20
+ * should resolve to null
21
+ */
22
+ const NO_TYPENAME_FLAGS = constants_js_1.FLAG_ERROR | constants_js_1.FLAG_STOPPED | constants_js_1.FLAG_POLY_SKIPPED | constants_js_1.FLAG_INHIBITED | constants_js_1.FLAG_NULL;
23
+ function hasParentLayerPlan(reason) {
24
+ return reason.type !== "root" && reason.type !== "combined";
17
25
  }
18
26
  function isDeferredLayerPlan(layerPlan) {
19
27
  const t = layerPlan.reason.type;
@@ -22,10 +30,6 @@ function isDeferredLayerPlan(layerPlan) {
22
30
  t === "mutationField" ||
23
31
  t === "defer");
24
32
  }
25
- function isPolymorphicLayerPlan(layerPlan) {
26
- const t = layerPlan.reason.type;
27
- return t === "polymorphic";
28
- }
29
33
  /**
30
34
  * A LayerPlan represents (via "reason") either the root (root), when something
31
35
  * happens at a later time (mutationField, defer), when plurality changes
@@ -52,9 +56,11 @@ function isPolymorphicLayerPlan(layerPlan) {
52
56
  *
53
57
  */
54
58
  class LayerPlan {
55
- constructor(operationPlan, parentLayerPlan, reason) {
59
+ constructor(operationPlan, reason) {
60
+ // This layer plan is dependent on the latest side effect. Note that when
61
+ // we set a `rootStep` later, if the root step is dependent on this step
62
+ // (directly or indirectly) we will clear this property.
56
63
  this.operationPlan = operationPlan;
57
- this.parentLayerPlan = parentLayerPlan;
58
64
  this.reason = reason;
59
65
  /**
60
66
  * Every layer plan has a "root step" that shapes the value the layer
@@ -88,15 +94,6 @@ class LayerPlan {
88
94
  this.steps = [];
89
95
  /** @internal */
90
96
  this.pendingSteps = [];
91
- /**
92
- * This goes along with `parentStep` in the reason, except it applies to all
93
- * layer plan types and we figure it out automatically from the parent layer
94
- * plan. If this step has an error at a given index, then it should be
95
- * treated as if the parentStep had an error at that same index.
96
- *
97
- * @internal
98
- */
99
- this.parentSideEffectStep = null;
100
97
  /**
101
98
  * This tracks the latest seen side effect at the current point in planning
102
99
  * (such that created steps take this to be their implicitSideEffectStep).
@@ -113,15 +110,90 @@ class LayerPlan {
113
110
  * @internal
114
111
  */
115
112
  this.phases = [];
113
+ // TODO: is it possible for this to go wrong by one of the stream items not
114
+ // streaming and the other one streaming? Technically the arguments need to
115
+ // match or it wouldn't be allowed to combine (the planning paths would
116
+ // differ because they factor in the argument step ids) but what if we
117
+ // decided to fulfil one without streaming and the other streaming only?
118
+ /**
119
+ * Populated during `finalize`, this will be empty except for phase
120
+ * transition layer plans (defer/stream) wherein it will contain a list of
121
+ * "unreachable" layer plan IDs relevant to the "combined" layer plans trying
122
+ * to refer to parent layer plans which are outside of this incremental
123
+ * boundary (e.g. if two lists both stream, we might combine those, but at
124
+ * runtime only one will be populated so we can't wait for the other to
125
+ * complete otherwise nothing will happen).
126
+ */
127
+ this.outOfBoundsLayerPlanIds = new Set();
116
128
  this._hasSetRootStep = false;
117
- // This layer plan is dependent on the latest side effect. Note that when
118
- // we set a `rootStep` later, if the root step is dependent on this step
119
- // (directly or indirectly) we will clear this property.
120
- this.parentSideEffectStep = parentLayerPlan?.latestSideEffectStep ?? null;
129
+ /** @internal */
130
+ this.combinations = [];
131
+ /** @internal */
132
+ this.finalCombinations = [];
121
133
  // There has yet to be any side effects created in this layer.
122
134
  this.latestSideEffectStep = null;
123
135
  this.stepsByConstructor = new Map();
124
- if (parentLayerPlan !== null) {
136
+ if (reason.type === "root") {
137
+ this.parentSideEffectStep = null;
138
+ this.depth = 0;
139
+ this.ancestry = [this];
140
+ this.deferBoundaryDepth = 0;
141
+ this.id = operationPlan.addLayerPlan(this);
142
+ assert.strictEqual(this.id, 0, "Root layer plan must have id=0, there must be only one");
143
+ }
144
+ else if (reason.type === "combined") {
145
+ this.parentSideEffectStep = null;
146
+ const firstParentLayerPlan = reason.parentLayerPlans[0];
147
+ const rootLp = firstParentLayerPlan.ancestry[0];
148
+ if (rootLp.reason.type !== "root") {
149
+ throw new Error("GrafastInternalError<e9290db3-9a1b-45af-a50e-baa9e161d7cc>: expected the 0'th entry in ancestry to be the root layer plan");
150
+ }
151
+ // TODO: is this calculated correctly?
152
+ let deferBoundaryDepth = 0;
153
+ this.ancestry = [];
154
+ /** Unskipped because it comes from the raw layer plans, we skip over those that don't match */
155
+ let prevUnskippedDeferBoundaryDepth = 0;
156
+ for (let i = 0, l = firstParentLayerPlan.ancestry.length; i < l; i++) {
157
+ const ancestor = firstParentLayerPlan.ancestry[i];
158
+ let match = true;
159
+ for (const lp of reason.parentLayerPlans) {
160
+ if (lp.ancestry[i] !== ancestor) {
161
+ // Shared ancestry fails here
162
+ match = false;
163
+ }
164
+ }
165
+ if (match) {
166
+ this.ancestry.push(ancestor);
167
+ if (ancestor.deferBoundaryDepth > prevUnskippedDeferBoundaryDepth) {
168
+ if (ancestor.deferBoundaryDepth === ancestor.depth) {
169
+ // They're the boundary
170
+ deferBoundaryDepth = this.ancestry.length - 1;
171
+ }
172
+ else {
173
+ // Treat the previous ancestor as the defer boundary
174
+ deferBoundaryDepth = this.ancestry.length - 2;
175
+ }
176
+ prevUnskippedDeferBoundaryDepth = ancestor.deferBoundaryDepth;
177
+ }
178
+ }
179
+ }
180
+ this.ancestry.push(this);
181
+ this.depth = this.ancestry.length - 1;
182
+ this.deferBoundaryDepth = deferBoundaryDepth;
183
+ this.id = operationPlan.addLayerPlan(this);
184
+ // Deliberately shadow!
185
+ for (const parentLayerPlan of reason.parentLayerPlans) {
186
+ parentLayerPlan.children.push(this);
187
+ }
188
+ }
189
+ else {
190
+ const parentLayerPlan = reason.parentLayerPlan;
191
+ if (reason.type === "polymorphicPartition") {
192
+ if (parentLayerPlan.reason.type !== "polymorphic") {
193
+ throw new Error(`GrafastInternalError<ef8fcb9a-5252-4593-915c-b3ebe4aa8eff>: a polymorphicPartition may only be a child of a polymorphic layer plan, but ${this} was created under ${parentLayerPlan}`);
194
+ }
195
+ }
196
+ this.parentSideEffectStep = parentLayerPlan.latestSideEffectStep ?? null;
125
197
  this.depth = parentLayerPlan.depth + 1;
126
198
  this.ancestry = [...parentLayerPlan.ancestry, this];
127
199
  if (isDeferredLayerPlan(this)) {
@@ -130,29 +202,27 @@ class LayerPlan {
130
202
  else {
131
203
  this.deferBoundaryDepth = parentLayerPlan.deferBoundaryDepth;
132
204
  }
133
- }
134
- else {
135
- this.depth = 0;
136
- this.ancestry = [this];
137
- this.deferBoundaryDepth = 0;
138
- }
139
- this.id = operationPlan.addLayerPlan(this);
140
- if (!parentLayerPlan) {
141
- assert.strictEqual(this.id, 0, "All but the first LayerPlan must have a parent");
142
- }
143
- else {
144
- assert.ok(reason.type != "root", "Non-root LayerPlan must have a parentStep");
205
+ this.id = operationPlan.addLayerPlan(this);
145
206
  parentLayerPlan.children.push(this);
146
207
  }
147
208
  }
148
209
  toString() {
149
210
  let chain = "";
150
211
  // eslint-disable-next-line @typescript-eslint/no-this-alias
212
+ let prev = this;
213
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
151
214
  let current = this;
152
- while ((current = current.parentLayerPlan)) {
215
+ while ((current = hasParentLayerPlan(current.reason)
216
+ ? current.reason.parentLayerPlan
217
+ : null)) {
153
218
  chain = chain + `∈${current.id}`;
219
+ prev = current;
154
220
  }
155
- const reasonExtra = this.reason.type === "polymorphic"
221
+ if (prev.reason.type === "combined") {
222
+ chain =
223
+ chain + `Σ${prev.reason.parentLayerPlans.map((p) => p.id).join("|")}`;
224
+ }
225
+ const reasonExtra = this.reason.type === "polymorphicPartition"
156
226
  ? `{${this.reason.typeNames.join(",")}}`
157
227
  : "";
158
228
  const deps = this.copyStepIds.length > 0 ? `/${this.copyStepIds}` : "";
@@ -185,22 +255,29 @@ class LayerPlan {
185
255
  return this.operationPlan._addStep(step);
186
256
  }
187
257
  finalize() {
188
- if (
189
- // this.reason.type === "nullableBoundary" ||
190
- this.reason.type === "listItem") {
191
- const u = this.copyStepIds.length;
192
- const signature = `${this.reason.type[0]}_${u}`;
193
- withNewBucketFactory(signature, u, this.reason.type, (fn) => {
194
- this.newBucket = fn(this.copyStepIds);
195
- });
196
- }
258
+ this.finalCombinations = this.combinations.map((c) => {
259
+ const { targetStepId, sources } = c;
260
+ const sourceStepsByLayerPlanId = Object.create(null);
261
+ for (const { layerPlanId, stepId } of sources) {
262
+ sourceStepsByLayerPlanId[layerPlanId] ??= [];
263
+ sourceStepsByLayerPlanId[layerPlanId].push(stepId);
264
+ }
265
+ return {
266
+ targetStepId,
267
+ sourceStepsByLayerPlanId,
268
+ };
269
+ });
197
270
  }
198
271
  newBucket(parentBucket) {
272
+ if (this.reason.type === "combined") {
273
+ throw new Error(`Use newCombinedBucket instead.`);
274
+ }
199
275
  const { copyStepIds } = this;
200
276
  const store = new Map();
201
277
  const polymorphicPathList = this.reason.type === "mutationField"
202
278
  ? parentBucket.polymorphicPathList
203
279
  : [];
280
+ const polymorphicType = this.reason.type === "polymorphic" ? [] : null;
204
281
  const iterators = this.reason.type === "mutationField" ? parentBucket.iterators : [];
205
282
  const map = new Map();
206
283
  const $parentSideEffect = this.parentSideEffectStep;
@@ -224,7 +301,7 @@ class LayerPlan {
224
301
  const hasNoNullsOrErrors = false;
225
302
  if (this.rootStep._isUnary) {
226
303
  const fieldValue = parentBucket.store.get(itemStepId);
227
- const forbiddenFlags = fieldValue._entryFlags & interfaces_js_1.FORBIDDEN_BY_NULLABLE_BOUNDARY_FLAGS;
304
+ const forbiddenFlags = fieldValue._entryFlags & constants_js_1.FORBIDDEN_BY_NULLABLE_BOUNDARY_FLAGS;
228
305
  if (forbiddenFlags) {
229
306
  size = 0;
230
307
  }
@@ -236,7 +313,7 @@ class LayerPlan {
236
313
  const parentBucketSize = parentBucket.size;
237
314
  for (let originalIndex = 0; originalIndex < parentBucketSize; originalIndex++) {
238
315
  if (parentSideEffectValue === null ||
239
- !(parentSideEffectValue._flagsAt(originalIndex) & interfaces_js_1.FLAG_ERROR)) {
316
+ !(parentSideEffectValue._flagsAt(originalIndex) & constants_js_1.FLAG_ERROR)) {
240
317
  const newIndex = size++;
241
318
  map.set(originalIndex, newIndex);
242
319
  polymorphicPathList[newIndex] =
@@ -264,8 +341,8 @@ class LayerPlan {
264
341
  }
265
342
  }
266
343
  else {
267
- const itemStepIdList = [];
268
- store.set(itemStepId, (0, executeBucket_js_1.batchExecutionValue)(itemStepIdList));
344
+ const ev = (0, executeBucket_js_1.batchExecutionValue)([]);
345
+ store.set(itemStepId, ev);
269
346
  for (const stepId of copyStepIds) {
270
347
  const ev = parentBucket.store.get(stepId);
271
348
  if (ev.isBatch) {
@@ -285,12 +362,11 @@ class LayerPlan {
285
362
  // we must "multiply up" (down) the store entries.
286
363
  for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
287
364
  if ((parentSideEffectValue === null ||
288
- !(parentSideEffectValue._flagsAt(originalIndex) & interfaces_js_1.FLAG_ERROR)) &&
289
- !(nullableStepStore._flagsAt(originalIndex) & interfaces_js_1.FLAG_NULL)) {
365
+ !(parentSideEffectValue._flagsAt(originalIndex) & constants_js_1.FLAG_ERROR)) &&
366
+ !(nullableStepStore._flagsAt(originalIndex) & constants_js_1.FLAG_NULL)) {
290
367
  const newIndex = size++;
291
368
  map.set(originalIndex, newIndex);
292
- const fieldValue = nullableStepStore.at(originalIndex);
293
- itemStepIdList[newIndex] = fieldValue;
369
+ ev._copyResult(newIndex, nullableStepStore, originalIndex);
294
370
  polymorphicPathList[newIndex] =
295
371
  parentBucket.polymorphicPathList[originalIndex];
296
372
  iterators[newIndex] = parentBucket.iterators[originalIndex];
@@ -338,16 +414,26 @@ class LayerPlan {
338
414
  for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
339
415
  const list = listStepStore.at(originalIndex);
340
416
  if ((parentSideEffectValue === null ||
341
- !(parentSideEffectValue._flagsAt(originalIndex) & interfaces_js_1.FLAG_ERROR)) &&
417
+ !(parentSideEffectValue._flagsAt(originalIndex) & constants_js_1.FLAG_ERROR)) &&
342
418
  Array.isArray(list)) {
343
419
  const newIndexes = [];
344
420
  map.set(originalIndex, newIndexes);
345
421
  for (let j = 0, l = list.length; j < l; j++) {
346
422
  const newIndex = size++;
347
423
  newIndexes.push(newIndex);
348
- ev.entries[newIndex] = list[j];
349
- // TODO: are these the right flags?
350
- ev._flags[newIndex] = list[j] == null ? interfaces_js_1.FLAG_NULL : interfaces_js_1.NO_FLAGS;
424
+ let val = list[j];
425
+ let flags = constants_js_1.NO_FLAGS;
426
+ if (val == null) {
427
+ flags = flags | constants_js_1.FLAG_NULL;
428
+ }
429
+ else if (typeof val === "object" && (0, error_js_1.isFlaggedValue)(val)) {
430
+ flags = val.flags;
431
+ val = val.value;
432
+ if (val == null) {
433
+ flags = flags | constants_js_1.FLAG_NULL;
434
+ }
435
+ }
436
+ ev._setResult(newIndex, val, flags);
351
437
  polymorphicPathList[newIndex] =
352
438
  parentBucket.polymorphicPathList[originalIndex];
353
439
  iterators[newIndex] = parentBucket.iterators[originalIndex];
@@ -375,20 +461,19 @@ class LayerPlan {
375
461
  break;
376
462
  }
377
463
  case "polymorphic": {
378
- const polymorphicPlanId = this.reason.parentStep.id;
379
- const polymorphicPlanStore = parentBucket.store.get(polymorphicPlanId);
380
- if (!polymorphicPlanStore) {
381
- throw new Error(`GrafastInternalError<af1417c6-752b-466e-af7e-cfc35724c3bc>: Entry for '${parentBucket.layerPlan.operationPlan.dangerouslyGetStep(polymorphicPlanId)}' not found in bucket for '${parentBucket.layerPlan}'`);
464
+ const parentStepId = this.reason.parentStep.id;
465
+ const typenameEV = parentBucket.store.get(parentStepId);
466
+ if (!typenameEV) {
467
+ throw new Error(`GrafastInternalError<af1417c6-752b-466e-af7e-cfc35724c3bc>: Entry for '${parentBucket.layerPlan.operationPlan.dangerouslyGetStep(parentStepId)}' not found in bucket for '${parentBucket.layerPlan}'`);
382
468
  }
383
- // We're only copying over the entries that match this type (note:
384
- // they may end up being null, but that's okay)
385
- const targetTypeNames = this.reason.typeNames;
469
+ const batchCopyStepIds = [];
386
470
  for (const stepId of copyStepIds) {
387
471
  const ev = parentBucket.store.get(stepId);
388
472
  if (!ev) {
389
473
  throw new Error(`GrafastInternalError<548f0d84-4556-4189-8655-fb16aa3345a6>: new bucket for ${this} wants to copy ${this.operationPlan.dangerouslyGetStep(stepId)}, but bucket for ${parentBucket.layerPlan} doesn't contain that plan`);
390
474
  }
391
475
  if (ev.isBatch) {
476
+ batchCopyStepIds.push(stepId);
392
477
  store.set(stepId, (0, executeBucket_js_1.batchExecutionValue)([]));
393
478
  }
394
479
  else {
@@ -396,37 +481,75 @@ class LayerPlan {
396
481
  }
397
482
  }
398
483
  for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
399
- const flags = polymorphicPlanStore._flagsAt(originalIndex);
400
- if (flags & (interfaces_js_1.FLAG_ERROR | interfaces_js_1.FLAG_INHIBITED | interfaces_js_1.FLAG_NULL)) {
484
+ const flags = typenameEV._flagsAt(originalIndex);
485
+ if ((flags & NO_TYPENAME_FLAGS) !== 0) {
401
486
  continue;
402
487
  }
403
488
  if (parentSideEffectValue !== null &&
404
- parentSideEffectValue._flagsAt(originalIndex) & interfaces_js_1.FLAG_ERROR) {
489
+ parentSideEffectValue._flagsAt(originalIndex) & constants_js_1.FLAG_ERROR) {
405
490
  continue;
406
491
  }
407
- const value = polymorphicPlanStore.at(originalIndex);
408
- const typeName = (0, polymorphic_js_1.resolveType)(value);
409
- if (!targetTypeNames.includes(typeName)) {
492
+ const polymorphicPath = parentBucket.polymorphicPathList.at(originalIndex);
493
+ const typeName = typenameEV.at(originalIndex);
494
+ if (!this.reason.typeNames.includes(typeName)) {
495
+ // Search: InvalidConcreteTypeName
496
+ // TODO: should we throw an error?
497
+ // Skip
410
498
  continue;
411
499
  }
412
500
  const newIndex = size++;
413
501
  map.set(originalIndex, newIndex);
414
- // PERF: might be faster if we look this up as a constant rather than using concatenation here
415
- const newPolymorphicPath = (parentBucket.polymorphicPathList[originalIndex] ?? "") +
416
- ">" +
417
- typeName;
418
- polymorphicPathList[newIndex] = newPolymorphicPath;
502
+ polymorphicPathList[newIndex] =
503
+ (polymorphicPath ?? "") + ">" + typeName;
504
+ polymorphicType[newIndex] = typeName;
419
505
  iterators[newIndex] = parentBucket.iterators[originalIndex];
420
- for (const planId of copyStepIds) {
506
+ for (const planId of batchCopyStepIds) {
421
507
  const ev = store.get(planId);
422
- if (ev.isBatch) {
423
- const orig = parentBucket.store.get(planId);
424
- ev._copyResult(newIndex, orig, originalIndex);
425
- }
508
+ const orig = parentBucket.store.get(planId);
509
+ ev._copyResult(newIndex, orig, originalIndex);
510
+ }
511
+ }
512
+ break;
513
+ }
514
+ case "polymorphicPartition": {
515
+ // Similar to polymorphic
516
+ const batchCopyStepIds = [];
517
+ for (const stepId of copyStepIds) {
518
+ const ev = parentBucket.store.get(stepId);
519
+ if (!ev) {
520
+ throw new Error(`GrafastInternalError<548f0d84-4556-4189-8655-fb16aa3345a6>: new bucket for ${this} wants to copy ${this.operationPlan.dangerouslyGetStep(stepId)}, but bucket for ${parentBucket.layerPlan} doesn't contain that plan`);
521
+ }
522
+ if (ev.isBatch) {
523
+ batchCopyStepIds.push(stepId);
524
+ store.set(stepId, (0, executeBucket_js_1.batchExecutionValue)([]));
525
+ }
526
+ else {
527
+ store.set(stepId, ev);
528
+ }
529
+ }
530
+ for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
531
+ if (parentSideEffectValue !== null &&
532
+ parentSideEffectValue._flagsAt(originalIndex) & constants_js_1.FLAG_ERROR) {
533
+ continue;
534
+ }
535
+ const typeName = parentBucket.polymorphicType.at(originalIndex);
536
+ if (!this.reason.typeNames.includes(typeName)) {
537
+ continue;
538
+ }
539
+ const newIndex = size++;
540
+ map.set(originalIndex, newIndex);
541
+ polymorphicPathList[newIndex] =
542
+ parentBucket.polymorphicPathList.at(originalIndex);
543
+ iterators[newIndex] = parentBucket.iterators[originalIndex];
544
+ for (const planId of batchCopyStepIds) {
545
+ const ev = store.get(planId);
546
+ const orig = parentBucket.store.get(planId);
547
+ ev._copyResult(newIndex, orig, originalIndex);
426
548
  }
427
549
  }
428
550
  break;
429
551
  }
552
+ // case "combined": See newCombinedBucket below
430
553
  case "subscription":
431
554
  case "defer": {
432
555
  // TODO
@@ -447,15 +570,16 @@ class LayerPlan {
447
570
  }
448
571
  if (size > 0) {
449
572
  // Reference
450
- const childBucket = (0, executeBucket_js_1.newBucket)({
573
+ const childBucket = (0, executeBucket_js_1.newBucket)(parentBucket, {
451
574
  layerPlan: this,
452
575
  size,
453
576
  store,
454
577
  // PERF: not necessarily, if we don't copy the errors, we don't have the errors.
455
578
  flagUnion: parentBucket.flagUnion,
456
579
  polymorphicPathList,
580
+ polymorphicType,
457
581
  iterators,
458
- }, parentBucket.metaByMetaKey);
582
+ });
459
583
  parentBucket.children[this.id] = {
460
584
  bucket: childBucket,
461
585
  map,
@@ -466,189 +590,175 @@ class LayerPlan {
466
590
  return null;
467
591
  }
468
592
  }
469
- }
470
- exports.LayerPlan = LayerPlan;
471
- const makeNewBucketCache = new lru_1.default({
472
- maxLength: 1000,
473
- });
474
- const makingNewBucketCallbacks = new Map();
475
- const te_parentBucketDotPolymorphicPathList = (0, tamedevil_1.default) `parentBucket.polymorphicPathList`;
476
- const te_parentBucketDotIterators = (0, tamedevil_1.default) `parentBucket.iterators`;
477
- const te_emptyArray = (0, tamedevil_1.default) `[]`;
478
- const ref_newBucket = tamedevil_1.default.ref(executeBucket_js_1.newBucket, "newBucket");
479
- const ref_batchExecutionValue = tamedevil_1.default.ref(executeBucket_js_1.batchExecutionValue, "batchExecutionValue");
480
- function makeNewBucketExpression(signature, reasonType, inner) {
481
- const expr = (0, tamedevil_1.default) `\
482
- (function ${tamedevil_1.default.identifier(`newBucket_${signature}`)}(parentBucket) {
483
- const store = new Map();
484
- const polymorphicPathList = ${reasonType === "mutationField"
485
- ? te_parentBucketDotPolymorphicPathList
486
- : te_emptyArray};
487
- const iterators = ${reasonType === "mutationField" ? te_parentBucketDotIterators : te_emptyArray};
488
- const map = new Map();
489
- let size = 0;
490
-
491
- ${inner}
492
-
493
- if (size > 0) {
494
- // Reference
495
- const childBucket = ${ref_newBucket}({
496
- layerPlan: this,
497
- size,
498
- store,
499
- // PERF: not necessarily, if we don't copy the errors, we don't have the errors.
500
- flagUnion: parentBucket.flagUnion,
501
- polymorphicPathList,
502
- iterators,
503
- }, parentBucket.metaByMetaKey);
504
- // PERF: set ourselves in more places so that we never have to call 'getChildBucketAndIndex'.
505
- parentBucket.children[this.id] = { bucket: childBucket, map };
506
-
507
- return childBucket;
508
- } else {
509
- return null;
510
- }
511
- })`;
512
- // te.debug(expr);
513
- return expr;
514
- }
515
- function newBucketFactoryInnerExpression(signature, copyCount, reasonType) {
516
- if (reasonType === "nullableBoundary") {
517
- if (Math.random() < 2) {
518
- throw new Error("This code no longer works since we added unary steps.");
593
+ newCombinedBucket(finalParentBucket) {
594
+ const t = this.reason.type;
595
+ if (t !== "combined") {
596
+ throw new Error(`GrafastInternalError<59c54cd0-ee32-478a-9e0e-4123eec2f8f5>: newCombinedBucket must only be called on combined layer plans`);
597
+ }
598
+ const { sharedState } = finalParentBucket;
599
+ const { copyStepIds } = this;
600
+ const store = new Map();
601
+ const polymorphicPathList = [];
602
+ const iterators = [];
603
+ const mapByParentLayerPlanId = Object.create(null);
604
+ let flagUnion = constants_js_1.NO_FLAGS;
605
+ let totalSize = 0;
606
+ const batchStepIdsToCopy = new Set();
607
+ for (const plp of this.reason.parentLayerPlans) {
608
+ mapByParentLayerPlanId[plp.id] = new Map();
609
+ const parentBucket = sharedState._retainedBuckets.get(plp.id);
610
+ if (!parentBucket)
611
+ continue;
612
+ flagUnion |= parentBucket.flagUnion;
613
+ totalSize += parentBucket.size;
614
+ const map = mapByParentLayerPlanId[plp.id];
615
+ for (let i = 0, l = parentBucket.size; i < l; i++) {
616
+ const sourcePolyPath = parentBucket.polymorphicPathList[i];
617
+ map.set(i, polymorphicPathList.length);
618
+ polymorphicPathList.push(sourcePolyPath);
619
+ }
620
+ for (const copyStepId of copyStepIds) {
621
+ if (store.has(copyStepId))
622
+ continue;
623
+ const ev = parentBucket.store.get(copyStepId);
624
+ if (ev == null) {
625
+ // No action
626
+ // TODO: do we need a placeholder for not found evs? I don't think so -
627
+ // it implies that the dependency bucket doesn't exist and thus nothing
628
+ // will use it?
629
+ }
630
+ else if (ev.isBatch) {
631
+ batchStepIdsToCopy.add(copyStepId);
632
+ }
633
+ else {
634
+ store.set(copyStepId, ev);
635
+ }
636
+ }
519
637
  }
520
- // PERF: if parent bucket has no nulls/errors in itemStepId
521
- // then we can just copy everything wholesale rather than building
522
- // new arrays and looping.
523
- const blocks = [];
524
- const copyBlocks = [];
525
- for (let i = 0; i < copyCount; i++) {
526
- const te_source = tamedevil_1.default.identifier(`source${i}`);
527
- const te_target = tamedevil_1.default.identifier(`target${i}`);
528
- const te_i = tamedevil_1.default.lit(i);
529
- blocks.push((0, tamedevil_1.default) `\
530
- const ${te_source} = parentBucket.store.get(copyStepIds[${te_i}]);
531
- const ${te_target} = ${te_source}.isBatch ? ${ref_batchExecutionValue}([]) : ${te_source};
532
- store.set(copyStepIds[${te_i}], ${te_target});
533
- `);
534
- copyBlocks.push((0, tamedevil_1.default) `\
535
- if(${te_target}.isBatch) {
536
- ${te_target}.entries[newIndex] = ${te_source}.at(originalIndex);
537
- }
538
- `);
638
+ if (totalSize === 0)
639
+ return null;
640
+ for (const stepId of batchStepIdsToCopy) {
641
+ const newEv = (0, executeBucket_js_1.batchExecutionValue)((0, utils_js_1.arrayOfLength)(totalSize, null), (0, utils_js_1.arrayOfLength)(totalSize, constants_js_1.FLAG_NULL | constants_js_1.FLAG_STOPPED));
642
+ store.set(stepId, newEv);
643
+ let offset = 0;
644
+ for (const plp of this.reason.parentLayerPlans) {
645
+ const parentBucket = sharedState._retainedBuckets.get(plp.id);
646
+ if (!parentBucket)
647
+ continue;
648
+ const sourceEv = parentBucket.store.get(stepId);
649
+ if (sourceEv != null) {
650
+ // Populate it with the values we care about
651
+ for (let i = 0, l = parentBucket.size; i < l; i++) {
652
+ newEv._copyResult(i + offset, sourceEv, i);
653
+ }
654
+ }
655
+ offset += parentBucket.size;
656
+ }
539
657
  }
540
- return makeNewBucketExpression(signature, reasonType, (0, tamedevil_1.default) `\
541
- const itemStepId = this.rootStep.id;
542
- const nullableStepStore = parentBucket.store.get(itemStepId);
543
-
544
- const itemStepIdList = [];
545
- store.set(itemStepId, ${ref_batchExecutionValue}(itemStepIdList));
546
-
547
- // Prepare store with an empty list for each copyPlanId
548
- ${tamedevil_1.default.join(blocks, "")}
549
-
550
- // We'll typically be creating fewer nullableBoundary bucket entries
551
- // than we have parent bucket entries (because we exclude nulls), so
552
- // we must "multiply up" (down) the store entries.
553
- for (
554
- let originalIndex = 0;
555
- originalIndex < parentBucket.size;
556
- originalIndex++
557
- ) {
558
- const fieldValue = nullableStepStore.at(originalIndex);
559
- if (fieldValue != null) {
560
- const newIndex = size++;
561
- map.set(originalIndex, newIndex);
562
- itemStepIdList[newIndex] = fieldValue;
563
-
564
- polymorphicPathList[newIndex] = parentBucket.polymorphicPathList[originalIndex];
565
- iterators[newIndex] = parentBucket.iterators[originalIndex];
566
- ${tamedevil_1.default.join(copyBlocks, "")}
567
- }
568
- }
569
- `);
570
- }
571
- else if (reasonType === "listItem") {
572
- const blocks = [];
573
- const copyBlocks = [];
574
- for (let i = 0; i < copyCount; i++) {
575
- const te_source = tamedevil_1.default.identifier(`source${i}`);
576
- const te_target = tamedevil_1.default.identifier(`target${i}`);
577
- const te_i = tamedevil_1.default.lit(i);
578
- blocks.push((0, tamedevil_1.default) `\
579
- const ${te_source} = parentBucket.store.get(copyStepIds[${te_i}]);
580
- const ${te_target} = ${te_source}.isBatch ? ${ref_batchExecutionValue}([]) : ${te_source};
581
- store.set(copyStepIds[${te_i}], ${te_target});
582
- `);
583
- copyBlocks.push((0, tamedevil_1.default) `\
584
- if (${te_target}.isBatch) {
585
- ${te_target}.entries[newIndex] = ${te_source}.at(originalIndex);
658
+ const $parentSideEffect = this.parentSideEffectStep;
659
+ if ($parentSideEffect) {
660
+ throw new Error(`Side effects were not expected at this position; this is likely an issue with your plans, but if not then please file an issue containing a minimal reproduction`);
586
661
  }
587
- `);
662
+ ////////////////////////////////////////////////////////////////////////////
663
+ //
664
+ // Code that would be in the switch statement if we were normal...
665
+ //
666
+ for (const { targetStepId, sourceStepsByLayerPlanId } of this
667
+ .finalCombinations) {
668
+ const ev = (0, executeBucket_js_1.batchExecutionValue)((0, utils_js_1.arrayOfLength)(totalSize, null), (0, utils_js_1.arrayOfLength)(totalSize, constants_js_1.FLAG_NULL | constants_js_1.FLAG_STOPPED));
669
+ store.set(targetStepId, ev);
670
+ let offset = 0;
671
+ for (const plp of this.reason.parentLayerPlans) {
672
+ const parentBucket = sharedState._retainedBuckets.get(plp.id);
673
+ if (parentBucket == null)
674
+ continue;
675
+ for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
676
+ const newIndex = originalIndex + offset;
677
+ if (sourceStepsByLayerPlanId[plp.id]) {
678
+ for (const stepId of sourceStepsByLayerPlanId[plp.id]) {
679
+ const sourceStore = parentBucket.store.get(stepId);
680
+ if (!sourceStore) {
681
+ const step = this.operationPlan.stepTracker.getStepById(stepId);
682
+ throw new Error(`GrafastInternalError<a48ca88c-e4b9-4a4f-9a38-846fa067f143>: missing source store for ${step} (${stepId}) in ${this}`);
683
+ }
684
+ if ((sourceStore._flagsAt(originalIndex) & SKIP_FLAGS) == 0) {
685
+ ev._copyResult(newIndex, sourceStore, originalIndex);
686
+ break;
687
+ }
688
+ }
689
+ }
690
+ iterators[newIndex] = parentBucket.iterators[originalIndex];
691
+ }
692
+ offset += parentBucket.size;
693
+ }
588
694
  }
589
- return makeNewBucketExpression(signature, reasonType, (0, tamedevil_1.default) `\
590
- const listStepId = this.reason.parentStep.id;
591
- const listStepStore = parentBucket.store.get(listStepId);
592
-
593
- const itemStepIdList = [];
594
- store.set(this.rootStep.id, ${ref_batchExecutionValue}(itemStepIdList));
595
-
596
- // Prepare store with an empty list for each copyPlanId
597
- ${tamedevil_1.default.join(blocks, "")}
598
-
599
- // We'll typically be creating more listItem bucket entries than we
600
- // have parent buckets, so we must "multiply up" the store entries.
601
- for (
602
- let originalIndex = 0;
603
- originalIndex < parentBucket.size;
604
- originalIndex++
605
- ) {
606
- const list = listStepStore.at(originalIndex);
607
- if (Array.isArray(list)) {
608
- const newIndexes = [];
609
- map.set(originalIndex, newIndexes);
610
- for (let j = 0, l = list.length; j < l; j++) {
611
- const newIndex = size++;
612
- newIndexes.push(newIndex);
613
- itemStepIdList[newIndex] = list[j];
614
-
615
- polymorphicPathList[newIndex] = parentBucket.polymorphicPathList[originalIndex];
616
- iterators[newIndex] = parentBucket.iterators[originalIndex];
617
- ${tamedevil_1.default.join(copyBlocks, "")}
618
- }
619
- }
620
- }
621
-
622
- `);
623
- }
624
- else {
625
- const never = reasonType;
626
- return never;
627
- }
628
- }
629
- function withNewBucketFactory(signature, copyCount, reasonType, callback) {
630
- const fn = makeNewBucketCache.get(signature);
631
- if (fn !== undefined) {
632
- return callback(fn);
695
+ //
696
+ // End: code that would be in the switch statement if we were normal.
697
+ //
698
+ ////////////////////////////////////////////////////////////////////////////
699
+ // Reference
700
+ const childBucket = (0, executeBucket_js_1.newBucket)({ metaByMetaKey: undefined /* use defaults */, sharedState }, {
701
+ layerPlan: this,
702
+ size: totalSize,
703
+ store,
704
+ // PERF: not necessarily, if we don't copy the errors, we don't have the errors.
705
+ flagUnion,
706
+ polymorphicPathList,
707
+ polymorphicType: null,
708
+ iterators,
709
+ });
710
+ for (const plp of this.reason.parentLayerPlans) {
711
+ const parentBucket = sharedState._retainedBuckets.get(plp.id);
712
+ if (parentBucket != null) {
713
+ const map = mapByParentLayerPlanId[plp.id];
714
+ parentBucket.children[this.id] = {
715
+ bucket: childBucket,
716
+ map,
717
+ };
718
+ }
719
+ }
720
+ return childBucket;
633
721
  }
634
- const building = makingNewBucketCallbacks.get(signature);
635
- if (building !== undefined) {
636
- building.push(callback);
637
- return;
722
+ addCombo(sources, $target) {
723
+ if (this.reason.type !== "combined") {
724
+ throw new Error(`Combinations may only be added to combined layer plans`);
725
+ }
726
+ this.combinations.push({
727
+ sources: sources.map((s) => ({
728
+ layerPlanId: s.layerPlan.id,
729
+ stepId: s.step.id,
730
+ })),
731
+ targetStepId: $target.id,
732
+ });
733
+ const { layerPlansByDependentStep } = this.operationPlan.stepTracker;
734
+ sources.forEach(({ step }) => {
735
+ let set = layerPlansByDependentStep.get(step);
736
+ if (!set) {
737
+ set = new Set();
738
+ layerPlansByDependentStep.set(step, set);
739
+ }
740
+ set.add(this);
741
+ });
638
742
  }
639
- const callbacks = [callback];
640
- makingNewBucketCallbacks.set(signature, callbacks);
641
- const executorExpression = newBucketFactoryInnerExpression(signature, copyCount, reasonType);
642
- const factoryExpression = (0, tamedevil_1.default) `\
643
- function ${tamedevil_1.default.identifier(`layerPlanNewBucketFactory_${signature}`)}(copyStepIds) {
644
- return ${executorExpression};
645
- }`;
646
- tamedevil_1.default.runInBatch(factoryExpression, (factory) => {
647
- makeNewBucketCache.set(signature, factory);
648
- makingNewBucketCallbacks.delete(signature);
649
- for (const callback of callbacks) {
650
- callback(factory);
743
+ /** @internal */
744
+ getPartition(typeNames, polymorphicPaths) {
745
+ const existing = this.children.find((c) => c.reason.type === "polymorphicPartition" &&
746
+ // Note: it's probably okay to use arraysMatch here even though order is
747
+ // unimportant because probably the order of all subsets will be the
748
+ // same, so we don't need to do an order-independent comparison (which
749
+ // would be more expensiv)
750
+ (0, utils_js_1.arraysMatch)(c.reason.typeNames, typeNames) &&
751
+ (0, utils_js_1.setsMatch)(c.reason.polymorphicPaths, polymorphicPaths));
752
+ if (existing) {
753
+ return existing;
651
754
  }
652
- });
755
+ return new LayerPlan(this.operationPlan, {
756
+ type: "polymorphicPartition",
757
+ parentLayerPlan: this,
758
+ typeNames,
759
+ polymorphicPaths,
760
+ });
761
+ }
653
762
  }
763
+ exports.LayerPlan = LayerPlan;
654
764
  //# sourceMappingURL=LayerPlan.js.map