grafast 0.1.1-beta.0 → 0.1.1-beta.2
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.
- package/README.md +1 -2
- package/dist/args.js +62 -0
- package/dist/assert.js +24 -0
- package/dist/bucket.js +4 -0
- package/dist/config.js +99 -0
- package/dist/constraints.js +72 -0
- package/dist/deferred.js +25 -0
- package/dist/dev.js +10 -0
- package/dist/engine/LayerPlan.js +536 -0
- package/dist/engine/OperationPlan.js +2543 -0
- package/dist/engine/OutputPlan.js +1059 -0
- package/dist/engine/StepTracker.js +524 -0
- package/dist/engine/executeBucket.js +700 -0
- package/dist/engine/executeOutputPlan.js +21 -0
- package/dist/engine/lib/withGlobalLayerPlan.js +36 -0
- package/dist/envelop.js +73 -5
- package/dist/error.js +62 -0
- package/dist/establishOperationPlan.js +186 -0
- package/dist/execute.js +80 -0
- package/dist/exportAs.js +57 -0
- package/dist/global.js +13 -0
- package/dist/grafastGraphql.js +133 -0
- package/dist/grafastPrint.js +177 -0
- package/dist/graphqlCollectFields.js +217 -0
- package/dist/graphqlMergeSelectionSets.js +60 -0
- package/dist/index.d.ts +161 -2
- package/dist/index.js +255 -499
- package/dist/input.js +159 -0
- package/dist/inspect.js +20 -0
- package/dist/interfaces.d.ts +3 -160
- package/dist/interfaces.js +63 -0
- package/dist/makeGrafastSchema.js +174 -0
- package/dist/mermaid.js +290 -7
- package/dist/operationPlan-input.js +449 -0
- package/dist/planJSONInterfaces.js +3 -0
- package/dist/polymorphic.js +73 -0
- package/dist/prepare.js +763 -0
- package/dist/step.js +396 -0
- package/dist/steps/__inputDynamicScalar.js +125 -0
- package/dist/steps/__inputList.js +110 -0
- package/dist/steps/__inputObject.js +128 -0
- package/dist/steps/__inputStaticLeaf.js +43 -0
- package/dist/steps/__item.js +50 -0
- package/dist/steps/__trackedValue.js +257 -0
- package/dist/steps/__value.js +47 -0
- package/dist/steps/access.js +183 -0
- package/dist/steps/applyTransforms.js +151 -0
- package/dist/steps/connection.js +315 -0
- package/dist/steps/constant.js +72 -0
- package/dist/steps/each.js +64 -0
- package/dist/steps/error.js +32 -0
- package/dist/steps/filter.js +32 -0
- package/dist/steps/first.js +49 -0
- package/dist/steps/graphqlResolver.js +260 -0
- package/dist/steps/groupBy.js +40 -0
- package/dist/steps/index.js +117 -0
- package/dist/steps/lambda.js +58 -0
- package/dist/steps/last.js +41 -0
- package/dist/steps/list.js +75 -0
- package/dist/steps/listTransform.js +185 -0
- package/dist/steps/listen.js +61 -0
- package/dist/steps/load.d.ts +4 -4
- package/dist/steps/load.js +310 -0
- package/dist/steps/node.d.ts +6 -6
- package/dist/steps/node.js +107 -0
- package/dist/steps/object.js +195 -0
- package/dist/steps/partitionByIndex.js +86 -0
- package/dist/steps/proxy.js +114 -0
- package/dist/steps/remapKeys.js +84 -0
- package/dist/steps/reverse.js +52 -0
- package/dist/steps/setter.js +28 -0
- package/dist/stringifyPayload.js +59 -0
- package/dist/stripAnsi.js +14 -0
- package/dist/subscribe.js +14 -0
- package/dist/thereCanBeOnlyOne.js +21 -0
- package/dist/timeSource.js +8 -0
- package/dist/utils.js +698 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +6 -0
- package/package.json +9 -4
- package/dist/LICENSES.txt +0 -300
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StepTracker = void 0;
|
|
4
|
+
const dev_js_1 = require("../dev.js");
|
|
5
|
+
const interfaces_js_1 = require("../interfaces.js");
|
|
6
|
+
/**
|
|
7
|
+
* We want everything else to treat things like `dependencies` as read only,
|
|
8
|
+
* however we ourselves want to be able to write to them, so we can use
|
|
9
|
+
* writeable for this.
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*/
|
|
13
|
+
function writeableArray(a) {
|
|
14
|
+
return a;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* This class keeps track of all of our steps, and the dependencies between
|
|
18
|
+
* steps and other steps, layer plans and steps, and output plans and steps.
|
|
19
|
+
*
|
|
20
|
+
* When a step is replaced by another step, all the dependencies are updated
|
|
21
|
+
* such that the replaced step simply evaporates.
|
|
22
|
+
*
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
class StepTracker {
|
|
26
|
+
constructor(operationPlan) {
|
|
27
|
+
this.operationPlan = operationPlan;
|
|
28
|
+
/** @internal */
|
|
29
|
+
this.stepCount = 0;
|
|
30
|
+
/** @internal */
|
|
31
|
+
this.activeSteps = new Set();
|
|
32
|
+
/** @internal */
|
|
33
|
+
this.stepById = [];
|
|
34
|
+
/** @internal */
|
|
35
|
+
this.aliasesById = [];
|
|
36
|
+
/** @internal */
|
|
37
|
+
this.stepsWithNoDependencies = new Set();
|
|
38
|
+
/** @internal */
|
|
39
|
+
this.outputPlansByRootStep = new Map();
|
|
40
|
+
/** @internal */
|
|
41
|
+
this.layerPlansByRootStep = new Map();
|
|
42
|
+
/** @internal */
|
|
43
|
+
this.layerPlansByParentStep = new Map();
|
|
44
|
+
/** @internal */
|
|
45
|
+
this.layerPlans = [];
|
|
46
|
+
/**
|
|
47
|
+
* All the OutputPlans that were created to allow a more efficient
|
|
48
|
+
* walkOutputPlans implementation.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
this.allOutputPlans = [];
|
|
53
|
+
this.nextStepIdToDeduplicate = 0;
|
|
54
|
+
}
|
|
55
|
+
newStepsSince(oldStepCount) {
|
|
56
|
+
return this.stepById.slice(oldStepCount);
|
|
57
|
+
}
|
|
58
|
+
forbid(key) {
|
|
59
|
+
this[key] = () => {
|
|
60
|
+
throw new Error(`StepTracker.${key}(...) is forbidden after 'finalize' phase`);
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/** Called when OperationPlan enters finalize phase. */
|
|
64
|
+
finalizeSteps() {
|
|
65
|
+
this.forbid("addStep");
|
|
66
|
+
this.forbid("addLayerPlan");
|
|
67
|
+
this.forbid("addOutputPlan");
|
|
68
|
+
this.forbid("deleteLayerPlan");
|
|
69
|
+
this.forbid("addStepDependency");
|
|
70
|
+
this.forbid("setLayerPlanRootStep");
|
|
71
|
+
this.forbid("replaceStep");
|
|
72
|
+
}
|
|
73
|
+
/** Called when OperationPlan is about to finalize the output plans. */
|
|
74
|
+
finalizeOutputPlans() {
|
|
75
|
+
this.forbid("setOutputPlanRootStep");
|
|
76
|
+
}
|
|
77
|
+
addStep($step) {
|
|
78
|
+
const stepId = this.stepCount++;
|
|
79
|
+
this.activeSteps.add($step);
|
|
80
|
+
this.stepsWithNoDependencies.add($step);
|
|
81
|
+
this.stepById[stepId] = $step;
|
|
82
|
+
this.aliasesById[stepId] = undefined;
|
|
83
|
+
this.addStepToItsLayerPlan($step);
|
|
84
|
+
return stepId;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* @internal
|
|
88
|
+
*/
|
|
89
|
+
addLayerPlan(layerPlan) {
|
|
90
|
+
const id = this.layerPlans.push(layerPlan) - 1;
|
|
91
|
+
switch (layerPlan.reason.type) {
|
|
92
|
+
case "root":
|
|
93
|
+
case "subscription":
|
|
94
|
+
case "mutationField":
|
|
95
|
+
case "defer": {
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
case "nullableBoundary":
|
|
99
|
+
case "listItem":
|
|
100
|
+
case "polymorphic": {
|
|
101
|
+
const store = this.layerPlansByParentStep.get(layerPlan.reason.parentStep);
|
|
102
|
+
if (store !== undefined) {
|
|
103
|
+
store.add(layerPlan);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const layerPlans = new Set();
|
|
107
|
+
layerPlans.add(layerPlan);
|
|
108
|
+
this.layerPlansByParentStep.set(layerPlan.reason.parentStep, layerPlans);
|
|
109
|
+
}
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case "subroutine": {
|
|
113
|
+
const parent = layerPlan.reason.parentStep;
|
|
114
|
+
if (parent[interfaces_js_1.$$subroutine] !== null) {
|
|
115
|
+
throw new Error(`Steps may currently only have one subroutine. If you have need for a step with multiple subroutines, please get in touch.`);
|
|
116
|
+
}
|
|
117
|
+
parent[interfaces_js_1.$$subroutine] =
|
|
118
|
+
layerPlan;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
default: {
|
|
122
|
+
const never = layerPlan.reason;
|
|
123
|
+
throw new Error(`Unexpected layerPlan reason ${never.type}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return id;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* @internal
|
|
130
|
+
*/
|
|
131
|
+
addOutputPlan(outputPlan) {
|
|
132
|
+
if (dev_js_1.isDev && !this.activeSteps.has(outputPlan.rootStep)) {
|
|
133
|
+
throw new Error(`GrafastInternalError<84485250-c4f3-4175-ab0c-360e073fa69f>: Root step '${outputPlan.rootStep}' is not active; perhaps it was replaced (replacement: ${this.getStepById(outputPlan.rootStep.id)})`);
|
|
134
|
+
}
|
|
135
|
+
this.allOutputPlans.push(outputPlan);
|
|
136
|
+
const store = this.outputPlansByRootStep.get(outputPlan.rootStep);
|
|
137
|
+
if (store !== undefined) {
|
|
138
|
+
store.add(outputPlan);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
const outputPlans = new Set();
|
|
142
|
+
outputPlans.add(outputPlan);
|
|
143
|
+
this.outputPlansByRootStep.set(outputPlan.rootStep, outputPlans);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* HIGHLY EXPERIMENTAL!
|
|
148
|
+
*
|
|
149
|
+
* @internal
|
|
150
|
+
*/
|
|
151
|
+
deleteLayerPlan(layerPlan) {
|
|
152
|
+
if (dev_js_1.isDev) {
|
|
153
|
+
if (layerPlan.children.length > 0) {
|
|
154
|
+
throw new Error("This layer plan has children... should we really be deleting it?!");
|
|
155
|
+
}
|
|
156
|
+
this.allOutputPlans.forEach((o) => {
|
|
157
|
+
if (o.layerPlan === layerPlan) {
|
|
158
|
+
throw new Error("An output plan depends on this layer plan... should we really be deleting it?!");
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
this.layerPlans[layerPlan.id] = null;
|
|
163
|
+
// Remove layerPlan from its parent
|
|
164
|
+
if (layerPlan.parentLayerPlan !== null) {
|
|
165
|
+
const idx = layerPlan.parentLayerPlan.children.indexOf(layerPlan);
|
|
166
|
+
if (idx >= 0) {
|
|
167
|
+
layerPlan.parentLayerPlan.children.splice(idx, 1);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Remove references
|
|
171
|
+
const $root = layerPlan.rootStep;
|
|
172
|
+
if ($root) {
|
|
173
|
+
this.layerPlansByRootStep.get($root).delete(layerPlan);
|
|
174
|
+
}
|
|
175
|
+
if (layerPlan.reason.type !== "subroutine") {
|
|
176
|
+
const $parent = "parentStep" in layerPlan.reason ? layerPlan.reason.parentStep : null;
|
|
177
|
+
if ($parent) {
|
|
178
|
+
this.layerPlansByParentStep
|
|
179
|
+
.get($parent)
|
|
180
|
+
.delete(layerPlan);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Remove all plans in this layer
|
|
184
|
+
const handled = new Set();
|
|
185
|
+
const handle = (step) => {
|
|
186
|
+
if (handled.has(step))
|
|
187
|
+
return;
|
|
188
|
+
handled.add(step);
|
|
189
|
+
// Handle dependents first
|
|
190
|
+
for (const dependent of step.dependents) {
|
|
191
|
+
if (dependent.step.layerPlan === layerPlan) {
|
|
192
|
+
handle(dependent.step);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
this.eradicate(step);
|
|
196
|
+
};
|
|
197
|
+
for (const step of this.activeSteps) {
|
|
198
|
+
if (step.layerPlan === layerPlan) {
|
|
199
|
+
handle(step);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
getStepById(id, allowUnset = false) {
|
|
204
|
+
const step = this.stepById[id];
|
|
205
|
+
if (!step && !allowUnset) {
|
|
206
|
+
throw new Error(`Illegal step access? Step with id ${id} doesn't exist`);
|
|
207
|
+
}
|
|
208
|
+
if (dev_js_1.isDev) {
|
|
209
|
+
if (step && !this.activeSteps.has(step)) {
|
|
210
|
+
throw new Error(`${step} is not active, but we retrieved it from stepTracker.getStepById(${id}, ${allowUnset})`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return step;
|
|
214
|
+
}
|
|
215
|
+
addStepDependency($dependent, $dependency) {
|
|
216
|
+
if (!this.activeSteps.has($dependent)) {
|
|
217
|
+
throw new Error(`Cannot add ${$dependency} as a dependency of ${$dependent}; the latter is deleted!`);
|
|
218
|
+
}
|
|
219
|
+
if (!this.activeSteps.has($dependency)) {
|
|
220
|
+
throw new Error(`Cannot add ${$dependency} as a dependency of ${$dependent}; the former is deleted!`);
|
|
221
|
+
}
|
|
222
|
+
this.stepsWithNoDependencies.delete($dependent);
|
|
223
|
+
const dependencyIndex = writeableArray($dependent.dependencies).push($dependency) - 1;
|
|
224
|
+
writeableArray($dependency.dependents).push({
|
|
225
|
+
step: $dependent,
|
|
226
|
+
dependencyIndex,
|
|
227
|
+
});
|
|
228
|
+
return dependencyIndex;
|
|
229
|
+
}
|
|
230
|
+
setOutputPlanRootStep(outputPlan, $dependency) {
|
|
231
|
+
if (!this.activeSteps.has($dependency)) {
|
|
232
|
+
throw new Error(`Cannot add ${$dependency} to ${outputPlan} because it's deleted`);
|
|
233
|
+
}
|
|
234
|
+
const $existing = outputPlan.rootStep;
|
|
235
|
+
if ($existing) {
|
|
236
|
+
const outputPlansBy$existing = this.outputPlansByRootStep.get($existing);
|
|
237
|
+
if (!outputPlansBy$existing) {
|
|
238
|
+
throw new Error(`GrafastInternalError<f39690fc-f565-40d9-a781-e68a3bf5e84a>: ${outputPlan}.rootStep (${$existing}) isn't in 'outputPlansByRootStep'`);
|
|
239
|
+
}
|
|
240
|
+
outputPlansBy$existing.delete(outputPlan);
|
|
241
|
+
if (outputPlansBy$existing.size === 0) {
|
|
242
|
+
// PERF: Cleanup, tree shake, etc
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
outputPlan.rootStep = $dependency;
|
|
246
|
+
const store = this.outputPlansByRootStep.get($dependency);
|
|
247
|
+
if (store !== undefined) {
|
|
248
|
+
store.add(outputPlan);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
const outputPlans = new Set();
|
|
252
|
+
outputPlans.add(outputPlan);
|
|
253
|
+
this.outputPlansByRootStep.set($dependency, outputPlans);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
setLayerPlanRootStep(layerPlan, $dependency) {
|
|
257
|
+
if (!this.activeSteps.has($dependency)) {
|
|
258
|
+
throw new Error(`Cannot add ${$dependency} to ${layerPlan} because it's deleted`);
|
|
259
|
+
}
|
|
260
|
+
const $existing = layerPlan.rootStep;
|
|
261
|
+
if ($existing) {
|
|
262
|
+
const layerPlansBy$existing = this.layerPlansByRootStep.get($existing);
|
|
263
|
+
if (!layerPlansBy$existing) {
|
|
264
|
+
throw new Error(`GrafastInternalError<7b5b7fe6-d403-48bd-a75f-1c9557b9a030>: ${layerPlan}.rootStep (${$existing}) isn't in 'layerPlansByRootStep'`);
|
|
265
|
+
}
|
|
266
|
+
layerPlansBy$existing.delete(layerPlan);
|
|
267
|
+
if (layerPlansBy$existing.size === 0) {
|
|
268
|
+
this.layerPlansByRootStep.delete($existing);
|
|
269
|
+
// PERF: Cleanup, tree shake, etc
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
layerPlan.rootStep = $dependency;
|
|
273
|
+
const store = this.layerPlansByRootStep.get($dependency);
|
|
274
|
+
if (store !== undefined) {
|
|
275
|
+
store.add(layerPlan);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
const layerPlans = new Set();
|
|
279
|
+
layerPlans.add(layerPlan);
|
|
280
|
+
this.layerPlansByRootStep.set($dependency, layerPlans);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/** @internal */
|
|
284
|
+
replaceStep($original, $replacement) {
|
|
285
|
+
if (!this.activeSteps.has($original)) {
|
|
286
|
+
// OPTIMIZE: seems like there's unnecessary work being done here.
|
|
287
|
+
// console.trace(`${$original} should be replaced with ${$replacement} but it's no longer alive`);
|
|
288
|
+
// Already handled
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
// Replace all references to $original with $replacement
|
|
292
|
+
const oldAliases = this.aliasesById[$original.id];
|
|
293
|
+
const newAliases = this.aliasesById[$replacement.id] ?? [$replacement.id];
|
|
294
|
+
this.aliasesById[$replacement.id] = newAliases;
|
|
295
|
+
if (oldAliases !== undefined) {
|
|
296
|
+
for (const id of oldAliases) {
|
|
297
|
+
this.stepById[id] = $replacement;
|
|
298
|
+
newAliases.push(id);
|
|
299
|
+
}
|
|
300
|
+
this.aliasesById[$original.id] = undefined;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
this.stepById[$original.id] = $replacement;
|
|
304
|
+
newAliases.push($original.id);
|
|
305
|
+
}
|
|
306
|
+
{
|
|
307
|
+
// Transfer step dependents of $original to $replacement
|
|
308
|
+
const dependents = $original.dependents;
|
|
309
|
+
if (dependents.length > 0) {
|
|
310
|
+
const replacementDependents = writeableArray($replacement.dependents);
|
|
311
|
+
for (const dependent of dependents) {
|
|
312
|
+
writeableArray(dependent.step.dependencies)[dependent.dependencyIndex] = $replacement;
|
|
313
|
+
replacementDependents.push(dependent);
|
|
314
|
+
}
|
|
315
|
+
$original.dependents = [];
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
{
|
|
319
|
+
// Convert root step of output plans from $original to $replacement
|
|
320
|
+
const outputPlans = this.outputPlansByRootStep.get($original);
|
|
321
|
+
if (outputPlans?.size) {
|
|
322
|
+
let outputPlansByReplacementStep = this.outputPlansByRootStep.get($replacement);
|
|
323
|
+
if (!outputPlansByReplacementStep) {
|
|
324
|
+
outputPlansByReplacementStep = new Set();
|
|
325
|
+
this.outputPlansByRootStep.set($replacement, outputPlansByReplacementStep);
|
|
326
|
+
}
|
|
327
|
+
for (const outputPlan of outputPlans) {
|
|
328
|
+
outputPlan.rootStep = $replacement;
|
|
329
|
+
outputPlansByReplacementStep.add(outputPlan);
|
|
330
|
+
}
|
|
331
|
+
outputPlans.clear();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
{
|
|
335
|
+
// Convert root step of layer plans from $original to $replacement
|
|
336
|
+
const layerPlans = this.layerPlansByRootStep.get($original);
|
|
337
|
+
if (layerPlans?.size) {
|
|
338
|
+
let layerPlansByReplacementRootStep = this.layerPlansByRootStep.get($replacement);
|
|
339
|
+
if (!layerPlansByReplacementRootStep) {
|
|
340
|
+
layerPlansByReplacementRootStep = new Set();
|
|
341
|
+
this.layerPlansByRootStep.set($replacement, layerPlansByReplacementRootStep);
|
|
342
|
+
}
|
|
343
|
+
for (const layerPlan of layerPlans) {
|
|
344
|
+
layerPlan.rootStep = $replacement;
|
|
345
|
+
layerPlansByReplacementRootStep.add(layerPlan);
|
|
346
|
+
}
|
|
347
|
+
layerPlans.clear();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// NOTE: had to add the code ensuring all the layer plan parentStepId's
|
|
351
|
+
// existed to fix polymorphism, but it feels wrong. Should we be doing
|
|
352
|
+
// something different?
|
|
353
|
+
{
|
|
354
|
+
// Convert parent step of layer plans from $original to $replacement
|
|
355
|
+
const layerPlans = this.layerPlansByParentStep.get($original);
|
|
356
|
+
if (layerPlans?.size) {
|
|
357
|
+
let layerPlansByReplacementParentStep = this.layerPlansByParentStep.get($replacement);
|
|
358
|
+
if (!layerPlansByReplacementParentStep) {
|
|
359
|
+
layerPlansByReplacementParentStep = new Set();
|
|
360
|
+
this.layerPlansByParentStep.set($replacement, layerPlansByReplacementParentStep);
|
|
361
|
+
}
|
|
362
|
+
for (const layerPlan of layerPlans) {
|
|
363
|
+
layerPlan.reason.parentStep = $replacement;
|
|
364
|
+
layerPlansByReplacementParentStep.add(layerPlan);
|
|
365
|
+
}
|
|
366
|
+
layerPlans.clear();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// NOTE: I don't think side-effect plans need any special handling, since
|
|
370
|
+
// they cannot be deduplicated.
|
|
371
|
+
// NOTE: there may be more work required here for 'subprocedure' layerPlans
|
|
372
|
+
// (e.g. making sure their steps are retained), but it's not clear what
|
|
373
|
+
// work is necessary and we've not seen any issues from this yet.
|
|
374
|
+
// Remove this step (and perform localized tree-shaking)
|
|
375
|
+
this.eradicate($original);
|
|
376
|
+
}
|
|
377
|
+
treeShakeSteps() {
|
|
378
|
+
for (const $step of this.activeSteps) {
|
|
379
|
+
if (this.isNotNeeded($step)) {
|
|
380
|
+
this.eradicate($step);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Return true if this step can be tree-shaken.
|
|
386
|
+
*/
|
|
387
|
+
isNotNeeded($step) {
|
|
388
|
+
if ($step.dependents.length !== 0)
|
|
389
|
+
return false;
|
|
390
|
+
if ($step.hasSideEffects)
|
|
391
|
+
return false;
|
|
392
|
+
const s1 = this.outputPlansByRootStep.get($step);
|
|
393
|
+
if (s1 && s1.size !== 0)
|
|
394
|
+
return false;
|
|
395
|
+
const s2 = this.layerPlansByRootStep.get($step);
|
|
396
|
+
if (s2 && s2.size !== 0)
|
|
397
|
+
return false;
|
|
398
|
+
const s3 = this.layerPlansByParentStep.get($step);
|
|
399
|
+
if (s3 && s3.size !== 0)
|
|
400
|
+
return false;
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Only for use during planField.
|
|
405
|
+
*/
|
|
406
|
+
purgeBackTo(count) {
|
|
407
|
+
const upper = this.stepCount;
|
|
408
|
+
const toRemove = new Set();
|
|
409
|
+
for (let i = count; i < upper; i++) {
|
|
410
|
+
const step = this.stepById[i];
|
|
411
|
+
if (step) {
|
|
412
|
+
toRemove.add(step);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
const remove = (step) => {
|
|
416
|
+
if (this.stepById[step.id] !== step) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (toRemove.has(step)) {
|
|
420
|
+
for (const dependent of step.dependents) {
|
|
421
|
+
if (dependent.step.id >= count) {
|
|
422
|
+
remove(dependent.step);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
this.eradicate(step);
|
|
426
|
+
toRemove.delete(step);
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
for (const step of toRemove) {
|
|
430
|
+
remove(step);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* ONLY CALL THIS IF NOTHING DEPENDS ON $original! It's intended to be called
|
|
435
|
+
* from `replaceStep` or from itself.
|
|
436
|
+
*
|
|
437
|
+
* This method removes $original from the various maps/sets/lists, and also
|
|
438
|
+
* removes the fact that it was dependent on other steps. If these other
|
|
439
|
+
* steps no longer have any dependents (steps, layer plans or output plans)
|
|
440
|
+
* then they can also be eradicated _except_ during the 'plan' phase.
|
|
441
|
+
*/
|
|
442
|
+
eradicate($original) {
|
|
443
|
+
if ($original[interfaces_js_1.$$subroutine] !== null) {
|
|
444
|
+
this.deleteLayerPlan($original[interfaces_js_1.$$subroutine]);
|
|
445
|
+
}
|
|
446
|
+
this.removeStepFromItsLayerPlan($original);
|
|
447
|
+
const oldAliases = this.aliasesById[$original.id];
|
|
448
|
+
if (oldAliases !== undefined) {
|
|
449
|
+
for (const id of oldAliases) {
|
|
450
|
+
// Nothing needs us, so set ourself null (DELIBERATELY BYPASSES TYPESCRIPT!)
|
|
451
|
+
this.stepById[id] = null;
|
|
452
|
+
}
|
|
453
|
+
this.aliasesById[$original.id] = undefined;
|
|
454
|
+
}
|
|
455
|
+
else if (this.stepById[$original.id] === $original) {
|
|
456
|
+
this.stepById[$original.id] = null;
|
|
457
|
+
}
|
|
458
|
+
// Since this step is being removed, it doesn't need its dependencies any more
|
|
459
|
+
const oldDependencies = $original.dependencies;
|
|
460
|
+
for (const $dependency of oldDependencies) {
|
|
461
|
+
// $dependency is no longer a dependent of $original, since we're getting
|
|
462
|
+
// rid of $original
|
|
463
|
+
$dependency.dependents = $dependency.dependents.filter((dependent) => dependent.step !== $original);
|
|
464
|
+
// If we've done our first tree-shake, let's keep it tidy in here.
|
|
465
|
+
if (this.operationPlan.phase !== "plan" &&
|
|
466
|
+
this.isNotNeeded($dependency)) {
|
|
467
|
+
// Nothing depends on $dependency and it has no side effects - we can get rid of it!
|
|
468
|
+
this.eradicate($dependency);
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
// Ensure nothing depends on this step - steps, layer plans, output plans.
|
|
472
|
+
// This should already be the case, so we just do it in dev as a
|
|
473
|
+
// consistency check.
|
|
474
|
+
if (dev_js_1.isDev) {
|
|
475
|
+
if ($original.dependents.length > 0) {
|
|
476
|
+
throw new Error(`${$original} eradicated, but it is needed by ${$original.dependents.map((d) => d.step)}`);
|
|
477
|
+
}
|
|
478
|
+
const outputPlansByRoot = this.outputPlansByRootStep.get($original);
|
|
479
|
+
if (outputPlansByRoot && outputPlansByRoot.size !== 0) {
|
|
480
|
+
throw new Error(`${$original} eradicated, but it is needed by ${[
|
|
481
|
+
...outputPlansByRoot,
|
|
482
|
+
]}`);
|
|
483
|
+
}
|
|
484
|
+
const layerPlansByRoot = this.layerPlansByRootStep.get($original);
|
|
485
|
+
if (layerPlansByRoot && layerPlansByRoot.size !== 0) {
|
|
486
|
+
throw new Error(`${$original} eradicated, but it is needed by ${[
|
|
487
|
+
...layerPlansByRoot,
|
|
488
|
+
]}`);
|
|
489
|
+
}
|
|
490
|
+
const layerPlansByParent = this.layerPlansByParentStep.get($original);
|
|
491
|
+
if (layerPlansByParent && layerPlansByParent.size !== 0) {
|
|
492
|
+
throw new Error(`${$original} eradicated, but it is needed by ${[
|
|
493
|
+
...layerPlansByParent,
|
|
494
|
+
]}`);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
this.stepsWithNoDependencies.delete($original);
|
|
498
|
+
this.outputPlansByRootStep.delete($original);
|
|
499
|
+
this.layerPlansByRootStep.delete($original);
|
|
500
|
+
this.layerPlansByParentStep.delete($original);
|
|
501
|
+
this.activeSteps.delete($original);
|
|
502
|
+
// Referencing $original after this will likely cause errors.
|
|
503
|
+
$original.destroy();
|
|
504
|
+
}
|
|
505
|
+
moveStepToLayerPlan(step, targetLayerPlan) {
|
|
506
|
+
this.removeStepFromItsLayerPlan(step);
|
|
507
|
+
step.layerPlan = targetLayerPlan;
|
|
508
|
+
this.addStepToItsLayerPlan(step);
|
|
509
|
+
}
|
|
510
|
+
addStepToItsLayerPlan(step) {
|
|
511
|
+
const { layerPlan: { stepsByConstructor }, constructor, } = step;
|
|
512
|
+
let set = stepsByConstructor.get(constructor);
|
|
513
|
+
if (!set) {
|
|
514
|
+
set = new Set();
|
|
515
|
+
stepsByConstructor.set(constructor, set);
|
|
516
|
+
}
|
|
517
|
+
set.add(step);
|
|
518
|
+
}
|
|
519
|
+
removeStepFromItsLayerPlan(step) {
|
|
520
|
+
step.layerPlan.stepsByConstructor.get(step.constructor).delete(step);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
exports.StepTracker = StepTracker;
|
|
524
|
+
//# sourceMappingURL=StepTracker.js.map
|