@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 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 import_behavioral_ir = require("@suss/behavioral-ir");
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: "catch", expression: null },
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(childrenOf(node));
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(stmt, stmt.condition, "negative", thenExit)
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(_stmt, _path, _ctx) {
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 terminal of ownTerminals) {
396
- recordTerminal(ctx, terminal, stmt, path);
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 handler(
400
- stmt,
401
- path,
402
- ctx
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 = mergeRejoined(nextFrontiers);
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, import_behavioral_ir.withHttpMetadata)(metadata, http);
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, import_behavioral_ir.withGraphqlMetadata)(metadata, graphql);
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, import_behavioral_ir.exchangesHttpResponses)(raw.boundaryBinding);
895
+ return (0, import_behavioral_ir2.exchangesHttpResponses)(raw.boundaryBinding);
852
896
  }
853
897
  function detectGaps(raw, transitions, options) {
854
898
  if (options.gapHandling === "silent") {