@suss/extractor 0.34.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1101 -207
- package/dist/index.d.cts +323 -23
- package/dist/index.d.ts +323 -23
- package/dist/index.js +1085 -201
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { createHash as
|
|
2
|
+
import { createHash as createHash7 } from "crypto";
|
|
3
3
|
import {
|
|
4
4
|
effectKey,
|
|
5
5
|
exchangesHttpResponses as exchangesHttpResponses2,
|
|
@@ -199,29 +199,82 @@ function composeOne(summary, chain, keepGaps) {
|
|
|
199
199
|
if (wrappers.length === 0) {
|
|
200
200
|
return narrowed;
|
|
201
201
|
}
|
|
202
|
-
const responses = respondedInstead(wrappers);
|
|
203
|
-
const
|
|
204
|
-
const
|
|
202
|
+
const responses = settledUncaught(respondedInstead(wrappers), wrappers);
|
|
203
|
+
const unitOwn = settledUncaught(summary.transitions, wrappers);
|
|
204
|
+
const own = [...responses, ...unitOwn];
|
|
205
|
+
const handled = handledThrows(wrappers, thrownBy(own));
|
|
206
|
+
const transitions = beside(summary, unitOwn, responses, handled);
|
|
205
207
|
if (!keepGaps) {
|
|
206
208
|
return transitions === summary.transitions ? narrowed : { ...narrowed, transitions };
|
|
207
209
|
}
|
|
208
210
|
const gaps = withContractStatusGaps(
|
|
209
211
|
summary,
|
|
210
|
-
|
|
211
|
-
|
|
212
|
+
own,
|
|
213
|
+
everyHandlerOutcome(wrappers)
|
|
212
214
|
);
|
|
213
215
|
if (transitions === summary.transitions && gaps === summary.gaps) {
|
|
214
216
|
return narrowed;
|
|
215
217
|
}
|
|
216
218
|
return { ...narrowed, transitions, gaps };
|
|
217
219
|
}
|
|
218
|
-
function beside(summary, responses, handled) {
|
|
219
|
-
|
|
220
|
-
const onThrow = throws ? handled : [];
|
|
221
|
-
if (responses.length === 0 && onThrow.length === 0) {
|
|
220
|
+
function beside(summary, unitOwn, responses, handled) {
|
|
221
|
+
if (responses.length === 0 && handled.length === 0 && unitOwn === summary.transitions) {
|
|
222
222
|
return summary.transitions;
|
|
223
223
|
}
|
|
224
|
-
return withDistinctIds([...responses, ...
|
|
224
|
+
return withDistinctIds([...responses, ...unitOwn, ...handled]);
|
|
225
|
+
}
|
|
226
|
+
function settledUncaught(transitions, wrappers) {
|
|
227
|
+
const handlers = wrappers.filter(
|
|
228
|
+
(wrapper) => wrapper.reference.onThrow === true
|
|
229
|
+
);
|
|
230
|
+
let changed = false;
|
|
231
|
+
const settled = transitions.flatMap((transition) => {
|
|
232
|
+
const { output } = transition;
|
|
233
|
+
if (output.type !== "throw") {
|
|
234
|
+
return [transition];
|
|
235
|
+
}
|
|
236
|
+
const caught = caughtOnRoute(handlers, output);
|
|
237
|
+
if (caught === "sure") {
|
|
238
|
+
changed = true;
|
|
239
|
+
return [markedCaught(transition)];
|
|
240
|
+
}
|
|
241
|
+
if (output.statusWhenUncaught === void 0) {
|
|
242
|
+
return [transition];
|
|
243
|
+
}
|
|
244
|
+
changed = true;
|
|
245
|
+
const response = {
|
|
246
|
+
...transition,
|
|
247
|
+
output: {
|
|
248
|
+
type: "response",
|
|
249
|
+
statusCode: { type: "literal", value: output.statusWhenUncaught },
|
|
250
|
+
body: null,
|
|
251
|
+
headers: {}
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
return caught === "uncertain" ? [transition, response] : [response];
|
|
255
|
+
});
|
|
256
|
+
return changed ? settled : transitions;
|
|
257
|
+
}
|
|
258
|
+
function markedCaught(transition) {
|
|
259
|
+
return {
|
|
260
|
+
...transition,
|
|
261
|
+
metadata: withWrapperMetadata(transition.metadata, {
|
|
262
|
+
...readWrapperMetadata2(transition),
|
|
263
|
+
caught: true
|
|
264
|
+
})
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function caughtOnRoute(handlers, thrown) {
|
|
268
|
+
if (handlers.some((handler) => handler.reference.catches === void 0)) {
|
|
269
|
+
return "sure";
|
|
270
|
+
}
|
|
271
|
+
const matches = handlers.map(
|
|
272
|
+
(handler) => catchMatch(handler.reference, thrown)
|
|
273
|
+
);
|
|
274
|
+
if (matches.includes("yes")) {
|
|
275
|
+
return "sure";
|
|
276
|
+
}
|
|
277
|
+
return matches.includes("maybe") ? "uncertain" : "no";
|
|
225
278
|
}
|
|
226
279
|
function respondedInstead(wrappers) {
|
|
227
280
|
return wrappers.flatMap(
|
|
@@ -233,11 +286,91 @@ function respondedInstead(wrappers) {
|
|
|
233
286
|
)
|
|
234
287
|
);
|
|
235
288
|
}
|
|
236
|
-
function
|
|
289
|
+
function thrownBy(transitions) {
|
|
290
|
+
return transitions.flatMap(
|
|
291
|
+
(t) => t.output.type === "throw" ? [t.output] : []
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
function everyHandlerOutcome(wrappers) {
|
|
237
295
|
return wrappers.flatMap(
|
|
238
296
|
(wrapper) => wrapper.reference.onThrow === true ? attribute(wrapper.summary.transitions, wrapper.reference) : []
|
|
239
297
|
);
|
|
240
298
|
}
|
|
299
|
+
function handledThrows(wrappers, thrown) {
|
|
300
|
+
const caught = catchesAny(wrappers, thrown);
|
|
301
|
+
return [...oncePerHandler(wrappers, caught)].flatMap(
|
|
302
|
+
([wrapper, how]) => attribute(
|
|
303
|
+
wrapper.summary.transitions,
|
|
304
|
+
wrapper.reference,
|
|
305
|
+
how === "uncertain"
|
|
306
|
+
)
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
function oncePerHandler(wrappers, caught) {
|
|
310
|
+
const byHandler = /* @__PURE__ */ new Map();
|
|
311
|
+
for (const wrapper of wrappers) {
|
|
312
|
+
const how = caught.get(wrapper);
|
|
313
|
+
if (how === void 0) {
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const earlier = byHandler.get(wrapper.summary);
|
|
317
|
+
if (earlier === void 0 || earlier[1] === "uncertain" && how === "sure") {
|
|
318
|
+
byHandler.set(wrapper.summary, [wrapper, how]);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return new Map(byHandler.values());
|
|
322
|
+
}
|
|
323
|
+
function catchesAny(wrappers, thrown) {
|
|
324
|
+
const caught = /* @__PURE__ */ new Map();
|
|
325
|
+
if (thrown.length === 0) {
|
|
326
|
+
return caught;
|
|
327
|
+
}
|
|
328
|
+
const handlers = wrappers.filter(
|
|
329
|
+
(wrapper) => wrapper.reference.onThrow === true
|
|
330
|
+
);
|
|
331
|
+
for (const handler of handlers) {
|
|
332
|
+
if (handler.reference.catches === void 0) {
|
|
333
|
+
caught.set(handler, "sure");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const listing = handlers.filter(
|
|
337
|
+
(handler) => handler.reference.catches !== void 0
|
|
338
|
+
);
|
|
339
|
+
for (const one of thrown) {
|
|
340
|
+
for (const [handler, how] of catchersOf(listing, one)) {
|
|
341
|
+
if (caught.get(handler) !== "sure") {
|
|
342
|
+
caught.set(handler, how);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return caught;
|
|
347
|
+
}
|
|
348
|
+
function catchersOf(handlers, thrown) {
|
|
349
|
+
const found = [];
|
|
350
|
+
for (const handler of handlers) {
|
|
351
|
+
const match = catchMatch(handler.reference, thrown);
|
|
352
|
+
if (match === "yes") {
|
|
353
|
+
found.push([handler, found.length === 0 ? "sure" : "uncertain"]);
|
|
354
|
+
return found;
|
|
355
|
+
}
|
|
356
|
+
if (match === "maybe") {
|
|
357
|
+
found.push([handler, "uncertain"]);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return found;
|
|
361
|
+
}
|
|
362
|
+
function catchMatch(reference, thrown) {
|
|
363
|
+
const ancestors = thrown.exceptionAncestors;
|
|
364
|
+
if (thrown.exceptionType === null || ancestors === void 0) {
|
|
365
|
+
return "maybe";
|
|
366
|
+
}
|
|
367
|
+
const classes = /* @__PURE__ */ new Set([thrown.exceptionType, ...ancestors]);
|
|
368
|
+
if ((reference.catches ?? []).some((name) => classes.has(name))) {
|
|
369
|
+
return "yes";
|
|
370
|
+
}
|
|
371
|
+
const unread = thrown.ancestryIncomplete === true && reference.mayCatchUnreadClasses === true;
|
|
372
|
+
return unread || reference.mayCatchAny === true ? "maybe" : "no";
|
|
373
|
+
}
|
|
241
374
|
function withContractStatusGaps(summary, composed, handled) {
|
|
242
375
|
const contract = readHttpMetadata(summary)?.declaredContract;
|
|
243
376
|
const binding = summary.identity.boundaryBinding;
|
|
@@ -268,10 +401,13 @@ function coversUnit(reference, summary) {
|
|
|
268
401
|
const binding = summary.identity.boundaryBinding;
|
|
269
402
|
return binding !== null && withinScope(binding, reference.scope);
|
|
270
403
|
}
|
|
271
|
-
function attribute(transitions, reference) {
|
|
404
|
+
function attribute(transitions, reference, catchUncertain = false) {
|
|
272
405
|
return transitions.map((transition) => ({
|
|
273
406
|
...transition,
|
|
274
|
-
metadata: withWrapperMetadata(transition.metadata, {
|
|
407
|
+
metadata: withWrapperMetadata(transition.metadata, {
|
|
408
|
+
from: reference,
|
|
409
|
+
...catchUncertain ? { catchUncertain } : {}
|
|
410
|
+
})
|
|
275
411
|
}));
|
|
276
412
|
}
|
|
277
413
|
function withDistinctIds(transitions) {
|
|
@@ -384,13 +520,111 @@ function markExitCodeFrom(summary, marked) {
|
|
|
384
520
|
summary.metadata = left;
|
|
385
521
|
}
|
|
386
522
|
|
|
523
|
+
// src/helperHandOff.ts
|
|
524
|
+
import { predicateRefs, replacePredicateRefs } from "@suss/behavioral-ir";
|
|
525
|
+
var MAX_HELPER_PATHS = 16;
|
|
526
|
+
function throughHelper(branch, at, helperBranches) {
|
|
527
|
+
return helperBranches.map((helper) => {
|
|
528
|
+
const conditions = [...branch.conditions, ...helper.conditions];
|
|
529
|
+
const expectedInput = mergeReadShapes(
|
|
530
|
+
branch.expectedInput ?? null,
|
|
531
|
+
helper.expectedInput ?? null
|
|
532
|
+
);
|
|
533
|
+
const reads = expectedInput === null ? {} : { expectedInput };
|
|
534
|
+
if (helper.terminal.kind !== "throw" && helper.terminal.kind !== "exit") {
|
|
535
|
+
return {
|
|
536
|
+
...branch,
|
|
537
|
+
...reads,
|
|
538
|
+
conditions,
|
|
539
|
+
isDefault: branch.isDefault && helper.isDefault
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
return {
|
|
543
|
+
...branch,
|
|
544
|
+
...reads,
|
|
545
|
+
conditions,
|
|
546
|
+
terminal: { ...helper.terminal, location: at },
|
|
547
|
+
location: at,
|
|
548
|
+
isDefault: false
|
|
549
|
+
};
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
function mergeReadShapes(a, b) {
|
|
553
|
+
if (a === null || b === null) {
|
|
554
|
+
return a ?? b;
|
|
555
|
+
}
|
|
556
|
+
if (a.type !== "record" || b.type !== "record") {
|
|
557
|
+
return a.type === "record" ? a : b;
|
|
558
|
+
}
|
|
559
|
+
const properties = { ...a.properties };
|
|
560
|
+
for (const [name, shape] of Object.entries(b.properties)) {
|
|
561
|
+
const known = properties[name];
|
|
562
|
+
properties[name] = known === void 0 ? shape : mergeReadShapes(known, shape) ?? shape;
|
|
563
|
+
}
|
|
564
|
+
return { ...a, properties };
|
|
565
|
+
}
|
|
566
|
+
function splitAtHandOffs(branch, sites, from = 0) {
|
|
567
|
+
for (let index = from; index < sites.length; index++) {
|
|
568
|
+
const site = sites[index];
|
|
569
|
+
const reached = site.alwaysRuns === true || runsBefore(site.line, branch.terminal.location.end);
|
|
570
|
+
if (!reached || !guardsHoldOn(site.preconditions, branch.conditions)) {
|
|
571
|
+
continue;
|
|
572
|
+
}
|
|
573
|
+
return throughHelper(branch, site.at, site.helper).flatMap(
|
|
574
|
+
(path10) => path10.terminal === branch.terminal ? splitAtHandOffs(path10, sites, index + 1) : [path10]
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
return [branch];
|
|
578
|
+
}
|
|
579
|
+
function helperPathsOnVariables(helperBranches, passed) {
|
|
580
|
+
const renamed = helperBranches.map((branch) => ({
|
|
581
|
+
...branch,
|
|
582
|
+
conditions: branch.conditions.map((condition) => ({
|
|
583
|
+
...condition,
|
|
584
|
+
structured: condition.structured === null ? null : onCallerVariables(condition.structured, passed)
|
|
585
|
+
}))
|
|
586
|
+
}));
|
|
587
|
+
const variables = new Set(passed.values());
|
|
588
|
+
const testsWhatItGot = renamed.some(
|
|
589
|
+
(branch) => branch.conditions.some(
|
|
590
|
+
(condition) => condition.structured !== null && predicateRefs(condition.structured).some(
|
|
591
|
+
(ref) => variables.has(rootName(ref) ?? "")
|
|
592
|
+
)
|
|
593
|
+
)
|
|
594
|
+
);
|
|
595
|
+
return testsWhatItGot && renamed.length <= MAX_HELPER_PATHS ? renamed : null;
|
|
596
|
+
}
|
|
597
|
+
function onCallerVariables(predicate, passed) {
|
|
598
|
+
const rename = (ref) => {
|
|
599
|
+
if (ref.type === "derived") {
|
|
600
|
+
return { ...ref, from: rename(ref.from) };
|
|
601
|
+
}
|
|
602
|
+
if (ref.type === "input") {
|
|
603
|
+
const name = passed.get(ref.inputRef);
|
|
604
|
+
return name === void 0 ? ref : { type: "dependency", name, accessChain: ref.path };
|
|
605
|
+
}
|
|
606
|
+
if (ref.type === "dependency") {
|
|
607
|
+
const name = passed.get(ref.name);
|
|
608
|
+
return name === void 0 ? ref : { ...ref, name };
|
|
609
|
+
}
|
|
610
|
+
return ref;
|
|
611
|
+
};
|
|
612
|
+
return replacePredicateRefs(predicate, rename);
|
|
613
|
+
}
|
|
614
|
+
function rootName(ref) {
|
|
615
|
+
if (ref.type === "derived") {
|
|
616
|
+
return rootName(ref.from);
|
|
617
|
+
}
|
|
618
|
+
return ref.type === "dependency" ? ref.name : null;
|
|
619
|
+
}
|
|
620
|
+
|
|
387
621
|
// src/moduleImports.ts
|
|
388
|
-
function stampModuleImports(summaries,
|
|
622
|
+
function stampModuleImports(summaries, importsOf2) {
|
|
389
623
|
const byFile = /* @__PURE__ */ new Map();
|
|
390
624
|
for (const summary of summaries) {
|
|
391
625
|
const file = summary.location.file;
|
|
392
626
|
if (!byFile.has(file)) {
|
|
393
|
-
const found =
|
|
627
|
+
const found = importsOf2(file);
|
|
394
628
|
byFile.set(
|
|
395
629
|
file,
|
|
396
630
|
found === void 0 ? void 0 : [...new Set(found)].sort()
|
|
@@ -685,8 +919,8 @@ var catchEntryCond = () => fixedCond(
|
|
|
685
919
|
"positive",
|
|
686
920
|
"catchBlock"
|
|
687
921
|
);
|
|
688
|
-
function classify(
|
|
689
|
-
return
|
|
922
|
+
function classify(path10, home, isAncestorOrSelf) {
|
|
923
|
+
return path10.map((cond) => {
|
|
690
924
|
if (cond.branchStmt === null) {
|
|
691
925
|
return cond.info;
|
|
692
926
|
}
|
|
@@ -751,9 +985,16 @@ function chargeBudget(state) {
|
|
|
751
985
|
);
|
|
752
986
|
}
|
|
753
987
|
}
|
|
754
|
-
function
|
|
988
|
+
function limitOpenPaths(paths) {
|
|
989
|
+
if (paths.length > MAX_PATHS) {
|
|
990
|
+
throw new PathBudgetExceeded(
|
|
991
|
+
`path budget exceeded, more than ${MAX_PATHS} paths`
|
|
992
|
+
);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
function recordTerminal(ctx, terminal, home, path10) {
|
|
755
996
|
chargeBudget(ctx.state);
|
|
756
|
-
const info = classify(
|
|
997
|
+
const info = classify(path10, home, ctx.isAncestorOrSelf);
|
|
757
998
|
const existing = ctx.state.byTerminal.get(terminal) ?? [];
|
|
758
999
|
existing.push(info);
|
|
759
1000
|
ctx.state.byTerminal.set(terminal, existing);
|
|
@@ -764,15 +1005,15 @@ function containsTerminal(ctx, stmt) {
|
|
|
764
1005
|
}
|
|
765
1006
|
return childrenOf(stmt).some((child) => containsTerminal(ctx, child));
|
|
766
1007
|
}
|
|
767
|
-
function stepIf(stmt,
|
|
1008
|
+
function stepIf(stmt, path10, ctx) {
|
|
768
1009
|
const thenExit = exitKindOfList(stmt.thenBody);
|
|
769
1010
|
const elseExit = stmt.elseBody === null ? null : exitKindOfList(stmt.elseBody);
|
|
770
1011
|
const thenPath = [
|
|
771
|
-
...
|
|
1012
|
+
...path10,
|
|
772
1013
|
branchCond(stmt, stmt.condition, "positive", elseExit)
|
|
773
1014
|
];
|
|
774
1015
|
const elsePath = [
|
|
775
|
-
...
|
|
1016
|
+
...path10,
|
|
776
1017
|
branchCond(
|
|
777
1018
|
stmt,
|
|
778
1019
|
stmt.condition,
|
|
@@ -789,7 +1030,7 @@ function stepIf(stmt, path6, ctx) {
|
|
|
789
1030
|
}
|
|
790
1031
|
return out;
|
|
791
1032
|
}
|
|
792
|
-
function stepSwitch(stmt,
|
|
1033
|
+
function stepSwitch(stmt, path10, ctx) {
|
|
793
1034
|
const out = [];
|
|
794
1035
|
const negations = [];
|
|
795
1036
|
let defaultRanBody = false;
|
|
@@ -799,7 +1040,7 @@ function stepSwitch(stmt, path6, ctx) {
|
|
|
799
1040
|
if (hasStrayBreak(group.body)) {
|
|
800
1041
|
throw new UnmodeledFlow("non-trailing break in switch clause");
|
|
801
1042
|
}
|
|
802
|
-
const groupPath = group.condition === null ? [...
|
|
1043
|
+
const groupPath = group.condition === null ? [...path10, ...negations] : [...path10, fixedCond(group.condition, "positive", "explicit")];
|
|
803
1044
|
const conts = enumerate(ctx, group.body, groupPath);
|
|
804
1045
|
if (conts.length > 0) {
|
|
805
1046
|
if (!group.hasTrailingBreak && !fallthroughSafe) {
|
|
@@ -816,24 +1057,24 @@ function stepSwitch(stmt, path6, ctx) {
|
|
|
816
1057
|
}
|
|
817
1058
|
}
|
|
818
1059
|
if (!defaultRanBody) {
|
|
819
|
-
out.push([...
|
|
1060
|
+
out.push([...path10, ...negations]);
|
|
820
1061
|
}
|
|
821
1062
|
return out;
|
|
822
1063
|
}
|
|
823
|
-
function stepLoop(stmt,
|
|
1064
|
+
function stepLoop(stmt, path10, ctx) {
|
|
824
1065
|
const bodyExit = exitKindOfList(stmt.body);
|
|
825
1066
|
if (containsTerminal(ctx, stmt)) {
|
|
826
1067
|
enumerate(ctx, stmt.body, [
|
|
827
|
-
...
|
|
1068
|
+
...path10,
|
|
828
1069
|
loopIterationCond(stmt.condition.sourceText)
|
|
829
1070
|
]);
|
|
830
1071
|
}
|
|
831
1072
|
if (bodyExit !== null) {
|
|
832
|
-
return [[...
|
|
1073
|
+
return [[...path10, loopCompletedCond(stmt.condition.sourceText, bodyExit)]];
|
|
833
1074
|
}
|
|
834
|
-
return [
|
|
1075
|
+
return [path10];
|
|
835
1076
|
}
|
|
836
|
-
function stepTry(stmt,
|
|
1077
|
+
function stepTry(stmt, path10, ctx) {
|
|
837
1078
|
if (stmt.finallyBody !== null) {
|
|
838
1079
|
const finallyHasTerminal = stmt.finallyBody.some(
|
|
839
1080
|
(s) => containsTerminal(ctx, s)
|
|
@@ -843,22 +1084,22 @@ function stepTry(stmt, path6, ctx) {
|
|
|
843
1084
|
}
|
|
844
1085
|
}
|
|
845
1086
|
const out = [];
|
|
846
|
-
out.push(...enumerate(ctx, stmt.tryBody,
|
|
1087
|
+
out.push(...enumerate(ctx, stmt.tryBody, path10));
|
|
847
1088
|
if (stmt.catchBody !== null) {
|
|
848
|
-
const catchPath = [...
|
|
1089
|
+
const catchPath = [...path10, catchEntryCond()];
|
|
849
1090
|
out.push(...enumerate(ctx, stmt.catchBody, catchPath));
|
|
850
1091
|
}
|
|
851
1092
|
return out;
|
|
852
1093
|
}
|
|
853
|
-
function stepExit(stmt,
|
|
1094
|
+
function stepExit(stmt, path10, ctx) {
|
|
854
1095
|
const collector = ctx.state.callbackExits[ctx.state.callbackExits.length - 1];
|
|
855
1096
|
if (collector !== void 0 && (stmt.exit === "return" || stmt.exit === "throw")) {
|
|
856
|
-
collector.push(
|
|
1097
|
+
collector.push(path10);
|
|
857
1098
|
}
|
|
858
1099
|
return [];
|
|
859
1100
|
}
|
|
860
|
-
function stepOpaque(_stmt,
|
|
861
|
-
return [
|
|
1101
|
+
function stepOpaque(_stmt, path10, _ctx) {
|
|
1102
|
+
return [path10];
|
|
862
1103
|
}
|
|
863
1104
|
var stepHandlers = {
|
|
864
1105
|
if: stepIf,
|
|
@@ -868,22 +1109,23 @@ var stepHandlers = {
|
|
|
868
1109
|
exit: stepExit,
|
|
869
1110
|
opaque: stepOpaque
|
|
870
1111
|
};
|
|
871
|
-
function stepCallback(ctx, body,
|
|
1112
|
+
function stepCallback(ctx, body, path10) {
|
|
872
1113
|
const exits = [];
|
|
873
1114
|
ctx.state.callbackExits.push(exits);
|
|
874
1115
|
let fellThrough;
|
|
875
1116
|
try {
|
|
876
|
-
fellThrough = enumerate(ctx, body,
|
|
1117
|
+
fellThrough = enumerate(ctx, body, path10);
|
|
877
1118
|
} finally {
|
|
878
1119
|
ctx.state.callbackExits.pop();
|
|
879
1120
|
}
|
|
880
1121
|
const out = [...fellThrough, ...exits];
|
|
881
|
-
return out.length === 0 ? [
|
|
1122
|
+
return out.length === 0 ? [path10] : out;
|
|
882
1123
|
}
|
|
883
|
-
function stepStatement(ctx, stmt,
|
|
884
|
-
let paths = [
|
|
1124
|
+
function stepStatement(ctx, stmt, path10) {
|
|
1125
|
+
let paths = [path10];
|
|
885
1126
|
for (const body of stmt.callbacks ?? []) {
|
|
886
1127
|
paths = paths.flatMap((each) => stepCallback(ctx, body, each));
|
|
1128
|
+
limitOpenPaths(paths);
|
|
887
1129
|
}
|
|
888
1130
|
const ownTerminals = ctx.terminalsByStmt.get(stmt) ?? [];
|
|
889
1131
|
for (const each of withRejoined(paths)) {
|
|
@@ -900,7 +1142,7 @@ function stepStatement(ctx, stmt, path6) {
|
|
|
900
1142
|
)
|
|
901
1143
|
);
|
|
902
1144
|
}
|
|
903
|
-
function soleDisagreement(left, right) {
|
|
1145
|
+
function soleDisagreement(left, right, keepsArms) {
|
|
904
1146
|
if (left.length !== right.length) {
|
|
905
1147
|
return null;
|
|
906
1148
|
}
|
|
@@ -919,9 +1161,10 @@ function soleDisagreement(left, right) {
|
|
|
919
1161
|
}
|
|
920
1162
|
found = at;
|
|
921
1163
|
}
|
|
922
|
-
|
|
1164
|
+
const test = found === null ? null : left[found]?.info.expression ?? null;
|
|
1165
|
+
return test !== null && keepsArms(test) ? null : found;
|
|
923
1166
|
}
|
|
924
|
-
function mergeRejoined(paths) {
|
|
1167
|
+
function mergeRejoined(paths, keepsArms = KEEPS_NO_ARMS) {
|
|
925
1168
|
let current = paths;
|
|
926
1169
|
for (let round = 0; round < current.length; round++) {
|
|
927
1170
|
const out = [];
|
|
@@ -936,7 +1179,11 @@ function mergeRejoined(paths) {
|
|
|
936
1179
|
if (taken.has(j)) {
|
|
937
1180
|
continue;
|
|
938
1181
|
}
|
|
939
|
-
const at = soleDisagreement(
|
|
1182
|
+
const at = soleDisagreement(
|
|
1183
|
+
combined,
|
|
1184
|
+
current[j],
|
|
1185
|
+
keepsArms
|
|
1186
|
+
);
|
|
940
1187
|
if (at === null) {
|
|
941
1188
|
continue;
|
|
942
1189
|
}
|
|
@@ -962,21 +1209,18 @@ function enumerate(ctx, stmts, prefix) {
|
|
|
962
1209
|
let frontiers = [[...prefix]];
|
|
963
1210
|
for (const stmt of stmts) {
|
|
964
1211
|
const nextFrontiers = [];
|
|
965
|
-
for (const
|
|
966
|
-
nextFrontiers.push(...stepStatement(ctx, stmt,
|
|
1212
|
+
for (const path10 of mergeRejoined(frontiers, ctx.keepsArms)) {
|
|
1213
|
+
nextFrontiers.push(...stepStatement(ctx, stmt, path10));
|
|
967
1214
|
}
|
|
968
1215
|
frontiers = nextFrontiers;
|
|
969
|
-
|
|
970
|
-
throw new PathBudgetExceeded(
|
|
971
|
-
`path budget exceeded, more than ${MAX_PATHS} paths`
|
|
972
|
-
);
|
|
973
|
-
}
|
|
1216
|
+
limitOpenPaths(frontiers);
|
|
974
1217
|
if (frontiers.length === 0) {
|
|
975
1218
|
break;
|
|
976
1219
|
}
|
|
977
1220
|
}
|
|
978
1221
|
return frontiers;
|
|
979
1222
|
}
|
|
1223
|
+
var KEEPS_NO_ARMS = () => false;
|
|
980
1224
|
function buildParentMap(statements) {
|
|
981
1225
|
const parentOf = /* @__PURE__ */ new Map();
|
|
982
1226
|
const visit = (stmt, parent) => {
|
|
@@ -1010,13 +1254,14 @@ function enumerateStructuredPaths(input) {
|
|
|
1010
1254
|
};
|
|
1011
1255
|
const ctx = {
|
|
1012
1256
|
terminalsByStmt: input.terminalsByStmt,
|
|
1257
|
+
keepsArms: input.keepsArms ?? KEEPS_NO_ARMS,
|
|
1013
1258
|
state,
|
|
1014
1259
|
isAncestorOrSelf
|
|
1015
1260
|
};
|
|
1016
1261
|
const continuations = withRejoined(enumerate(ctx, input.statements, []));
|
|
1017
|
-
for (const
|
|
1262
|
+
for (const path10 of continuations) {
|
|
1018
1263
|
chargeBudget(state);
|
|
1019
|
-
state.fallthrough.push(classify(
|
|
1264
|
+
state.fallthrough.push(classify(path10, null, isAncestorOrSelf));
|
|
1020
1265
|
}
|
|
1021
1266
|
return { byTerminal: state.byTerminal, fallthrough: state.fallthrough };
|
|
1022
1267
|
}
|
|
@@ -1059,8 +1304,8 @@ function sharedGatingConditions(paths, readPredicate) {
|
|
|
1059
1304
|
return [];
|
|
1060
1305
|
}
|
|
1061
1306
|
const shared = new Set(first.map(keyOf2));
|
|
1062
|
-
for (const
|
|
1063
|
-
const here = new Set(
|
|
1307
|
+
for (const path10 of rest) {
|
|
1308
|
+
const here = new Set(path10.map(keyOf2));
|
|
1064
1309
|
for (const value of shared) {
|
|
1065
1310
|
if (!here.has(value)) {
|
|
1066
1311
|
shared.delete(value);
|
|
@@ -1168,15 +1413,12 @@ var EnclosingNodes = class {
|
|
|
1168
1413
|
|
|
1169
1414
|
// src/paths/nodeWalk.ts
|
|
1170
1415
|
var SKIP_CHILDREN = /* @__PURE__ */ Symbol("skipChildren");
|
|
1171
|
-
function walkDescendants(root, carried, visitor) {
|
|
1172
|
-
for (const child of root
|
|
1173
|
-
if (child === null) {
|
|
1174
|
-
continue;
|
|
1175
|
-
}
|
|
1416
|
+
function walkDescendants(root, carried, childrenOf2, visitor) {
|
|
1417
|
+
for (const child of childrenOf2(root)) {
|
|
1176
1418
|
visitor.at(child, carried);
|
|
1177
1419
|
const inner = visitor.into(child, carried);
|
|
1178
1420
|
if (inner !== SKIP_CHILDREN) {
|
|
1179
|
-
walkDescendants(child, inner, visitor);
|
|
1421
|
+
walkDescendants(child, inner, childrenOf2, visitor);
|
|
1180
1422
|
}
|
|
1181
1423
|
}
|
|
1182
1424
|
}
|
|
@@ -1255,6 +1497,11 @@ function valueToReadFurtherFrom(reading) {
|
|
|
1255
1497
|
return reading.kind === "written" ? reading.value : null;
|
|
1256
1498
|
}
|
|
1257
1499
|
|
|
1500
|
+
// src/redirectOption.ts
|
|
1501
|
+
function redirectDeliveryWhenSet(option, value) {
|
|
1502
|
+
return option.handsBack.includes(value) ? "response" : "followed";
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1258
1505
|
// src/testFiles.ts
|
|
1259
1506
|
function isListedTestFile(file, listed) {
|
|
1260
1507
|
if (listed === void 0) {
|
|
@@ -1324,17 +1571,179 @@ function quoted(text, key) {
|
|
|
1324
1571
|
}
|
|
1325
1572
|
|
|
1326
1573
|
// src/adapterStamp.ts
|
|
1574
|
+
import { createHash as createHash2 } from "crypto";
|
|
1575
|
+
import fs3 from "fs";
|
|
1576
|
+
import path5 from "path";
|
|
1577
|
+
import { fileURLToPath } from "url";
|
|
1578
|
+
|
|
1579
|
+
// src/codeHash.ts
|
|
1327
1580
|
import { createHash } from "crypto";
|
|
1328
1581
|
import fs2 from "fs";
|
|
1329
1582
|
import { createRequire } from "module";
|
|
1330
1583
|
import path4 from "path";
|
|
1331
|
-
|
|
1332
|
-
var
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1584
|
+
var SUSS_SCOPE = "@suss/";
|
|
1585
|
+
var IMPORT_FORMS = /\b(?:from|import)\s*\(?\s*["']([^"'\s]+)["']|require\s*\(\s*["']([^"'\s]+)["']/g;
|
|
1586
|
+
var CONDITIONS = {
|
|
1587
|
+
import: /* @__PURE__ */ new Set(["import", "node", "default"]),
|
|
1588
|
+
require: /* @__PURE__ */ new Set(["require", "node", "default"])
|
|
1589
|
+
};
|
|
1590
|
+
function createCodeHasher() {
|
|
1591
|
+
const read = /* @__PURE__ */ new Map();
|
|
1592
|
+
function readOnce(file) {
|
|
1593
|
+
const known = read.get(file);
|
|
1594
|
+
if (known !== void 0) {
|
|
1595
|
+
return known;
|
|
1596
|
+
}
|
|
1597
|
+
const found = readCodeFile(file);
|
|
1598
|
+
read.set(file, found);
|
|
1599
|
+
return found;
|
|
1600
|
+
}
|
|
1601
|
+
function codeFiles(entryFile) {
|
|
1602
|
+
const entry = realFile(entryFile);
|
|
1603
|
+
if (entry === null || readOnce(entry) === null) {
|
|
1604
|
+
return [];
|
|
1605
|
+
}
|
|
1606
|
+
const found = [entry];
|
|
1607
|
+
const seen = new Set(found);
|
|
1608
|
+
for (let at = 0; at < found.length; at++) {
|
|
1609
|
+
for (const next of readOnce(found[at])?.imports ?? []) {
|
|
1610
|
+
if (seen.has(next)) {
|
|
1611
|
+
continue;
|
|
1612
|
+
}
|
|
1613
|
+
seen.add(next);
|
|
1614
|
+
if (readOnce(next) !== null) {
|
|
1615
|
+
found.push(next);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
return found;
|
|
1620
|
+
}
|
|
1621
|
+
function codeHash(entryFile) {
|
|
1622
|
+
const files = codeFiles(entryFile);
|
|
1623
|
+
if (files.length === 0) {
|
|
1624
|
+
return "";
|
|
1625
|
+
}
|
|
1626
|
+
const hash = createHash("sha256");
|
|
1627
|
+
for (const file of files) {
|
|
1628
|
+
hash.update(read.get(file)?.digest ?? "");
|
|
1629
|
+
}
|
|
1630
|
+
return hash.digest("hex").slice(0, 16);
|
|
1631
|
+
}
|
|
1632
|
+
return { codeFiles, codeHash };
|
|
1633
|
+
}
|
|
1634
|
+
var processCodeHasher = createCodeHasher();
|
|
1635
|
+
function readCodeFile(file) {
|
|
1636
|
+
let text;
|
|
1637
|
+
try {
|
|
1638
|
+
text = fs2.readFileSync(file);
|
|
1639
|
+
} catch {
|
|
1640
|
+
return null;
|
|
1641
|
+
}
|
|
1642
|
+
return {
|
|
1643
|
+
digest: createHash("sha256").update(text).digest("hex"),
|
|
1644
|
+
imports: importsOf(file, text.toString("utf8"))
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
function importsOf(file, text) {
|
|
1648
|
+
const asked = /* @__PURE__ */ new Set();
|
|
1649
|
+
const found = [];
|
|
1650
|
+
for (const match of text.matchAll(IMPORT_FORMS)) {
|
|
1651
|
+
const kind = match[1] === void 0 ? "require" : "import";
|
|
1652
|
+
const specifier = match[1] ?? match[2] ?? "";
|
|
1653
|
+
if (asked.has(`${kind} ${specifier}`)) {
|
|
1654
|
+
continue;
|
|
1655
|
+
}
|
|
1656
|
+
asked.add(`${kind} ${specifier}`);
|
|
1657
|
+
const target = resolveImport(specifier, file, kind);
|
|
1658
|
+
if (target !== null) {
|
|
1659
|
+
found.push(target);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
return found;
|
|
1663
|
+
}
|
|
1664
|
+
function resolveImport(specifier, fromFile, kind) {
|
|
1665
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
1666
|
+
return realFile(path4.resolve(path4.dirname(fromFile), specifier));
|
|
1667
|
+
}
|
|
1668
|
+
if (specifier.startsWith(SUSS_SCOPE)) {
|
|
1669
|
+
return resolvePackageImport(specifier, fromFile, kind);
|
|
1670
|
+
}
|
|
1671
|
+
return null;
|
|
1672
|
+
}
|
|
1673
|
+
function resolvePackageImport(specifier, fromFile, kind) {
|
|
1674
|
+
const [scope = "", name = "", ...rest] = specifier.split("/");
|
|
1675
|
+
const packageName = `${scope}/${name}`;
|
|
1676
|
+
const subpath = rest.length === 0 ? "." : `./${rest.join("/")}`;
|
|
1677
|
+
const lookIn = createRequire(fromFile).resolve.paths(packageName) ?? [];
|
|
1678
|
+
for (const dir of lookIn) {
|
|
1679
|
+
const packageDir = path4.join(dir, packageName);
|
|
1680
|
+
const manifest = readManifest(packageDir);
|
|
1681
|
+
if (manifest === null) {
|
|
1682
|
+
continue;
|
|
1683
|
+
}
|
|
1684
|
+
const target = exportTarget(manifest, subpath, CONDITIONS[kind]);
|
|
1685
|
+
return target === null ? null : realFile(path4.join(packageDir, target));
|
|
1686
|
+
}
|
|
1687
|
+
return null;
|
|
1688
|
+
}
|
|
1689
|
+
function readManifest(packageDir) {
|
|
1690
|
+
try {
|
|
1691
|
+
return JSON.parse(
|
|
1692
|
+
fs2.readFileSync(path4.join(packageDir, "package.json"), "utf8")
|
|
1693
|
+
);
|
|
1694
|
+
} catch {
|
|
1695
|
+
return null;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
function exportTarget(manifest, subpath, conditions) {
|
|
1699
|
+
if (manifest.exports === void 0) {
|
|
1700
|
+
return subpath === "." ? manifest.main ?? "index.js" : subpath;
|
|
1701
|
+
}
|
|
1702
|
+
return conditionalTarget(subpathEntry(manifest.exports, subpath), conditions);
|
|
1703
|
+
}
|
|
1704
|
+
function subpathEntry(exportsField, subpath) {
|
|
1705
|
+
const isSubpathMap = typeof exportsField === "object" && exportsField !== null && !Array.isArray(exportsField) && Object.keys(exportsField).some((key) => key.startsWith("."));
|
|
1706
|
+
if (isSubpathMap) {
|
|
1707
|
+
return exportsField[subpath];
|
|
1708
|
+
}
|
|
1709
|
+
return subpath === "." ? exportsField : void 0;
|
|
1710
|
+
}
|
|
1711
|
+
function conditionalTarget(value, conditions) {
|
|
1712
|
+
if (typeof value === "string") {
|
|
1713
|
+
return value;
|
|
1714
|
+
}
|
|
1715
|
+
if (Array.isArray(value)) {
|
|
1716
|
+
for (const each of value) {
|
|
1717
|
+
const found = conditionalTarget(each, conditions);
|
|
1718
|
+
if (found !== null) {
|
|
1719
|
+
return found;
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
return null;
|
|
1723
|
+
}
|
|
1724
|
+
if (value === null || typeof value !== "object") {
|
|
1725
|
+
return null;
|
|
1726
|
+
}
|
|
1727
|
+
for (const [condition, target] of Object.entries(value)) {
|
|
1728
|
+
if (!conditions.has(condition)) {
|
|
1729
|
+
continue;
|
|
1730
|
+
}
|
|
1731
|
+
const found = conditionalTarget(target, conditions);
|
|
1732
|
+
if (found !== null) {
|
|
1733
|
+
return found;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
return null;
|
|
1737
|
+
}
|
|
1738
|
+
function realFile(file) {
|
|
1739
|
+
try {
|
|
1740
|
+
return fs2.realpathSync(file);
|
|
1741
|
+
} catch {
|
|
1742
|
+
return null;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
// src/adapterStamp.ts
|
|
1338
1747
|
var SOURCE_STAMP = { kind: "source" };
|
|
1339
1748
|
function createAdapterStamp(config) {
|
|
1340
1749
|
let cachedCodeStamp = null;
|
|
@@ -1369,19 +1778,19 @@ function createAdapterStamp(config) {
|
|
|
1369
1778
|
function readAdapterCodeStamp(moduleUrl) {
|
|
1370
1779
|
try {
|
|
1371
1780
|
const selfPath = fileURLToPath(moduleUrl);
|
|
1372
|
-
const hash = computeDistHashFrom(
|
|
1781
|
+
const hash = computeDistHashFrom(path5.dirname(selfPath), processCodeHasher);
|
|
1373
1782
|
return hash.length > 0 ? { kind: "bundle", hash } : SOURCE_STAMP;
|
|
1374
1783
|
} catch {
|
|
1375
1784
|
return SOURCE_STAMP;
|
|
1376
1785
|
}
|
|
1377
1786
|
}
|
|
1378
|
-
function computeDistHashFrom(dir) {
|
|
1379
|
-
const candidates = [
|
|
1787
|
+
function computeDistHashFrom(dir, hasher = createCodeHasher()) {
|
|
1788
|
+
const candidates = [path5.join(dir, "index.js"), path5.join(dir, "index.cjs")];
|
|
1380
1789
|
for (const candidate of candidates) {
|
|
1381
|
-
if (!
|
|
1790
|
+
if (!fs3.existsSync(candidate)) {
|
|
1382
1791
|
continue;
|
|
1383
1792
|
}
|
|
1384
|
-
return
|
|
1793
|
+
return hasher.codeHash(candidate);
|
|
1385
1794
|
}
|
|
1386
1795
|
return "";
|
|
1387
1796
|
}
|
|
@@ -1389,10 +1798,10 @@ function computeContentHash(paths) {
|
|
|
1389
1798
|
if (paths.length === 0) {
|
|
1390
1799
|
return "";
|
|
1391
1800
|
}
|
|
1392
|
-
const hash =
|
|
1801
|
+
const hash = createHash2("sha256");
|
|
1393
1802
|
for (const file of paths) {
|
|
1394
1803
|
try {
|
|
1395
|
-
hash.update(
|
|
1804
|
+
hash.update(fs3.readFileSync(file));
|
|
1396
1805
|
} catch {
|
|
1397
1806
|
return "";
|
|
1398
1807
|
}
|
|
@@ -1403,12 +1812,12 @@ function projectFileStamp(paths) {
|
|
|
1403
1812
|
if (paths.length === 0) {
|
|
1404
1813
|
return "none";
|
|
1405
1814
|
}
|
|
1406
|
-
const hash =
|
|
1815
|
+
const hash = createHash2("sha256");
|
|
1407
1816
|
for (const file of [...paths].sort()) {
|
|
1408
1817
|
hash.update(file);
|
|
1409
1818
|
hash.update("\0");
|
|
1410
1819
|
try {
|
|
1411
|
-
hash.update(
|
|
1820
|
+
hash.update(fs3.readFileSync(file));
|
|
1412
1821
|
} catch {
|
|
1413
1822
|
hash.update("absent");
|
|
1414
1823
|
}
|
|
@@ -1421,8 +1830,9 @@ function extractionConfigStamp(config) {
|
|
|
1421
1830
|
["includeReachable", optionalText(config.includeReachable)],
|
|
1422
1831
|
["workspaceRoot", config.workspaceRoot],
|
|
1423
1832
|
["projectRoot", config.projectRoot],
|
|
1424
|
-
["importRoots", config.importRoots?.join(
|
|
1425
|
-
["modules", modulesStamp(config.modules)]
|
|
1833
|
+
["importRoots", config.importRoots?.join(path5.delimiter)],
|
|
1834
|
+
["modules", modulesStamp(config.modules)],
|
|
1835
|
+
["walkedDirectory", config.walkedDirectory]
|
|
1426
1836
|
];
|
|
1427
1837
|
return parts.flatMap(
|
|
1428
1838
|
([name, value]) => value === void 0 ? [] : [`${name}=${value}`]
|
|
@@ -1435,26 +1845,288 @@ function runDigest(packsDigest, packs, files) {
|
|
|
1435
1845
|
const inputs = packs.flatMap((pack) => pack.discoveryInputs?.(files) ?? []);
|
|
1436
1846
|
return `${packsDigest}|reads:${projectFileStamp(inputs)}`;
|
|
1437
1847
|
}
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1848
|
+
|
|
1849
|
+
// src/cache.ts
|
|
1850
|
+
import { createHash as createHash5 } from "crypto";
|
|
1851
|
+
import fs7 from "fs/promises";
|
|
1852
|
+
import path8 from "path";
|
|
1853
|
+
import { readJsonFile as readJsonFile3, writeDocumentFile as writeDocumentFile2 } from "@suss/behavioral-ir/files";
|
|
1854
|
+
|
|
1855
|
+
// src/cacheIndex.ts
|
|
1856
|
+
import { BOUNDARY_ROLE, displayLabel } from "@suss/behavioral-ir";
|
|
1857
|
+
import { readJsonFile, writeDocumentFile } from "@suss/behavioral-ir/files";
|
|
1858
|
+
function entriesOf(units) {
|
|
1859
|
+
const boundaries = [];
|
|
1860
|
+
const callees = [];
|
|
1861
|
+
units.forEach((summary, unit) => {
|
|
1862
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1863
|
+
const add = (key, role) => {
|
|
1864
|
+
if (key !== null && !seen.has(`${role} ${key}`)) {
|
|
1865
|
+
seen.add(`${role} ${key}`);
|
|
1866
|
+
boundaries.push([key, unit, role]);
|
|
1867
|
+
}
|
|
1868
|
+
};
|
|
1869
|
+
const own = summary.identity?.boundaryBinding ?? null;
|
|
1870
|
+
if (own !== null) {
|
|
1871
|
+
add(
|
|
1872
|
+
keyOf3(own),
|
|
1873
|
+
BOUNDARY_ROLE[summary.kind] === "provider" ? "serves" : "calls"
|
|
1874
|
+
);
|
|
1875
|
+
}
|
|
1876
|
+
const spellings = /* @__PURE__ */ new Set();
|
|
1877
|
+
for (const transition of summary.transitions ?? []) {
|
|
1878
|
+
for (const effect of transition.effects ?? []) {
|
|
1879
|
+
if (effect.type === "interaction") {
|
|
1880
|
+
add(keyOf3(effect.binding), "calls");
|
|
1881
|
+
}
|
|
1882
|
+
if (effect.type === "invocation") {
|
|
1883
|
+
spellings.add(effect.callee);
|
|
1884
|
+
}
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
for (const spelling of spellings) {
|
|
1888
|
+
callees.push([spelling, unit]);
|
|
1889
|
+
}
|
|
1890
|
+
});
|
|
1891
|
+
return { boundaries, callees };
|
|
1892
|
+
}
|
|
1893
|
+
function indexOf(shards) {
|
|
1894
|
+
const boundaries = {};
|
|
1895
|
+
const callees = {};
|
|
1896
|
+
shards.forEach(({ entries }, file) => {
|
|
1897
|
+
for (const [key, unit, role] of entries.boundaries) {
|
|
1898
|
+
listAt(boundaries, key).push([file, unit, role]);
|
|
1899
|
+
}
|
|
1900
|
+
for (const [spelling, unit] of entries.callees) {
|
|
1901
|
+
listAt(callees, spelling).push([file, unit]);
|
|
1902
|
+
}
|
|
1903
|
+
});
|
|
1904
|
+
return {
|
|
1905
|
+
files: shards.map(({ file, id }) => [file, id]),
|
|
1906
|
+
boundaries,
|
|
1907
|
+
callees
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
function listAt(record, key) {
|
|
1911
|
+
const existing = Object.hasOwn(record, key) ? record[key] : void 0;
|
|
1912
|
+
if (existing !== void 0) {
|
|
1913
|
+
return existing;
|
|
1914
|
+
}
|
|
1915
|
+
const created = [];
|
|
1916
|
+
record[key] = created;
|
|
1917
|
+
return created;
|
|
1918
|
+
}
|
|
1919
|
+
function entriesByShard(index) {
|
|
1920
|
+
const byShard = /* @__PURE__ */ new Map();
|
|
1921
|
+
const at = index.files.map(([, id]) => {
|
|
1922
|
+
const entries = { boundaries: [], callees: [] };
|
|
1923
|
+
byShard.set(id, entries);
|
|
1924
|
+
return entries;
|
|
1925
|
+
});
|
|
1926
|
+
for (const [key, units] of Object.entries(index.boundaries)) {
|
|
1927
|
+
for (const [file, unit, role] of units) {
|
|
1928
|
+
at[file]?.boundaries.push([key, unit, role]);
|
|
1445
1929
|
}
|
|
1446
1930
|
}
|
|
1447
|
-
|
|
1931
|
+
for (const [spelling, units] of Object.entries(index.callees)) {
|
|
1932
|
+
for (const [file, unit] of units) {
|
|
1933
|
+
at[file]?.callees.push([spelling, unit]);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
return byShard;
|
|
1937
|
+
}
|
|
1938
|
+
function readStoreIndex(file) {
|
|
1939
|
+
try {
|
|
1940
|
+
const index = readJsonFile(file);
|
|
1941
|
+
return Array.isArray(index.files) ? index : null;
|
|
1942
|
+
} catch {
|
|
1943
|
+
return null;
|
|
1944
|
+
}
|
|
1945
|
+
}
|
|
1946
|
+
function writeStoreIndex(file, index) {
|
|
1947
|
+
writeDocumentFile(file, index);
|
|
1948
|
+
}
|
|
1949
|
+
function keyOf3(binding) {
|
|
1950
|
+
try {
|
|
1951
|
+
return displayLabel(binding);
|
|
1952
|
+
} catch {
|
|
1953
|
+
return null;
|
|
1954
|
+
}
|
|
1448
1955
|
}
|
|
1449
1956
|
|
|
1450
|
-
// src/
|
|
1957
|
+
// src/cacheShards.ts
|
|
1451
1958
|
import { createHash as createHash3 } from "crypto";
|
|
1452
|
-
import fs4 from "fs
|
|
1453
|
-
import
|
|
1959
|
+
import fs4 from "fs";
|
|
1960
|
+
import path6 from "path";
|
|
1961
|
+
import {
|
|
1962
|
+
documentPieces,
|
|
1963
|
+
readJsonFile as readJsonFile2,
|
|
1964
|
+
writeFileAtomically
|
|
1965
|
+
} from "@suss/behavioral-ir/files";
|
|
1966
|
+
var SHARDS_DIR = "shards";
|
|
1967
|
+
var RECORDS_DIR = "records";
|
|
1968
|
+
var STORED_ID = /^[0-9a-f]{32}\.json$/;
|
|
1969
|
+
function writeShard(entryDir, content) {
|
|
1970
|
+
return writeOnce(path6.join(entryDir, SHARDS_DIR), interned(content));
|
|
1971
|
+
}
|
|
1972
|
+
function readShard(entryDir, id, file) {
|
|
1973
|
+
const stored = readStored(path6.join(entryDir, SHARDS_DIR), id);
|
|
1974
|
+
if (stored?.file !== file || !Array.isArray(stored.units)) {
|
|
1975
|
+
return null;
|
|
1976
|
+
}
|
|
1977
|
+
const take = takerFor(stored.intern ?? []);
|
|
1978
|
+
return {
|
|
1979
|
+
file: stored.file,
|
|
1980
|
+
units: stored.units.map((unit) => expanded(unit, take))
|
|
1981
|
+
};
|
|
1982
|
+
}
|
|
1983
|
+
function writeRecord(entryDir, meta) {
|
|
1984
|
+
return writeOnce(path6.join(entryDir, RECORDS_DIR), { meta });
|
|
1985
|
+
}
|
|
1986
|
+
function readRecord(entryDir, id) {
|
|
1987
|
+
const stored = readStored(path6.join(entryDir, RECORDS_DIR), id);
|
|
1988
|
+
return typeof stored === "object" && stored !== null ? stored : null;
|
|
1989
|
+
}
|
|
1990
|
+
function recordReader(entryDir) {
|
|
1991
|
+
const opened = /* @__PURE__ */ new Map();
|
|
1992
|
+
return (id) => {
|
|
1993
|
+
if (!opened.has(id)) {
|
|
1994
|
+
const record2 = readRecord(entryDir, id);
|
|
1995
|
+
opened.set(id, record2);
|
|
1996
|
+
return record2;
|
|
1997
|
+
}
|
|
1998
|
+
const record = opened.get(id) ?? null;
|
|
1999
|
+
return record === null ? null : copyOfJson(record);
|
|
2000
|
+
};
|
|
2001
|
+
}
|
|
2002
|
+
function removeStoredOutside(entryDir, keep) {
|
|
2003
|
+
for (const kind of [SHARDS_DIR, RECORDS_DIR]) {
|
|
2004
|
+
const root = path6.join(entryDir, kind);
|
|
2005
|
+
for (const prefix of namesIn(root)) {
|
|
2006
|
+
const dir = path6.join(root, prefix);
|
|
2007
|
+
for (const name of namesIn(dir)) {
|
|
2008
|
+
if (STORED_ID.test(name) && !keep.has(name.slice(0, -".json".length))) {
|
|
2009
|
+
fs4.rmSync(path6.join(dir, name), { force: true });
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
function namesIn(dir) {
|
|
2016
|
+
try {
|
|
2017
|
+
return fs4.readdirSync(dir);
|
|
2018
|
+
} catch {
|
|
2019
|
+
return [];
|
|
2020
|
+
}
|
|
2021
|
+
}
|
|
2022
|
+
function writeOnce(root, value) {
|
|
2023
|
+
const pieces = [...documentPieces(value)];
|
|
2024
|
+
const hash = createHash3("sha256");
|
|
2025
|
+
for (const piece of pieces) {
|
|
2026
|
+
hash.update(piece);
|
|
2027
|
+
}
|
|
2028
|
+
const id = hash.digest("hex").slice(0, 32);
|
|
2029
|
+
const file = storedPath(root, id);
|
|
2030
|
+
if (!fs4.existsSync(file)) {
|
|
2031
|
+
writeFileAtomically(file, pieces);
|
|
2032
|
+
}
|
|
2033
|
+
return id;
|
|
2034
|
+
}
|
|
2035
|
+
function readStored(root, id) {
|
|
2036
|
+
try {
|
|
2037
|
+
return readJsonFile2(storedPath(root, id));
|
|
2038
|
+
} catch {
|
|
2039
|
+
return void 0;
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
function storedPath(root, id) {
|
|
2043
|
+
return path6.join(root, id.slice(0, 2), `${id}.json`);
|
|
2044
|
+
}
|
|
2045
|
+
function interned(content) {
|
|
2046
|
+
const intern = [];
|
|
2047
|
+
const byText = /* @__PURE__ */ new Map();
|
|
2048
|
+
const byObject = /* @__PURE__ */ new Map();
|
|
2049
|
+
const positionOf = (value) => {
|
|
2050
|
+
const known = byObject.get(value);
|
|
2051
|
+
if (known !== void 0) {
|
|
2052
|
+
return known;
|
|
2053
|
+
}
|
|
2054
|
+
const text = JSON.stringify(value) ?? "null";
|
|
2055
|
+
let position = byText.get(text);
|
|
2056
|
+
if (position === void 0) {
|
|
2057
|
+
position = intern.length;
|
|
2058
|
+
intern.push(value);
|
|
2059
|
+
byText.set(text, position);
|
|
2060
|
+
}
|
|
2061
|
+
if (typeof value === "object" && value !== null) {
|
|
2062
|
+
byObject.set(value, position);
|
|
2063
|
+
}
|
|
2064
|
+
return position;
|
|
2065
|
+
};
|
|
2066
|
+
const positions = (values) => Array.isArray(values) ? values.map(positionOf) : values;
|
|
2067
|
+
const units = content.units.map((summary) => ({
|
|
2068
|
+
...summary,
|
|
2069
|
+
transitions: summary.transitions.map((transition) => ({
|
|
2070
|
+
...transition,
|
|
2071
|
+
conditions: positions(transition.conditions),
|
|
2072
|
+
effects: positions(transition.effects)
|
|
2073
|
+
})),
|
|
2074
|
+
gaps: summary.gaps.map((gap) => ({
|
|
2075
|
+
...gap,
|
|
2076
|
+
conditions: positions(gap.conditions)
|
|
2077
|
+
}))
|
|
2078
|
+
}));
|
|
2079
|
+
return {
|
|
2080
|
+
file: content.file,
|
|
2081
|
+
intern,
|
|
2082
|
+
units
|
|
2083
|
+
};
|
|
2084
|
+
}
|
|
2085
|
+
function expanded(unit, take) {
|
|
2086
|
+
const values = (positions) => Array.isArray(positions) ? positions.map((at) => take(at)) : positions;
|
|
2087
|
+
const transitions = Array.isArray(unit.transitions) ? unit.transitions : [];
|
|
2088
|
+
const gaps = Array.isArray(unit.gaps) ? unit.gaps : [];
|
|
2089
|
+
return {
|
|
2090
|
+
...unit,
|
|
2091
|
+
transitions: transitions.map((transition) => ({
|
|
2092
|
+
...transition,
|
|
2093
|
+
conditions: values(transition.conditions),
|
|
2094
|
+
effects: values(transition.effects)
|
|
2095
|
+
})),
|
|
2096
|
+
gaps: gaps.map((gap) => ({
|
|
2097
|
+
...gap,
|
|
2098
|
+
conditions: values(gap.conditions)
|
|
2099
|
+
}))
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
function takerFor(intern) {
|
|
2103
|
+
const handedOut = /* @__PURE__ */ new Set();
|
|
2104
|
+
return (position) => {
|
|
2105
|
+
const value = intern[position];
|
|
2106
|
+
if (!handedOut.has(position)) {
|
|
2107
|
+
handedOut.add(position);
|
|
2108
|
+
return value;
|
|
2109
|
+
}
|
|
2110
|
+
return copyOfJson(value);
|
|
2111
|
+
};
|
|
2112
|
+
}
|
|
2113
|
+
function copyOfJson(value) {
|
|
2114
|
+
if (Array.isArray(value)) {
|
|
2115
|
+
return value.map(copyOfJson);
|
|
2116
|
+
}
|
|
2117
|
+
if (typeof value === "object" && value !== null) {
|
|
2118
|
+
const copy = {};
|
|
2119
|
+
for (const key of Object.keys(value)) {
|
|
2120
|
+
copy[key] = copyOfJson(value[key]);
|
|
2121
|
+
}
|
|
2122
|
+
return copy;
|
|
2123
|
+
}
|
|
2124
|
+
return value;
|
|
2125
|
+
}
|
|
1454
2126
|
|
|
1455
2127
|
// src/cacheStamps.ts
|
|
1456
|
-
import { createHash as
|
|
1457
|
-
import
|
|
2128
|
+
import { createHash as createHash4 } from "crypto";
|
|
2129
|
+
import fs5 from "fs/promises";
|
|
1458
2130
|
var RECENT_CHANGE_MS = 2e3;
|
|
1459
2131
|
function stampMayMissAWrite(stat, statAt) {
|
|
1460
2132
|
return Math.max(stat.mtimeMs, stat.ctimeMs) > statAt - RECENT_CHANGE_MS;
|
|
@@ -1475,7 +2147,7 @@ async function startRun(files, configPath) {
|
|
|
1475
2147
|
}
|
|
1476
2148
|
async function statAtStart(filePath) {
|
|
1477
2149
|
try {
|
|
1478
|
-
const stat = await
|
|
2150
|
+
const stat = await fs5.stat(filePath);
|
|
1479
2151
|
return {
|
|
1480
2152
|
stamp: { path: filePath, mtimeMs: stat.mtimeMs, size: stat.size },
|
|
1481
2153
|
ctimeMs: stat.ctimeMs
|
|
@@ -1525,7 +2197,7 @@ async function recordedStamp(start, run, prior) {
|
|
|
1525
2197
|
return start.stamp;
|
|
1526
2198
|
}
|
|
1527
2199
|
const filePath = start.stamp.path;
|
|
1528
|
-
const now = await
|
|
2200
|
+
const now = await fs5.stat(filePath).catch(() => null);
|
|
1529
2201
|
if (now === null || now.mtimeMs !== start.stamp.mtimeMs || now.size !== start.stamp.size || now.ctimeMs !== start.ctimeMs) {
|
|
1530
2202
|
return null;
|
|
1531
2203
|
}
|
|
@@ -1542,8 +2214,8 @@ function reusableHash(prior, stamp) {
|
|
|
1542
2214
|
}
|
|
1543
2215
|
async function hashFile(filePath) {
|
|
1544
2216
|
try {
|
|
1545
|
-
const content = await
|
|
1546
|
-
return
|
|
2217
|
+
const content = await fs5.readFile(filePath);
|
|
2218
|
+
return createHash4("sha256").update(content).digest("hex").slice(0, 16);
|
|
1547
2219
|
} catch {
|
|
1548
2220
|
return null;
|
|
1549
2221
|
}
|
|
@@ -1558,11 +2230,30 @@ function fileStampEquals(a, b) {
|
|
|
1558
2230
|
return a.path === b.path && a.mtimeMs === b.mtimeMs && a.size === b.size;
|
|
1559
2231
|
}
|
|
1560
2232
|
|
|
2233
|
+
// src/ignoredDirectory.ts
|
|
2234
|
+
import fs6 from "fs";
|
|
2235
|
+
import path7 from "path";
|
|
2236
|
+
function makeIgnoredDirectory(dir) {
|
|
2237
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
2238
|
+
const ignore = path7.join(dir, ".gitignore");
|
|
2239
|
+
if (!fs6.existsSync(ignore)) {
|
|
2240
|
+
fs6.writeFileSync(ignore, "*\n");
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
|
|
1561
2244
|
// src/cache.ts
|
|
1562
|
-
var SCHEMA_VERSION = "
|
|
2245
|
+
var SCHEMA_VERSION = "10";
|
|
2246
|
+
var MANIFEST = "manifest.json";
|
|
2247
|
+
var INDEX = "index.json";
|
|
1563
2248
|
var MAX_ENTRIES = 2;
|
|
1564
2249
|
var ENTRY_PREFIX = "key-";
|
|
1565
2250
|
var ENTRY_DIR_NAME = new RegExp(`^${ENTRY_PREFIX}[0-9a-f]{16}$`);
|
|
2251
|
+
function ownersWhereWritten(summaries, walkedFileOf) {
|
|
2252
|
+
return summaries.map((summary) => {
|
|
2253
|
+
const walked = walkedFileOf(summary.location.file);
|
|
2254
|
+
return walked === void 0 ? [] : [walked];
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
1566
2257
|
function createCacheLayer(cacheDir) {
|
|
1567
2258
|
if (cacheDir === null) {
|
|
1568
2259
|
return {
|
|
@@ -1582,7 +2273,7 @@ function createCacheLayer(cacheDir) {
|
|
|
1582
2273
|
const lookupWith = async (input, run) => {
|
|
1583
2274
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1584
2275
|
const manifest = await manifests.readAtRunStart(
|
|
1585
|
-
|
|
2276
|
+
path8.join(entryDir, MANIFEST)
|
|
1586
2277
|
);
|
|
1587
2278
|
if (manifest === null) {
|
|
1588
2279
|
return missDiag(await describeAbsentEntry(cacheDir));
|
|
@@ -1597,11 +2288,15 @@ function createCacheLayer(cacheDir) {
|
|
|
1597
2288
|
if (!await filesStillMatch(manifest.files, run)) {
|
|
1598
2289
|
return missDiag("files-changed");
|
|
1599
2290
|
}
|
|
2291
|
+
const summaries = storedSummaries(entryDir, manifest);
|
|
2292
|
+
if (summaries === null) {
|
|
2293
|
+
return missDiag("no-manifest");
|
|
2294
|
+
}
|
|
1600
2295
|
await markUsed(entryDir);
|
|
1601
2296
|
manifests.forget();
|
|
1602
2297
|
return {
|
|
1603
2298
|
kind: "hit",
|
|
1604
|
-
summaries
|
|
2299
|
+
summaries,
|
|
1605
2300
|
diagnostic: { kind: "hit" }
|
|
1606
2301
|
};
|
|
1607
2302
|
};
|
|
@@ -1621,10 +2316,8 @@ function createCacheLayer(cacheDir) {
|
|
|
1621
2316
|
},
|
|
1622
2317
|
async plan(input) {
|
|
1623
2318
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1624
|
-
const manifest = await manifests.readAgain(
|
|
1625
|
-
|
|
1626
|
-
);
|
|
1627
|
-
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0 || manifest.owners === void 0) {
|
|
2319
|
+
const manifest = await manifests.readAgain(path8.join(entryDir, MANIFEST));
|
|
2320
|
+
if (manifest === null || manifest.roots === void 0 || manifest.rootMeta === void 0) {
|
|
1628
2321
|
return null;
|
|
1629
2322
|
}
|
|
1630
2323
|
const run = await runFor(input);
|
|
@@ -1635,14 +2328,17 @@ function createCacheLayer(cacheDir) {
|
|
|
1635
2328
|
)) {
|
|
1636
2329
|
return null;
|
|
1637
2330
|
}
|
|
2331
|
+
const summaries = storedSummaries(entryDir, manifest);
|
|
2332
|
+
const records = storedRecords(entryDir, manifest);
|
|
2333
|
+
if (summaries === null || records === null) {
|
|
2334
|
+
return null;
|
|
2335
|
+
}
|
|
1638
2336
|
await markUsed(entryDir);
|
|
1639
|
-
return buildPlan(manifest, run);
|
|
2337
|
+
return buildPlan(manifest, records, summaries, run);
|
|
1640
2338
|
},
|
|
1641
2339
|
async write(input, summaries, attribution) {
|
|
1642
2340
|
const entryDir = entryDirFor(cacheDir, input);
|
|
1643
|
-
const previous = await manifests.readAgain(
|
|
1644
|
-
path5.join(entryDir, "manifest.json")
|
|
1645
|
-
);
|
|
2341
|
+
const previous = await manifests.readAgain(path8.join(entryDir, MANIFEST));
|
|
1646
2342
|
manifests.forget();
|
|
1647
2343
|
const known = runs.get(input);
|
|
1648
2344
|
const run = known ?? await runFor(input);
|
|
@@ -1658,58 +2354,119 @@ function createCacheLayer(cacheDir) {
|
|
|
1658
2354
|
)
|
|
1659
2355
|
);
|
|
1660
2356
|
const files = recorded.filter((stamp) => stamp !== null);
|
|
2357
|
+
const encoded = attribution === void 0 ? null : encodeAttribution(
|
|
2358
|
+
attribution,
|
|
2359
|
+
(meta) => writeRecord(entryDir, meta)
|
|
2360
|
+
);
|
|
2361
|
+
makeIgnoredDirectory(cacheDir);
|
|
2362
|
+
const shards = writeShards(entryDir, summaries, encoded);
|
|
1661
2363
|
const manifest = {
|
|
1662
2364
|
schemaVersion: SCHEMA_VERSION,
|
|
1663
2365
|
adapterPacksDigest: input.adapterPacksDigest,
|
|
1664
2366
|
configStamp,
|
|
1665
2367
|
files,
|
|
1666
|
-
summaries,
|
|
1667
|
-
|
|
2368
|
+
summaryCount: summaries.length,
|
|
2369
|
+
shards,
|
|
2370
|
+
...encoded === null ? {} : encoded.stored
|
|
1668
2371
|
};
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
2372
|
+
writeDocumentFile2(path8.join(entryDir, MANIFEST), manifest);
|
|
2373
|
+
removeStoredOutside(
|
|
2374
|
+
entryDir,
|
|
2375
|
+
/* @__PURE__ */ new Set([...storedIds(manifest), ...storedIds(previous)])
|
|
1673
2376
|
);
|
|
1674
2377
|
await evictOldEntries(cacheDir, entryDir);
|
|
1675
2378
|
}
|
|
1676
2379
|
};
|
|
1677
2380
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
2381
|
+
function storedIds(manifest) {
|
|
2382
|
+
return [
|
|
2383
|
+
...(manifest?.shards ?? []).map((shard) => shard.id),
|
|
2384
|
+
...(manifest?.rootMeta ?? []).flatMap(
|
|
2385
|
+
(root) => root.record === void 0 ? [] : [root.record]
|
|
2386
|
+
)
|
|
2387
|
+
];
|
|
2388
|
+
}
|
|
2389
|
+
function writeShards(entryDir, summaries, encoded) {
|
|
2390
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
2391
|
+
summaries.forEach((summary, position) => {
|
|
2392
|
+
const file = summary.location?.file ?? "";
|
|
2393
|
+
const shard = byFile.get(file) ?? {
|
|
2394
|
+
content: { file, units: [] },
|
|
2395
|
+
order: [],
|
|
2396
|
+
owners: []
|
|
2397
|
+
};
|
|
2398
|
+
byFile.set(file, shard);
|
|
2399
|
+
shard.content.units.push(summary);
|
|
2400
|
+
shard.order.push(position);
|
|
2401
|
+
shard.owners.push(encoded?.owners[position] ?? []);
|
|
2402
|
+
});
|
|
2403
|
+
const indexFile = path8.join(entryDir, INDEX);
|
|
2404
|
+
const before = readStoreIndex(indexFile);
|
|
2405
|
+
const known = before === null ? /* @__PURE__ */ new Map() : entriesByShard(before);
|
|
2406
|
+
const sorted = [...byFile].sort(([a], [b]) => a < b ? -1 : 1);
|
|
2407
|
+
const written = sorted.map(([file, { content, order, owners }]) => {
|
|
2408
|
+
const id = writeShard(entryDir, content);
|
|
2409
|
+
return {
|
|
2410
|
+
shard: {
|
|
2411
|
+
file,
|
|
2412
|
+
id,
|
|
2413
|
+
order,
|
|
2414
|
+
...encoded === null ? {} : { owners }
|
|
2415
|
+
},
|
|
2416
|
+
entries: known.get(id) ?? entriesOf(content.units)
|
|
2417
|
+
};
|
|
2418
|
+
});
|
|
2419
|
+
writeStoreIndex(
|
|
2420
|
+
indexFile,
|
|
2421
|
+
indexOf(
|
|
2422
|
+
written.map(({ shard, entries }) => ({
|
|
2423
|
+
file: shard.file,
|
|
2424
|
+
id: shard.id,
|
|
2425
|
+
entries
|
|
2426
|
+
}))
|
|
2427
|
+
)
|
|
2428
|
+
);
|
|
2429
|
+
return written.map(({ shard }) => shard);
|
|
2430
|
+
}
|
|
2431
|
+
function storedSummaries(entryDir, manifest) {
|
|
2432
|
+
const summaries = new Array(
|
|
2433
|
+
manifest.summaryCount
|
|
2434
|
+
);
|
|
2435
|
+
for (const shard of manifest.shards) {
|
|
2436
|
+
const content = readShard(entryDir, shard.id, shard.file);
|
|
2437
|
+
if (content === null || content.units.length !== shard.order.length) {
|
|
2438
|
+
return null;
|
|
1687
2439
|
}
|
|
2440
|
+
shard.order.forEach((position, i) => {
|
|
2441
|
+
summaries[position] = content.units[i];
|
|
2442
|
+
});
|
|
1688
2443
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
if (before === void 0) {
|
|
1693
|
-
changed.add(p);
|
|
1694
|
-
added.add(p);
|
|
1695
|
-
} else if (!fileStampEquals(before, stamp)) {
|
|
1696
|
-
if (before.contentHash === void 0) {
|
|
1697
|
-
changed.add(p);
|
|
1698
|
-
} else {
|
|
1699
|
-
toVerify.push(p);
|
|
1700
|
-
}
|
|
1701
|
-
} else if (before.verifyHash === true) {
|
|
1702
|
-
toVerify.push(p);
|
|
2444
|
+
for (let position = 0; position < summaries.length; position++) {
|
|
2445
|
+
if (summaries[position] === void 0) {
|
|
2446
|
+
return null;
|
|
1703
2447
|
}
|
|
1704
2448
|
}
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
2449
|
+
return summaries;
|
|
2450
|
+
}
|
|
2451
|
+
function storedRecords(entryDir, manifest) {
|
|
2452
|
+
const records = /* @__PURE__ */ new Map();
|
|
2453
|
+
const roots = manifest.roots ?? [];
|
|
2454
|
+
const readRecord2 = recordReader(entryDir);
|
|
2455
|
+
for (const [i, root] of (manifest.rootMeta ?? []).entries()) {
|
|
2456
|
+
const rootPath = roots[i];
|
|
2457
|
+
if (rootPath === void 0 || root.record === void 0) {
|
|
2458
|
+
continue;
|
|
2459
|
+
}
|
|
2460
|
+
const record = readRecord2(root.record);
|
|
2461
|
+
if (record === null) {
|
|
2462
|
+
return null;
|
|
2463
|
+
}
|
|
2464
|
+
records.set(rootPath, record.meta);
|
|
2465
|
+
}
|
|
2466
|
+
return records;
|
|
2467
|
+
}
|
|
2468
|
+
async function buildPlan(manifest, records, stored, run) {
|
|
2469
|
+
const { changed, added, removed } = await changedSince(manifest, run);
|
|
1713
2470
|
const roots = /* @__PURE__ */ new Map();
|
|
1714
2471
|
const rootNames = manifest.roots ?? [];
|
|
1715
2472
|
const depPaths = manifest.depPaths ?? [];
|
|
@@ -1719,23 +2476,24 @@ async function buildPlan(manifest, run) {
|
|
|
1719
2476
|
});
|
|
1720
2477
|
let rootsDeclined = 0;
|
|
1721
2478
|
rootNames.forEach((rootPath, i) => {
|
|
1722
|
-
const
|
|
1723
|
-
if (
|
|
2479
|
+
const record = manifest.rootMeta?.[i];
|
|
2480
|
+
if (record === void 0) {
|
|
1724
2481
|
return;
|
|
1725
2482
|
}
|
|
1726
|
-
if (!
|
|
2483
|
+
if (!record.cacheable) {
|
|
1727
2484
|
rootsDeclined += 1;
|
|
1728
2485
|
}
|
|
1729
2486
|
roots.set(rootPath, {
|
|
1730
2487
|
path: rootPath,
|
|
1731
|
-
cacheable:
|
|
1732
|
-
deps: pathsOf(
|
|
1733
|
-
claims:
|
|
1734
|
-
meta:
|
|
1735
|
-
packs:
|
|
1736
|
-
...
|
|
2488
|
+
cacheable: record.cacheable,
|
|
2489
|
+
deps: pathsOf(record.deps),
|
|
2490
|
+
claims: record.claims,
|
|
2491
|
+
meta: records.get(rootPath),
|
|
2492
|
+
packs: record.packs,
|
|
2493
|
+
...record.imports === void 0 ? {} : { imports: pathsOf(record.imports) }
|
|
1737
2494
|
});
|
|
1738
2495
|
});
|
|
2496
|
+
const current = new Set(run.files.map((f) => f.stamp.path));
|
|
1739
2497
|
const unchanged = (filePath, deps) => current.has(filePath) && !changed.has(filePath) && !deps.some((d) => changed.has(d) || removed.has(d));
|
|
1740
2498
|
const validRoots = /* @__PURE__ */ new Set();
|
|
1741
2499
|
for (const [rootPath, record] of roots) {
|
|
@@ -1743,14 +2501,14 @@ async function buildPlan(manifest, run) {
|
|
|
1743
2501
|
validRoots.add(rootPath);
|
|
1744
2502
|
}
|
|
1745
2503
|
}
|
|
1746
|
-
const units = (manifest.units ?? []).flatMap((
|
|
1747
|
-
const file = depPaths[
|
|
2504
|
+
const units = (manifest.units ?? []).flatMap((unit) => {
|
|
2505
|
+
const file = depPaths[unit.file];
|
|
1748
2506
|
return file === void 0 ? [] : [
|
|
1749
2507
|
{
|
|
1750
|
-
key:
|
|
2508
|
+
key: unit.key,
|
|
1751
2509
|
file,
|
|
1752
|
-
deps: pathsOf(
|
|
1753
|
-
data:
|
|
2510
|
+
deps: pathsOf(unit.deps),
|
|
2511
|
+
data: unit.data
|
|
1754
2512
|
}
|
|
1755
2513
|
];
|
|
1756
2514
|
});
|
|
@@ -1768,7 +2526,7 @@ async function buildPlan(manifest, run) {
|
|
|
1768
2526
|
}
|
|
1769
2527
|
}
|
|
1770
2528
|
}
|
|
1771
|
-
const
|
|
2529
|
+
const ownerPaths = ownersInRunOrder(manifest);
|
|
1772
2530
|
return {
|
|
1773
2531
|
changed,
|
|
1774
2532
|
removed,
|
|
@@ -1780,36 +2538,81 @@ async function buildPlan(manifest, run) {
|
|
|
1780
2538
|
reuse(valid) {
|
|
1781
2539
|
const summaries = [];
|
|
1782
2540
|
const reusedOwners = [];
|
|
1783
|
-
|
|
1784
|
-
const
|
|
1785
|
-
|
|
1786
|
-
return p === void 0 ? [] : [p];
|
|
1787
|
-
});
|
|
1788
|
-
if (ownerPaths.some((p) => valid.has(p))) {
|
|
2541
|
+
stored.forEach((summary, i) => {
|
|
2542
|
+
const owners = ownerPaths[i] ?? [];
|
|
2543
|
+
if (owners.some((p) => valid.has(p))) {
|
|
1789
2544
|
summaries.push(summary);
|
|
1790
|
-
reusedOwners.push(
|
|
2545
|
+
reusedOwners.push(owners.filter((p) => valid.has(p)));
|
|
1791
2546
|
}
|
|
1792
2547
|
});
|
|
1793
2548
|
return { summaries, owners: reusedOwners };
|
|
1794
2549
|
},
|
|
1795
2550
|
allSummaries() {
|
|
1796
|
-
return
|
|
2551
|
+
return stored;
|
|
1797
2552
|
},
|
|
1798
2553
|
attribution() {
|
|
1799
2554
|
return {
|
|
1800
2555
|
roots: [...roots.values()],
|
|
1801
|
-
owners:
|
|
1802
|
-
(ownerIds) => ownerIds.flatMap((o) => {
|
|
1803
|
-
const p = rootNames[o];
|
|
1804
|
-
return p === void 0 ? [] : [p];
|
|
1805
|
-
})
|
|
1806
|
-
),
|
|
2556
|
+
owners: ownerPaths,
|
|
1807
2557
|
units
|
|
1808
2558
|
};
|
|
1809
2559
|
}
|
|
1810
2560
|
};
|
|
1811
2561
|
}
|
|
1812
|
-
function
|
|
2562
|
+
function ownersInRunOrder(manifest) {
|
|
2563
|
+
const rootNames = manifest.roots ?? [];
|
|
2564
|
+
const owners = Array.from(
|
|
2565
|
+
{ length: manifest.summaryCount },
|
|
2566
|
+
() => []
|
|
2567
|
+
);
|
|
2568
|
+
for (const shard of manifest.shards ?? []) {
|
|
2569
|
+
shard.order.forEach((position, i) => {
|
|
2570
|
+
owners[position] = (shard.owners?.[i] ?? []).flatMap((o) => {
|
|
2571
|
+
const p = rootNames[o];
|
|
2572
|
+
return p === void 0 ? [] : [p];
|
|
2573
|
+
});
|
|
2574
|
+
});
|
|
2575
|
+
}
|
|
2576
|
+
return owners;
|
|
2577
|
+
}
|
|
2578
|
+
async function changedSince(manifest, run) {
|
|
2579
|
+
const stored = new Map(manifest.files.map((f) => [f.path, f]));
|
|
2580
|
+
const current = new Map(run.files.map((f) => [f.stamp.path, f.stamp]));
|
|
2581
|
+
const changed = /* @__PURE__ */ new Set();
|
|
2582
|
+
const added = /* @__PURE__ */ new Set();
|
|
2583
|
+
const removed = /* @__PURE__ */ new Set();
|
|
2584
|
+
for (const p of stored.keys()) {
|
|
2585
|
+
if (!current.has(p)) {
|
|
2586
|
+
removed.add(p);
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
const toVerify = [];
|
|
2590
|
+
for (const [p, stamp] of current) {
|
|
2591
|
+
const before = stored.get(p);
|
|
2592
|
+
if (before === void 0) {
|
|
2593
|
+
changed.add(p);
|
|
2594
|
+
added.add(p);
|
|
2595
|
+
} else if (!fileStampEquals(before, stamp)) {
|
|
2596
|
+
if (before.contentHash === void 0) {
|
|
2597
|
+
changed.add(p);
|
|
2598
|
+
} else {
|
|
2599
|
+
toVerify.push(p);
|
|
2600
|
+
}
|
|
2601
|
+
} else if (before.verifyHash === true) {
|
|
2602
|
+
toVerify.push(p);
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
await Promise.all(
|
|
2606
|
+
toVerify.map(async (p) => {
|
|
2607
|
+
const hash = await hashOf(run, p);
|
|
2608
|
+
if (hash === null || hash !== stored.get(p)?.contentHash) {
|
|
2609
|
+
changed.add(p);
|
|
2610
|
+
}
|
|
2611
|
+
})
|
|
2612
|
+
);
|
|
2613
|
+
return { changed, added, removed };
|
|
2614
|
+
}
|
|
2615
|
+
function encodeAttribution(attribution, storeRecord) {
|
|
1813
2616
|
const roots = attribution.roots.map((r) => r.path);
|
|
1814
2617
|
const rootIndex = new Map(roots.map((p, i) => [p, i]));
|
|
1815
2618
|
const depIndex = /* @__PURE__ */ new Map();
|
|
@@ -1825,10 +2628,10 @@ function encodeAttribution(attribution) {
|
|
|
1825
2628
|
return id;
|
|
1826
2629
|
};
|
|
1827
2630
|
const rootMeta = attribution.roots.map((r) => ({
|
|
2631
|
+
...r.meta === void 0 ? {} : { record: storeRecord(r.meta) },
|
|
1828
2632
|
cacheable: r.cacheable,
|
|
1829
2633
|
deps: r.deps.map(depIdOf),
|
|
1830
2634
|
claims: r.claims,
|
|
1831
|
-
meta: r.meta,
|
|
1832
2635
|
packs: r.packs,
|
|
1833
2636
|
...r.imports === void 0 ? {} : { imports: r.imports.map(depIdOf) }
|
|
1834
2637
|
}));
|
|
@@ -1845,16 +2648,18 @@ function encodeAttribution(attribution) {
|
|
|
1845
2648
|
data: unit.data
|
|
1846
2649
|
}));
|
|
1847
2650
|
return {
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
2651
|
+
stored: {
|
|
2652
|
+
roots,
|
|
2653
|
+
rootMeta,
|
|
2654
|
+
depPaths,
|
|
2655
|
+
...units === void 0 ? {} : { units }
|
|
2656
|
+
},
|
|
2657
|
+
owners
|
|
1853
2658
|
};
|
|
1854
2659
|
}
|
|
1855
2660
|
async function describeAbsentEntry(cacheDir) {
|
|
1856
2661
|
try {
|
|
1857
|
-
const entries = await
|
|
2662
|
+
const entries = await fs7.readdir(cacheDir, { withFileTypes: true });
|
|
1858
2663
|
return entries.some((e) => e.isDirectory() && isEntryDir(e.name)) ? "key-changed" : "no-manifest";
|
|
1859
2664
|
} catch {
|
|
1860
2665
|
return "no-manifest";
|
|
@@ -1866,8 +2671,8 @@ function entryDirFor(cacheDir, input) {
|
|
|
1866
2671
|
input.adapterPacksDigest,
|
|
1867
2672
|
input.configPath ?? ""
|
|
1868
2673
|
].join(" ");
|
|
1869
|
-
const name =
|
|
1870
|
-
return
|
|
2674
|
+
const name = createHash5("sha256").update(key).digest("hex").slice(0, 16);
|
|
2675
|
+
return path8.join(cacheDir, `${ENTRY_PREFIX}${name}`);
|
|
1871
2676
|
}
|
|
1872
2677
|
function isEntryDir(name) {
|
|
1873
2678
|
return ENTRY_DIR_NAME.test(name);
|
|
@@ -1875,24 +2680,24 @@ function isEntryDir(name) {
|
|
|
1875
2680
|
async function markUsed(entryDir) {
|
|
1876
2681
|
const now = /* @__PURE__ */ new Date();
|
|
1877
2682
|
try {
|
|
1878
|
-
await
|
|
2683
|
+
await fs7.utimes(entryDir, now, now);
|
|
1879
2684
|
} catch {
|
|
1880
2685
|
}
|
|
1881
2686
|
}
|
|
1882
2687
|
async function evictOldEntries(cacheDir, keepDir) {
|
|
1883
2688
|
try {
|
|
1884
|
-
await
|
|
1885
|
-
const entries = await
|
|
2689
|
+
await fs7.rm(path8.join(cacheDir, "manifest.json"), { force: true });
|
|
2690
|
+
const entries = await fs7.readdir(cacheDir, { withFileTypes: true });
|
|
1886
2691
|
const dirs = await Promise.all(
|
|
1887
2692
|
entries.filter((e) => e.isDirectory() && isEntryDir(e.name)).map(async (e) => {
|
|
1888
|
-
const dir =
|
|
1889
|
-
const stat = await
|
|
2693
|
+
const dir = path8.join(cacheDir, e.name);
|
|
2694
|
+
const stat = await fs7.stat(dir);
|
|
1890
2695
|
return { dir, mtimeMs: stat.mtimeMs };
|
|
1891
2696
|
})
|
|
1892
2697
|
);
|
|
1893
2698
|
const doomed = dirs.filter((d) => d.dir !== keepDir).sort((a, b) => b.mtimeMs - a.mtimeMs).slice(MAX_ENTRIES - 1);
|
|
1894
2699
|
await Promise.all(
|
|
1895
|
-
doomed.map((d) =>
|
|
2700
|
+
doomed.map((d) => fs7.rm(d.dir, { recursive: true, force: true }))
|
|
1896
2701
|
);
|
|
1897
2702
|
} catch {
|
|
1898
2703
|
}
|
|
@@ -1907,7 +2712,7 @@ var ManifestReads = class {
|
|
|
1907
2712
|
last = null;
|
|
1908
2713
|
async readAtRunStart(manifestPath) {
|
|
1909
2714
|
const stamp = await manifestStamp(manifestPath);
|
|
1910
|
-
const manifest = await
|
|
2715
|
+
const manifest = await readManifest2(manifestPath);
|
|
1911
2716
|
this.last = { path: manifestPath, stamp, manifest };
|
|
1912
2717
|
return manifest;
|
|
1913
2718
|
}
|
|
@@ -1924,23 +2729,60 @@ var ManifestReads = class {
|
|
|
1924
2729
|
};
|
|
1925
2730
|
async function manifestStamp(manifestPath) {
|
|
1926
2731
|
try {
|
|
1927
|
-
const stat = await
|
|
2732
|
+
const stat = await fs7.stat(manifestPath);
|
|
1928
2733
|
return `${stat.ino}:${stat.mtimeMs}:${stat.size}`;
|
|
1929
2734
|
} catch {
|
|
1930
2735
|
return null;
|
|
1931
2736
|
}
|
|
1932
2737
|
}
|
|
1933
|
-
async function
|
|
2738
|
+
async function readManifest2(manifestPath) {
|
|
1934
2739
|
try {
|
|
1935
|
-
const
|
|
1936
|
-
return
|
|
2740
|
+
const manifest = readJsonFile3(manifestPath);
|
|
2741
|
+
return Array.isArray(manifest.shards) ? manifest : null;
|
|
1937
2742
|
} catch {
|
|
1938
2743
|
return null;
|
|
1939
2744
|
}
|
|
1940
2745
|
}
|
|
1941
2746
|
|
|
2747
|
+
// src/cacheLocation.ts
|
|
2748
|
+
import { createHash as createHash6 } from "crypto";
|
|
2749
|
+
import fs8 from "fs";
|
|
2750
|
+
import path9 from "path";
|
|
2751
|
+
var CACHE_DIR_ENV = "SUSS_CACHE_DIR";
|
|
2752
|
+
function chosenCacheRoot() {
|
|
2753
|
+
const chosen = process.env[CACHE_DIR_ENV];
|
|
2754
|
+
if (chosen === void 0 || chosen === "") {
|
|
2755
|
+
return null;
|
|
2756
|
+
}
|
|
2757
|
+
return path9.resolve(chosen);
|
|
2758
|
+
}
|
|
2759
|
+
function realPathOrSelf(dir) {
|
|
2760
|
+
try {
|
|
2761
|
+
return fs8.realpathSync(dir);
|
|
2762
|
+
} catch {
|
|
2763
|
+
return dir;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
function projectKey(projectDir) {
|
|
2767
|
+
return createHash6("sha256").update(realPathOrSelf(path9.resolve(projectDir))).digest("hex").slice(0, 16);
|
|
2768
|
+
}
|
|
2769
|
+
function extractionCacheDirFor(projectDir) {
|
|
2770
|
+
const root = chosenCacheRoot();
|
|
2771
|
+
if (root === null) {
|
|
2772
|
+
return path9.join(projectDir, ".suss", "cache");
|
|
2773
|
+
}
|
|
2774
|
+
return path9.join(root, "cache", projectKey(projectDir));
|
|
2775
|
+
}
|
|
2776
|
+
function liveRecordFor(projectDir) {
|
|
2777
|
+
const root = chosenCacheRoot();
|
|
2778
|
+
if (root === null) {
|
|
2779
|
+
return path9.join(projectDir, ".suss", "live", "server.json");
|
|
2780
|
+
}
|
|
2781
|
+
return path9.join(root, "live", `${projectKey(projectDir)}.json`);
|
|
2782
|
+
}
|
|
2783
|
+
|
|
1942
2784
|
// src/extractionReport.ts
|
|
1943
|
-
import { BOUNDARY_ROLE } from "@suss/behavioral-ir";
|
|
2785
|
+
import { BOUNDARY_ROLE as BOUNDARY_ROLE2 } from "@suss/behavioral-ir";
|
|
1944
2786
|
var emptyTally = () => ({
|
|
1945
2787
|
candidateFiles: 0,
|
|
1946
2788
|
unitsDiscovered: 0,
|
|
@@ -1990,7 +2832,7 @@ function summaryCountsByPack(summaries) {
|
|
|
1990
2832
|
}
|
|
1991
2833
|
const entry = counts.get(recognition) ?? emptyCounts();
|
|
1992
2834
|
entry.bound += 1;
|
|
1993
|
-
if (
|
|
2835
|
+
if (BOUNDARY_ROLE2[summary.kind] === "provider") {
|
|
1994
2836
|
entry.providers += 1;
|
|
1995
2837
|
}
|
|
1996
2838
|
if (summary.transitions.length > 0) {
|
|
@@ -2215,6 +3057,17 @@ function undocumentedDeclarations(gradients) {
|
|
|
2215
3057
|
detail: gradient.withoutExample.join(", ")
|
|
2216
3058
|
}));
|
|
2217
3059
|
}
|
|
3060
|
+
function packConfigCheck(needs) {
|
|
3061
|
+
return {
|
|
3062
|
+
name: "every pack that needs an option was given it",
|
|
3063
|
+
code: "no-config",
|
|
3064
|
+
audience: "run",
|
|
3065
|
+
violations: needs.map((need) => ({
|
|
3066
|
+
label: need.pack,
|
|
3067
|
+
detail: `reads nothing until ${need.option} is set, for example ${need.example}. Write that to a JSON file and pass -f ${need.pack}=<config.json>.`
|
|
3068
|
+
}))
|
|
3069
|
+
};
|
|
3070
|
+
}
|
|
2218
3071
|
function evaluatePackHealth(report) {
|
|
2219
3072
|
const gradients = packGradients(report);
|
|
2220
3073
|
return [
|
|
@@ -2367,7 +3220,7 @@ function makeTransitionId(functionName, branch) {
|
|
|
2367
3220
|
const { terminal } = branch;
|
|
2368
3221
|
const statusKey = terminal.statusCode === null ? "none" : terminal.statusCode.type === "literal" ? String(terminal.statusCode.value) : `dyn:${terminal.statusCode.sourceText}`;
|
|
2369
3222
|
const conditionSig = branch.conditions.map((c) => `${c.polarity}:${c.sourceText}`).join(";");
|
|
2370
|
-
const conditionHash =
|
|
3223
|
+
const conditionHash = createHash7("sha1").update(conditionSig).digest("hex").slice(0, 7);
|
|
2371
3224
|
return `${functionName}:${terminal.kind}:${statusKey}:${conditionHash}`;
|
|
2372
3225
|
}
|
|
2373
3226
|
function collapseReading(table, reading) {
|
|
@@ -2426,6 +3279,7 @@ function unreadSentences(raw) {
|
|
|
2426
3279
|
...raw.branches.flatMap(readingsOfBranch)
|
|
2427
3280
|
];
|
|
2428
3281
|
return [
|
|
3282
|
+
...raw.readFailure !== void 0 ? [raw.readFailure] : [],
|
|
2429
3283
|
...raw.unreadBinding !== void 0 ? [raw.unreadBinding] : [],
|
|
2430
3284
|
...handedOver.map(unreadReasonOf).filter((reason) => reason !== null)
|
|
2431
3285
|
];
|
|
@@ -2588,6 +3442,12 @@ function buildHttpMetadataValue(raw) {
|
|
|
2588
3442
|
if (raw.failureDelivery !== void 0) {
|
|
2589
3443
|
http.failureDelivery = raw.failureDelivery;
|
|
2590
3444
|
}
|
|
3445
|
+
if (raw.redirectDelivery !== void 0) {
|
|
3446
|
+
http.redirectDelivery = raw.redirectDelivery;
|
|
3447
|
+
}
|
|
3448
|
+
if (raw.declaredStatuses !== void 0 && raw.declaredStatuses.length > 0) {
|
|
3449
|
+
http.declaredStatuses = raw.declaredStatuses;
|
|
3450
|
+
}
|
|
2591
3451
|
return Object.keys(http).length > 0 ? http : null;
|
|
2592
3452
|
}
|
|
2593
3453
|
function buildGraphqlMetadataValue(raw) {
|
|
@@ -2655,13 +3515,16 @@ function detectGaps(raw, transitions, options) {
|
|
|
2655
3515
|
return gaps;
|
|
2656
3516
|
}
|
|
2657
3517
|
function bodyWentUnread(raw) {
|
|
3518
|
+
if (raw.readFailure !== void 0) {
|
|
3519
|
+
return true;
|
|
3520
|
+
}
|
|
2658
3521
|
if (raw.bodyContent === "absent" || raw.bodyContent === "elsewhere") {
|
|
2659
3522
|
return true;
|
|
2660
3523
|
}
|
|
2661
3524
|
return raw.bodyContent === "statements" && raw.branches.length === 0;
|
|
2662
3525
|
}
|
|
2663
3526
|
function describeUnreadBody(raw) {
|
|
2664
|
-
if (!bodyWentUnread(raw)) {
|
|
3527
|
+
if (!bodyWentUnread(raw) || raw.readFailure !== void 0) {
|
|
2665
3528
|
return null;
|
|
2666
3529
|
}
|
|
2667
3530
|
if (raw.bodyContent === "absent") {
|
|
@@ -2733,10 +3596,16 @@ var terminalConverters = {
|
|
|
2733
3596
|
headers: {}
|
|
2734
3597
|
};
|
|
2735
3598
|
}
|
|
3599
|
+
const ancestry = t.exceptionAncestry;
|
|
2736
3600
|
return {
|
|
2737
3601
|
type: "throw",
|
|
2738
3602
|
exceptionType: t.exceptionType,
|
|
2739
|
-
message: t.message
|
|
3603
|
+
message: t.message,
|
|
3604
|
+
...ancestry === void 0 ? {} : {
|
|
3605
|
+
exceptionAncestors: ancestry.ancestors,
|
|
3606
|
+
...ancestry.incomplete ? { ancestryIncomplete: true } : {}
|
|
3607
|
+
},
|
|
3608
|
+
...t.statusWhenUncaught === void 0 ? {} : { statusWhenUncaught: t.statusWhenUncaught }
|
|
2740
3609
|
};
|
|
2741
3610
|
},
|
|
2742
3611
|
render: (t) => ({
|
|
@@ -2805,11 +3674,13 @@ function paramToInput(param) {
|
|
|
2805
3674
|
};
|
|
2806
3675
|
}
|
|
2807
3676
|
export {
|
|
3677
|
+
CACHE_DIR_ENV,
|
|
2808
3678
|
EnclosingNodes,
|
|
2809
3679
|
IdMap,
|
|
2810
3680
|
IdSet,
|
|
2811
3681
|
KeptParses,
|
|
2812
3682
|
MAX_ENTRIES,
|
|
3683
|
+
MAX_HELPER_PATHS,
|
|
2813
3684
|
MAX_PATHS,
|
|
2814
3685
|
MODULE_SURFACE_RECOGNITION,
|
|
2815
3686
|
PathBudgetExceeded,
|
|
@@ -2821,6 +3692,7 @@ export {
|
|
|
2821
3692
|
assembleSummary,
|
|
2822
3693
|
assessConfidence,
|
|
2823
3694
|
buildUngatedExtractionReport,
|
|
3695
|
+
chosenCacheRoot,
|
|
2824
3696
|
commonDirectoryOf,
|
|
2825
3697
|
composeWrappers,
|
|
2826
3698
|
computeContentHash,
|
|
@@ -2828,6 +3700,7 @@ export {
|
|
|
2828
3700
|
configuredCallOption,
|
|
2829
3701
|
createAdapterStamp,
|
|
2830
3702
|
createCacheLayer,
|
|
3703
|
+
createCodeHasher,
|
|
2831
3704
|
createPackTallies,
|
|
2832
3705
|
createTimer,
|
|
2833
3706
|
detectGaps,
|
|
@@ -2836,24 +3709,33 @@ export {
|
|
|
2836
3709
|
enumerateOrDegrade,
|
|
2837
3710
|
enumerateStructuredPaths,
|
|
2838
3711
|
evaluatePackHealth,
|
|
3712
|
+
extractionCacheDirFor,
|
|
2839
3713
|
extractionConfigStamp,
|
|
2840
3714
|
firstWrittenReading,
|
|
2841
3715
|
formatPackHealth,
|
|
2842
3716
|
guardsHoldOn,
|
|
3717
|
+
helperPathsOnVariables,
|
|
2843
3718
|
httpRouteDiscovery,
|
|
2844
3719
|
isListedTestFile,
|
|
3720
|
+
liveRecordFor,
|
|
3721
|
+
makeIgnoredDirectory,
|
|
2845
3722
|
makeTransitionId,
|
|
2846
3723
|
mapReading,
|
|
2847
3724
|
markReturnsAsExitCode,
|
|
2848
3725
|
matchesTestFileName,
|
|
3726
|
+
mergeReadShapes,
|
|
2849
3727
|
moduleInitStructure,
|
|
2850
3728
|
moduleOfFile,
|
|
2851
3729
|
noopTimer,
|
|
3730
|
+
ownersWhereWritten,
|
|
3731
|
+
packConfigCheck,
|
|
2852
3732
|
packGradients,
|
|
2853
3733
|
paramToInput,
|
|
3734
|
+
processCodeHasher,
|
|
2854
3735
|
projectFileStamp,
|
|
2855
3736
|
rawConditionToPredicate,
|
|
2856
3737
|
recordPackFailure,
|
|
3738
|
+
redirectDeliveryWhenSet,
|
|
2857
3739
|
registrationHelperDiscovery,
|
|
2858
3740
|
routeHelperIndex,
|
|
2859
3741
|
runDigest,
|
|
@@ -2862,6 +3744,7 @@ export {
|
|
|
2862
3744
|
settleModules,
|
|
2863
3745
|
sharedGatingConditions,
|
|
2864
3746
|
sourceRefsOf,
|
|
3747
|
+
splitAtHandOffs,
|
|
2865
3748
|
stampMayMissAWrite,
|
|
2866
3749
|
stampModuleImports,
|
|
2867
3750
|
stampModules,
|
|
@@ -2869,6 +3752,7 @@ export {
|
|
|
2869
3752
|
summaryCountsByPack,
|
|
2870
3753
|
tallyUnit,
|
|
2871
3754
|
terminalToOutput,
|
|
3755
|
+
throughHelper,
|
|
2872
3756
|
unreadableReading,
|
|
2873
3757
|
unwrapJsonStringify,
|
|
2874
3758
|
valueToReadFurtherFrom,
|