@suss/extractor 0.8.0 → 0.10.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 +68 -24
- package/dist/index.d.cts +274 -249
- package/dist/index.d.ts +274 -249
- package/dist/index.js +66 -21
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -47,7 +47,7 @@ __export(index_exports, {
|
|
|
47
47
|
});
|
|
48
48
|
module.exports = __toCommonJS(index_exports);
|
|
49
49
|
var import_node_crypto = require("crypto");
|
|
50
|
-
var
|
|
50
|
+
var import_behavioral_ir2 = require("@suss/behavioral-ir");
|
|
51
51
|
|
|
52
52
|
// src/inputReads.ts
|
|
53
53
|
function inputReadsOf(args) {
|
|
@@ -167,6 +167,7 @@ function unwrapJsonStringify(body) {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
// src/paths/enumeratePaths.ts
|
|
170
|
+
var import_behavioral_ir = require("@suss/behavioral-ir");
|
|
170
171
|
var MAX_PATHS = 256;
|
|
171
172
|
var UnmodeledFlow = class extends Error {
|
|
172
173
|
};
|
|
@@ -210,7 +211,7 @@ var loopCompletedCond = (headerText, exit) => fixedCond(
|
|
|
210
211
|
exit === "throw" ? "earlyThrow" : "earlyReturn"
|
|
211
212
|
);
|
|
212
213
|
var catchEntryCond = () => fixedCond(
|
|
213
|
-
{ sourceText:
|
|
214
|
+
{ sourceText: import_behavioral_ir.CATCH_ENTRY_TEXT, expression: null },
|
|
214
215
|
"positive",
|
|
215
216
|
"catchBlock"
|
|
216
217
|
);
|
|
@@ -220,7 +221,7 @@ function classify(path, home, isAncestorOrSelf) {
|
|
|
220
221
|
return cond.info;
|
|
221
222
|
}
|
|
222
223
|
const encloses = home !== null && isAncestorOrSelf(cond.branchStmt, home);
|
|
223
|
-
if (encloses || cond.info.polarity === "positive") {
|
|
224
|
+
if (encloses || cond.info.polarity === "positive" || cond.oppositeExit === null) {
|
|
224
225
|
return { ...cond.info, source: "explicit" };
|
|
225
226
|
}
|
|
226
227
|
const source = cond.oppositeExit === "throw" ? "earlyThrow" : "earlyReturn";
|
|
@@ -228,6 +229,9 @@ function classify(path, home, isAncestorOrSelf) {
|
|
|
228
229
|
});
|
|
229
230
|
}
|
|
230
231
|
function childrenOf(stmt) {
|
|
232
|
+
return [...ownBlocksOf(stmt), ...(stmt.callbacks ?? []).flat()];
|
|
233
|
+
}
|
|
234
|
+
function ownBlocksOf(stmt) {
|
|
231
235
|
if (stmt.kind === "if") {
|
|
232
236
|
return stmt.elseBody === null ? stmt.thenBody : [...stmt.thenBody, ...stmt.elseBody];
|
|
233
237
|
}
|
|
@@ -254,7 +258,7 @@ function hasStrayBreak(nodes) {
|
|
|
254
258
|
if (node.kind === "switch" || node.kind === "loop") {
|
|
255
259
|
return false;
|
|
256
260
|
}
|
|
257
|
-
return hasStrayBreak(
|
|
261
|
+
return hasStrayBreak(ownBlocksOf(node));
|
|
258
262
|
});
|
|
259
263
|
}
|
|
260
264
|
function exitKindOfList(stmts) {
|
|
@@ -291,11 +295,6 @@ function containsTerminal(ctx, stmt) {
|
|
|
291
295
|
return childrenOf(stmt).some((child) => containsTerminal(ctx, child));
|
|
292
296
|
}
|
|
293
297
|
function stepIf(stmt, path, ctx) {
|
|
294
|
-
const armsExit = stmt.exitKind !== null;
|
|
295
|
-
const armsHaveTerminals = containsTerminal(ctx, stmt);
|
|
296
|
-
if (!armsExit && !armsHaveTerminals) {
|
|
297
|
-
return [path];
|
|
298
|
-
}
|
|
299
298
|
const thenExit = exitKindOfList(stmt.thenBody);
|
|
300
299
|
const elseExit = stmt.elseBody === null ? null : exitKindOfList(stmt.elseBody);
|
|
301
300
|
const thenPath = [
|
|
@@ -304,7 +303,12 @@ function stepIf(stmt, path, ctx) {
|
|
|
304
303
|
];
|
|
305
304
|
const elsePath = [
|
|
306
305
|
...path,
|
|
307
|
-
branchCond(
|
|
306
|
+
branchCond(
|
|
307
|
+
stmt,
|
|
308
|
+
stmt.condition,
|
|
309
|
+
"negative",
|
|
310
|
+
stmt.elseBody === null ? thenExit : null
|
|
311
|
+
)
|
|
308
312
|
];
|
|
309
313
|
const out = [];
|
|
310
314
|
out.push(...enumerate(ctx, stmt.thenBody, thenPath));
|
|
@@ -376,7 +380,11 @@ function stepTry(stmt, path, ctx) {
|
|
|
376
380
|
}
|
|
377
381
|
return out;
|
|
378
382
|
}
|
|
379
|
-
function stepExit(
|
|
383
|
+
function stepExit(stmt, path, ctx) {
|
|
384
|
+
const collector = ctx.state.callbackExits[ctx.state.callbackExits.length - 1];
|
|
385
|
+
if (collector !== void 0 && (stmt.exit === "return" || stmt.exit === "throw")) {
|
|
386
|
+
collector.push(path);
|
|
387
|
+
}
|
|
380
388
|
return [];
|
|
381
389
|
}
|
|
382
390
|
function stepOpaque(_stmt, path, _ctx) {
|
|
@@ -390,16 +398,36 @@ var stepHandlers = {
|
|
|
390
398
|
exit: stepExit,
|
|
391
399
|
opaque: stepOpaque
|
|
392
400
|
};
|
|
401
|
+
function stepCallback(ctx, body, path) {
|
|
402
|
+
const exits = [];
|
|
403
|
+
ctx.state.callbackExits.push(exits);
|
|
404
|
+
let fellThrough;
|
|
405
|
+
try {
|
|
406
|
+
fellThrough = enumerate(ctx, body, path);
|
|
407
|
+
} finally {
|
|
408
|
+
ctx.state.callbackExits.pop();
|
|
409
|
+
}
|
|
410
|
+
const out = [...fellThrough, ...exits];
|
|
411
|
+
return out.length === 0 ? [path] : out;
|
|
412
|
+
}
|
|
393
413
|
function stepStatement(ctx, stmt, path) {
|
|
414
|
+
let paths = [path];
|
|
415
|
+
for (const body of stmt.callbacks ?? []) {
|
|
416
|
+
paths = paths.flatMap((each) => stepCallback(ctx, body, each));
|
|
417
|
+
}
|
|
394
418
|
const ownTerminals = ctx.terminalsByStmt.get(stmt) ?? [];
|
|
395
|
-
for (const
|
|
396
|
-
|
|
419
|
+
for (const each of withRejoined(paths)) {
|
|
420
|
+
for (const terminal of ownTerminals) {
|
|
421
|
+
recordTerminal(ctx, terminal, stmt, each);
|
|
422
|
+
}
|
|
397
423
|
}
|
|
398
424
|
const handler = stepHandlers[stmt.kind];
|
|
399
|
-
return
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
425
|
+
return paths.flatMap(
|
|
426
|
+
(each) => handler(
|
|
427
|
+
stmt,
|
|
428
|
+
each,
|
|
429
|
+
ctx
|
|
430
|
+
)
|
|
403
431
|
);
|
|
404
432
|
}
|
|
405
433
|
function soleDisagreement(left, right) {
|
|
@@ -456,14 +484,18 @@ function mergeRejoined(paths) {
|
|
|
456
484
|
}
|
|
457
485
|
return current;
|
|
458
486
|
}
|
|
487
|
+
function withRejoined(paths) {
|
|
488
|
+
const merged = mergeRejoined(paths);
|
|
489
|
+
return merged.length === paths.length ? paths : [...merged, ...paths];
|
|
490
|
+
}
|
|
459
491
|
function enumerate(ctx, stmts, prefix) {
|
|
460
492
|
let frontiers = [[...prefix]];
|
|
461
493
|
for (const stmt of stmts) {
|
|
462
494
|
const nextFrontiers = [];
|
|
463
|
-
for (const path of frontiers) {
|
|
495
|
+
for (const path of mergeRejoined(frontiers)) {
|
|
464
496
|
nextFrontiers.push(...stepStatement(ctx, stmt, path));
|
|
465
497
|
}
|
|
466
|
-
frontiers =
|
|
498
|
+
frontiers = nextFrontiers;
|
|
467
499
|
if (frontiers.length > MAX_PATHS) {
|
|
468
500
|
throw new PathBudgetExceeded(
|
|
469
501
|
`path budget exceeded, more than ${MAX_PATHS} paths`
|
|
@@ -503,14 +535,15 @@ function enumerateStructuredPaths(input) {
|
|
|
503
535
|
const state = {
|
|
504
536
|
byTerminal: /* @__PURE__ */ new Map(),
|
|
505
537
|
fallthrough: [],
|
|
506
|
-
pathCount: 0
|
|
538
|
+
pathCount: 0,
|
|
539
|
+
callbackExits: []
|
|
507
540
|
};
|
|
508
541
|
const ctx = {
|
|
509
542
|
terminalsByStmt: input.terminalsByStmt,
|
|
510
543
|
state,
|
|
511
544
|
isAncestorOrSelf
|
|
512
545
|
};
|
|
513
|
-
const continuations = enumerate(ctx, input.statements, []);
|
|
546
|
+
const continuations = withRejoined(enumerate(ctx, input.statements, []));
|
|
514
547
|
for (const path of continuations) {
|
|
515
548
|
chargeBudget(state);
|
|
516
549
|
state.fallthrough.push(classify(path, null, isAncestorOrSelf));
|
|
@@ -803,11 +836,16 @@ function buildMetadata(raw) {
|
|
|
803
836
|
let metadata = {};
|
|
804
837
|
const http = buildHttpMetadataValue(raw);
|
|
805
838
|
if (http !== null) {
|
|
806
|
-
metadata = (0,
|
|
839
|
+
metadata = (0, import_behavioral_ir2.withHttpMetadata)(metadata, http);
|
|
807
840
|
}
|
|
808
841
|
const graphql = buildGraphqlMetadataValue(raw);
|
|
809
842
|
if (graphql !== null) {
|
|
810
|
-
metadata = (0,
|
|
843
|
+
metadata = (0, import_behavioral_ir2.withGraphqlMetadata)(metadata, graphql);
|
|
844
|
+
}
|
|
845
|
+
if (raw.sourceDocumentLabel !== void 0) {
|
|
846
|
+
metadata = (0, import_behavioral_ir2.withSourceDocumentMetadata)(metadata, {
|
|
847
|
+
label: raw.sourceDocumentLabel
|
|
848
|
+
});
|
|
811
849
|
}
|
|
812
850
|
return Object.keys(metadata).length > 0 ? metadata : null;
|
|
813
851
|
}
|
|
@@ -826,6 +864,12 @@ function buildHttpMetadataValue(raw) {
|
|
|
826
864
|
if (raw.statusAccessors !== void 0 && raw.statusAccessors.length > 0) {
|
|
827
865
|
http.statusAccessors = raw.statusAccessors;
|
|
828
866
|
}
|
|
867
|
+
if (raw.successAccessors !== void 0 && raw.successAccessors.length > 0) {
|
|
868
|
+
http.successAccessors = raw.successAccessors;
|
|
869
|
+
}
|
|
870
|
+
if (raw.failureDelivery !== void 0) {
|
|
871
|
+
http.failureDelivery = raw.failureDelivery;
|
|
872
|
+
}
|
|
829
873
|
return Object.keys(http).length > 0 ? http : null;
|
|
830
874
|
}
|
|
831
875
|
function buildGraphqlMetadataValue(raw) {
|
|
@@ -848,7 +892,7 @@ function answersWithHttpResponses(raw) {
|
|
|
848
892
|
if (raw.boundaryBinding === null || raw.boundaryBinding === void 0) {
|
|
849
893
|
return true;
|
|
850
894
|
}
|
|
851
|
-
return (0,
|
|
895
|
+
return (0, import_behavioral_ir2.exchangesHttpResponses)(raw.boundaryBinding);
|
|
852
896
|
}
|
|
853
897
|
function detectGaps(raw, transitions, options) {
|
|
854
898
|
if (options.gapHandling === "silent") {
|