@suss/adapter-typescript 0.22.3 → 0.22.4

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
@@ -31,6 +31,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  ADAPTER_VERSION: () => ADAPTER_VERSION,
34
+ GENERIC_TERMINALS: () => GENERIC_TERMINALS,
35
+ NO_BARRIERS: () => NO_BARRIERS,
34
36
  ResolutionStore: () => ResolutionStore,
35
37
  TypeScriptWhySession: () => TypeScriptWhySession,
36
38
  accessContextFor: () => accessContextFor,
@@ -51,6 +53,7 @@ __export(index_exports, {
51
53
  findNearestTsconfig: () => findNearestTsconfig,
52
54
  findTerminals: () => findTerminals,
53
55
  functionTargetOf: () => functionTargetOf,
56
+ hasBody: () => hasBody,
54
57
  importDeclarationsOf: () => importDeclarationsOf,
55
58
  importedNamesOf: () => importedNamesOf,
56
59
  importedRootsOf: () => importedRootsOf,
@@ -66,6 +69,7 @@ __export(index_exports, {
66
69
  resolveAliasedSymbol: () => resolveAliasedSymbol,
67
70
  resolveSubject: () => resolveSubject,
68
71
  rootIdentifier: () => rootIdentifier,
72
+ startsItsOwnScope: () => startsItsOwnScope,
69
73
  stubEvidence: () => stubEvidence,
70
74
  stubEvidenceIn: () => stubEvidenceIn,
71
75
  workspaceRootFor: () => workspaceRootFor
@@ -3732,6 +3736,18 @@ var ResolutionStore = class {
3732
3736
  const target = factKeyOf(value);
3733
3737
  return this.askAbout(target, "wanted", () => this.lookupObject(target));
3734
3738
  }
3739
+ /**
3740
+ * The function a call returns: `app.use(requireCaller(config))`
3741
+ * registers what the factory gives back. A separate question from
3742
+ * `resolveCallable`, which keeps a call unresolved on purpose so an
3743
+ * unwrapping answer wins; this one is asked only after that has
3744
+ * declined. Two returned functions give null, like every other
3745
+ * single-answer question here.
3746
+ */
3747
+ resolveReturnedCallable(call) {
3748
+ const target = factKeyOf(call);
3749
+ return this.askAbout(target, "wanted", () => this.lookupReturned(target));
3750
+ }
3735
3751
  /**
3736
3752
  * For a value that is neither a function nor an object, such as a
3737
3753
  * GraphQL document kept in a constant in another file.
@@ -4175,6 +4191,21 @@ var ResolutionStore = class {
4175
4191
  }
4176
4192
  return [...candidates][0];
4177
4193
  }
4194
+ lookupReturned(call) {
4195
+ this.derive();
4196
+ const candidates = /* @__PURE__ */ new Set();
4197
+ for (const target of this.answersFor("wantedGivesBack", nodeId(call))) {
4198
+ const node = this.table.byId.get(target);
4199
+ if (node === void 0 || !isFunctionRoot(node)) {
4200
+ continue;
4201
+ }
4202
+ candidates.add(node);
4203
+ }
4204
+ if (candidates.size !== 1) {
4205
+ return null;
4206
+ }
4207
+ return [...candidates][0];
4208
+ }
4178
4209
  /**
4179
4210
  * Two candidates give null, since ambiguity is nothing. The value
4180
4211
  * itself is never a result either, or an identifier whose chain went
@@ -5282,7 +5313,27 @@ function functionValueOf(value, resolution) {
5282
5313
  return null;
5283
5314
  }
5284
5315
  const resolved = resolution.resolveCallable(written);
5285
- return resolved === null ? null : toFunctionRoot(resolved);
5316
+ if (resolved !== null) {
5317
+ return toFunctionRoot(resolved);
5318
+ }
5319
+ if (!import_ts_morph19.Node.isCallExpression(written)) {
5320
+ return null;
5321
+ }
5322
+ const returned = resolution.resolveReturnedCallable(written);
5323
+ return returned === null ? null : toFunctionRoot(returned);
5324
+ }
5325
+ function propertyNameOf(property) {
5326
+ if (import_ts_morph19.Node.isPropertyAssignment(property) || import_ts_morph19.Node.isShorthandPropertyAssignment(property) || import_ts_morph19.Node.isMethodDeclaration(property)) {
5327
+ return property.getName();
5328
+ }
5329
+ return null;
5330
+ }
5331
+ function propertyFunctionOf(property, resolution) {
5332
+ if (import_ts_morph19.Node.isMethodDeclaration(property)) {
5333
+ return property;
5334
+ }
5335
+ const held = propertyValueOf(property);
5336
+ return held === null ? null : functionValueOf(held, resolution);
5286
5337
  }
5287
5338
  function objectLiteralOf(value, resolution) {
5288
5339
  return literalValueOf(
@@ -8742,7 +8793,7 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
8742
8793
  }
8743
8794
  const schemaSdl = extractTypeDefsSdl(config, store);
8744
8795
  for (const typeProp of propertiesOf(resolversObj, store)) {
8745
- const typeName = resolverPropertyName(typeProp);
8796
+ const typeName = propertyNameOf(typeProp);
8746
8797
  if (typeName === null || excludeTypes.has(typeName)) {
8747
8798
  continue;
8748
8799
  }
@@ -8751,11 +8802,11 @@ function discoverResolverMaps(sourceFile, match, kind, resolution) {
8751
8802
  continue;
8752
8803
  }
8753
8804
  for (const fieldProp of propertiesOf(typeObj, store)) {
8754
- const fieldName = resolverPropertyName(fieldProp);
8805
+ const fieldName = propertyNameOf(fieldProp);
8755
8806
  if (fieldName === null) {
8756
8807
  continue;
8757
8808
  }
8758
- const fn = resolverPropertyFunction(fieldProp, store);
8809
+ const fn = propertyFunctionOf(fieldProp, store);
8759
8810
  if (fn === null) {
8760
8811
  continue;
8761
8812
  }
@@ -8819,22 +8870,6 @@ function writtenSdl(expr) {
8819
8870
  }
8820
8871
  return null;
8821
8872
  }
8822
- function resolverPropertyName(prop) {
8823
- if (import_ts_morph38.Node.isPropertyAssignment(prop) || import_ts_morph38.Node.isMethodDeclaration(prop)) {
8824
- return prop.getName();
8825
- }
8826
- if (import_ts_morph38.Node.isShorthandPropertyAssignment(prop)) {
8827
- return prop.getName();
8828
- }
8829
- return null;
8830
- }
8831
- function resolverPropertyFunction(prop, resolution) {
8832
- if (import_ts_morph38.Node.isMethodDeclaration(prop)) {
8833
- return prop;
8834
- }
8835
- const held = propertyValueOf(prop);
8836
- return held === null ? null : functionValueOf(held, resolution);
8837
- }
8838
8873
 
8839
8874
  // src/discovery/index.ts
8840
8875
  function runPattern(sourceFile, pattern, resolution, mountPrefixes, expandedElsewhere) {
@@ -12240,7 +12275,7 @@ function countUnmatchedReturns(func, terminals, barriers = NO_BARRIERS) {
12240
12275
  });
12241
12276
  return unmatched;
12242
12277
  }
12243
- function extractRawBranches(func, terminalPatterns, invocationRecognizers = [], accessRecognizers = [], barriers = NO_BARRIERS, resolution, originatesFrom, anchorCallsOf, resolveCallee2) {
12278
+ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [], accessRecognizers = [], barriers = NO_BARRIERS, resolution, originatesFrom, anchorCallsOf, resolveCallee2, collectCallAccounting = false) {
12244
12279
  const terminals = findTerminals(
12245
12280
  func,
12246
12281
  terminalPatterns,
@@ -12328,8 +12363,8 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
12328
12363
  seenBranches.add(key);
12329
12364
  return true;
12330
12365
  });
12366
+ const terminalNodes = new Set(terminals.map(({ node }) => node));
12331
12367
  if (invocations.length > 0) {
12332
- const terminalNodes = new Set(terminals.map(({ node }) => node));
12333
12368
  const sideEffects = invocations.filter(
12334
12369
  (i) => !writesTerminal(i.node, terminalNodes)
12335
12370
  );
@@ -12345,7 +12380,39 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
12345
12380
  branch.extraEffects = [...branch.extraEffects ?? [], ...extra];
12346
12381
  }
12347
12382
  }
12348
- return { branches: distinctBranches, terminals };
12383
+ return {
12384
+ branches: distinctBranches,
12385
+ terminals,
12386
+ ...collectCallAccounting ? {
12387
+ callAccounting: invocations.map(
12388
+ (site) => accountFor(site, terminalNodes, distinctBranches)
12389
+ )
12390
+ } : {}
12391
+ };
12392
+ }
12393
+ function accountFor(site, terminalNodes, branches) {
12394
+ const { node, line } = site;
12395
+ const callee = node.getExpression().getText();
12396
+ if (writesTerminal(node, terminalNodes)) {
12397
+ return { node, callee, line, outcome: "terminal" };
12398
+ }
12399
+ const call = {
12400
+ line,
12401
+ alwaysRuns: site.alwaysRuns,
12402
+ preconditions: preconditionsOf(site.effect)
12403
+ };
12404
+ if (branches.some((branch) => firesOn(call, branch))) {
12405
+ return { node, callee, line, outcome: "invocation" };
12406
+ }
12407
+ const reachable = branches.some(
12408
+ (branch) => site.alwaysRuns || (0, import_extractor5.runsBefore)(line, branch.terminal.location.end)
12409
+ );
12410
+ return {
12411
+ node,
12412
+ callee,
12413
+ line,
12414
+ outcome: reachable ? "unrecorded" : "unreachable"
12415
+ };
12349
12416
  }
12350
12417
 
12351
12418
  // src/bootstrap/sourceFileLookup.ts
@@ -12560,7 +12627,7 @@ function unwrapContractInit(init) {
12560
12627
  }
12561
12628
  return null;
12562
12629
  }
12563
- function extractEndpointContract(endpointNode, pattern, framework) {
12630
+ function extractEndpointContract(endpointNode, pattern, framework, resolution) {
12564
12631
  if (!import_ts_morph56.Node.isObjectLiteralExpression(endpointNode)) {
12565
12632
  return null;
12566
12633
  }
@@ -12585,9 +12652,10 @@ function extractEndpointContract(endpointNode, pattern, framework) {
12585
12652
  }
12586
12653
  }
12587
12654
  if (propName === pattern.responseExtraction.property) {
12588
- const val = prop.getInitializer();
12589
- if (val !== void 0 && import_ts_morph56.Node.isObjectLiteralExpression(val)) {
12590
- for (const respProp of val.getProperties()) {
12655
+ const written = prop.getInitializer();
12656
+ const val = written === void 0 ? null : objectLiteralOf(written, resolution);
12657
+ if (val !== null) {
12658
+ for (const respProp of propertiesOf(val, resolution)) {
12591
12659
  if (!import_ts_morph56.Node.isPropertyAssignment(respProp)) {
12592
12660
  continue;
12593
12661
  }
@@ -12626,7 +12694,12 @@ function readContract(unit, pattern, framework, resolution) {
12626
12694
  if (endpointNode === null) {
12627
12695
  return null;
12628
12696
  }
12629
- return extractEndpointContract(endpointNode, pattern, framework);
12697
+ return extractEndpointContract(
12698
+ endpointNode,
12699
+ pattern,
12700
+ framework,
12701
+ resolution
12702
+ );
12630
12703
  }
12631
12704
  const routerInfo = findRouterCall(unit);
12632
12705
  if (routerInfo === null) {
@@ -12647,7 +12720,12 @@ function readContract(unit, pattern, framework, resolution) {
12647
12720
  if (endpointInit === void 0) {
12648
12721
  continue;
12649
12722
  }
12650
- return extractEndpointContract(endpointInit, pattern, framework);
12723
+ return extractEndpointContract(
12724
+ endpointInit,
12725
+ pattern,
12726
+ framework,
12727
+ resolution
12728
+ );
12651
12729
  }
12652
12730
  return null;
12653
12731
  }
@@ -12724,7 +12802,12 @@ function readContractForClientCall(callExpression, methodName, pattern, framewor
12724
12802
  if (endpointInit === void 0) {
12725
12803
  continue;
12726
12804
  }
12727
- return extractEndpointContract(endpointInit, pattern, framework);
12805
+ return extractEndpointContract(
12806
+ endpointInit,
12807
+ pattern,
12808
+ framework,
12809
+ resolution
12810
+ );
12728
12811
  }
12729
12812
  return null;
12730
12813
  }
@@ -13476,7 +13559,11 @@ function recordEdge(edgesByChild, candidate) {
13476
13559
  // src/discovery/wrapperIndex.ts
13477
13560
  var import_ts_morph60 = require("ts-morph");
13478
13561
  var import_resolution6 = require("@suss/resolution");
13479
- var NO_WRAPPERS = { wrappersFor: () => [], unitsIn: () => [] };
13562
+ var NO_WRAPPERS = {
13563
+ wrappersFor: () => [],
13564
+ unfollowedFor: () => [],
13565
+ unitsIn: () => []
13566
+ };
13480
13567
  var ANONYMOUS = "<anon>";
13481
13568
  function buildWrapperIndex(packsByFile, resolution, mountPrefixes) {
13482
13569
  const workByPack = /* @__PURE__ */ new Map();
@@ -13502,21 +13589,32 @@ function buildWrapperIndex(packsByFile, resolution, mountPrefixes) {
13502
13589
  }
13503
13590
  }
13504
13591
  const bySubject = /* @__PURE__ */ new Map();
13592
+ const unfollowedBySubject = /* @__PURE__ */ new Map();
13505
13593
  const unitsByFile = /* @__PURE__ */ new Map();
13594
+ const stopsSeen = /* @__PURE__ */ new Set();
13506
13595
  let found = false;
13507
13596
  for (const [packName, work] of workByPack) {
13508
13597
  const candidates = [];
13509
13598
  for (const { sourceFile, pattern, match, wraps } of work) {
13510
- candidates.push(
13511
- ...discoverWrapperRegistrations(
13512
- sourceFile,
13513
- pattern,
13514
- match,
13515
- wraps,
13516
- resolution,
13517
- mountPrefixes
13518
- )
13599
+ const scan = discoverWrapperRegistrations(
13600
+ sourceFile,
13601
+ pattern,
13602
+ match,
13603
+ wraps,
13604
+ resolution,
13605
+ mountPrefixes
13519
13606
  );
13607
+ candidates.push(...scan.candidates);
13608
+ for (const { subjectId, callId, stop } of scan.unresolved) {
13609
+ if (stopsSeen.has(callId)) {
13610
+ continue;
13611
+ }
13612
+ stopsSeen.add(callId);
13613
+ found = true;
13614
+ const stops = unfollowedBySubject.get(subjectId) ?? [];
13615
+ stops.push(stop);
13616
+ unfollowedBySubject.set(subjectId, stops);
13617
+ }
13520
13618
  }
13521
13619
  for (const candidate of mostSpecific(candidates)) {
13522
13620
  found = true;
@@ -13534,6 +13632,7 @@ function buildWrapperIndex(packsByFile, resolution, mountPrefixes) {
13534
13632
  }
13535
13633
  return {
13536
13634
  wrappersFor: (subjectId) => bySubject.get(subjectId) ?? [],
13635
+ unfollowedFor: (subjectId) => unfollowedBySubject.get(subjectId) ?? [],
13537
13636
  unitsIn: (file, pack) => unitsByFile.get(unitKey(file, pack)) ?? []
13538
13637
  };
13539
13638
  }
@@ -13567,10 +13666,20 @@ function discoverWrapperRegistrations(sourceFile, pattern, match, wraps, resolut
13567
13666
  match.importName,
13568
13667
  resolution
13569
13668
  );
13669
+ if ("constructorOption" in wraps) {
13670
+ return discoverConstructorOptions(
13671
+ sourceFile,
13672
+ pattern,
13673
+ wraps,
13674
+ subjects,
13675
+ resolution
13676
+ );
13677
+ }
13570
13678
  if (subjects.size === 0 && !storeCanFindSubjects(sourceFile, match, resolution)) {
13571
- return [];
13679
+ return { candidates: [], unresolved: [] };
13572
13680
  }
13573
13681
  const candidates = [];
13682
+ const unresolved = [];
13574
13683
  sourceFile.forEachDescendant((node) => {
13575
13684
  if (!import_ts_morph60.Node.isCallExpression(node)) {
13576
13685
  return;
@@ -13593,8 +13702,13 @@ function discoverWrapperRegistrations(sourceFile, pattern, match, wraps, resolut
13593
13702
  if (targetArg === void 0) {
13594
13703
  return;
13595
13704
  }
13705
+ const subjectId = nodeId(subjectNode);
13596
13706
  const target = functionValueOf(targetArg, resolution);
13597
13707
  if (target === null) {
13708
+ const stop = factoryStopOf(targetArg);
13709
+ if (stop !== null) {
13710
+ unresolved.push({ subjectId, callId: nodeId(node), stop });
13711
+ }
13598
13712
  return;
13599
13713
  }
13600
13714
  if (wraps.arity !== void 0 && target.getParameters().length !== wraps.arity) {
@@ -13604,29 +13718,136 @@ function discoverWrapperRegistrations(sourceFile, pattern, match, wraps, resolut
13604
13718
  if (scope === null) {
13605
13719
  return;
13606
13720
  }
13607
- const subjectId = nodeId(subjectNode);
13608
13721
  const mountedScope = scope === void 0 ? void 0 : mountedAt(subjectId, mountPrefixes, scope);
13609
- const named2 = functionNameOrAnon(target) !== ANONYMOUS;
13610
- candidates.push({
13611
- subjectId,
13612
- callId: nodeId(node),
13613
- targetId: nodeId(target),
13614
- byArity: wraps.arity !== void 0,
13615
- target,
13616
- pattern,
13617
- registeredIn: sourceFile.getFilePath(),
13618
- named: named2,
13619
- reference: {
13620
- file: target.getSourceFile().getFilePath(),
13621
- // A function written out at the registration call has no name
13622
- // of its own, so it goes by the method that registered it.
13623
- name: named2 ? functionNameOrAnon(target) : wraps.method,
13624
- ...wraps.throwParam === void 0 ? {} : { onThrow: true },
13625
- ...mountedScope === void 0 ? {} : { scope: mountedScope }
13626
- }
13627
- });
13722
+ candidates.push(
13723
+ candidateOf(
13724
+ {
13725
+ subjectId,
13726
+ callId: nodeId(node),
13727
+ target,
13728
+ label: labelFor(targetArg, wraps),
13729
+ byArity: wraps.arity !== void 0,
13730
+ onThrow: wraps.throwParam !== void 0,
13731
+ scope: mountedScope
13732
+ },
13733
+ pattern,
13734
+ sourceFile
13735
+ )
13736
+ );
13628
13737
  });
13629
- return candidates;
13738
+ return { candidates, unresolved };
13739
+ }
13740
+ function discoverConstructorOptions(sourceFile, pattern, wraps, subjects, resolution) {
13741
+ const candidates = [];
13742
+ const unresolved = [];
13743
+ const seen = /* @__PURE__ */ new Set();
13744
+ for (const construction of subjects.values()) {
13745
+ const subjectId = nodeId(construction);
13746
+ if (seen.has(subjectId) || construction.getSourceFile() !== sourceFile) {
13747
+ continue;
13748
+ }
13749
+ seen.add(subjectId);
13750
+ const option = constructorOptionOf(construction, wraps, resolution);
13751
+ if (option === void 0) {
13752
+ continue;
13753
+ }
13754
+ const callId = nodeId(option);
13755
+ const written = propertyValueOf(option);
13756
+ const target = propertyFunctionOf(option, resolution);
13757
+ if (target === null) {
13758
+ const stop = written === null ? null : factoryStopOf(written);
13759
+ if (stop !== null) {
13760
+ unresolved.push({ subjectId, callId, stop });
13761
+ }
13762
+ continue;
13763
+ }
13764
+ candidates.push(
13765
+ candidateOf(
13766
+ {
13767
+ subjectId,
13768
+ callId,
13769
+ target,
13770
+ label: (written === null ? void 0 : factoryNameOf(written)) ?? wraps.constructorOption,
13771
+ byArity: false,
13772
+ onThrow: wraps.throwParam !== void 0,
13773
+ scope: void 0
13774
+ },
13775
+ pattern,
13776
+ sourceFile
13777
+ )
13778
+ );
13779
+ }
13780
+ return { candidates, unresolved };
13781
+ }
13782
+ function constructorOptionOf(construction, wraps, resolution) {
13783
+ if (!(import_ts_morph60.Node.isNewExpression(construction) || import_ts_morph60.Node.isCallExpression(construction))) {
13784
+ return void 0;
13785
+ }
13786
+ const optionsArg = construction.getArguments()[wraps.targetPosition];
13787
+ if (optionsArg === void 0) {
13788
+ return void 0;
13789
+ }
13790
+ const options = objectLiteralOf(optionsArg, resolution);
13791
+ if (options === null) {
13792
+ return void 0;
13793
+ }
13794
+ return propertiesOf(options, resolution).find(
13795
+ (property) => propertyNameOf(property) === wraps.constructorOption
13796
+ );
13797
+ }
13798
+ function candidateOf(registration, pattern, sourceFile) {
13799
+ const { target, label, onThrow, scope } = registration;
13800
+ const named2 = functionNameOrAnon(target) !== ANONYMOUS;
13801
+ return {
13802
+ subjectId: registration.subjectId,
13803
+ callId: registration.callId,
13804
+ targetId: nodeId(target),
13805
+ byArity: registration.byArity,
13806
+ target,
13807
+ pattern,
13808
+ registeredIn: sourceFile.getFilePath(),
13809
+ named: named2,
13810
+ reference: {
13811
+ file: target.getSourceFile().getFilePath(),
13812
+ name: named2 ? functionNameOrAnon(target) : label,
13813
+ ...onThrow ? { onThrow: true } : {},
13814
+ ...scope === void 0 ? {} : { scope }
13815
+ }
13816
+ };
13817
+ }
13818
+ function labelFor(targetArg, wraps) {
13819
+ return factoryNameOf(targetArg) ?? wraps.method;
13820
+ }
13821
+ function factoryNameOf(targetArg) {
13822
+ const written = factKeyOf(targetArg);
13823
+ if (!import_ts_morph60.Node.isCallExpression(written)) {
13824
+ return void 0;
13825
+ }
13826
+ const callee = written.getExpression();
13827
+ if (import_ts_morph60.Node.isIdentifier(callee)) {
13828
+ return callee.getText();
13829
+ }
13830
+ if (import_ts_morph60.Node.isPropertyAccessExpression(callee)) {
13831
+ return callee.getName();
13832
+ }
13833
+ return void 0;
13834
+ }
13835
+ function factoryStopOf(targetArg) {
13836
+ const written = factKeyOf(targetArg);
13837
+ if (!import_ts_morph60.Node.isCallExpression(written)) {
13838
+ return null;
13839
+ }
13840
+ const callee = factoryNameOf(targetArg);
13841
+ if (callee === void 0) {
13842
+ return null;
13843
+ }
13844
+ const reason = classifyStop(
13845
+ declarationsBehind(written.getExpression().getSymbol())
13846
+ );
13847
+ if (!(0, import_behavioral_ir2.worthRecording)(reason)) {
13848
+ return null;
13849
+ }
13850
+ return { callee, reason: "unresolvedWrapper" };
13630
13851
  }
13631
13852
  function mountedAt(subjectId, mountPrefixes, scope) {
13632
13853
  const prefix = mountPrefixes?.prefixForId?.(subjectId) ?? "";
@@ -13998,22 +14219,23 @@ var import_ts_morph62 = require("ts-morph");
13998
14219
  var import_behavioral_ir6 = require("@suss/behavioral-ir");
13999
14220
  var import_datalog4 = require("@suss/datalog");
14000
14221
  var import_extractor7 = require("@suss/extractor");
14222
+ var GENERIC_TERMINALS = [
14223
+ { kind: "return", match: { type: "returnStatement" }, extraction: {} },
14224
+ { kind: "throw", match: { type: "throwExpression" }, extraction: {} },
14225
+ {
14226
+ // Implicit fall-through at the end of a function body: covers
14227
+ // void-returning orchestrators that never write `return`.
14228
+ kind: "return",
14229
+ match: { type: "functionFallthrough" },
14230
+ extraction: {}
14231
+ }
14232
+ ];
14001
14233
  var reachablePack = {
14002
14234
  name: "reachable",
14003
14235
  languages: ["typescript"],
14004
14236
  protocol: "in-process",
14005
14237
  discovery: [],
14006
- terminals: [
14007
- { kind: "return", match: { type: "returnStatement" }, extraction: {} },
14008
- { kind: "throw", match: { type: "throwExpression" }, extraction: {} },
14009
- {
14010
- // Implicit fall-through at the end of a function body: covers
14011
- // void-returning orchestrators that never write `return`.
14012
- kind: "return",
14013
- match: { type: "functionFallthrough" },
14014
- extraction: {}
14015
- }
14016
- ],
14238
+ terminals: GENERIC_TERMINALS,
14017
14239
  inputMapping: { type: "allPositional" }
14018
14240
  };
14019
14241
  function nodeKey(func) {
@@ -15807,10 +16029,10 @@ var FUNCTION_FALLTHROUGH_TERMINAL = {
15807
16029
  match: { type: "functionFallthrough" },
15808
16030
  extraction: {}
15809
16031
  };
15810
- function thrownValueAt(unit) {
15811
- return unit.pattern?.wraps?.throwParam;
16032
+ function frameworkValueAt(unit) {
16033
+ return unit.pattern?.wraps?.throwParam ?? unit.pattern?.wraps?.resultParam;
15812
16034
  }
15813
- function pastThrownValue(terminals, at) {
16035
+ function pastFrameworkValue(terminals, at) {
15814
16036
  if (at === void 0) {
15815
16037
  return terminals;
15816
16038
  }
@@ -15824,7 +16046,7 @@ function pastThrownValue(terminals, at) {
15824
16046
  } : pattern
15825
16047
  );
15826
16048
  }
15827
- function rolesPastThrownValue(mapping, at) {
16049
+ function rolesPastFrameworkValue(mapping, at) {
15828
16050
  if (at === void 0 || mapping.type !== "positionalParams") {
15829
16051
  return mapping;
15830
16052
  }
@@ -15850,7 +16072,7 @@ function continuationTerminal(unit) {
15850
16072
  }
15851
16073
  function terminalsFor(unit, pack) {
15852
16074
  const declared = [
15853
- ...unit.terminals ?? pastThrownValue(pack.terminals, thrownValueAt(unit)),
16075
+ ...unit.terminals ?? pastFrameworkValue(pack.terminals, frameworkValueAt(unit)),
15854
16076
  ...continuationTerminal(unit)
15855
16077
  ];
15856
16078
  if (unit.callSite === void 0) {
@@ -15868,7 +16090,7 @@ function readCodeStructure(unit, pack, invocationRecognizers, accessRecognizers,
15868
16090
  }
15869
16091
  const params = extractParameters(
15870
16092
  func,
15871
- unit.inputMapping ?? rolesPastThrownValue(pack.inputMapping, thrownValueAt(unit))
16093
+ unit.inputMapping ?? rolesPastFrameworkValue(pack.inputMapping, frameworkValueAt(unit))
15872
16094
  );
15873
16095
  const extracted = extractRawBranches(
15874
16096
  func,
@@ -16370,8 +16592,10 @@ function extractFromSourceFile(sourceFile, frameworks, claimedUnits, options, ta
16370
16592
  }
16371
16593
  }
16372
16594
  const summary = (0, import_extractor11.assembleSummary)(raw, options);
16373
- if (unit.unfollowed !== void 0 && options?.gapHandling !== "silent") {
16374
- summary.gaps.push((0, import_behavioral_ir2.unfollowedCallGap)(unit.unfollowed));
16595
+ if (options?.gapHandling !== "silent") {
16596
+ for (const stop of unfollowedStopsOf(unit, wrappers)) {
16597
+ summary.gaps.push((0, import_behavioral_ir2.unfollowedCallGap)(stop));
16598
+ }
16375
16599
  }
16376
16600
  if (unit.metadata !== void 0 && Object.keys(unit.metadata).length > 0) {
16377
16601
  summary.metadata = {
@@ -16424,6 +16648,13 @@ function stampWrappers(raw, unit, wrappers) {
16424
16648
  recordFileDependency(wrapper.file);
16425
16649
  }
16426
16650
  }
16651
+ function unfollowedStopsOf(unit, wrappers) {
16652
+ const stops = unit.unfollowed === void 0 ? [] : [unit.unfollowed];
16653
+ if (wrappers === void 0 || unit.registrationSubjectId === void 0) {
16654
+ return stops;
16655
+ }
16656
+ return [...stops, ...wrappers.unfollowedFor(unit.registrationSubjectId)];
16657
+ }
16427
16658
  function emitLibraryEnvReadMarkers(summaries, project, frameworks) {
16428
16659
  for (const pack of frameworks) {
16429
16660
  for (const declared of pack.libraryEnvVars ?? []) {
@@ -17138,7 +17369,7 @@ function createTypeScriptAdapter(suppliedConfig) {
17138
17369
  });
17139
17370
  const composed = timer.time(
17140
17371
  "composeWrappers",
17141
- () => (0, import_extractor11.composeWrappers)(enriched)
17372
+ () => (0, import_extractor11.composeWrappers)(enriched, config.extractorOptions ?? {})
17142
17373
  );
17143
17374
  if (config.onTiming !== void 0) {
17144
17375
  config.onTiming(timer.report());
@@ -17758,6 +17989,8 @@ function stubEvidence(options) {
17758
17989
  // Annotate the CommonJS export names for ESM import in node:
17759
17990
  0 && (module.exports = {
17760
17991
  ADAPTER_VERSION,
17992
+ GENERIC_TERMINALS,
17993
+ NO_BARRIERS,
17761
17994
  ResolutionStore,
17762
17995
  TypeScriptWhySession,
17763
17996
  accessContextFor,
@@ -17778,6 +18011,7 @@ function stubEvidence(options) {
17778
18011
  findNearestTsconfig,
17779
18012
  findTerminals,
17780
18013
  functionTargetOf,
18014
+ hasBody,
17781
18015
  importDeclarationsOf,
17782
18016
  importedNamesOf,
17783
18017
  importedRootsOf,
@@ -17793,6 +18027,7 @@ function stubEvidence(options) {
17793
18027
  resolveAliasedSymbol,
17794
18028
  resolveSubject,
17795
18029
  rootIdentifier,
18030
+ startsItsOwnScope,
17796
18031
  stubEvidence,
17797
18032
  stubEvidenceIn,
17798
18033
  workspaceRootFor