@chenglou/freerange 0.0.2 → 0.0.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/fr.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // src/project.ts
4
4
  import { existsSync, realpathSync } from "node:fs";
5
5
  import { resolve as resolve3 } from "node:path";
6
- import * as ts12 from "typescript";
6
+ import * as ts14 from "typescript";
7
7
 
8
8
  // src/domain/number.ts
9
9
  var float64Scratch = new Float64Array(1);
@@ -663,6 +663,7 @@ function declaredKindOf(category) {
663
663
  case "kind":
664
664
  return category.declaredKind;
665
665
  case "importedConstant":
666
+ case "function":
666
667
  case "import":
667
668
  case "opaque":
668
669
  return null;
@@ -775,20 +776,61 @@ function siteLocation(program, site) {
775
776
  return { line: low + 1, column: span.start - lineStarts[low] + 1 };
776
777
  }
777
778
 
778
- // src/requirements/infer.ts
779
- function createExpressionContext(fn, parameterExpressions, parameterIdentityKeys, identityNamespace = `${fn.name}/`) {
780
- const identityKeys = parameterIdentityKeys ?? fn.parameters.map((_, index) => `p${index}`);
781
- if (identityKeys.length !== fn.parameters.length) {
782
- throw new Error(`Expected ${fn.parameters.length} parameter identity keys for ${fn.name}`);
779
+ // src/domain/value-identity.ts
780
+ function createValueIdentityOwner(parent = null) {
781
+ return { kind: "valueIdentityOwner", parent };
782
+ }
783
+ function sameValueIdentity(left, right) {
784
+ if (left === right)
785
+ return true;
786
+ if (left.kind !== right.kind)
787
+ return false;
788
+ switch (left.kind) {
789
+ case "local":
790
+ return right.kind === "local" && left.owner === right.owner && left.value === right.value;
791
+ case "property":
792
+ return right.kind === "property" && left.property === right.property && sameValueIdentity(left.object, right.object);
793
+ case "arrayIndex":
794
+ return right.kind === "arrayIndex" && sameValueIdentity(left.array, right.array) && sameValueIdentity(left.index, right.index);
783
795
  }
796
+ }
797
+ function valueIdentityUsesOwner(identity, owner) {
798
+ switch (identity.kind) {
799
+ case "local": {
800
+ let current = identity.owner;
801
+ while (current != null) {
802
+ if (current === owner)
803
+ return true;
804
+ current = current.parent;
805
+ }
806
+ return false;
807
+ }
808
+ case "property":
809
+ return valueIdentityUsesOwner(identity.object, owner);
810
+ case "arrayIndex":
811
+ return valueIdentityUsesOwner(identity.array, owner) || valueIdentityUsesOwner(identity.index, owner);
812
+ }
813
+ }
814
+
815
+ // src/requirements/infer.ts
816
+ function createExpressionContext(fn, parameterExpressions, parameterIdentities, identityOwner = createValueIdentityOwner()) {
784
817
  const context = {
785
818
  parameterExpressions,
786
- parameterIdentityKeys: identityKeys,
787
- identityNamespace,
819
+ parameterIdentities: [],
820
+ identityOwner,
821
+ identityByValue: [],
788
822
  parameterIndexByValue: [],
789
823
  instructionByValue: [],
790
824
  instructionCount: 0
791
825
  };
826
+ context.parameterIdentities = parameterIdentities ?? fn.parameters.map((parameter) => ({
827
+ kind: "local",
828
+ owner: identityOwner,
829
+ value: parameter.value
830
+ }));
831
+ if (context.parameterIdentities.length !== fn.parameters.length) {
832
+ throw new Error(`Expected ${fn.parameters.length} parameter identities for ${fn.name}`);
833
+ }
792
834
  for (let index = 0;index < fn.parameters.length; index++) {
793
835
  context.parameterIndexByValue[fn.parameters[index].value] = index;
794
836
  }
@@ -891,28 +933,58 @@ function staticRequirement(instruction, site, context, purpose) {
891
933
  }
892
934
  return null;
893
935
  }
894
- function canonicalValueKey(value, context) {
936
+ function canonicalValueIdentity(value, context) {
937
+ const cached = context.identityByValue[value];
938
+ if (cached != null)
939
+ return cached;
895
940
  const stored = resolveStoredValue(value, context);
896
- if (stored !== value)
897
- return canonicalValueKey(stored, context);
941
+ if (stored !== value) {
942
+ const identity2 = canonicalValueIdentity(stored, context);
943
+ context.identityByValue[value] = identity2;
944
+ return identity2;
945
+ }
898
946
  const parameterIndex = context.parameterIndexByValue[value];
899
- if (parameterIndex != null)
900
- return context.parameterIdentityKeys[parameterIndex] ?? `p${parameterIndex}`;
947
+ if (parameterIndex != null) {
948
+ const identity2 = context.parameterIdentities[parameterIndex];
949
+ if (identity2 == null)
950
+ throw new Error(`Missing identity for parameter ${parameterIndex}`);
951
+ context.identityByValue[value] = identity2;
952
+ return identity2;
953
+ }
901
954
  const producer = context.instructionByValue[value];
955
+ let identity;
902
956
  if (producer?.kind === "property") {
903
- return `${canonicalValueKey(producer.object, context)}.${JSON.stringify(producer.property)}`;
904
- }
905
- if (producer?.kind === "arrayLength")
906
- return `${canonicalValueKey(producer.array, context)}.length`;
907
- if (producer?.kind === "stringLength")
908
- return `${canonicalValueKey(producer.value, context)}.length`;
909
- if (producer?.kind === "arrayIndex") {
910
- return `${canonicalValueKey(producer.array, context)}[${canonicalValueKey(producer.index, context)}]`;
957
+ identity = {
958
+ kind: "property",
959
+ object: canonicalValueIdentity(producer.object, context),
960
+ property: producer.property
961
+ };
962
+ } else if (producer?.kind === "arrayLength") {
963
+ identity = {
964
+ kind: "property",
965
+ object: canonicalValueIdentity(producer.array, context),
966
+ property: "length"
967
+ };
968
+ } else if (producer?.kind === "stringLength") {
969
+ identity = {
970
+ kind: "property",
971
+ object: canonicalValueIdentity(producer.value, context),
972
+ property: "length"
973
+ };
974
+ } else if (producer?.kind === "arrayIndex") {
975
+ identity = {
976
+ kind: "arrayIndex",
977
+ array: canonicalValueIdentity(producer.array, context),
978
+ index: canonicalValueIdentity(producer.index, context)
979
+ };
980
+ } else {
981
+ identity = { kind: "local", owner: context.identityOwner, value };
911
982
  }
912
- return `v:${context.identityNamespace}${value}`;
983
+ context.identityByValue[value] = identity;
984
+ return identity;
913
985
  }
914
986
  function sameRuntimeValue(left, right, context) {
915
- return left === right || canonicalValueKey(left, context) === canonicalValueKey(right, context);
987
+ return left === right || sameValueIdentity(canonicalValueIdentity(left, context), canonicalValueIdentity(right, context));
916
988
  }
917
989
  function addPrecondition(preconditions, candidate) {
918
990
  if (candidate.kind === "declaredNumberCheck") {
@@ -1078,10 +1150,10 @@ function completedEvaluation(evaluation) {
1078
1150
 
1079
1151
  // src/engine/state.ts
1080
1152
  function hasNonzeroFact(facts, value) {
1081
- return facts.some((fact) => fact.kind === "nonzero" && fact.value === value);
1153
+ return facts.some((fact) => fact.kind === "nonzero" && sameValueIdentity(fact.value, value));
1082
1154
  }
1083
1155
  function hasIndexFact(facts, kind, index, array) {
1084
- return facts.some((fact) => fact.kind === kind && fact.index === index && fact.array === array);
1156
+ return facts.some((fact) => fact.kind === kind && sameValueIdentity(fact.index, index) && sameValueIdentity(fact.array, array));
1085
1157
  }
1086
1158
  function addValueFact(facts, candidate) {
1087
1159
  if (!facts.some((fact) => sameValueFact(fact, candidate)))
@@ -1103,18 +1175,19 @@ function intersectValueFact(left, right) {
1103
1175
  return left;
1104
1176
  if (left.kind === "nonzero" || right.kind === "nonzero")
1105
1177
  return null;
1106
- if (left.index !== right.index || left.array !== right.array)
1178
+ if (!sameValueIdentity(left.index, right.index) || !sameValueIdentity(left.array, right.array))
1107
1179
  return null;
1108
1180
  return { kind: "belowLength", index: left.index, array: left.array };
1109
1181
  }
1110
1182
  function sameValueFact(left, right) {
1111
1183
  if (left.kind !== right.kind)
1112
1184
  return false;
1113
- if (left.kind === "nonzero" && right.kind === "nonzero")
1114
- return left.value === right.value;
1185
+ if (left.kind === "nonzero" && right.kind === "nonzero") {
1186
+ return sameValueIdentity(left.value, right.value);
1187
+ }
1115
1188
  if (left.kind === "nonzero" || right.kind === "nonzero")
1116
1189
  return false;
1117
- return left.index === right.index && left.array === right.array;
1190
+ return sameValueIdentity(left.index, right.index) && sameValueIdentity(left.array, right.array);
1118
1191
  }
1119
1192
  function emptySharedState(moduleCount) {
1120
1193
  return Array.from({ length: moduleCount }, () => null);
@@ -1268,10 +1341,10 @@ function evaluateInstructionKinded(instruction, state, context) {
1268
1341
  const index = requiredNumberWithFacts(state, instruction.index, context.expressionContext);
1269
1342
  const element = sequence.kind === "tuple" ? tupleElement(sequence, index) : sequence.element;
1270
1343
  const length = sequence.kind === "tuple" ? constantNumber(sequence.elements.length) : sequence.length;
1271
- const indexKey = canonicalValueKey(instruction.index, context.expressionContext);
1272
- const arrayKey = canonicalValueKey(instruction.array, context.expressionContext);
1273
- const assumedValid = hasIndexFact(state.valueFacts, "validIndex", indexKey, arrayKey);
1274
- const inBounds = assumedValid || index.integer && !index.mayBeNaN && index.lower >= 0 && index.upper < length.lower || index.integer && !index.mayBeNaN && index.lower >= 0 && hasIndexFact(state.valueFacts, "belowLength", indexKey, arrayKey);
1344
+ const indexIdentity = canonicalValueIdentity(instruction.index, context.expressionContext);
1345
+ const arrayIdentity = canonicalValueIdentity(instruction.array, context.expressionContext);
1346
+ const assumedValid = hasIndexFact(state.valueFacts, "validIndex", indexIdentity, arrayIdentity);
1347
+ const inBounds = assumedValid || index.integer && !index.mayBeNaN && index.lower >= 0 && index.upper < length.lower || index.integer && !index.mayBeNaN && index.lower >= 0 && hasIndexFact(state.valueFacts, "belowLength", indexIdentity, arrayIdentity);
1275
1348
  const firstPossibleIndex = Math.ceil(Math.max(index.lower, 0));
1276
1349
  const lastPossibleIndex = Math.floor(Math.min(index.upper, length.upper - 1));
1277
1350
  const provablyOut = element == null || firstPossibleIndex > lastPossibleIndex;
@@ -1298,7 +1371,11 @@ function evaluateInstructionKinded(instruction, state, context) {
1298
1371
  addBoundsAssumption(context.boundsAssumptions, { site: instruction.site, kind: "elementInBounds" });
1299
1372
  }
1300
1373
  writeThroughProducers(state, instruction.index, validIndexNumber(index), context.expressionContext.instructionByValue);
1301
- addValueFact(state.valueFacts, { kind: "validIndex", index: indexKey, array: arrayKey });
1374
+ addValueFact(state.valueFacts, {
1375
+ kind: "validIndex",
1376
+ index: indexIdentity,
1377
+ array: arrayIdentity
1378
+ });
1302
1379
  }
1303
1380
  return passthroughValue(element);
1304
1381
  }
@@ -1507,6 +1584,15 @@ function evaluateInstructionKinded(instruction, state, context) {
1507
1584
  return computedNumber(maximumNumbers(operands), operands, instruction.site);
1508
1585
  }
1509
1586
  case "call": {
1587
+ if (instruction.binding != null && state.shared[instruction.binding] == null) {
1588
+ return {
1589
+ kind: "stop",
1590
+ stop: {
1591
+ site: instruction.site,
1592
+ reason: { kind: "moduleRead", binding: instruction.binding }
1593
+ }
1594
+ };
1595
+ }
1510
1596
  const callee = context.program.functions[instruction.function];
1511
1597
  if (callee == null)
1512
1598
  throw new Error(`Unknown function ${instruction.function}`);
@@ -1518,9 +1604,9 @@ function evaluateInstructionKinded(instruction, state, context) {
1518
1604
  }
1519
1605
  const arguments_ = instruction.arguments.map((id) => requiredValue(state, id));
1520
1606
  const argumentExpressions = instruction.arguments.map((id) => numericExpression(id, context.expressionContext));
1521
- const argumentKeys = instruction.arguments.map((id) => canonicalValueKey(id, context.expressionContext));
1522
- const calleeNamespace = `${context.expressionContext.identityNamespace}call:${instruction.function}:${instruction.site}/`;
1523
- const evaluation = context.evaluateFunction(instruction.function, arguments_, argumentExpressions, state.shared, context.callStack, state.valueFacts, argumentKeys, calleeNamespace);
1607
+ const argumentIdentities = instruction.arguments.map((id) => canonicalValueIdentity(id, context.expressionContext));
1608
+ const calleeOwner = createValueIdentityOwner(context.expressionContext.identityOwner);
1609
+ const evaluation = context.evaluateFunction(instruction.function, arguments_, argumentExpressions, state.shared, context.callStack, state.valueFacts, argumentIdentities, calleeOwner);
1524
1610
  const completed = completedEvaluation(evaluation);
1525
1611
  if (completed == null) {
1526
1612
  if (evaluation.stops.length === 0 && evaluation.normal == null) {
@@ -1541,7 +1627,7 @@ function evaluateInstructionKinded(instruction, state, context) {
1541
1627
  return { kind: "stop", stop: { site: instruction.site, reason: { kind: "calleeStopped", callee: instruction.function } } };
1542
1628
  }
1543
1629
  state.shared = completed.sharedState;
1544
- state.valueFacts = completed.valueFacts.filter((fact) => !valueFactUsesNamespace(fact, calleeNamespace));
1630
+ state.valueFacts = completed.valueFacts.filter((fact) => !valueFactUsesOwner(fact, calleeOwner));
1545
1631
  for (let index = 0;index < callee.parameters.length; index++) {
1546
1632
  refineFiniteCallArgument(state, instruction.arguments[index], callee.parameters[index].type, context.expressionContext);
1547
1633
  }
@@ -1583,11 +1669,10 @@ function addBoundsAssumption(assumptions, candidate) {
1583
1669
  assumptions.push(candidate);
1584
1670
  }
1585
1671
  }
1586
- function valueFactUsesNamespace(fact, namespace) {
1587
- const marker = `v:${namespace}`;
1672
+ function valueFactUsesOwner(fact, owner) {
1588
1673
  if (fact.kind === "nonzero")
1589
- return fact.value.includes(marker);
1590
- return fact.index.includes(marker) || fact.array.includes(marker);
1674
+ return valueIdentityUsesOwner(fact.value, owner);
1675
+ return valueIdentityUsesOwner(fact.index, owner) || valueIdentityUsesOwner(fact.array, owner);
1591
1676
  }
1592
1677
  function sentinelsAdmit(sentinels, sentinel) {
1593
1678
  return sentinels === "both" || sentinels === sentinel;
@@ -1947,8 +2032,8 @@ function refineComparison(state, comparison, truth, expressionContext) {
1947
2032
  if (rightProducer?.kind === "arrayLength") {
1948
2033
  addValueFact(result.valueFacts, {
1949
2034
  kind: "belowLength",
1950
- index: canonicalValueKey(comparison.left, expressionContext),
1951
- array: canonicalValueKey(rightProducer.array, expressionContext)
2035
+ index: canonicalValueIdentity(comparison.left, expressionContext),
2036
+ array: canonicalValueIdentity(rightProducer.array, expressionContext)
1952
2037
  });
1953
2038
  }
1954
2039
  }
@@ -1957,8 +2042,8 @@ function refineComparison(state, comparison, truth, expressionContext) {
1957
2042
  if (leftProducer?.kind === "arrayLength") {
1958
2043
  addValueFact(result.valueFacts, {
1959
2044
  kind: "belowLength",
1960
- index: canonicalValueKey(comparison.right, expressionContext),
1961
- array: canonicalValueKey(leftProducer.array, expressionContext)
2045
+ index: canonicalValueIdentity(comparison.right, expressionContext),
2046
+ array: canonicalValueIdentity(leftProducer.array, expressionContext)
1962
2047
  });
1963
2048
  }
1964
2049
  }
@@ -2013,12 +2098,13 @@ function numberWithFacts(state, id, expressionContext) {
2013
2098
  if (held?.kind !== "number")
2014
2099
  return null;
2015
2100
  let result = held;
2016
- const key = canonicalValueKey(id, expressionContext);
2017
- if (state.valueFacts.some((fact) => fact.kind === "validIndex" && fact.index === key)) {
2101
+ const identity = canonicalValueIdentity(id, expressionContext);
2102
+ if (state.valueFacts.some((fact) => fact.kind === "validIndex" && sameValueIdentity(fact.index, identity))) {
2018
2103
  result = validIndexNumber(result);
2019
2104
  }
2020
- if (hasNonzeroFact(state.valueFacts, key))
2105
+ if (hasNonzeroFact(state.valueFacts, identity)) {
2021
2106
  result = excludePointFrom(result, constantNumber(0));
2107
+ }
2022
2108
  return result;
2023
2109
  }
2024
2110
  function validIndexNumber(value2) {
@@ -2040,7 +2126,10 @@ function recordNonzeroComparisonFacts(state, check, expressionContext) {
2040
2126
  }
2041
2127
  }
2042
2128
  function recordNonzeroValueFact(state, value2, expressionContext) {
2043
- addValueFact(state.valueFacts, { kind: "nonzero", value: canonicalValueKey(value2, expressionContext) });
2129
+ addValueFact(state.valueFacts, {
2130
+ kind: "nonzero",
2131
+ value: canonicalValueIdentity(value2, expressionContext)
2132
+ });
2044
2133
  }
2045
2134
  function requiredBoolean(state, id) {
2046
2135
  const value2 = requiredValue(state, id);
@@ -2431,7 +2520,7 @@ function analyzeProgram(program) {
2431
2520
  initializerState[binding] = constantNumber(category.value);
2432
2521
  }
2433
2522
  }
2434
- const initializer = runEvaluation(program.initializer, null, [], [], initializerState, program, [], { identityNamespace: "module/" });
2523
+ const initializer = runEvaluation(program.initializer, null, [], [], initializerState, program, []);
2435
2524
  const moduleValues = publishedModuleValues(program, initializer.run, initializer.evaluation);
2436
2525
  const functionEntrySharedState = seedModuleSlots(program, moduleValues);
2437
2526
  const moduleReads = transitiveModuleBindings(functionUsage(program));
@@ -2452,8 +2541,7 @@ function analyzeProgram(program) {
2452
2541
  argumentExpressions.push({ kind: "parameter", index });
2453
2542
  }
2454
2543
  const { evaluation } = runEvaluation(fn, functionID, arguments_, argumentExpressions, sharedState, program, [], {
2455
- boundsAssumptions: moduleReads[functionID].size > 0 ? initializerBounds : [],
2456
- identityNamespace: `function:${functionID}/`
2544
+ boundsAssumptions: moduleReads[functionID].size > 0 ? initializerBounds : []
2457
2545
  });
2458
2546
  functions.push(publishedAnalysis(fn, evaluation));
2459
2547
  }
@@ -2567,9 +2655,9 @@ function publishedModuleValues(program, run, evaluation) {
2567
2655
  }
2568
2656
  const fullyAnalyzed = evaluation.stops.length === 0 && program.initializerSkips.length === 0 && program.functions.every((lowered) => lowered.kind === "lowered");
2569
2657
  return program.moduleBindings.map((binding, index) => {
2570
- if (binding.category.kind !== "value" || demoted.has(index))
2658
+ if (binding.category.kind !== "value" && binding.category.kind !== "function" || demoted.has(index))
2571
2659
  return null;
2572
- if (holdsMutableStructure(binding.category.declaredKind) && !fullyAnalyzed)
2660
+ if (binding.category.kind === "value" && holdsMutableStructure(binding.category.declaredKind) && !fullyAnalyzed)
2573
2661
  return null;
2574
2662
  const slot = end?.[index];
2575
2663
  return slot ?? null;
@@ -2588,7 +2676,7 @@ function runEvaluation(fn, functionID, arguments_, argumentExpressions, sharedSt
2588
2676
  for (let index = 0;index < fn.parameters.length; index++) {
2589
2677
  initial.values[fn.parameters[index].value] = arguments_[index];
2590
2678
  }
2591
- const expressionContext = createExpressionContext(fn, argumentExpressions, seed.parameterIdentityKeys, seed.identityNamespace ?? fn.name);
2679
+ const expressionContext = createExpressionContext(fn, argumentExpressions, seed.parameterIdentities, seed.identityOwner);
2592
2680
  const preconditions = [];
2593
2681
  const boundsAssumptions = [...seed.boundsAssumptions ?? []];
2594
2682
  const successors = blockSuccessors(fn);
@@ -2607,13 +2695,13 @@ function runEvaluation(fn, functionID, arguments_, argumentExpressions, sharedSt
2607
2695
  expressionContext,
2608
2696
  preconditions,
2609
2697
  boundsAssumptions,
2610
- evaluateFunction: (callee, values, expressions, calleeState, stack, valueFacts, parameterIdentityKeys, identityNamespace) => {
2698
+ evaluateFunction: (callee, values, expressions, calleeState, stack, valueFacts, parameterIdentities, identityOwner) => {
2611
2699
  const calleeFn = program.functions[callee];
2612
2700
  if (calleeFn == null)
2613
2701
  throw new Error(`Unknown function ${callee}`);
2614
2702
  if (calleeFn.kind !== "lowered")
2615
2703
  throw new Error(`Analysis reached unlowered function ${calleeFn.name}`);
2616
- return runEvaluation(calleeFn, callee, values, expressions, calleeState, program, stack, { valueFacts, parameterIdentityKeys, identityNamespace }).evaluation;
2704
+ return runEvaluation(calleeFn, callee, values, expressions, calleeState, program, stack, { valueFacts, parameterIdentities, identityOwner }).evaluation;
2617
2705
  }
2618
2706
  };
2619
2707
  let queueIndex = 0;
@@ -2887,17 +2975,18 @@ function reachableFrom(successors, start) {
2887
2975
  }
2888
2976
 
2889
2977
  // src/lower/program.ts
2890
- import * as ts8 from "typescript";
2978
+ import * as ts10 from "typescript";
2891
2979
 
2892
2980
  // src/lower/accept.ts
2893
2981
  import * as ts from "typescript";
2894
2982
 
2895
2983
  // src/lower/context.ts
2896
- function createFunctionContext(sourceFile, checker, functionsBySymbol, moduleBindingsBySymbol, sites, staticAnnotations = []) {
2984
+ function createFunctionContext(sourceFile, checker, program, functionsBySymbol, moduleBindingsBySymbol, sites, staticAnnotations = [], returnsVoid = true) {
2897
2985
  const entry = { loopHeader: null, parameters: [], instructions: [], terminator: null };
2898
2986
  return {
2899
2987
  sourceFile,
2900
2988
  checker,
2989
+ program,
2901
2990
  functionsBySymbol,
2902
2991
  moduleBindingsBySymbol,
2903
2992
  staticAnnotations: new Map(staticAnnotations.map((annotation) => [annotation.call, annotation])),
@@ -2908,6 +2997,7 @@ function createFunctionContext(sourceFile, checker, functionsBySymbol, moduleBin
2908
2997
  bindings: new Map,
2909
2998
  parameters: [],
2910
2999
  assertions: [],
3000
+ returnsVoid,
2911
3001
  loops: []
2912
3002
  };
2913
3003
  }
@@ -3025,8 +3115,10 @@ function unsupported(node, reason) {
3025
3115
  }
3026
3116
 
3027
3117
  // src/lower/accept.ts
3028
- function assertAccepted(root) {
3118
+ function assertAccepted(root, deferFunctionBodies = false) {
3029
3119
  const visit = (node) => {
3120
+ if (deferFunctionBodies && node !== root && ts.isFunctionLike(node))
3121
+ return;
3030
3122
  if (ts.isTypeNode(node))
3031
3123
  return;
3032
3124
  if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node) || ts.isJsxFragment(node)) {
@@ -3101,11 +3193,29 @@ function evalMention(sourceFile) {
3101
3193
  }
3102
3194
 
3103
3195
  // src/lower/expression.ts
3104
- import * as ts4 from "typescript";
3196
+ import * as ts5 from "typescript";
3105
3197
 
3106
- // src/lower/platform.ts
3198
+ // src/lower/numeric-intersection.ts
3107
3199
  import * as ts2 from "typescript";
3200
+ function numberConstituent(type) {
3201
+ if ((type.flags & ts2.TypeFlags.NumberLike) !== 0)
3202
+ return type;
3203
+ if (!type.isIntersection())
3204
+ return null;
3205
+ const numberTypes = type.types.filter((member) => (member.flags & ts2.TypeFlags.NumberLike) !== 0);
3206
+ if (numberTypes.length !== 1)
3207
+ return null;
3208
+ for (const member of type.types) {
3209
+ if (member !== numberTypes[0] && (member.flags & ts2.TypeFlags.Object) === 0)
3210
+ return null;
3211
+ }
3212
+ return numberTypes[0];
3213
+ }
3214
+
3215
+ // src/lower/platform.ts
3216
+ import * as ts3 from "typescript";
3108
3217
  var anyFinite = { lower: -Number.MAX_VALUE, upper: Number.MAX_VALUE };
3218
+ var maximumDateTime = 8640000000000000;
3109
3219
  var catalog = [
3110
3220
  { path: ["document", "documentElement", "clientWidth"], call: false, fact: { lower: 0, upper: Number.MAX_VALUE, integer: true } },
3111
3221
  { path: ["document", "documentElement", "clientHeight"], call: false, fact: { lower: 0, upper: Number.MAX_VALUE, integer: true } },
@@ -3116,25 +3226,32 @@ var catalog = [
3116
3226
  { path: ["document", "body", "scrollTop"], call: false, fact: { ...anyFinite, integer: false } },
3117
3227
  { path: ["document", "body", "scrollLeft"], call: false, fact: { ...anyFinite, integer: false } },
3118
3228
  { path: ["performance", "now"], call: true, fact: { lower: 0, upper: Number.MAX_VALUE, integer: false } },
3119
- { path: ["Date", "now"], call: true, fact: { lower: 0, upper: Number.MAX_VALUE, integer: true } }
3229
+ { path: ["Date", "now"], call: true, fact: { lower: -maximumDateTime, upper: maximumDateTime, integer: true } },
3230
+ { path: ["Math", "random"], call: true, fact: { lower: 0, upper: 0.9999999999999999, integer: false } }
3120
3231
  ];
3121
- function platformFact(expression, call, checker) {
3232
+ function platformFact(expression, call, checker, program) {
3122
3233
  const parts = [];
3123
3234
  let current = expression;
3124
- while (ts2.isPropertyAccessExpression(current)) {
3235
+ while (ts3.isPropertyAccessExpression(current)) {
3125
3236
  parts.unshift(current.name.text);
3126
3237
  current = current.expression;
3127
3238
  }
3128
- if (!ts2.isIdentifier(current))
3239
+ if (!ts3.isIdentifier(current))
3129
3240
  return null;
3130
3241
  parts.unshift(current.text);
3131
3242
  const entry = catalog.find((candidate) => candidate.call === call && candidate.path.length === parts.length && candidate.path.every((segment, index) => segment === parts[index]));
3132
3243
  if (entry == null)
3133
3244
  return null;
3134
- if (!declaredOnlyInDeclarationFiles(checker.getSymbolAtLocation(current)))
3245
+ if (!hasDefaultLibraryDeclaration(checker.getSymbolAtLocation(current), program))
3135
3246
  return null;
3136
3247
  return entry.fact;
3137
3248
  }
3249
+ function hasDefaultLibraryDeclaration(symbol, program) {
3250
+ const declarations = symbol?.declarations;
3251
+ if (declarations == null || declarations.length === 0)
3252
+ return false;
3253
+ return declarations.some((declaration) => program.isSourceFileDefaultLibrary(declaration.getSourceFile()));
3254
+ }
3138
3255
  function declaredOnlyInDeclarationFiles(symbol) {
3139
3256
  const declarations = symbol?.declarations;
3140
3257
  if (declarations == null || declarations.length === 0)
@@ -3143,16 +3260,16 @@ function declaredOnlyInDeclarationFiles(symbol) {
3143
3260
  }
3144
3261
 
3145
3262
  // src/lower/literals.ts
3146
- import * as ts3 from "typescript";
3263
+ import * as ts4 from "typescript";
3147
3264
  function numericLiteralValue(expression) {
3148
3265
  const current = unwrapLiteral(expression);
3149
- if (ts3.isNumericLiteral(current))
3266
+ if (ts4.isNumericLiteral(current))
3150
3267
  return Number(current.text);
3151
- if (ts3.isPrefixUnaryExpression(current) && (current.operator === ts3.SyntaxKind.PlusToken || current.operator === ts3.SyntaxKind.MinusToken)) {
3268
+ if (ts4.isPrefixUnaryExpression(current) && (current.operator === ts4.SyntaxKind.PlusToken || current.operator === ts4.SyntaxKind.MinusToken)) {
3152
3269
  const operand = unwrapLiteral(current.operand);
3153
- if (!ts3.isNumericLiteral(operand))
3270
+ if (!ts4.isNumericLiteral(operand))
3154
3271
  return null;
3155
- return Number(operand.text) * (current.operator === ts3.SyntaxKind.MinusToken ? -1 : 1);
3272
+ return Number(operand.text) * (current.operator === ts4.SyntaxKind.MinusToken ? -1 : 1);
3156
3273
  }
3157
3274
  return null;
3158
3275
  }
@@ -3161,13 +3278,13 @@ function parameterDefaultLiteral(initializer, checker) {
3161
3278
  const number = numericLiteralValue(current);
3162
3279
  if (number != null)
3163
3280
  return Number.isFinite(number) ? { kind: "number", value: number } : null;
3164
- if (current.kind === ts3.SyntaxKind.TrueKeyword || current.kind === ts3.SyntaxKind.FalseKeyword) {
3165
- return { kind: "boolean", value: current.kind === ts3.SyntaxKind.TrueKeyword };
3281
+ if (current.kind === ts4.SyntaxKind.TrueKeyword || current.kind === ts4.SyntaxKind.FalseKeyword) {
3282
+ return { kind: "boolean", value: current.kind === ts4.SyntaxKind.TrueKeyword };
3166
3283
  }
3167
- if (ts3.isStringLiteral(current) || ts3.isNoSubstitutionTemplateLiteral(current)) {
3284
+ if (ts4.isStringLiteral(current) || ts4.isNoSubstitutionTemplateLiteral(current)) {
3168
3285
  return { kind: "opaque", content: current.text };
3169
3286
  }
3170
- if (current.kind === ts3.SyntaxKind.NullKeyword)
3287
+ if (current.kind === ts4.SyntaxKind.NullKeyword)
3171
3288
  return { kind: "nullish", sentinel: "null" };
3172
3289
  if (isUndefinedGlobal(current, checker)) {
3173
3290
  return { kind: "nullish", sentinel: "undefined" };
@@ -3175,10 +3292,10 @@ function parameterDefaultLiteral(initializer, checker) {
3175
3292
  return null;
3176
3293
  }
3177
3294
  function isUndefinedGlobal(expression, checker) {
3178
- if (!ts3.isIdentifier(expression) || expression.text !== "undefined")
3295
+ if (!ts4.isIdentifier(expression) || expression.text !== "undefined")
3179
3296
  return false;
3180
3297
  const symbol = checker.getSymbolAtLocation(expression);
3181
- const global = checker.resolveName("undefined", undefined, ts3.SymbolFlags.Value, false);
3298
+ const global = checker.resolveName("undefined", undefined, ts4.SymbolFlags.Value, false);
3182
3299
  return symbol != null && symbol === global;
3183
3300
  }
3184
3301
  function parameterDefaultFits(default_, declared) {
@@ -3207,7 +3324,7 @@ function parameterDefaultFits(default_, declared) {
3207
3324
  }
3208
3325
  function unwrapLiteral(expression) {
3209
3326
  let current = expression;
3210
- while (ts3.isParenthesizedExpression(current) || ts3.isAsExpression(current) || ts3.isTypeAssertionExpression(current))
3327
+ while (ts4.isParenthesizedExpression(current) || ts4.isAsExpression(current) || ts4.isTypeAssertionExpression(current))
3211
3328
  current = current.expression;
3212
3329
  return current;
3213
3330
  }
@@ -3257,7 +3374,7 @@ function lowerStatementExpression(expression, context) {
3257
3374
  return;
3258
3375
  }
3259
3376
  case "compound": {
3260
- if (assignment.operator === "add" && (context.checker.getTypeAtLocation(current).flags & ts4.TypeFlags.StringLike) !== 0) {
3377
+ if (assignment.operator === "add" && (context.checker.getTypeAtLocation(current).flags & ts5.TypeFlags.StringLike) !== 0) {
3261
3378
  lowerExpression(assignment.node.right, context);
3262
3379
  const concatenated = addInstruction(context, current, { kind: "opaqueConstant" });
3263
3380
  assignIdentifier(symbol, assignment.target, concatenated, current, context);
@@ -3276,7 +3393,7 @@ function lowerStatementExpression(expression, context) {
3276
3393
  const one = addInstruction(context, current, { kind: "constant", value: 1 });
3277
3394
  const value2 = addInstruction(context, current, {
3278
3395
  kind: "binary",
3279
- operator: assignment.node.operator === ts4.SyntaxKind.PlusPlusToken ? "add" : "subtract",
3396
+ operator: assignment.node.operator === ts5.SyntaxKind.PlusPlusToken ? "add" : "subtract",
3280
3397
  left: previous,
3281
3398
  right: one
3282
3399
  });
@@ -3289,43 +3406,43 @@ function lowerStatementExpression(expression, context) {
3289
3406
  }
3290
3407
  function lowerExpression(expression, context) {
3291
3408
  const current = unwrap(expression, context.checker);
3292
- if (ts4.isNumericLiteral(current)) {
3409
+ if (ts5.isNumericLiteral(current)) {
3293
3410
  return addInstruction(context, current, { kind: "constant", value: Number(current.text) });
3294
3411
  }
3295
- if (current.kind === ts4.SyntaxKind.TrueKeyword || current.kind === ts4.SyntaxKind.FalseKeyword) {
3296
- return addInstruction(context, current, { kind: "booleanConstant", value: current.kind === ts4.SyntaxKind.TrueKeyword });
3412
+ if (current.kind === ts5.SyntaxKind.TrueKeyword || current.kind === ts5.SyntaxKind.FalseKeyword) {
3413
+ return addInstruction(context, current, { kind: "booleanConstant", value: current.kind === ts5.SyntaxKind.TrueKeyword });
3297
3414
  }
3298
- if (ts4.isPrefixUnaryExpression(current) && current.operator === ts4.SyntaxKind.PlusToken) {
3415
+ if (ts5.isPrefixUnaryExpression(current) && current.operator === ts5.SyntaxKind.PlusToken) {
3299
3416
  const positive = unwrap(current.operand, context.checker);
3300
- if (ts4.isNumericLiteral(positive)) {
3417
+ if (ts5.isNumericLiteral(positive)) {
3301
3418
  return addInstruction(context, current, { kind: "constant", value: Number(positive.text) });
3302
3419
  }
3303
- throw unsupported(current, { kind: "expressionForm", syntax: ts4.SyntaxKind[current.kind] });
3420
+ throw unsupported(current, { kind: "expressionForm", syntax: ts5.SyntaxKind[current.kind] });
3304
3421
  }
3305
- if (ts4.isPrefixUnaryExpression(current) && current.operator === ts4.SyntaxKind.MinusToken) {
3422
+ if (ts5.isPrefixUnaryExpression(current) && current.operator === ts5.SyntaxKind.MinusToken) {
3306
3423
  const negated = unwrap(current.operand, context.checker);
3307
- if (ts4.isNumericLiteral(negated)) {
3424
+ if (ts5.isNumericLiteral(negated)) {
3308
3425
  return addInstruction(context, current, { kind: "constant", value: -Number(negated.text) });
3309
3426
  }
3310
- if (isGlobalInfinity(negated, context.checker)) {
3427
+ if (isStandardGlobal(negated, "Infinity", context)) {
3311
3428
  return addInstruction(context, current, { kind: "constant", value: Number.NEGATIVE_INFINITY });
3312
3429
  }
3313
3430
  const zero = addInstruction(context, current, { kind: "constant", value: 0 });
3314
3431
  const value2 = lowerExpression(current.operand, context);
3315
3432
  return addInstruction(context, current, { kind: "binary", operator: "subtract", left: zero, right: value2 });
3316
3433
  }
3317
- if (ts4.isPrefixUnaryExpression(current) && current.operator === ts4.SyntaxKind.ExclamationToken) {
3434
+ if (ts5.isPrefixUnaryExpression(current) && current.operator === ts5.SyntaxKind.ExclamationToken) {
3318
3435
  requireBooleanCondition(current.operand, context.checker);
3319
3436
  const value2 = lowerExpression(current.operand, context);
3320
3437
  return addInstruction(context, current, { kind: "not", value: value2 });
3321
3438
  }
3322
- if (ts4.isConditionalExpression(current)) {
3439
+ if (ts5.isConditionalExpression(current)) {
3323
3440
  return lowerConditionalExpression(current, context);
3324
3441
  }
3325
- if (ts4.isIdentifier(current)) {
3442
+ if (ts5.isIdentifier(current)) {
3326
3443
  return identifierValue(requiredSymbol(current, context.checker), current, context);
3327
3444
  }
3328
- if (ts4.isArrayLiteralExpression(current)) {
3445
+ if (ts5.isArrayLiteralExpression(current)) {
3329
3446
  const literalType = context.checker.getTypeAtLocation(current);
3330
3447
  const literalKind = valueKind(literalType, context.checker);
3331
3448
  if (literalKind !== "array" && literalKind !== "tuple" && current.elements.length > 0) {
@@ -3333,23 +3450,23 @@ function lowerExpression(expression, context) {
3333
3450
  }
3334
3451
  const elements = [];
3335
3452
  for (const element of current.elements) {
3336
- if (ts4.isSpreadElement(element) || ts4.isOmittedExpression(element)) {
3337
- throw unsupported(element, { kind: "expressionForm", syntax: ts4.SyntaxKind[element.kind] });
3453
+ if (ts5.isSpreadElement(element) || ts5.isOmittedExpression(element)) {
3454
+ throw unsupported(element, { kind: "expressionForm", syntax: ts5.SyntaxKind[element.kind] });
3338
3455
  }
3339
3456
  elements.push(lowerExpression(element, context));
3340
3457
  }
3341
3458
  return addInstruction(context, current, { kind: "arrayLiteral", elements, form: literalKind === "tuple" ? "tuple" : "array" });
3342
3459
  }
3343
- if (ts4.isNonNullExpression(current) && ts4.isElementAccessExpression(current.expression)) {
3460
+ if (ts5.isNonNullExpression(current) && ts5.isElementAccessExpression(current.expression)) {
3344
3461
  return lowerElementAccess(current.expression, true, context);
3345
3462
  }
3346
- if (ts4.isElementAccessExpression(current)) {
3463
+ if (ts5.isElementAccessExpression(current)) {
3347
3464
  return lowerElementAccess(current, false, context);
3348
3465
  }
3349
- if (ts4.isObjectLiteralExpression(current)) {
3466
+ if (ts5.isObjectLiteralExpression(current)) {
3350
3467
  const properties = new Map;
3351
3468
  for (const property of current.properties) {
3352
- if (ts4.isShorthandPropertyAssignment(property)) {
3469
+ if (ts5.isShorthandPropertyAssignment(property)) {
3353
3470
  const symbol = context.checker.getShorthandAssignmentValueSymbol(property);
3354
3471
  if (symbol == null)
3355
3472
  throw unsupported(property, { kind: "missingSymbol" });
@@ -3359,21 +3476,21 @@ function lowerExpression(expression, context) {
3359
3476
  });
3360
3477
  continue;
3361
3478
  }
3362
- if (ts4.isPropertyAssignment(property)) {
3479
+ if (ts5.isPropertyAssignment(property)) {
3363
3480
  const name = propertyName(property.name);
3364
3481
  if (name === "__proto__")
3365
3482
  throw unsupported(property, { kind: "protoProperty" });
3366
3483
  properties.set(name, { name, value: lowerExpression(property.initializer, context) });
3367
3484
  continue;
3368
3485
  }
3369
- if (ts4.isSpreadAssignment(property))
3486
+ if (ts5.isSpreadAssignment(property))
3370
3487
  throw unsupported(property, { kind: "objectSpread" });
3371
3488
  throw unsupported(property, { kind: "objectPropertyForm" });
3372
3489
  }
3373
3490
  const contextual = context.checker.getContextualType(current);
3374
3491
  const fillOptionalsFrom = (recordType) => {
3375
3492
  for (const member of context.checker.getPropertiesOfType(recordType)) {
3376
- if ((member.flags & ts4.SymbolFlags.Optional) === 0 || properties.has(member.name))
3493
+ if ((member.flags & ts5.SymbolFlags.Optional) === 0 || properties.has(member.name))
3377
3494
  continue;
3378
3495
  const absent = addInstruction(context, current, { kind: "nullishConstant", sentinel: "undefined" });
3379
3496
  properties.set(member.name, { name: member.name, value: absent });
@@ -3406,25 +3523,25 @@ function lowerExpression(expression, context) {
3406
3523
  if (identifierAssignment(current) != null) {
3407
3524
  throw unsupported(current, { kind: "assignmentInValuePosition" });
3408
3525
  }
3409
- if (ts4.isBinaryExpression(current) && (current.operatorToken.kind === ts4.SyntaxKind.AmpersandAmpersandToken || current.operatorToken.kind === ts4.SyntaxKind.BarBarToken)) {
3526
+ if (ts5.isBinaryExpression(current) && (current.operatorToken.kind === ts5.SyntaxKind.AmpersandAmpersandToken || current.operatorToken.kind === ts5.SyntaxKind.BarBarToken)) {
3410
3527
  return lowerLogicalExpression(current, context);
3411
3528
  }
3412
- if (current.kind === ts4.SyntaxKind.NullKeyword) {
3529
+ if (current.kind === ts5.SyntaxKind.NullKeyword) {
3413
3530
  return addInstruction(context, current, { kind: "nullishConstant", sentinel: "null" });
3414
3531
  }
3415
- if (ts4.isStringLiteral(current) || ts4.isNoSubstitutionTemplateLiteral(current)) {
3532
+ if (ts5.isStringLiteral(current) || ts5.isNoSubstitutionTemplateLiteral(current)) {
3416
3533
  return addInstruction(context, current, { kind: "opaqueConstant", content: current.text });
3417
3534
  }
3418
- if (ts4.isAsExpression(current) || ts4.isTypeAssertionExpression(current)) {
3535
+ if (ts5.isAsExpression(current) || ts5.isTypeAssertionExpression(current)) {
3419
3536
  lowerExpression(current.expression, context);
3420
3537
  return addInstruction(context, current, { kind: "opaqueConstant" });
3421
3538
  }
3422
- if (ts4.isTemplateExpression(current)) {
3539
+ if (ts5.isTemplateExpression(current)) {
3423
3540
  for (const span of current.templateSpans)
3424
3541
  lowerExpression(span.expression, context);
3425
3542
  return addInstruction(context, current, { kind: "opaqueConstant" });
3426
3543
  }
3427
- if (ts4.isBinaryExpression(current) && current.operatorToken.kind === ts4.SyntaxKind.QuestionQuestionToken) {
3544
+ if (ts5.isBinaryExpression(current) && current.operatorToken.kind === ts5.SyntaxKind.QuestionQuestionToken) {
3428
3545
  const resultType = context.checker.getTypeAtLocation(current);
3429
3546
  if (valueKind(resultType, context.checker) == null) {
3430
3547
  throw unsupported(current, { kind: "valueType", typeText: context.checker.typeToString(resultType) });
@@ -3433,11 +3550,11 @@ function lowerExpression(expression, context) {
3433
3550
  const notMissing = addInstruction(context, current, { kind: "nullishCheck", value: left, sentinel: "nullish", negated: true });
3434
3551
  return lowerValueBranch(current, notMissing, () => left, () => lowerExpression(current.right, context), context);
3435
3552
  }
3436
- if (ts4.isBinaryExpression(current)) {
3553
+ if (ts5.isBinaryExpression(current)) {
3437
3554
  const missingCheck = missingSentinelCheck(current, context);
3438
3555
  if (missingCheck != null)
3439
3556
  return missingCheck;
3440
- if (current.operatorToken.kind === ts4.SyntaxKind.InstanceOfKeyword && ts4.isIdentifier(current.right) && declaredOnlyInDeclarationFiles(context.checker.getSymbolAtLocation(current.right))) {
3557
+ if (current.operatorToken.kind === ts5.SyntaxKind.InstanceOfKeyword && ts5.isIdentifier(current.right) && declaredOnlyInDeclarationFiles(context.checker.getSymbolAtLocation(current.right))) {
3441
3558
  lowerExpression(current.left, context);
3442
3559
  return addInstruction(context, current, { kind: "unknownBoolean" });
3443
3560
  }
@@ -3447,7 +3564,7 @@ function lowerExpression(expression, context) {
3447
3564
  const opaqueComparison = opaqueEqualityCheck(current, context);
3448
3565
  if (opaqueComparison != null)
3449
3566
  return opaqueComparison;
3450
- if (current.operatorToken.kind === ts4.SyntaxKind.PlusToken && (context.checker.getTypeAtLocation(current).flags & ts4.TypeFlags.StringLike) !== 0) {
3567
+ if (current.operatorToken.kind === ts5.SyntaxKind.PlusToken && (context.checker.getTypeAtLocation(current).flags & ts5.TypeFlags.StringLike) !== 0) {
3451
3568
  lowerExpression(current.left, context);
3452
3569
  lowerExpression(current.right, context);
3453
3570
  return addInstruction(context, current, { kind: "opaqueConstant" });
@@ -3468,13 +3585,13 @@ function lowerExpression(expression, context) {
3468
3585
  const right = lowerExpression(current.right, context);
3469
3586
  return arithmetic != null ? addInstruction(context, current, { kind: "binary", operator: arithmetic, left, right }) : addInstruction(context, current, { kind: "compare", operator: comparison, left, right });
3470
3587
  }
3471
- if (ts4.isCallExpression(current)) {
3588
+ if (ts5.isCallExpression(current)) {
3472
3589
  const staticAnnotation = context.staticAnnotations.get(current);
3473
3590
  if (staticAnnotation != null)
3474
3591
  return lowerStaticAnnotation(staticAnnotation, context);
3475
- if (ts4.isIdentifier(current.expression)) {
3592
+ if (ts5.isIdentifier(current.expression)) {
3476
3593
  const globalName = current.expression.text;
3477
- if ((globalName === "parseFloat" || globalName === "parseInt" || globalName === "Number") && declaredOnlyInDeclarationFiles(context.checker.getSymbolAtLocation(current.expression))) {
3594
+ if ((globalName === "parseFloat" || globalName === "parseInt" || globalName === "Number") && isStandardGlobal(current.expression, globalName, context)) {
3478
3595
  for (const argument of current.arguments)
3479
3596
  lowerExpression(argument, context);
3480
3597
  return addInstruction(context, current, { kind: "parsedNumber", integer: globalName === "parseInt" });
@@ -3499,7 +3616,8 @@ function lowerExpression(expression, context) {
3499
3616
  arguments_.push(lowerParameterDefault(default_2, parameter.initializer, context));
3500
3617
  continue;
3501
3618
  }
3502
- if (parameter.questionToken != null) {
3619
+ const callableParameter = callee.signature?.declaration?.parameters[index];
3620
+ if (callableParameter != null && ts5.isParameter(callableParameter) && callableParameter.questionToken != null) {
3503
3621
  arguments_.push(addInstruction(context, parameter, { kind: "nullishConstant", sentinel: "undefined" }));
3504
3622
  continue;
3505
3623
  }
@@ -3519,15 +3637,20 @@ function lowerExpression(expression, context) {
3519
3637
  });
3520
3638
  arguments_.push(lowerValueBranch(argument, supplied, () => value2, () => lowerParameterDefault(default_, parameter.initializer, context), context));
3521
3639
  }
3522
- return addInstruction(context, current, { kind: "call", function: callee.id, arguments: arguments_ });
3640
+ return addInstruction(context, current, {
3641
+ kind: "call",
3642
+ function: callee.id,
3643
+ arguments: arguments_,
3644
+ binding: callee.binding
3645
+ });
3523
3646
  }
3524
- if (ts4.isPropertyAccessExpression(current.expression)) {
3525
- const platformCall = current.arguments.length === 0 ? platformFact(current.expression, true, context.checker) : null;
3647
+ if (ts5.isPropertyAccessExpression(current.expression)) {
3648
+ const platformCall = current.arguments.length === 0 ? platformFact(current.expression, true, context.checker, context.program) : null;
3526
3649
  if (platformCall != null) {
3527
3650
  return addInstruction(context, current, { kind: "platformValue", ...platformCall });
3528
3651
  }
3529
3652
  const method = current.expression.name.text;
3530
- const standardMath = isStandardMathObject(current.expression.expression, context.checker);
3653
+ const standardMath = isStandardGlobal(current.expression.expression, "Math", context);
3531
3654
  if (standardMath && method === "floor" && current.arguments.length === 1) {
3532
3655
  requireNumberType(current.arguments[0], context.checker);
3533
3656
  const value2 = lowerExpression(current.arguments[0], context);
@@ -3549,7 +3672,7 @@ function lowerExpression(expression, context) {
3549
3672
  const values = current.arguments.map((argument) => lowerExpression(argument, context));
3550
3673
  return addInstruction(context, current, { kind: method === "min" ? "minimum" : "maximum", values });
3551
3674
  }
3552
- const standardNumber = isStandardNumberObject(current.expression.expression, context.checker);
3675
+ const standardNumber = isStandardGlobal(current.expression.expression, "Number", context);
3553
3676
  if (standardNumber && (method === "parseFloat" || method === "parseInt") && current.arguments.length >= 1) {
3554
3677
  for (const argument of current.arguments)
3555
3678
  lowerExpression(argument, context);
@@ -3564,7 +3687,7 @@ function lowerExpression(expression, context) {
3564
3687
  value: value2
3565
3688
  });
3566
3689
  }
3567
- const arrayMethod = ts4.isPropertyAccessExpression(current.expression) && context.checker.isArrayType(context.checker.getTypeAtLocation(current.expression.expression)) ? current.expression.name.text === "reduce" ? "reduce" : "other" : null;
3690
+ const arrayMethod = ts5.isPropertyAccessExpression(current.expression) && context.checker.isArrayType(context.checker.getTypeAtLocation(current.expression.expression)) ? current.expression.name.text === "reduce" ? "reduce" : "other" : null;
3568
3691
  throw unsupported(current, {
3569
3692
  kind: "call",
3570
3693
  callee: calleeDisplayName(current.expression, context.sourceFile),
@@ -3572,8 +3695,8 @@ function lowerExpression(expression, context) {
3572
3695
  });
3573
3696
  }
3574
3697
  }
3575
- if (ts4.isPropertyAccessExpression(current)) {
3576
- const platform = platformFact(current, false, context.checker);
3698
+ if (ts5.isPropertyAccessExpression(current)) {
3699
+ const platform = platformFact(current, false, context.checker, context.program);
3577
3700
  if (platform != null) {
3578
3701
  return addInstruction(context, current, { kind: "platformValue", ...platform });
3579
3702
  }
@@ -3591,12 +3714,12 @@ function lowerExpression(expression, context) {
3591
3714
  const array = lowerExpression(current.expression, context);
3592
3715
  return addInstruction(context, current, { kind: "arrayLength", array });
3593
3716
  }
3594
- if (receiverKind === "opaque" && current.name.text === "length" && (objectType.flags & ts4.TypeFlags.StringLike) !== 0) {
3717
+ if (receiverKind === "opaque" && current.name.text === "length" && (objectType.flags & ts5.TypeFlags.StringLike) !== 0) {
3595
3718
  const value2 = lowerExpression(current.expression, context);
3596
3719
  return addInstruction(context, current, { kind: "stringLength", value: value2 });
3597
3720
  }
3598
- const receiverSymbol = ts4.isIdentifier(current.expression) ? context.checker.getSymbolAtLocation(current.expression) : undefined;
3599
- if (receiverSymbol != null && (receiverSymbol.flags & (ts4.SymbolFlags.RegularEnum | ts4.SymbolFlags.ConstEnum)) !== 0) {
3721
+ const receiverSymbol = ts5.isIdentifier(current.expression) ? context.checker.getSymbolAtLocation(current.expression) : undefined;
3722
+ if (receiverSymbol != null && (receiverSymbol.flags & (ts5.SymbolFlags.RegularEnum | ts5.SymbolFlags.ConstEnum)) !== 0) {
3600
3723
  throw unsupported(current, { kind: "enumMemberRead" });
3601
3724
  }
3602
3725
  if (receiverKind !== "object" && receiverKind !== "taggedUnion") {
@@ -3606,7 +3729,7 @@ function lowerExpression(expression, context) {
3606
3729
  const object = lowerExpression(current.expression, context);
3607
3730
  return addInstruction(context, current, { kind: "property", object, property: current.name.text });
3608
3731
  }
3609
- throw unsupported(current, { kind: "expressionForm", syntax: ts4.SyntaxKind[current.kind] });
3732
+ throw unsupported(current, { kind: "expressionForm", syntax: ts5.SyntaxKind[current.kind] });
3610
3733
  }
3611
3734
  function lowerStaticAnnotation(annotation, context) {
3612
3735
  if (annotation.kind === "invalid") {
@@ -3623,15 +3746,15 @@ function lowerStaticAnnotation(annotation, context) {
3623
3746
  if (requirement == null) {
3624
3747
  throw unsupported(condition, {
3625
3748
  kind: "staticAssertionForm",
3626
- problem: staticAssertionProblem(condition, context.checker, "callerRequirement")
3749
+ problem: staticAssertionProblem(condition, context, "callerRequirement")
3627
3750
  });
3628
3751
  }
3629
3752
  value2 = lowerWrittenRequirement(requirement, condition, context);
3630
3753
  } else {
3631
- if (!supportedWrittenAssertion(condition, context.checker)) {
3754
+ if (!supportedWrittenAssertion(condition, context)) {
3632
3755
  throw unsupported(condition, {
3633
3756
  kind: "staticAssertionForm",
3634
- problem: staticAssertionProblem(condition, context.checker, "directCheck")
3757
+ problem: staticAssertionProblem(condition, context, "directCheck")
3635
3758
  });
3636
3759
  }
3637
3760
  value2 = lowerExpression(condition, context);
@@ -3653,7 +3776,7 @@ function lowerStaticAnnotation(annotation, context) {
3653
3776
  }
3654
3777
  function writtenRequirement(condition, context) {
3655
3778
  const current = unwrapParentheses(condition);
3656
- if (ts4.isCallExpression(current) && current.questionDotToken == null && current.arguments.length === 1 && ts4.isPropertyAccessExpression(current.expression) && current.expression.questionDotToken == null && isStandardNumberObject(current.expression.expression, context.checker) && (current.expression.name.text === "isInteger" || current.expression.name.text === "isFinite")) {
3779
+ if (ts5.isCallExpression(current) && current.questionDotToken == null && current.arguments.length === 1 && ts5.isPropertyAccessExpression(current.expression) && current.expression.questionDotToken == null && isStandardGlobal(current.expression.expression, "Number", context) && (current.expression.name.text === "isInteger" || current.expression.name.text === "isFinite")) {
3657
3780
  const argument = current.arguments[0];
3658
3781
  const value2 = staticRequirementParameterPathValue(argument, context);
3659
3782
  return value2 == null ? null : {
@@ -3662,7 +3785,7 @@ function writtenRequirement(condition, context) {
3662
3785
  value: value2
3663
3786
  };
3664
3787
  }
3665
- if (!ts4.isBinaryExpression(current) || !staticAssertionComparison(current.operatorToken.kind))
3788
+ if (!ts5.isBinaryExpression(current) || !staticAssertionComparison(current.operatorToken.kind))
3666
3789
  return null;
3667
3790
  const leftParameter = staticRequirementParameterPathValue(current.left, context);
3668
3791
  const rightParameter = staticRequirementParameterPathValue(current.right, context);
@@ -3678,10 +3801,10 @@ function writtenRequirement(condition, context) {
3678
3801
  function staticRequirementParameterPathValue(expression, context) {
3679
3802
  requireNumberType(expression, context.checker);
3680
3803
  let root = unwrapParentheses(expression);
3681
- while (ts4.isPropertyAccessExpression(root) && root.questionDotToken == null) {
3804
+ while (ts5.isPropertyAccessExpression(root) && root.questionDotToken == null) {
3682
3805
  root = unwrapParentheses(root.expression);
3683
3806
  }
3684
- if (!ts4.isIdentifier(root))
3807
+ if (!ts5.isIdentifier(root))
3685
3808
  return null;
3686
3809
  const symbol = context.checker.getSymbolAtLocation(root);
3687
3810
  const rootValue = symbol == null ? null : context.bindings.get(symbol);
@@ -3708,14 +3831,14 @@ function staticFiniteValue(expression, context) {
3708
3831
  if (literal != null)
3709
3832
  return Number.isFinite(literal) ? literal : null;
3710
3833
  const unwrapped = unwrapParentheses(current);
3711
- if (!ts4.isIdentifier(unwrapped))
3834
+ if (!ts5.isIdentifier(unwrapped))
3712
3835
  return null;
3713
3836
  const symbol = resolvedSymbol(context.checker.getSymbolAtLocation(unwrapped), context.checker);
3714
3837
  if (symbol == null || seen.has(symbol))
3715
3838
  return null;
3716
3839
  seen.add(symbol);
3717
3840
  const declaration = symbol.valueDeclaration;
3718
- if (declaration == null || !ts4.isVariableDeclaration(declaration) || (ts4.getCombinedNodeFlags(declaration) & ts4.NodeFlags.Const) === 0 || declaration.getSourceFile().isDeclarationFile || declaration.initializer == null)
3841
+ if (declaration == null || !ts5.isVariableDeclaration(declaration) || (ts5.getCombinedNodeFlags(declaration) & ts5.NodeFlags.Const) === 0 || declaration.getSourceFile().isDeclarationFile || declaration.initializer == null)
3719
3842
  return null;
3720
3843
  current = declaration.initializer;
3721
3844
  }
@@ -3740,25 +3863,25 @@ function lowerWrittenRequirement(requirement, condition, context) {
3740
3863
  right: lowerOperand(requirement.right)
3741
3864
  });
3742
3865
  }
3743
- function supportedWrittenAssertion(condition, checker) {
3866
+ function supportedWrittenAssertion(condition, context) {
3744
3867
  const current = unwrapParentheses(condition);
3745
- if (ts4.isBinaryExpression(current) && staticAssertionComparison(current.operatorToken.kind)) {
3746
- return staticAssertionNumericAtom(current.left, checker) && staticAssertionNumericAtom(current.right, checker);
3868
+ if (ts5.isBinaryExpression(current) && staticAssertionComparison(current.operatorToken.kind)) {
3869
+ return staticAssertionNumericAtom(current.left, context.checker) && staticAssertionNumericAtom(current.right, context.checker);
3747
3870
  }
3748
- const operand = staticNumberCheckOperand(current, checker);
3749
- return operand != null && staticAssertionNumericAtom(operand, checker);
3871
+ const operand = staticNumberCheckOperand(current, context);
3872
+ return operand != null && staticAssertionNumericAtom(operand, context.checker);
3750
3873
  }
3751
3874
  function staticAssertionNumericAtom(expression, checker) {
3752
3875
  return staticAssertionAtom(expression) && valueKind(checker.getTypeAtLocation(expression), checker) === "number";
3753
3876
  }
3754
3877
  function staticAssertionComparison(kind) {
3755
3878
  switch (kind) {
3756
- case ts4.SyntaxKind.LessThanToken:
3757
- case ts4.SyntaxKind.LessThanEqualsToken:
3758
- case ts4.SyntaxKind.GreaterThanToken:
3759
- case ts4.SyntaxKind.GreaterThanEqualsToken:
3760
- case ts4.SyntaxKind.EqualsEqualsEqualsToken:
3761
- case ts4.SyntaxKind.ExclamationEqualsEqualsToken:
3879
+ case ts5.SyntaxKind.LessThanToken:
3880
+ case ts5.SyntaxKind.LessThanEqualsToken:
3881
+ case ts5.SyntaxKind.GreaterThanToken:
3882
+ case ts5.SyntaxKind.GreaterThanEqualsToken:
3883
+ case ts5.SyntaxKind.EqualsEqualsEqualsToken:
3884
+ case ts5.SyntaxKind.ExclamationEqualsEqualsToken:
3762
3885
  return true;
3763
3886
  default:
3764
3887
  return false;
@@ -3766,54 +3889,54 @@ function staticAssertionComparison(kind) {
3766
3889
  }
3767
3890
  function staticAssertionAtomProblem(expression) {
3768
3891
  const current = unwrapParentheses(expression);
3769
- if (ts4.isIdentifier(current) || ts4.isNumericLiteral(current))
3892
+ if (ts5.isIdentifier(current) || ts5.isNumericLiteral(current))
3770
3893
  return null;
3771
- if (ts4.isPrefixUnaryExpression(current) && (current.operator === ts4.SyntaxKind.PlusToken || current.operator === ts4.SyntaxKind.MinusToken)) {
3772
- return ts4.isNumericLiteral(unwrapParentheses(current.operand)) ? null : "bindValueFirst";
3894
+ if (ts5.isPrefixUnaryExpression(current) && (current.operator === ts5.SyntaxKind.PlusToken || current.operator === ts5.SyntaxKind.MinusToken)) {
3895
+ return ts5.isNumericLiteral(unwrapParentheses(current.operand)) ? null : "bindValueFirst";
3773
3896
  }
3774
- if (ts4.isElementAccessExpression(current))
3897
+ if (ts5.isElementAccessExpression(current))
3775
3898
  return "bindValueFirst";
3776
- if (ts4.isNonNullExpression(current))
3899
+ if (ts5.isNonNullExpression(current))
3777
3900
  return staticAssertionAtomProblem(current.expression);
3778
- if (ts4.isCallExpression(current))
3901
+ if (ts5.isCallExpression(current))
3779
3902
  return "functionCall";
3780
- if (ts4.isBinaryExpression(current))
3903
+ if (ts5.isBinaryExpression(current))
3781
3904
  return "bindValueFirst";
3782
- if (ts4.isPropertyAccessExpression(current)) {
3905
+ if (ts5.isPropertyAccessExpression(current)) {
3783
3906
  return current.questionDotToken == null ? staticAssertionAtomProblem(current.expression) : "directCheck";
3784
3907
  }
3785
3908
  return "directCheck";
3786
3909
  }
3787
3910
  function staticAssertionAtom(expression) {
3788
3911
  const current = unwrapParentheses(expression);
3789
- if (ts4.isIdentifier(current) || ts4.isNumericLiteral(current))
3912
+ if (ts5.isIdentifier(current) || ts5.isNumericLiteral(current))
3790
3913
  return true;
3791
- if (ts4.isPrefixUnaryExpression(current) && (current.operator === ts4.SyntaxKind.PlusToken || current.operator === ts4.SyntaxKind.MinusToken)) {
3792
- return ts4.isNumericLiteral(unwrapParentheses(current.operand));
3914
+ if (ts5.isPrefixUnaryExpression(current) && (current.operator === ts5.SyntaxKind.PlusToken || current.operator === ts5.SyntaxKind.MinusToken)) {
3915
+ return ts5.isNumericLiteral(unwrapParentheses(current.operand));
3793
3916
  }
3794
- return ts4.isPropertyAccessExpression(current) && current.questionDotToken == null && staticAssertionAtom(current.expression);
3917
+ return ts5.isPropertyAccessExpression(current) && current.questionDotToken == null && staticAssertionAtom(current.expression);
3795
3918
  }
3796
- function staticAssertionProblem(condition, checker, fallback) {
3919
+ function staticAssertionProblem(condition, context, fallback) {
3797
3920
  const current = unwrapParentheses(condition);
3798
- if (ts4.isBinaryExpression(current) && staticAssertionComparison(current.operatorToken.kind)) {
3921
+ if (ts5.isBinaryExpression(current) && staticAssertionComparison(current.operatorToken.kind)) {
3799
3922
  return staticAssertionAtomProblem(current.left) ?? staticAssertionAtomProblem(current.right) ?? fallback;
3800
3923
  }
3801
- const operand = staticNumberCheckOperand(current, checker);
3924
+ const operand = staticNumberCheckOperand(current, context);
3802
3925
  if (operand != null)
3803
3926
  return staticAssertionAtomProblem(operand) ?? fallback;
3804
- if (ts4.isCallExpression(current))
3927
+ if (ts5.isCallExpression(current))
3805
3928
  return "functionCall";
3806
3929
  return "directCheck";
3807
3930
  }
3808
- function staticNumberCheckOperand(expression, checker) {
3809
- if (!ts4.isCallExpression(expression) || expression.questionDotToken != null || expression.arguments.length !== 1 || !ts4.isPropertyAccessExpression(expression.expression) || expression.expression.questionDotToken != null)
3931
+ function staticNumberCheckOperand(expression, context) {
3932
+ if (!ts5.isCallExpression(expression) || expression.questionDotToken != null || expression.arguments.length !== 1 || !ts5.isPropertyAccessExpression(expression.expression) || expression.expression.questionDotToken != null)
3810
3933
  return null;
3811
3934
  const callee = expression.expression;
3812
- return isStandardNumberObject(callee.expression, checker) && (callee.name.text === "isInteger" || callee.name.text === "isFinite" || callee.name.text === "isNaN") ? expression.arguments[0] : null;
3935
+ return isStandardGlobal(callee.expression, "Number", context) && (callee.name.text === "isInteger" || callee.name.text === "isFinite" || callee.name.text === "isNaN") ? expression.arguments[0] : null;
3813
3936
  }
3814
3937
  function unwrapParentheses(expression) {
3815
3938
  let current = expression;
3816
- while (ts4.isParenthesizedExpression(current))
3939
+ while (ts5.isParenthesizedExpression(current))
3817
3940
  current = current.expression;
3818
3941
  return current;
3819
3942
  }
@@ -3832,30 +3955,30 @@ function removableStaticConditionInstruction(instruction) {
3832
3955
  }
3833
3956
  }
3834
3957
  function identifierAssignment(node) {
3835
- if (ts4.isBinaryExpression(node) && ts4.isIdentifier(node.left)) {
3836
- if (node.operatorToken.kind === ts4.SyntaxKind.EqualsToken)
3958
+ if (ts5.isBinaryExpression(node) && ts5.isIdentifier(node.left)) {
3959
+ if (node.operatorToken.kind === ts5.SyntaxKind.EqualsToken)
3837
3960
  return { form: "assign", target: node.left, node };
3838
3961
  const operator = compoundAssignmentOperator(node.operatorToken.kind);
3839
3962
  if (operator != null)
3840
3963
  return { form: "compound", target: node.left, node, operator };
3841
- const logical = node.operatorToken.kind === ts4.SyntaxKind.QuestionQuestionEqualsToken ? "nullish" : node.operatorToken.kind === ts4.SyntaxKind.BarBarEqualsToken ? "or" : node.operatorToken.kind === ts4.SyntaxKind.AmpersandAmpersandEqualsToken ? "and" : null;
3964
+ const logical = node.operatorToken.kind === ts5.SyntaxKind.QuestionQuestionEqualsToken ? "nullish" : node.operatorToken.kind === ts5.SyntaxKind.BarBarEqualsToken ? "or" : node.operatorToken.kind === ts5.SyntaxKind.AmpersandAmpersandEqualsToken ? "and" : null;
3842
3965
  if (logical != null)
3843
3966
  return { form: "logical", target: node.left, node, logical };
3844
3967
  }
3845
- if ((ts4.isPrefixUnaryExpression(node) || ts4.isPostfixUnaryExpression(node)) && (node.operator === ts4.SyntaxKind.PlusPlusToken || node.operator === ts4.SyntaxKind.MinusMinusToken) && ts4.isIdentifier(node.operand)) {
3968
+ if ((ts5.isPrefixUnaryExpression(node) || ts5.isPostfixUnaryExpression(node)) && (node.operator === ts5.SyntaxKind.PlusPlusToken || node.operator === ts5.SyntaxKind.MinusMinusToken) && ts5.isIdentifier(node.operand)) {
3846
3969
  return { form: "update", target: node.operand, node };
3847
3970
  }
3848
3971
  return null;
3849
3972
  }
3850
3973
  function compoundAssignmentOperator(kind) {
3851
3974
  switch (kind) {
3852
- case ts4.SyntaxKind.PlusEqualsToken:
3975
+ case ts5.SyntaxKind.PlusEqualsToken:
3853
3976
  return "add";
3854
- case ts4.SyntaxKind.MinusEqualsToken:
3977
+ case ts5.SyntaxKind.MinusEqualsToken:
3855
3978
  return "subtract";
3856
- case ts4.SyntaxKind.AsteriskEqualsToken:
3979
+ case ts5.SyntaxKind.AsteriskEqualsToken:
3857
3980
  return "multiply";
3858
- case ts4.SyntaxKind.SlashEqualsToken:
3981
+ case ts5.SyntaxKind.SlashEqualsToken:
3859
3982
  return "divide";
3860
3983
  default:
3861
3984
  return null;
@@ -3871,6 +3994,15 @@ function lowerValueBranch(node, condition, lowerTrueArm, lowerFalseArm, context)
3871
3994
  whenFalse: { block: whenFalse, arguments: [] },
3872
3995
  site: addSite(context, node)
3873
3996
  });
3997
+ return joinValueBranches(node, whenTrue, whenFalse, lowerTrueArm, lowerFalseArm, context);
3998
+ }
3999
+ function lowerBranchingValue(node, condition, lowerTrueArm, lowerFalseArm, context) {
4000
+ const whenTrue = createBlock(context);
4001
+ const whenFalse = createBlock(context);
4002
+ lowerBranchingCondition(condition, whenTrue, whenFalse, context);
4003
+ return joinValueBranches(node, whenTrue, whenFalse, lowerTrueArm, lowerFalseArm, context);
4004
+ }
4005
+ function joinValueBranches(node, whenTrue, whenFalse, lowerTrueArm, lowerFalseArm, context) {
3874
4006
  context.currentBlock = context.blocks[whenTrue];
3875
4007
  const trueValue = lowerTrueArm();
3876
4008
  const trueBlock = context.currentBlock;
@@ -3897,33 +4029,12 @@ function lowerConditionalExpression(expression, context) {
3897
4029
  if (valueKind(resultType, context.checker) == null) {
3898
4030
  throw unsupported(expression, { kind: "valueType", typeText: context.checker.typeToString(resultType) });
3899
4031
  }
3900
- const whenTrue = createBlock(context);
3901
- const whenFalse = createBlock(context);
3902
- lowerBranchingCondition(expression.condition, whenTrue, whenFalse, context);
3903
- context.currentBlock = context.blocks[whenTrue];
3904
- const trueValue = lowerExpression(expression.whenTrue, context);
3905
- const trueBlock = context.currentBlock;
3906
- context.currentBlock = context.blocks[whenFalse];
3907
- const falseValue = lowerExpression(expression.whenFalse, context);
3908
- const falseBlock = context.currentBlock;
3909
- const continuation = createBlock(context, 1);
3910
- terminate(trueBlock, {
3911
- kind: "jump",
3912
- target: { block: continuation, arguments: [trueValue] },
3913
- site: addSite(context, expression)
3914
- });
3915
- terminate(falseBlock, {
3916
- kind: "jump",
3917
- target: { block: continuation, arguments: [falseValue] },
3918
- site: addSite(context, expression)
3919
- });
3920
- context.currentBlock = context.blocks[continuation];
3921
- return context.currentBlock.parameters[0];
4032
+ return lowerBranchingValue(expression, expression.condition, () => lowerExpression(expression.whenTrue, context), () => lowerExpression(expression.whenFalse, context), context);
3922
4033
  }
3923
4034
  function lowerBranchingCondition(expression, whenTrue, whenFalse, context) {
3924
4035
  const current = unwrap(expression, context.checker);
3925
- if (ts4.isBinaryExpression(current) && (current.operatorToken.kind === ts4.SyntaxKind.AmpersandAmpersandToken || current.operatorToken.kind === ts4.SyntaxKind.BarBarToken)) {
3926
- const isAnd = current.operatorToken.kind === ts4.SyntaxKind.AmpersandAmpersandToken;
4036
+ if (ts5.isBinaryExpression(current) && (current.operatorToken.kind === ts5.SyntaxKind.AmpersandAmpersandToken || current.operatorToken.kind === ts5.SyntaxKind.BarBarToken)) {
4037
+ const isAnd = current.operatorToken.kind === ts5.SyntaxKind.AmpersandAmpersandToken;
3927
4038
  const middle = createBlock(context);
3928
4039
  if (isAnd) {
3929
4040
  lowerBranchingCondition(current.left, middle, whenFalse, context);
@@ -3934,7 +4045,7 @@ function lowerBranchingCondition(expression, whenTrue, whenFalse, context) {
3934
4045
  lowerBranchingCondition(current.right, whenTrue, whenFalse, context);
3935
4046
  return;
3936
4047
  }
3937
- if (ts4.isPrefixUnaryExpression(current) && current.operator === ts4.SyntaxKind.ExclamationToken) {
4048
+ if (ts5.isPrefixUnaryExpression(current) && current.operator === ts5.SyntaxKind.ExclamationToken) {
3938
4049
  lowerBranchingCondition(current.operand, whenFalse, whenTrue, context);
3939
4050
  return;
3940
4051
  }
@@ -3952,21 +4063,20 @@ function lowerBranchingCondition(expression, whenTrue, whenFalse, context) {
3952
4063
  function lowerLogicalExpression(expression, context) {
3953
4064
  requireBooleanCondition(expression.left, context.checker);
3954
4065
  requireBooleanCondition(expression.right, context.checker);
3955
- const isAnd = expression.operatorToken.kind === ts4.SyntaxKind.AmpersandAmpersandToken;
3956
- const condition = lowerExpression(expression.left, context);
3957
- return lowerValueBranch(expression, condition, () => isAnd ? lowerExpression(expression.right, context) : addInstruction(context, expression, { kind: "booleanConstant", value: true }), () => isAnd ? addInstruction(context, expression, { kind: "booleanConstant", value: false }) : lowerExpression(expression.right, context), context);
4066
+ const isAnd = expression.operatorToken.kind === ts5.SyntaxKind.AmpersandAmpersandToken;
4067
+ return lowerBranchingValue(expression, expression.left, () => isAnd ? lowerExpression(expression.right, context) : addInstruction(context, expression, { kind: "booleanConstant", value: true }), () => isAnd ? addInstruction(context, expression, { kind: "booleanConstant", value: false }) : lowerExpression(expression.right, context), context);
3958
4068
  }
3959
4069
  function arithmeticOperator(kind) {
3960
4070
  switch (kind) {
3961
- case ts4.SyntaxKind.PlusToken:
4071
+ case ts5.SyntaxKind.PlusToken:
3962
4072
  return "add";
3963
- case ts4.SyntaxKind.MinusToken:
4073
+ case ts5.SyntaxKind.MinusToken:
3964
4074
  return "subtract";
3965
- case ts4.SyntaxKind.AsteriskToken:
4075
+ case ts5.SyntaxKind.AsteriskToken:
3966
4076
  return "multiply";
3967
- case ts4.SyntaxKind.SlashToken:
4077
+ case ts5.SyntaxKind.SlashToken:
3968
4078
  return "divide";
3969
- case ts4.SyntaxKind.PercentToken:
4079
+ case ts5.SyntaxKind.PercentToken:
3970
4080
  return "remainder";
3971
4081
  default:
3972
4082
  return null;
@@ -3974,19 +4084,19 @@ function arithmeticOperator(kind) {
3974
4084
  }
3975
4085
  function comparisonOperator(kind) {
3976
4086
  switch (kind) {
3977
- case ts4.SyntaxKind.LessThanToken:
4087
+ case ts5.SyntaxKind.LessThanToken:
3978
4088
  return "lessThan";
3979
- case ts4.SyntaxKind.LessThanEqualsToken:
4089
+ case ts5.SyntaxKind.LessThanEqualsToken:
3980
4090
  return "lessThanOrEqual";
3981
- case ts4.SyntaxKind.GreaterThanToken:
4091
+ case ts5.SyntaxKind.GreaterThanToken:
3982
4092
  return "greaterThan";
3983
- case ts4.SyntaxKind.GreaterThanEqualsToken:
4093
+ case ts5.SyntaxKind.GreaterThanEqualsToken:
3984
4094
  return "greaterThanOrEqual";
3985
- case ts4.SyntaxKind.EqualsEqualsToken:
3986
- case ts4.SyntaxKind.EqualsEqualsEqualsToken:
4095
+ case ts5.SyntaxKind.EqualsEqualsToken:
4096
+ case ts5.SyntaxKind.EqualsEqualsEqualsToken:
3987
4097
  return "equal";
3988
- case ts4.SyntaxKind.ExclamationEqualsToken:
3989
- case ts4.SyntaxKind.ExclamationEqualsEqualsToken:
4098
+ case ts5.SyntaxKind.ExclamationEqualsToken:
4099
+ case ts5.SyntaxKind.ExclamationEqualsEqualsToken:
3990
4100
  return "notEqual";
3991
4101
  default:
3992
4102
  return null;
@@ -3994,12 +4104,12 @@ function comparisonOperator(kind) {
3994
4104
  }
3995
4105
  function requireNumberType(node, checker) {
3996
4106
  const type = checker.getTypeAtLocation(node);
3997
- if (valueKind(type, checker) !== "number" && (type.flags & ts4.TypeFlags.Any) === 0) {
4107
+ if (valueKind(type, checker) !== "number" && (type.flags & ts5.TypeFlags.Any) === 0) {
3998
4108
  throw unsupported(node, { kind: "nonNumberOperand", typeText: checker.typeToString(type) });
3999
4109
  }
4000
4110
  }
4001
4111
  function typeCanIncludeUndefined(type) {
4002
- if ((type.flags & (ts4.TypeFlags.Undefined | ts4.TypeFlags.Any | ts4.TypeFlags.Unknown)) !== 0)
4112
+ if ((type.flags & (ts5.TypeFlags.Undefined | ts5.TypeFlags.Any | ts5.TypeFlags.Unknown)) !== 0)
4003
4113
  return true;
4004
4114
  return type.isUnion() && type.types.some(typeCanIncludeUndefined);
4005
4115
  }
@@ -4032,19 +4142,19 @@ function valueKind(type, checker, depth = 0) {
4032
4142
  return result;
4033
4143
  }
4034
4144
  function valueKindUncached(type, checker, depth) {
4035
- if ((type.flags & ts4.TypeFlags.NumberLike) !== 0)
4145
+ if (numberConstituent(type) != null)
4036
4146
  return "number";
4037
- if ((type.flags & ts4.TypeFlags.BooleanLike) !== 0)
4147
+ if ((type.flags & ts5.TypeFlags.BooleanLike) !== 0)
4038
4148
  return "boolean";
4039
- if ((type.flags & ts4.TypeFlags.StringLike) !== 0)
4149
+ if ((type.flags & ts5.TypeFlags.StringLike) !== 0)
4040
4150
  return "opaque";
4041
4151
  if (checker.isTupleType(type))
4042
4152
  return "tuple";
4043
4153
  if (checker.isArrayType(type)) {
4044
- const element = checker.getIndexTypeOfType(type, ts4.IndexKind.Number);
4154
+ const element = checker.getIndexTypeOfType(type, ts5.IndexKind.Number);
4045
4155
  return element != null && valueKind(element, checker, depth + 1) != null ? "array" : null;
4046
4156
  }
4047
- const objectLike = (type.flags & ts4.TypeFlags.Object) !== 0 || type.isIntersection() && type.types.every((member) => valueKind(member, checker, depth + 1) === "object");
4157
+ const objectLike = (type.flags & ts5.TypeFlags.Object) !== 0 || type.isIntersection() && type.types.every((member) => valueKind(member, checker, depth + 1) === "object");
4048
4158
  if (objectLike) {
4049
4159
  if (checker.getIndexInfosOfType(type).length > 0)
4050
4160
  return null;
@@ -4055,10 +4165,10 @@ function valueKindUncached(type, checker, depth) {
4055
4165
  const anchored = checker.getPropertiesOfType(type).some((property) => checker.getTypeOfSymbol(property).getCallSignatures().length === 0);
4056
4166
  return anchored ? "object" : null;
4057
4167
  }
4058
- if ((type.flags & (ts4.TypeFlags.Unknown | ts4.TypeFlags.Any)) !== 0)
4168
+ if ((type.flags & (ts5.TypeFlags.Unknown | ts5.TypeFlags.Any)) !== 0)
4059
4169
  return "opaque";
4060
4170
  if (type.isUnion()) {
4061
- const missingFlags = ts4.TypeFlags.Null | ts4.TypeFlags.Undefined;
4171
+ const missingFlags = ts5.TypeFlags.Null | ts5.TypeFlags.Undefined;
4062
4172
  if (type.types.some((member) => (member.flags & missingFlags) !== 0)) {
4063
4173
  const rest = nonMissingUnionMembers(type);
4064
4174
  const restKind = classifyUnionMembers(rest, checker, depth + 1);
@@ -4077,7 +4187,7 @@ function nonMissingUnionMembers(type) {
4077
4187
  const cached = nonMissingUnionMembersCache.get(type);
4078
4188
  if (cached != null)
4079
4189
  return cached;
4080
- const missingFlags = ts4.TypeFlags.Null | ts4.TypeFlags.Undefined;
4190
+ const missingFlags = ts5.TypeFlags.Null | ts5.TypeFlags.Undefined;
4081
4191
  const members = type.types.filter((member) => (member.flags & missingFlags) === 0);
4082
4192
  nonMissingUnionMembersCache.set(type, members);
4083
4193
  return members;
@@ -4107,7 +4217,7 @@ function taggedUnionPropertyUncached(members, checker, depth) {
4107
4217
  const qualifies = (candidateName, singleLiteralOnly) => {
4108
4218
  for (const member of members) {
4109
4219
  const property = checker.getPropertyOfType(member, candidateName);
4110
- if (property == null || (property.flags & ts4.SymbolFlags.Optional) !== 0)
4220
+ if (property == null || (property.flags & ts5.SymbolFlags.Optional) !== 0)
4111
4221
  return false;
4112
4222
  const literals = tagLiteralValues(checker.getTypeOfSymbol(property));
4113
4223
  if (literals == null || singleLiteralOnly && literals.length !== 1)
@@ -4117,7 +4227,7 @@ function taggedUnionPropertyUncached(members, checker, depth) {
4117
4227
  };
4118
4228
  for (const singleLiteralOnly of [true, false]) {
4119
4229
  for (const candidate of checker.getPropertiesOfType(first)) {
4120
- if ((candidate.flags & ts4.SymbolFlags.Optional) !== 0)
4230
+ if ((candidate.flags & ts5.SymbolFlags.Optional) !== 0)
4121
4231
  continue;
4122
4232
  if (qualifies(candidate.name, singleLiteralOnly))
4123
4233
  return candidate.name;
@@ -4126,28 +4236,28 @@ function taggedUnionPropertyUncached(members, checker, depth) {
4126
4236
  return null;
4127
4237
  }
4128
4238
  function calleeDisplayName(expression, sourceFile) {
4129
- if (ts4.isPropertyAccessExpression(expression)) {
4239
+ if (ts5.isPropertyAccessExpression(expression)) {
4130
4240
  const receiver = expression.expression;
4131
- const receiverName = ts4.isIdentifier(receiver) ? receiver.text : ts4.isPropertyAccessExpression(receiver) && ts4.isIdentifier(receiver.expression) ? `${receiver.expression.text}.${receiver.name.text}` : "(…)";
4241
+ const receiverName = ts5.isIdentifier(receiver) ? receiver.text : ts5.isPropertyAccessExpression(receiver) && ts5.isIdentifier(receiver.expression) ? `${receiver.expression.text}.${receiver.name.text}` : "(…)";
4132
4242
  return `${receiverName}.${expression.name.text}`;
4133
4243
  }
4134
4244
  return expression.getText(sourceFile).replace(/\s+/g, " ").slice(0, 60);
4135
4245
  }
4136
4246
  function writtenTagLiteral(literal, tagProperty, context) {
4137
- if (!ts4.isObjectLiteralExpression(literal))
4247
+ if (!ts5.isObjectLiteralExpression(literal))
4138
4248
  return null;
4139
4249
  for (const property of literal.properties) {
4140
- if (!ts4.isPropertyAssignment(property))
4250
+ if (!ts5.isPropertyAssignment(property))
4141
4251
  continue;
4142
- const name = ts4.isIdentifier(property.name) || ts4.isStringLiteral(property.name) ? property.name.text : null;
4252
+ const name = ts5.isIdentifier(property.name) || ts5.isStringLiteral(property.name) ? property.name.text : null;
4143
4253
  if (name !== tagProperty)
4144
4254
  continue;
4145
4255
  const initializer = unwrap(property.initializer, context.checker);
4146
- if (ts4.isStringLiteral(initializer) || ts4.isNoSubstitutionTemplateLiteral(initializer))
4256
+ if (ts5.isStringLiteral(initializer) || ts5.isNoSubstitutionTemplateLiteral(initializer))
4147
4257
  return initializer.text;
4148
- if (initializer.kind === ts4.SyntaxKind.TrueKeyword)
4258
+ if (initializer.kind === ts5.SyntaxKind.TrueKeyword)
4149
4259
  return true;
4150
- if (initializer.kind === ts4.SyntaxKind.FalseKeyword)
4260
+ if (initializer.kind === ts5.SyntaxKind.FalseKeyword)
4151
4261
  return false;
4152
4262
  return null;
4153
4263
  }
@@ -4157,7 +4267,7 @@ function tagLiteralValues(type) {
4157
4267
  const single = (member) => {
4158
4268
  if (member.isStringLiteral())
4159
4269
  return member.value;
4160
- if ((member.flags & ts4.TypeFlags.BooleanLiteral) !== 0) {
4270
+ if ((member.flags & ts5.TypeFlags.BooleanLiteral) !== 0) {
4161
4271
  return member.intrinsicName === "true";
4162
4272
  }
4163
4273
  return null;
@@ -4204,10 +4314,10 @@ function structuralTypeWalkCompletes(type, checker, seen) {
4204
4314
  if (checker.isArrayType(type)) {
4205
4315
  if (seen.length >= 8 || seen.includes(type))
4206
4316
  return false;
4207
- const element = checker.getIndexTypeOfType(type, ts4.IndexKind.Number);
4317
+ const element = checker.getIndexTypeOfType(type, ts5.IndexKind.Number);
4208
4318
  return element == null || structuralTypeWalkCompletes(element, checker, [...seen, type]);
4209
4319
  }
4210
- if ((type.flags & ts4.TypeFlags.Object) === 0)
4320
+ if ((type.flags & ts5.TypeFlags.Object) === 0)
4211
4321
  return true;
4212
4322
  if (seen.length >= 8 || seen.includes(type))
4213
4323
  return false;
@@ -4222,7 +4332,7 @@ function structuralTypeWalkCompletes(type, checker, seen) {
4222
4332
  function structuralPropertiesComplete(type, checker, seen) {
4223
4333
  const nextSeen = [...seen, type];
4224
4334
  for (const property of checker.getPropertiesOfType(type)) {
4225
- if ((property.flags & ts4.SymbolFlags.Optional) !== 0)
4335
+ if ((property.flags & ts5.SymbolFlags.Optional) !== 0)
4226
4336
  continue;
4227
4337
  if (!structuralTypeWalkCompletes(checker.getTypeOfSymbol(property), checker, nextSeen))
4228
4338
  return false;
@@ -4241,12 +4351,6 @@ function requireBooleanCondition(node, checker) {
4241
4351
  });
4242
4352
  }
4243
4353
  function requireAccessedPropertyKind(access, checker) {
4244
- const receiverType = checker.getTypeAtLocation(access.expression);
4245
- const presentType = access.questionDotToken != null ? checker.getNonNullableType(receiverType) : receiverType;
4246
- const property = checker.getPropertyOfType(presentType, access.name.text);
4247
- if (valueKind(presentType, checker) === "object" && property != null && declaredOnlyInDeclarationFiles(property)) {
4248
- throw unsupported(access, { kind: "prototypeMemberRead", property: access.name.text });
4249
- }
4250
4354
  const type = checker.getTypeAtLocation(access);
4251
4355
  if (valueKind(type, checker) != null)
4252
4356
  return;
@@ -4255,17 +4359,12 @@ function requireAccessedPropertyKind(access, checker) {
4255
4359
  function resolvedSymbol(symbol, checker) {
4256
4360
  if (symbol == null)
4257
4361
  return null;
4258
- return (symbol.flags & ts4.SymbolFlags.Alias) === 0 ? symbol : checker.getAliasedSymbol(symbol);
4259
- }
4260
- function isStandardMathObject(expression, checker) {
4261
- if (!ts4.isIdentifier(expression) || expression.text !== "Math")
4262
- return false;
4263
- return declaredOnlyInDeclarationFiles(checker.getSymbolAtLocation(expression));
4362
+ return (symbol.flags & ts5.SymbolFlags.Alias) === 0 ? symbol : checker.getAliasedSymbol(symbol);
4264
4363
  }
4265
- function isStandardNumberObject(expression, checker) {
4266
- if (!ts4.isIdentifier(expression) || expression.text !== "Number")
4364
+ function isStandardGlobal(expression, name, context) {
4365
+ if (!ts5.isIdentifier(expression) || expression.text !== name)
4267
4366
  return false;
4268
- return declaredOnlyInDeclarationFiles(checker.getSymbolAtLocation(expression));
4367
+ return hasDefaultLibraryDeclaration(context.checker.getSymbolAtLocation(expression), context.program);
4269
4368
  }
4270
4369
  function lowerElementAccess(access, asserted, context) {
4271
4370
  const receiverType = context.checker.getTypeAtLocation(access.expression);
@@ -4280,7 +4379,7 @@ function lowerElementAccess(access, asserted, context) {
4280
4379
  requireNumberType(access.argumentExpression, context.checker);
4281
4380
  const array = lowerExpression(access.expression, context);
4282
4381
  const index = lowerExpression(access.argumentExpression, context);
4283
- const missingFlag = ts4.TypeFlags.Undefined;
4382
+ const missingFlag = ts5.TypeFlags.Undefined;
4284
4383
  const staticTypeAllowsUndefined = (resultType.flags & missingFlag) !== 0 || resultType.isUnion() && resultType.types.some((member) => (member.flags & missingFlag) !== 0);
4285
4384
  return addInstruction(context, access, {
4286
4385
  kind: "arrayIndex",
@@ -4291,7 +4390,7 @@ function lowerElementAccess(access, asserted, context) {
4291
4390
  }
4292
4391
  function taggedUnionTagRead(expression, context) {
4293
4392
  const unwrapped = unwrap(expression, context.checker);
4294
- if (!ts4.isPropertyAccessExpression(unwrapped))
4393
+ if (!ts5.isPropertyAccessExpression(unwrapped))
4295
4394
  return null;
4296
4395
  const objectType = context.checker.getTypeAtLocation(unwrapped.expression);
4297
4396
  if (valueKind(objectType, context.checker) !== "taggedUnion" || !objectType.isUnion())
@@ -4301,17 +4400,17 @@ function taggedUnionTagRead(expression, context) {
4301
4400
  }
4302
4401
  function tagCheckComparison(expression, context) {
4303
4402
  const operator = expression.operatorToken.kind;
4304
- const equals = operator === ts4.SyntaxKind.EqualsEqualsEqualsToken || operator === ts4.SyntaxKind.EqualsEqualsToken;
4305
- const notEquals = operator === ts4.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts4.SyntaxKind.ExclamationEqualsToken;
4403
+ const equals = operator === ts5.SyntaxKind.EqualsEqualsEqualsToken || operator === ts5.SyntaxKind.EqualsEqualsToken;
4404
+ const notEquals = operator === ts5.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts5.SyntaxKind.ExclamationEqualsToken;
4306
4405
  if (!equals && !notEquals)
4307
4406
  return null;
4308
4407
  const literalOf = (side) => {
4309
4408
  const unwrapped = unwrap(side, context.checker);
4310
- if (ts4.isStringLiteral(unwrapped) || ts4.isNoSubstitutionTemplateLiteral(unwrapped))
4409
+ if (ts5.isStringLiteral(unwrapped) || ts5.isNoSubstitutionTemplateLiteral(unwrapped))
4311
4410
  return unwrapped.text;
4312
- if (unwrapped.kind === ts4.SyntaxKind.TrueKeyword)
4411
+ if (unwrapped.kind === ts5.SyntaxKind.TrueKeyword)
4313
4412
  return true;
4314
- if (unwrapped.kind === ts4.SyntaxKind.FalseKeyword)
4413
+ if (unwrapped.kind === ts5.SyntaxKind.FalseKeyword)
4315
4414
  return false;
4316
4415
  return null;
4317
4416
  };
@@ -4329,7 +4428,7 @@ function tagCheckComparison(expression, context) {
4329
4428
  }
4330
4429
  function opaqueEqualityCheck(expression, context) {
4331
4430
  const operator = expression.operatorToken.kind;
4332
- const isEquality = operator === ts4.SyntaxKind.EqualsEqualsEqualsToken || operator === ts4.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts4.SyntaxKind.EqualsEqualsToken || operator === ts4.SyntaxKind.ExclamationEqualsToken;
4431
+ const isEquality = operator === ts5.SyntaxKind.EqualsEqualsEqualsToken || operator === ts5.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts5.SyntaxKind.EqualsEqualsToken || operator === ts5.SyntaxKind.ExclamationEqualsToken;
4333
4432
  if (!isEquality)
4334
4433
  return null;
4335
4434
  const opaqueOrMissingOpaque = (side) => {
@@ -4338,7 +4437,7 @@ function opaqueEqualityCheck(expression, context) {
4338
4437
  if (kind === "opaque")
4339
4438
  return true;
4340
4439
  if (kind === "nullable" && type.isUnion()) {
4341
- const missing = ts4.TypeFlags.Null | ts4.TypeFlags.Undefined;
4440
+ const missing = ts5.TypeFlags.Null | ts5.TypeFlags.Undefined;
4342
4441
  const rest = type.types.filter((member) => (member.flags & missing) === 0);
4343
4442
  return rest.length >= 1 && rest.every((member) => valueKind(member, context.checker) === "opaque");
4344
4443
  }
@@ -4352,14 +4451,14 @@ function opaqueEqualityCheck(expression, context) {
4352
4451
  }
4353
4452
  function missingSentinelCheck(expression, context) {
4354
4453
  const operator = expression.operatorToken.kind;
4355
- const strict = operator === ts4.SyntaxKind.EqualsEqualsEqualsToken || operator === ts4.SyntaxKind.ExclamationEqualsEqualsToken;
4356
- const loose = operator === ts4.SyntaxKind.EqualsEqualsToken || operator === ts4.SyntaxKind.ExclamationEqualsToken;
4454
+ const strict = operator === ts5.SyntaxKind.EqualsEqualsEqualsToken || operator === ts5.SyntaxKind.ExclamationEqualsEqualsToken;
4455
+ const loose = operator === ts5.SyntaxKind.EqualsEqualsToken || operator === ts5.SyntaxKind.ExclamationEqualsToken;
4357
4456
  if (!strict && !loose)
4358
4457
  return null;
4359
- const negated = operator === ts4.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts4.SyntaxKind.ExclamationEqualsToken;
4458
+ const negated = operator === ts5.SyntaxKind.ExclamationEqualsEqualsToken || operator === ts5.SyntaxKind.ExclamationEqualsToken;
4360
4459
  const sentinelOf = (side) => {
4361
4460
  const unwrapped = unwrap(side, context.checker);
4362
- if (unwrapped.kind === ts4.SyntaxKind.NullKeyword)
4461
+ if (unwrapped.kind === ts5.SyntaxKind.NullKeyword)
4363
4462
  return "null";
4364
4463
  if (isUndefinedGlobal(unwrapped, context.checker))
4365
4464
  return "undefined";
@@ -4367,39 +4466,39 @@ function missingSentinelCheck(expression, context) {
4367
4466
  };
4368
4467
  const isUndefinedString = (side) => {
4369
4468
  const unwrapped = unwrap(side, context.checker);
4370
- return ts4.isStringLiteral(unwrapped) && unwrapped.text === "undefined";
4469
+ return ts5.isStringLiteral(unwrapped) && unwrapped.text === "undefined";
4371
4470
  };
4372
- if (ts4.isTypeOfExpression(expression.left) && isUndefinedString(expression.right)) {
4471
+ if (ts5.isTypeOfExpression(expression.left) && isUndefinedString(expression.right)) {
4373
4472
  const value3 = lowerExpression(expression.left.expression, context);
4374
4473
  return addInstruction(context, expression, { kind: "nullishCheck", value: value3, sentinel: "undefined", negated });
4375
4474
  }
4376
- if (ts4.isTypeOfExpression(expression.right) && isUndefinedString(expression.left)) {
4475
+ if (ts5.isTypeOfExpression(expression.right) && isUndefinedString(expression.left)) {
4377
4476
  const value3 = lowerExpression(expression.right.expression, context);
4378
4477
  return addInstruction(context, expression, { kind: "nullishCheck", value: value3, sentinel: "undefined", negated });
4379
4478
  }
4380
4479
  const primitiveTypeofFlags = (side) => {
4381
4480
  const unwrapped = unwrap(side, context.checker);
4382
- if (!ts4.isStringLiteral(unwrapped))
4481
+ if (!ts5.isStringLiteral(unwrapped))
4383
4482
  return null;
4384
4483
  switch (unwrapped.text) {
4385
4484
  case "number":
4386
- return ts4.TypeFlags.NumberLike;
4485
+ return ts5.TypeFlags.NumberLike;
4387
4486
  case "string":
4388
- return ts4.TypeFlags.StringLike;
4487
+ return ts5.TypeFlags.StringLike;
4389
4488
  case "boolean":
4390
- return ts4.TypeFlags.BooleanLike;
4489
+ return ts5.TypeFlags.BooleanLike;
4391
4490
  default:
4392
4491
  return null;
4393
4492
  }
4394
4493
  };
4395
4494
  const rightFlags = primitiveTypeofFlags(expression.right);
4396
4495
  const leftFlags = primitiveTypeofFlags(expression.left);
4397
- const typeofSide = ts4.isTypeOfExpression(expression.left) && rightFlags != null ? { operand: expression.left, flags: rightFlags } : ts4.isTypeOfExpression(expression.right) && leftFlags != null ? { operand: expression.right, flags: leftFlags } : null;
4496
+ const typeofSide = ts5.isTypeOfExpression(expression.left) && rightFlags != null ? { operand: expression.left, flags: rightFlags } : ts5.isTypeOfExpression(expression.right) && leftFlags != null ? { operand: expression.right, flags: leftFlags } : null;
4398
4497
  if (typeofSide != null) {
4399
4498
  const operandType = context.checker.getTypeAtLocation(typeofSide.operand.expression);
4400
- const missing = ts4.TypeFlags.Null | ts4.TypeFlags.Undefined;
4499
+ const missing = ts5.TypeFlags.Null | ts5.TypeFlags.Undefined;
4401
4500
  const members = operandType.isUnion() ? operandType.types : [operandType];
4402
- const restMatches = members.every((member) => (member.flags & missing) !== 0 || (member.flags & typeofSide.flags) !== 0) && members.some((member) => (member.flags & missing) === 0);
4501
+ const restMatches = members.every((member) => (member.flags & missing) !== 0 || (typeofSide.flags === ts5.TypeFlags.NumberLike ? valueKind(member, context.checker) === "number" : (member.flags & typeofSide.flags) !== 0)) && members.some((member) => (member.flags & missing) === 0);
4403
4502
  const value3 = lowerExpression(typeofSide.operand.expression, context);
4404
4503
  if (restMatches) {
4405
4504
  return addInstruction(context, expression, { kind: "nullishCheck", value: value3, sentinel: "nullish", negated: !negated });
@@ -4413,7 +4512,7 @@ function missingSentinelCheck(expression, context) {
4413
4512
  return null;
4414
4513
  const checked = leftSentinel == null ? expression.left : expression.right;
4415
4514
  const checkedType = context.checker.getTypeAtLocation(checked);
4416
- const missingFlags = ts4.TypeFlags.Null | ts4.TypeFlags.Undefined;
4515
+ const missingFlags = ts5.TypeFlags.Null | ts5.TypeFlags.Undefined;
4417
4516
  const pureSentinel = (checkedType.flags & missingFlags) !== 0 || checkedType.isUnion() && checkedType.types.every((member) => (member.flags & missingFlags) !== 0);
4418
4517
  if (!pureSentinel && valueKind(checkedType, context.checker) == null) {
4419
4518
  throw unsupported(checked, { kind: "valueType", typeText: context.checker.typeToString(checkedType) });
@@ -4426,11 +4525,6 @@ function missingSentinelCheck(expression, context) {
4426
4525
  negated
4427
4526
  });
4428
4527
  }
4429
- function isGlobalInfinity(expression, checker) {
4430
- if (!ts4.isIdentifier(expression) || expression.text !== "Infinity")
4431
- return false;
4432
- return declaredOnlyInDeclarationFiles(checker.getSymbolAtLocation(expression));
4433
- }
4434
4528
  function identifierValue(symbol, node, context) {
4435
4529
  const local = context.bindings.get(symbol);
4436
4530
  if (local != null)
@@ -4438,7 +4532,7 @@ function identifierValue(symbol, node, context) {
4438
4532
  const binding = context.moduleBindingsBySymbol.get(symbol);
4439
4533
  if (binding != null)
4440
4534
  return addInstruction(context, node, { kind: "moduleRead", binding });
4441
- if (isGlobalInfinity(node, context.checker)) {
4535
+ if (isStandardGlobal(node, "Infinity", context)) {
4442
4536
  return addInstruction(context, node, { kind: "constant", value: Number.POSITIVE_INFINITY });
4443
4537
  }
4444
4538
  if (isUndefinedGlobal(node, context.checker)) {
@@ -4457,25 +4551,25 @@ function assignIdentifier(symbol, node, value2, wholeExpression, context) {
4457
4551
  throw unsupported(node, { kind: "unknownIdentifier", name: node.text });
4458
4552
  }
4459
4553
  function propertyName(name) {
4460
- if (ts4.isIdentifier(name) || ts4.isStringLiteral(name) || ts4.isNumericLiteral(name))
4554
+ if (ts5.isIdentifier(name) || ts5.isStringLiteral(name) || ts5.isNumericLiteral(name))
4461
4555
  return name.text;
4462
4556
  throw unsupported(name, { kind: "computedPropertyName" });
4463
4557
  }
4464
4558
  function unwrap(expression, checker) {
4465
4559
  let current = expression;
4466
4560
  while (true) {
4467
- if (ts4.isParenthesizedExpression(current) || ts4.isSatisfiesExpression(current)) {
4561
+ if (ts5.isParenthesizedExpression(current) || ts5.isSatisfiesExpression(current)) {
4468
4562
  current = current.expression;
4469
4563
  continue;
4470
4564
  }
4471
- if ((ts4.isAsExpression(current) || ts4.isTypeAssertionExpression(current)) && ts4.isConstTypeReference(current.type)) {
4565
+ if ((ts5.isAsExpression(current) || ts5.isTypeAssertionExpression(current)) && ts5.isConstTypeReference(current.type)) {
4472
4566
  current = current.expression;
4473
4567
  continue;
4474
4568
  }
4475
- if (ts4.isNonNullExpression(current)) {
4569
+ if (ts5.isNonNullExpression(current)) {
4476
4570
  const assertedType = checker.getTypeAtLocation(current);
4477
4571
  const operandType = checker.getTypeAtLocation(current.expression);
4478
- if (ts4.isElementAccessExpression(current.expression) && valueKind(assertedType, checker) != null) {
4572
+ if (ts5.isElementAccessExpression(current.expression) && valueKind(assertedType, checker) != null) {
4479
4573
  return current;
4480
4574
  }
4481
4575
  if (valueKind(assertedType, checker) !== valueKind(operandType, checker)) {
@@ -4492,11 +4586,51 @@ function unwrap(expression, checker) {
4492
4586
  }
4493
4587
  }
4494
4588
 
4495
- // src/lower/module.ts
4589
+ // src/lower/function-unit.ts
4496
4590
  import * as ts6 from "typescript";
4591
+ function callableSignature(unit, checker) {
4592
+ if (unit.initializer == null) {
4593
+ return checker.getSignatureFromDeclaration(unit.declaration) ?? null;
4594
+ }
4595
+ const signatures = checker.getSignaturesOfType(checker.getTypeAtLocation(unit.name), ts6.SignatureKind.Call);
4596
+ if (signatures.length !== 1)
4597
+ return null;
4598
+ const signature = signatures[0];
4599
+ const signatureDeclaration = signature.declaration;
4600
+ if (signatureDeclaration == null || signature.thisParameter != null || signature.parameters.length !== unit.declaration.parameters.length || signatureDeclaration.parameters.some((parameter) => !ts6.isParameter(parameter) || parameter.dotDotDotToken != null)) {
4601
+ return null;
4602
+ }
4603
+ return signature;
4604
+ }
4605
+ function topLevelFunctionUnits(sourceFile) {
4606
+ const units = [];
4607
+ for (const statement of sourceFile.statements) {
4608
+ if (ts6.isFunctionDeclaration(statement) && statement.name != null) {
4609
+ units.push({ name: statement.name, declaration: statement, initializer: null });
4610
+ continue;
4611
+ }
4612
+ if (!ts6.isVariableStatement(statement) || (statement.declarationList.flags & ts6.NodeFlags.Const) === 0)
4613
+ continue;
4614
+ for (const initializer of statement.declarationList.declarations) {
4615
+ if (!ts6.isIdentifier(initializer.name) || initializer.initializer == null)
4616
+ continue;
4617
+ const declaration = directFunctionExpression(initializer.initializer);
4618
+ if (declaration != null) {
4619
+ units.push({ name: initializer.name, declaration, initializer });
4620
+ }
4621
+ }
4622
+ }
4623
+ return units;
4624
+ }
4625
+ function directFunctionExpression(expression) {
4626
+ return ts6.isArrowFunction(expression) || ts6.isFunctionExpression(expression) ? expression : null;
4627
+ }
4628
+
4629
+ // src/lower/module.ts
4630
+ import * as ts8 from "typescript";
4497
4631
 
4498
4632
  // src/lower/statements.ts
4499
- import * as ts5 from "typescript";
4633
+ import * as ts7 from "typescript";
4500
4634
  function lowerStatements(statements, context) {
4501
4635
  for (const statement of statements) {
4502
4636
  if (context.currentBlock.terminator != null)
@@ -4505,61 +4639,57 @@ function lowerStatements(statements, context) {
4505
4639
  }
4506
4640
  }
4507
4641
  function lowerStatement(statement, context) {
4508
- if (ts5.isVariableStatement(statement)) {
4642
+ if (ts7.isVariableStatement(statement)) {
4509
4643
  lowerVariableDeclarationList(statement.declarationList, context);
4510
4644
  return;
4511
4645
  }
4512
- if (ts5.isReturnStatement(statement)) {
4646
+ if (ts7.isReturnStatement(statement)) {
4513
4647
  let value2 = statement.expression == null ? null : lowerExpression(statement.expression, context);
4514
- if (value2 == null) {
4515
- const enclosing = ts5.findAncestor(statement, ts5.isFunctionDeclaration);
4516
- const signature = enclosing == null ? undefined : context.checker.getSignatureFromDeclaration(enclosing);
4517
- const returnType = signature == null ? null : context.checker.getReturnTypeOfSignature(signature);
4518
- const returnsVoid = returnType == null || (returnType.flags & (ts5.TypeFlags.Void | ts5.TypeFlags.Undefined)) !== 0;
4519
- if (!returnsVoid) {
4520
- value2 = addInstruction(context, statement, { kind: "nullishConstant", sentinel: "undefined" });
4521
- }
4648
+ if (context.returnsVoid)
4649
+ value2 = null;
4650
+ if (value2 == null && !context.returnsVoid) {
4651
+ value2 = addInstruction(context, statement, { kind: "nullishConstant", sentinel: "undefined" });
4522
4652
  }
4523
4653
  terminate(context.currentBlock, { kind: "return", value: value2, site: addSite(context, statement) });
4524
4654
  return;
4525
4655
  }
4526
- if (ts5.isExpressionStatement(statement)) {
4656
+ if (ts7.isExpressionStatement(statement)) {
4527
4657
  lowerStatementExpression(statement.expression, context);
4528
4658
  return;
4529
4659
  }
4530
- if (ts5.isIfStatement(statement)) {
4660
+ if (ts7.isIfStatement(statement)) {
4531
4661
  lowerIfStatement(statement, context);
4532
4662
  return;
4533
4663
  }
4534
- if (ts5.isForOfStatement(statement)) {
4664
+ if (ts7.isForOfStatement(statement)) {
4535
4665
  lowerForOfStatement(statement, context);
4536
4666
  return;
4537
4667
  }
4538
- if (ts5.isForStatement(statement)) {
4668
+ if (ts7.isForStatement(statement)) {
4539
4669
  lowerForStatement(statement, context);
4540
4670
  return;
4541
4671
  }
4542
- if (ts5.isWhileStatement(statement)) {
4672
+ if (ts7.isWhileStatement(statement)) {
4543
4673
  lowerWhileStatement(statement, context);
4544
4674
  return;
4545
4675
  }
4546
- if (ts5.isContinueStatement(statement)) {
4676
+ if (ts7.isContinueStatement(statement)) {
4547
4677
  lowerContinueStatement(statement, context);
4548
4678
  return;
4549
4679
  }
4550
- if (ts5.isBlock(statement)) {
4680
+ if (ts7.isBlock(statement)) {
4551
4681
  lowerStatements(statement.statements, context);
4552
4682
  return;
4553
4683
  }
4554
- if (ts5.isSwitchStatement(statement)) {
4684
+ if (ts7.isSwitchStatement(statement)) {
4555
4685
  lowerSwitchStatement(statement, context);
4556
4686
  return;
4557
4687
  }
4558
- if (ts5.isThrowStatement(statement)) {
4688
+ if (ts7.isThrowStatement(statement)) {
4559
4689
  terminate(context.currentBlock, { kind: "thrown", site: addSite(context, statement) });
4560
4690
  return;
4561
4691
  }
4562
- throw unsupported(statement, { kind: "statementForm", syntax: ts5.SyntaxKind[statement.kind] });
4692
+ throw unsupported(statement, { kind: "statementForm", syntax: ts7.SyntaxKind[statement.kind] });
4563
4693
  }
4564
4694
  function lowerIfStatement(statement, context) {
4565
4695
  const bindingsBeforeBranch = new Map(context.bindings);
@@ -4586,7 +4716,7 @@ function lowerSwitchStatement(statement, context) {
4586
4716
  const subjectType = context.checker.getTypeAtLocation(statement.expression);
4587
4717
  const subjectKind = valueKind(subjectType, context.checker);
4588
4718
  const tagUnionExpression = taggedUnionTagRead(statement.expression, context);
4589
- const missingFlags = ts5.TypeFlags.Null | ts5.TypeFlags.Undefined;
4719
+ const missingFlags = ts7.TypeFlags.Null | ts7.TypeFlags.Undefined;
4590
4720
  const nullableOpaqueSubject = subjectKind === "nullable" && subjectType.isUnion() && subjectType.types.every((member) => (member.flags & missingFlags) !== 0 || valueKind(member, context.checker) === "opaque");
4591
4721
  if (tagUnionExpression == null && subjectKind !== "number" && subjectKind !== "opaque" && !nullableOpaqueSubject) {
4592
4722
  throw unsupported(statement.expression, { kind: "switchSubject", typeText: context.checker.typeToString(subjectType) });
@@ -4598,7 +4728,7 @@ function lowerSwitchStatement(statement, context) {
4598
4728
  const clauses = statement.caseBlock.clauses;
4599
4729
  for (let index = 0;index < clauses.length; index++) {
4600
4730
  const clause = clauses[index];
4601
- if (ts5.isDefaultClause(clause)) {
4731
+ if (ts7.isDefaultClause(clause)) {
4602
4732
  if (index !== clauses.length - 1 || pendingLabels.length > 0) {
4603
4733
  throw unsupported(clause, { kind: "switchDefaultNotLast" });
4604
4734
  }
@@ -4619,7 +4749,7 @@ function lowerSwitchStatement(statement, context) {
4619
4749
  const lowerBody = (group) => {
4620
4750
  const body = group.statements;
4621
4751
  const last = body[body.length - 1];
4622
- const endsWithBreak = last != null && ts5.isBreakStatement(last);
4752
+ const endsWithBreak = last != null && ts7.isBreakStatement(last);
4623
4753
  lowerStatements(endsWithBreak ? body.slice(0, -1) : body, context);
4624
4754
  if (context.currentBlock.terminator == null) {
4625
4755
  if (!endsWithBreak)
@@ -4638,7 +4768,7 @@ function lowerSwitchStatement(statement, context) {
4638
4768
  let condition;
4639
4769
  if (tagUnionExpression != null) {
4640
4770
  const unwrappedLabel = label;
4641
- if (!ts5.isStringLiteral(unwrappedLabel) && !ts5.isNoSubstitutionTemplateLiteral(unwrappedLabel)) {
4771
+ if (!ts7.isStringLiteral(unwrappedLabel) && !ts7.isNoSubstitutionTemplateLiteral(unwrappedLabel)) {
4642
4772
  throw unsupported(label, { kind: "switchLabel", typeText: context.checker.typeToString(context.checker.getTypeAtLocation(label)) });
4643
4773
  }
4644
4774
  condition = addInstruction(context, label, { kind: "tagCheck", union: subject, tagValue: unwrappedLabel.text, negated: false });
@@ -4680,7 +4810,7 @@ function lowerSwitchStatement(statement, context) {
4680
4810
  mergeAtContinuation(exits, bindingsBefore, statement, context);
4681
4811
  }
4682
4812
  function lowerForOfStatement(statement, context) {
4683
- if (!ts5.isVariableDeclarationList(statement.initializer) || statement.initializer.declarations.length !== 1 || !ts5.isIdentifier(statement.initializer.declarations[0].name)) {
4813
+ if (!ts7.isVariableDeclarationList(statement.initializer) || statement.initializer.declarations.length !== 1 || !ts7.isIdentifier(statement.initializer.declarations[0].name)) {
4684
4814
  throw unsupported(statement.initializer, { kind: "variableDeclarationShape" });
4685
4815
  }
4686
4816
  const elementName = statement.initializer.declarations[0].name;
@@ -4757,7 +4887,7 @@ function lowerForOfStatement(statement, context) {
4757
4887
  }
4758
4888
  function lowerForStatement(statement, context) {
4759
4889
  if (statement.initializer != null) {
4760
- if (ts5.isVariableDeclarationList(statement.initializer)) {
4890
+ if (ts7.isVariableDeclarationList(statement.initializer)) {
4761
4891
  lowerVariableDeclarationList(statement.initializer, context);
4762
4892
  } else {
4763
4893
  lowerStatementExpression(statement.initializer, context);
@@ -4866,21 +4996,16 @@ function lowerBranch(statement, block, bindings, context) {
4866
4996
  }
4867
4997
  function lowerVariableDeclarationList(declarations, context) {
4868
4998
  for (const declaration of declarations.declarations) {
4869
- if (ts5.isObjectBindingPattern(declaration.name) && declaration.initializer != null) {
4999
+ if (ts7.isObjectBindingPattern(declaration.name) && declaration.initializer != null) {
4870
5000
  const source = lowerExpression(declaration.initializer, context);
4871
5001
  for (const element of declaration.name.elements) {
4872
- if (!ts5.isIdentifier(element.name) || element.dotDotDotToken != null || element.initializer != null) {
5002
+ if (!ts7.isIdentifier(element.name) || element.dotDotDotToken != null || element.initializer != null) {
4873
5003
  throw unsupported(element, { kind: "variableDeclarationShape" });
4874
5004
  }
4875
- const property = element.propertyName == null ? element.name.text : ts5.isIdentifier(element.propertyName) ? element.propertyName.text : null;
5005
+ const property = element.propertyName == null ? element.name.text : ts7.isIdentifier(element.propertyName) ? element.propertyName.text : null;
4876
5006
  if (property == null)
4877
5007
  throw unsupported(element, { kind: "variableDeclarationShape" });
4878
5008
  const elementType = context.checker.getTypeAtLocation(element.name);
4879
- const sourceType = context.checker.getTypeAtLocation(declaration.initializer);
4880
- const propertySymbol = context.checker.getPropertyOfType(sourceType, property);
4881
- if (propertySymbol != null && declaredOnlyInDeclarationFiles(propertySymbol)) {
4882
- throw unsupported(element, { kind: "prototypeMemberRead", property });
4883
- }
4884
5009
  if (valueKind(elementType, context.checker) == null) {
4885
5010
  throw unsupported(element, { kind: "valueType", typeText: context.checker.typeToString(elementType) });
4886
5011
  }
@@ -4889,7 +5014,7 @@ function lowerVariableDeclarationList(declarations, context) {
4889
5014
  }
4890
5015
  continue;
4891
5016
  }
4892
- if (!ts5.isIdentifier(declaration.name) || declaration.initializer == null) {
5017
+ if (!ts7.isIdentifier(declaration.name) || declaration.initializer == null) {
4893
5018
  throw unsupported(declaration, { kind: "variableDeclarationShape" });
4894
5019
  }
4895
5020
  const value2 = lowerExpression(declaration.initializer, context);
@@ -4908,12 +5033,12 @@ function lowerVariableDeclarationList(declarations, context) {
4908
5033
  function assignedSymbols(nodes, checker) {
4909
5034
  const symbols = new Set;
4910
5035
  const visit = (node) => {
4911
- if (ts5.isFunctionLike(node))
5036
+ if (ts7.isFunctionLike(node))
4912
5037
  return;
4913
5038
  const assignment = identifierAssignment(node);
4914
5039
  if (assignment != null)
4915
5040
  symbols.add(requiredSymbol(assignment.target, checker));
4916
- ts5.forEachChild(node, visit);
5041
+ ts7.forEachChild(node, visit);
4917
5042
  };
4918
5043
  for (const node of nodes)
4919
5044
  visit(node);
@@ -4932,45 +5057,46 @@ function scanModuleBindings(sourceFile, checker) {
4932
5057
  bindings.push({ name: name.text, category });
4933
5058
  };
4934
5059
  for (const statement of sourceFile.statements) {
4935
- if (ts6.isVariableStatement(statement)) {
4936
- if ((statement.declarationList.flags & (ts6.NodeFlags.Let | ts6.NodeFlags.Const)) === 0)
5060
+ if (ts8.isVariableStatement(statement)) {
5061
+ if ((statement.declarationList.flags & (ts8.NodeFlags.Let | ts8.NodeFlags.Const)) === 0)
4937
5062
  continue;
5063
+ const isConst = (statement.declarationList.flags & ts8.NodeFlags.Const) !== 0;
4938
5064
  for (const declarator of statement.declarationList.declarations) {
4939
- if (ts6.isIdentifier(declarator.name)) {
4940
- register(declarator.name, declaredCategory(declarator.name, checker));
5065
+ if (ts8.isIdentifier(declarator.name)) {
5066
+ register(declarator.name, isConst && declarator.initializer != null && directFunctionExpression(declarator.initializer) != null ? { kind: "function" } : declaredCategory(declarator.name, checker));
4941
5067
  continue;
4942
5068
  }
4943
- if (ts6.isObjectBindingPattern(declarator.name)) {
5069
+ if (ts8.isObjectBindingPattern(declarator.name)) {
4944
5070
  for (const element of declarator.name.elements) {
4945
- if (ts6.isIdentifier(element.name))
5071
+ if (ts8.isIdentifier(element.name))
4946
5072
  register(element.name, declaredCategory(element.name, checker));
4947
5073
  }
4948
5074
  }
4949
5075
  }
4950
5076
  continue;
4951
5077
  }
4952
- if (ts6.isImportDeclaration(statement)) {
5078
+ if (ts8.isImportDeclaration(statement)) {
4953
5079
  const clause = statement.importClause;
4954
5080
  if (clause == null || clause.isTypeOnly)
4955
5081
  continue;
4956
5082
  if (clause.name != null)
4957
5083
  register(clause.name, importedCategory(clause.name, checker));
4958
5084
  const named = clause.namedBindings;
4959
- if (named != null && ts6.isNamedImports(named)) {
5085
+ if (named != null && ts8.isNamedImports(named)) {
4960
5086
  for (const element of named.elements) {
4961
5087
  if (!element.isTypeOnly)
4962
5088
  register(element.name, importedCategory(element.name, checker));
4963
5089
  }
4964
5090
  }
4965
- if (named != null && ts6.isNamespaceImport(named))
5091
+ if (named != null && ts8.isNamespaceImport(named))
4966
5092
  register(named.name, { kind: "import" });
4967
5093
  }
4968
5094
  }
4969
5095
  const visit = (node, insideFunction) => {
4970
5096
  if (insideFunction)
4971
5097
  demoteModuleWritesInNode(node, checker, bindingsBySymbol, bindings);
4972
- const enteringFunction = insideFunction || ts6.isFunctionLike(node);
4973
- ts6.forEachChild(node, (child) => {
5098
+ const enteringFunction = insideFunction || ts8.isFunctionLike(node);
5099
+ ts8.forEachChild(node, (child) => {
4974
5100
  visit(child, enteringFunction);
4975
5101
  });
4976
5102
  };
@@ -4979,13 +5105,13 @@ function scanModuleBindings(sourceFile, checker) {
4979
5105
  }
4980
5106
  function importedCategory(name, checker) {
4981
5107
  const symbol = checker.getSymbolAtLocation(name);
4982
- if (symbol == null || (symbol.flags & ts6.SymbolFlags.Alias) === 0)
5108
+ if (symbol == null || (symbol.flags & ts8.SymbolFlags.Alias) === 0)
4983
5109
  return { kind: "import" };
4984
5110
  const target = checker.getAliasedSymbol(symbol);
4985
5111
  const declaration = target.valueDeclaration;
4986
- if (declaration == null || !ts6.isVariableDeclaration(declaration))
5112
+ if (declaration == null || !ts8.isVariableDeclaration(declaration))
4987
5113
  return { kind: "import" };
4988
- if ((ts6.getCombinedNodeFlags(declaration) & ts6.NodeFlags.Const) === 0)
5114
+ if ((ts8.getCombinedNodeFlags(declaration) & ts8.NodeFlags.Const) === 0)
4989
5115
  return { kind: "import" };
4990
5116
  if (declaration.getSourceFile().isDeclarationFile)
4991
5117
  return { kind: "import" };
@@ -5001,7 +5127,7 @@ function demoteModuleWritesInNode(node, checker, bindingsBySymbol, bindings, wri
5001
5127
  written[binding] = true;
5002
5128
  };
5003
5129
  const target = (expression) => {
5004
- if (ts6.isIdentifier(expression)) {
5130
+ if (ts8.isIdentifier(expression)) {
5005
5131
  const symbol = checker.getSymbolAtLocation(expression);
5006
5132
  const binding = symbol == null ? undefined : bindingsBySymbol.get(symbol);
5007
5133
  if (binding != null)
@@ -5009,39 +5135,39 @@ function demoteModuleWritesInNode(node, checker, bindingsBySymbol, bindings, wri
5009
5135
  return;
5010
5136
  }
5011
5137
  const visitPattern = (child) => {
5012
- if (ts6.isShorthandPropertyAssignment(child)) {
5138
+ if (ts8.isShorthandPropertyAssignment(child)) {
5013
5139
  const symbol = checker.getShorthandAssignmentValueSymbol(child);
5014
5140
  const binding = symbol == null ? undefined : bindingsBySymbol.get(symbol);
5015
5141
  if (binding != null)
5016
5142
  record(binding);
5017
- ts6.forEachChild(child, visitPattern);
5143
+ ts8.forEachChild(child, visitPattern);
5018
5144
  return;
5019
5145
  }
5020
- if (ts6.isIdentifier(child)) {
5146
+ if (ts8.isIdentifier(child)) {
5021
5147
  const symbol = checker.getSymbolAtLocation(child);
5022
5148
  const binding = symbol == null ? undefined : bindingsBySymbol.get(symbol);
5023
5149
  if (binding != null)
5024
5150
  record(binding);
5025
5151
  return;
5026
5152
  }
5027
- ts6.forEachChild(child, visitPattern);
5153
+ ts8.forEachChild(child, visitPattern);
5028
5154
  };
5029
- ts6.forEachChild(expression, visitPattern);
5155
+ ts8.forEachChild(expression, visitPattern);
5030
5156
  };
5031
- if (ts6.isBinaryExpression(node)) {
5157
+ if (ts8.isBinaryExpression(node)) {
5032
5158
  const kind = node.operatorToken.kind;
5033
- if (kind >= ts6.SyntaxKind.FirstAssignment && kind <= ts6.SyntaxKind.LastAssignment)
5159
+ if (kind >= ts8.SyntaxKind.FirstAssignment && kind <= ts8.SyntaxKind.LastAssignment)
5034
5160
  target(node.left);
5035
5161
  }
5036
- if ((ts6.isPrefixUnaryExpression(node) || ts6.isPostfixUnaryExpression(node)) && (node.operator === ts6.SyntaxKind.PlusPlusToken || node.operator === ts6.SyntaxKind.MinusMinusToken) && ts6.isExpression(node.operand)) {
5162
+ if ((ts8.isPrefixUnaryExpression(node) || ts8.isPostfixUnaryExpression(node)) && (node.operator === ts8.SyntaxKind.PlusPlusToken || node.operator === ts8.SyntaxKind.MinusMinusToken) && ts8.isExpression(node.operand)) {
5037
5163
  target(node.operand);
5038
5164
  }
5039
- if ((ts6.isForOfStatement(node) || ts6.isForInStatement(node)) && ts6.isExpression(node.initializer)) {
5165
+ if ((ts8.isForOfStatement(node) || ts8.isForInStatement(node)) && ts8.isExpression(node.initializer)) {
5040
5166
  target(node.initializer);
5041
5167
  }
5042
5168
  }
5043
- function lowerModuleInitializer(sourceFile, checker, functionsBySymbol, scan, sites) {
5044
- const context = createFunctionContext(sourceFile, checker, functionsBySymbol, scan.bindingsBySymbol, sites);
5169
+ function lowerModuleInitializer(sourceFile, checker, program, functionsBySymbol, scan, sites) {
5170
+ const context = createFunctionContext(sourceFile, checker, program, functionsBySymbol, scan.bindingsBySymbol, sites);
5045
5171
  const skips = [];
5046
5172
  const statements = sourceFile.statements;
5047
5173
  for (const statement of statements) {
@@ -5049,8 +5175,8 @@ function lowerModuleInitializer(sourceFile, checker, functionsBySymbol, scan, si
5049
5175
  continue;
5050
5176
  const recovery = snapshotLowering(context);
5051
5177
  try {
5052
- assertAccepted(statement);
5053
- if (ts6.isVariableStatement(statement)) {
5178
+ assertAccepted(statement, true);
5179
+ if (ts8.isVariableStatement(statement)) {
5054
5180
  lowerTopLevelDeclarations(statement, context, scan);
5055
5181
  continue;
5056
5182
  }
@@ -5088,31 +5214,31 @@ function lowerModuleInitializer(sourceFile, checker, functionsBySymbol, scan, si
5088
5214
  };
5089
5215
  }
5090
5216
  function containsArrayLiteral(root) {
5091
- if (ts6.isArrayLiteralExpression(root))
5217
+ if (ts8.isArrayLiteralExpression(root))
5092
5218
  return true;
5093
5219
  let found = false;
5094
- ts6.forEachChild(root, (child) => {
5220
+ ts8.forEachChild(root, (child) => {
5095
5221
  if (!found && containsArrayLiteral(child))
5096
5222
  found = true;
5097
5223
  });
5098
5224
  return found;
5099
5225
  }
5100
5226
  function forEachImmediatelyEvaluatedChild(node, visit) {
5101
- if (ts6.isFunctionLike(node)) {
5102
- if (node.name != null && ts6.isComputedPropertyName(node.name)) {
5227
+ if (ts8.isFunctionLike(node)) {
5228
+ if (node.name != null && ts8.isComputedPropertyName(node.name)) {
5103
5229
  visit(node.name.expression);
5104
5230
  }
5105
5231
  return;
5106
5232
  }
5107
- ts6.forEachChild(node, visit);
5233
+ ts8.forEachChild(node, visit);
5108
5234
  }
5109
5235
  function lowerSupportedArgumentsOfSkippedTopLevelCall(statement, stop, context) {
5110
- if (!ts6.isExpressionStatement(statement))
5236
+ if (!ts8.isExpressionStatement(statement))
5111
5237
  return;
5112
5238
  let expression = statement.expression;
5113
- while (ts6.isParenthesizedExpression(expression))
5239
+ while (ts8.isParenthesizedExpression(expression))
5114
5240
  expression = expression.expression;
5115
- if (!ts6.isCallExpression(expression) || expression !== stop.node || expression.questionDotToken != null || !plainCallTarget(expression.expression))
5241
+ if (!ts8.isCallExpression(expression) || expression !== stop.node || expression.questionDotToken != null || !plainCallTarget(expression.expression))
5116
5242
  return;
5117
5243
  for (const argument of expression.arguments) {
5118
5244
  const recovery = snapshotLowering(context);
@@ -5127,23 +5253,23 @@ function lowerSupportedArgumentsOfSkippedTopLevelCall(statement, stop, context)
5127
5253
  }
5128
5254
  }
5129
5255
  function plainCallTarget(expression) {
5130
- if (ts6.isIdentifier(expression))
5256
+ if (ts8.isIdentifier(expression))
5131
5257
  return true;
5132
- if (ts6.isParenthesizedExpression(expression))
5258
+ if (ts8.isParenthesizedExpression(expression))
5133
5259
  return plainCallTarget(expression.expression);
5134
- return ts6.isPropertyAccessExpression(expression) && expression.questionDotToken == null && plainCallTarget(expression.expression);
5260
+ return ts8.isPropertyAccessExpression(expression) && expression.questionDotToken == null && plainCallTarget(expression.expression);
5135
5261
  }
5136
5262
  function lowerTopLevelDeclarations(statement, context, scan) {
5137
5263
  for (const declarator of statement.declarationList.declarations) {
5138
5264
  if (declarator.initializer == null)
5139
5265
  throw new LoweringStop(declarator, { kind: "variableDeclarationShape" });
5140
- if (ts6.isObjectBindingPattern(declarator.name)) {
5266
+ if (ts8.isObjectBindingPattern(declarator.name)) {
5141
5267
  const source = lowerExpression(declarator.initializer, context);
5142
5268
  for (const element of declarator.name.elements) {
5143
- if (!ts6.isIdentifier(element.name) || element.dotDotDotToken != null || element.initializer != null) {
5269
+ if (!ts8.isIdentifier(element.name) || element.dotDotDotToken != null || element.initializer != null) {
5144
5270
  throw new LoweringStop(element, { kind: "variableDeclarationShape" });
5145
5271
  }
5146
- const property = element.propertyName == null ? element.name.text : ts6.isIdentifier(element.propertyName) ? element.propertyName.text : null;
5272
+ const property = element.propertyName == null ? element.name.text : ts8.isIdentifier(element.propertyName) ? element.propertyName.text : null;
5147
5273
  if (property == null)
5148
5274
  throw new LoweringStop(element, { kind: "variableDeclarationShape" });
5149
5275
  const elementType = context.checker.getTypeAtLocation(element.name);
@@ -5159,27 +5285,32 @@ function lowerTopLevelDeclarations(statement, context, scan) {
5159
5285
  }
5160
5286
  continue;
5161
5287
  }
5162
- if (!ts6.isIdentifier(declarator.name)) {
5288
+ if (!ts8.isIdentifier(declarator.name)) {
5163
5289
  throw new LoweringStop(declarator, { kind: "variableDeclarationShape" });
5164
5290
  }
5165
5291
  const symbol = context.checker.getSymbolAtLocation(declarator.name);
5166
5292
  const binding = symbol == null ? undefined : scan.bindingsBySymbol.get(symbol);
5167
5293
  if (binding == null)
5168
5294
  throw new LoweringStop(declarator, { kind: "variableDeclarationShape" });
5295
+ if ((statement.declarationList.flags & ts8.NodeFlags.Const) !== 0 && directFunctionExpression(declarator.initializer) != null) {
5296
+ const marker = addInstruction(context, declarator.initializer, { kind: "opaqueConstant" });
5297
+ addInstruction(context, declarator, { kind: "moduleWrite", binding, value: marker });
5298
+ continue;
5299
+ }
5169
5300
  const value2 = lowerExpression(declarator.initializer, context);
5170
5301
  addInstruction(context, declarator, { kind: "moduleWrite", binding, value: value2 });
5171
5302
  }
5172
5303
  }
5173
5304
  function skippedAtTopLevel(statement) {
5174
- return ts6.isFunctionDeclaration(statement) && statement.name != null || ts6.isImportDeclaration(statement) || ts6.isTypeAliasDeclaration(statement) || ts6.isInterfaceDeclaration(statement) || ts6.isExportDeclaration(statement);
5305
+ return ts8.isFunctionDeclaration(statement) && statement.name != null || ts8.isImportDeclaration(statement) || ts8.isTypeAliasDeclaration(statement) || ts8.isInterfaceDeclaration(statement) || ts8.isExportDeclaration(statement);
5175
5306
  }
5176
5307
  function scanSkippedModuleEffects(root, checker, bindingsBySymbol, bindings) {
5177
5308
  const directWrites = [];
5178
5309
  let invokesUnknownCode = false;
5179
5310
  const visit = (node) => {
5180
5311
  demoteModuleWritesInNode(node, checker, bindingsBySymbol, bindings, directWrites);
5181
- invokesUnknownCode ||= ts6.isCallExpression(node) || ts6.isNewExpression(node) || ts6.isTaggedTemplateExpression(node) || ts6.isAwaitExpression(node) || ts6.isYieldExpression(node) || ts6.isForOfStatement(node) || ts6.isSpreadElement(node) || ts6.isArrayBindingPattern(node) || ts6.isVariableDeclarationList(node) && (node.flags & ts6.NodeFlags.Using) !== 0 || ts6.isBinaryExpression(node) && (node.operatorToken.kind === ts6.SyntaxKind.InstanceOfKeyword || node.operatorToken.kind === ts6.SyntaxKind.EqualsToken && containsArrayLiteral(node.left)) || ts6.isJsxElement(node) || ts6.isJsxSelfClosingElement(node) || ts6.isJsxFragment(node) || ts6.isClassDeclaration(node) || ts6.isClassExpression(node);
5182
- if (ts6.isVariableDeclaration(node) && ts6.isIdentifier(node.name)) {
5312
+ invokesUnknownCode ||= ts8.isCallExpression(node) || ts8.isNewExpression(node) || ts8.isTaggedTemplateExpression(node) || ts8.isAwaitExpression(node) || ts8.isYieldExpression(node) || ts8.isForOfStatement(node) || ts8.isSpreadElement(node) || ts8.isArrayBindingPattern(node) || ts8.isVariableDeclarationList(node) && (node.flags & ts8.NodeFlags.Using) !== 0 || ts8.isBinaryExpression(node) && (node.operatorToken.kind === ts8.SyntaxKind.InstanceOfKeyword || node.operatorToken.kind === ts8.SyntaxKind.EqualsToken && containsArrayLiteral(node.left)) || ts8.isJsxElement(node) || ts8.isJsxSelfClosingElement(node) || ts8.isJsxFragment(node) || ts8.isClassDeclaration(node) || ts8.isClassExpression(node);
5313
+ if (ts8.isVariableDeclaration(node) && ts8.isIdentifier(node.name)) {
5183
5314
  const symbol = checker.getSymbolAtLocation(node.name);
5184
5315
  const binding = symbol == null ? undefined : bindingsBySymbol.get(symbol);
5185
5316
  if (binding != null) {
@@ -5201,7 +5332,7 @@ function declaredRecordProperties(type, checker, seen) {
5201
5332
  return null;
5202
5333
  const properties = [];
5203
5334
  for (const property of checker.getPropertiesOfType(type)) {
5204
- const optional = (property.flags & ts6.SymbolFlags.Optional) !== 0;
5335
+ const optional = (property.flags & ts8.SymbolFlags.Optional) !== 0;
5205
5336
  const walked = declaredKind(checker.getTypeOfSymbol(property), checker, [...seen, type]);
5206
5337
  const opaqueLeaf = { kind: "opaque" };
5207
5338
  const propertyDeclared = declaredOnlyInDeclarationFiles(property) ? opaqueLeaf : walked ?? opaqueLeaf;
@@ -5307,14 +5438,14 @@ function declaredKindUncached(type, checker, seen) {
5307
5438
  }
5308
5439
  if (inner == null)
5309
5440
  return null;
5310
- const admitsNull = type.types.some((member) => (member.flags & ts6.TypeFlags.Null) !== 0);
5311
- const admitsUndefined = type.types.some((member) => (member.flags & ts6.TypeFlags.Undefined) !== 0);
5441
+ const admitsNull = type.types.some((member) => (member.flags & ts8.TypeFlags.Null) !== 0);
5442
+ const admitsUndefined = type.types.some((member) => (member.flags & ts8.TypeFlags.Undefined) !== 0);
5312
5443
  return { kind: "nullish", inner, sentinels: admitsNull && admitsUndefined ? "both" : admitsNull ? "null" : "undefined" };
5313
5444
  }
5314
5445
  case "opaque":
5315
5446
  return { kind: "opaque" };
5316
5447
  case "array": {
5317
- const element = checker.getIndexTypeOfType(type, ts6.IndexKind.Number);
5448
+ const element = checker.getIndexTypeOfType(type, ts8.IndexKind.Number);
5318
5449
  if (element == null)
5319
5450
  return null;
5320
5451
  const elementKind = declaredKind(element, checker, [...seen, type]);
@@ -5366,13 +5497,14 @@ function declaredKindUncached(type, checker, seen) {
5366
5497
  }
5367
5498
  function numericLiteralInterval(type) {
5368
5499
  const members = type.isUnion() ? type.types : [type];
5369
- if (!members.every((member) => (member.flags & ts6.TypeFlags.NumberLiteral) !== 0 && (member.flags & ts6.TypeFlags.EnumLiteral) === 0))
5370
- return null;
5371
5500
  let lower = Infinity;
5372
5501
  let upper = -Infinity;
5373
5502
  let integer = true;
5374
5503
  for (const member of members) {
5375
- const value2 = member.value;
5504
+ const number = numberConstituent(member);
5505
+ if (number == null || (number.flags & ts8.TypeFlags.NumberLiteral) === 0 || (number.flags & ts8.TypeFlags.EnumLiteral) !== 0)
5506
+ return null;
5507
+ const value2 = number.value;
5376
5508
  if (!Number.isFinite(value2))
5377
5509
  return "nonFinite";
5378
5510
  lower = Math.min(lower, value2);
@@ -5419,7 +5551,7 @@ function joinScalarDeclaredKinds(members) {
5419
5551
  function tupleHasOptionalOrRestPositions(type, checker) {
5420
5552
  if (!checker.isTupleType(type))
5421
5553
  return false;
5422
- return type.target.elementFlags.some((flags) => (flags & ts6.ElementFlags.Required) === 0);
5554
+ return type.target.elementFlags.some((flags) => (flags & ts8.ElementFlags.Required) === 0);
5423
5555
  }
5424
5556
  function demote(bindings, binding) {
5425
5557
  const category = bindings[binding].category;
@@ -5433,6 +5565,7 @@ function demote(bindings, binding) {
5433
5565
  break;
5434
5566
  }
5435
5567
  case "kind":
5568
+ case "function":
5436
5569
  case "import":
5437
5570
  case "opaque":
5438
5571
  break;
@@ -5440,31 +5573,31 @@ function demote(bindings, binding) {
5440
5573
  }
5441
5574
 
5442
5575
  // src/lower/static-intrinsics.ts
5443
- import * as ts7 from "typescript";
5444
- function scanStaticAnnotations(sourceFile, declarations, checker) {
5445
- const ownerIndex = new Map(declarations.map((declaration, index) => [declaration, index]));
5446
- const callsByFunction = declarations.map(() => []);
5576
+ import * as ts9 from "typescript";
5577
+ function scanStaticAnnotations(sourceFile, functions, checker) {
5578
+ const ownerIndex = new Map(functions.map((unit, index) => [unit.declaration, index]));
5579
+ const callsByFunction = functions.map(() => []);
5447
5580
  const outsideTopLevelFunctions = [];
5448
5581
  const visit = (node) => {
5449
- if (ts7.isCallExpression(node) && isStaticIntent(node, checker)) {
5450
- const owner = ts7.findAncestor(node, ts7.isFunctionLike);
5451
- const index = owner != null && ts7.isFunctionDeclaration(owner) ? ownerIndex.get(owner) : undefined;
5582
+ if (ts9.isCallExpression(node) && isStaticIntent(node, checker)) {
5583
+ const owner = ts9.findAncestor(node, ts9.isFunctionLike);
5584
+ const index = owner == null ? undefined : ownerIndex.get(owner);
5452
5585
  if (index == null)
5453
5586
  outsideTopLevelFunctions.push(node);
5454
5587
  else
5455
5588
  callsByFunction[index].push(node);
5456
5589
  }
5457
- ts7.forEachChild(node, visit);
5590
+ ts9.forEachChild(node, visit);
5458
5591
  };
5459
5592
  visit(sourceFile);
5460
5593
  return {
5461
- functions: declarations.map((declaration, index) => {
5594
+ functions: functions.map((unit, index) => {
5462
5595
  const calls = callsByFunction[index];
5463
5596
  const callSet = new Set(calls);
5464
5597
  const leading = new Set;
5465
- if (declaration.body != null) {
5466
- for (const statement of declaration.body.statements) {
5467
- if (!ts7.isExpressionStatement(statement) || !ts7.isCallExpression(statement.expression) || !callSet.has(statement.expression))
5598
+ if (unit.declaration.body != null && ts9.isBlock(unit.declaration.body)) {
5599
+ for (const statement of unit.declaration.body.statements) {
5600
+ if (!ts9.isExpressionStatement(statement) || !ts9.isCallExpression(statement.expression) || !callSet.has(statement.expression))
5468
5601
  break;
5469
5602
  leading.add(statement.expression);
5470
5603
  }
@@ -5478,34 +5611,31 @@ function annotationForCall(call, role) {
5478
5611
  if (call.arguments.length !== 1) {
5479
5612
  return { kind: "invalid", call, role, node: call, problem: "argumentCount" };
5480
5613
  }
5481
- if (!ts7.isExpressionStatement(call.parent) || call.parent.expression !== call) {
5614
+ if (!ts9.isExpressionStatement(call.parent) || call.parent.expression !== call) {
5482
5615
  return { kind: "invalid", call, role, node: call, problem: "position" };
5483
5616
  }
5484
5617
  const callee = call.expression;
5485
- if (call.questionDotToken != null || ts7.isPropertyAccessExpression(callee) && callee.questionDotToken != null) {
5618
+ if (call.questionDotToken != null || ts9.isPropertyAccessExpression(callee) && callee.questionDotToken != null) {
5486
5619
  return { kind: "invalid", call, role, node: call, problem: "optionalCall" };
5487
5620
  }
5488
5621
  return { kind: "valid", call, role, condition: call.arguments[0] };
5489
5622
  }
5490
5623
  function isStaticIntent(call, checker) {
5491
- if (!ts7.isPropertyAccessExpression(call.expression))
5624
+ if (!ts9.isPropertyAccessExpression(call.expression))
5492
5625
  return false;
5493
5626
  const access = call.expression;
5494
- if (!ts7.isIdentifier(access.expression) || access.expression.text !== "console" || access.name.text !== "assert")
5627
+ if (!ts9.isIdentifier(access.expression) || access.expression.text !== "console" || access.name.text !== "assert")
5495
5628
  return false;
5496
5629
  const resolved = checker.getSymbolAtLocation(access.expression);
5497
- const globalConsole = checker.resolveName("console", undefined, ts7.SymbolFlags.Value, false);
5630
+ const globalConsole = checker.resolveName("console", undefined, ts9.SymbolFlags.Value, false);
5498
5631
  return resolved != null && resolved === globalConsole;
5499
5632
  }
5500
5633
 
5501
5634
  // src/lower/program.ts
5502
5635
  function lowerSource(checked, baseDirectory = process.cwd()) {
5503
- const { sourceFile, checker } = checked;
5504
- const declarations = [];
5505
- for (const statement of sourceFile.statements) {
5506
- if (ts8.isFunctionDeclaration(statement) && statement.name != null)
5507
- declarations.push(statement);
5508
- }
5636
+ const { sourceFile, program } = checked;
5637
+ const checker = program.getTypeChecker();
5638
+ const declarations = topLevelFunctionUnits(sourceFile);
5509
5639
  const staticScan = scanStaticAnnotations(sourceFile, declarations, checker);
5510
5640
  const recordStaticAnnotationIssues = (sites2) => staticScan.outsideTopLevelFunctions.map((call) => {
5511
5641
  sites2.push(nodeSpan(sourceFile, call));
@@ -5519,9 +5649,9 @@ function lowerSource(checked, baseDirectory = process.cwd()) {
5519
5649
  baseDirectory,
5520
5650
  lineStarts: [...sourceFile.getLineStarts()],
5521
5651
  sites: sites2,
5522
- functions: declarations.map((declaration, index) => ({
5652
+ functions: declarations.map((unit, index) => ({
5523
5653
  kind: "unsupported",
5524
- name: declaration.name.text,
5654
+ name: unit.name.text,
5525
5655
  hasStaticAnnotations: staticScan.functions[index].length > 0,
5526
5656
  site: 0,
5527
5657
  reason
@@ -5548,22 +5678,34 @@ function lowerSource(checked, baseDirectory = process.cwd()) {
5548
5678
  return rejectFile(nodeSpan(sourceFile, evalNode), { kind: "evalInFile" });
5549
5679
  }
5550
5680
  const functionsBySymbol = new Map;
5681
+ const scan = scanModuleBindings(sourceFile, checker);
5682
+ const topLevelFunctions = [];
5551
5683
  for (let index = 0;index < declarations.length; index++) {
5552
- const declaration = declarations[index];
5553
- const symbol = checker.getSymbolAtLocation(declaration.name);
5684
+ const unit = declarations[index];
5685
+ const symbol = checker.getSymbolAtLocation(unit.name);
5554
5686
  if (symbol == null)
5555
- throw new Error(`Function declaration ${declaration.name.text} has no TypeScript symbol`);
5556
- functionsBySymbol.set(symbol, { id: index, declaration });
5687
+ throw new Error(`Function ${unit.name.text} has no TypeScript symbol`);
5688
+ const binding = scan.bindingsBySymbol.get(symbol);
5689
+ if (unit.initializer != null && binding == null) {
5690
+ throw new Error(`Const-bound function ${unit.name.text} has no module binding`);
5691
+ }
5692
+ const fn = {
5693
+ ...unit,
5694
+ id: index,
5695
+ binding: unit.initializer == null ? null : binding,
5696
+ signature: callableSignature(unit, checker)
5697
+ };
5698
+ topLevelFunctions.push(fn);
5699
+ functionsBySymbol.set(symbol, fn);
5557
5700
  }
5558
- const scan = scanModuleBindings(sourceFile, checker);
5559
5701
  const sites = [];
5560
5702
  const staticAnnotationIssues = recordStaticAnnotationIssues(sites);
5561
5703
  const functions = [];
5562
- for (let index = 0;index < declarations.length; index++) {
5563
- const declaration = declarations[index];
5704
+ for (let index = 0;index < topLevelFunctions.length; index++) {
5705
+ const declaration = topLevelFunctions[index];
5564
5706
  const staticAnnotations = staticScan.functions[index];
5565
5707
  try {
5566
- functions.push(lowerFunction(declaration, staticAnnotations, sourceFile, checker, functionsBySymbol, scan, sites));
5708
+ functions.push(lowerFunction(declaration, staticAnnotations, sourceFile, checker, program, functionsBySymbol, scan, sites));
5567
5709
  } catch (error) {
5568
5710
  if (!(error instanceof LoweringStop))
5569
5711
  throw error;
@@ -5577,7 +5719,7 @@ function lowerSource(checked, baseDirectory = process.cwd()) {
5577
5719
  });
5578
5720
  }
5579
5721
  }
5580
- const { initializer, skips } = lowerModuleInitializer(sourceFile, checker, functionsBySymbol, scan, sites);
5722
+ const { initializer, skips } = lowerModuleInitializer(sourceFile, checker, program, functionsBySymbol, scan, sites);
5581
5723
  return {
5582
5724
  file: sourceFile.fileName,
5583
5725
  baseDirectory,
@@ -5590,7 +5732,8 @@ function lowerSource(checked, baseDirectory = process.cwd()) {
5590
5732
  initializerSkips: skips
5591
5733
  };
5592
5734
  }
5593
- function lowerFunction(declaration, staticAnnotations, sourceFile, checker, functionsBySymbol, scan, sites) {
5735
+ function lowerFunction(unit, staticAnnotations, sourceFile, checker, program, functionsBySymbol, scan, sites) {
5736
+ const { declaration } = unit;
5594
5737
  for (const annotation of staticAnnotations) {
5595
5738
  if (annotation.kind === "invalid") {
5596
5739
  throw unsupported(annotation.node, { kind: "staticAssertionForm", problem: annotation.problem });
@@ -5598,24 +5741,28 @@ function lowerFunction(declaration, staticAnnotations, sourceFile, checker, func
5598
5741
  }
5599
5742
  if (declaration.body == null)
5600
5743
  throw unsupported(declaration, { kind: "functionWithoutBody" });
5601
- if (declaration.asteriskToken != null || declaration.modifiers?.some((modifier) => modifier.kind === ts8.SyntaxKind.AsyncKeyword) === true) {
5744
+ if (!ts10.isArrowFunction(declaration) && declaration.asteriskToken != null || declaration.modifiers?.some((modifier) => modifier.kind === ts10.SyntaxKind.AsyncKeyword) === true) {
5602
5745
  throw unsupported(declaration, { kind: "asyncOrGeneratorFunction" });
5603
5746
  }
5604
5747
  assertAccepted(declaration);
5605
- const signature = checker.getSignatureFromDeclaration(declaration);
5606
- if (signature != null && checker.getTypePredicateOfSignature(signature) != null) {
5607
- throw unsupported(declaration, { kind: "typePredicate" });
5748
+ const signature = unit.signature;
5749
+ if (signature == null) {
5750
+ throw unsupported(unit.name, {
5751
+ kind: unit.initializer == null ? "functionWithoutSignature" : "constFunctionSignature"
5752
+ });
5608
5753
  }
5609
- const returnType = functionReturnType(declaration, checker);
5610
- const returnsVoid = (returnType.flags & (ts8.TypeFlags.Void | ts8.TypeFlags.Undefined | ts8.TypeFlags.Never)) !== 0;
5754
+ const returnType = checker.getReturnTypeOfSignature(signature);
5755
+ const returnsVoid = (returnType.flags & (ts10.TypeFlags.Void | ts10.TypeFlags.Undefined | ts10.TypeFlags.Never)) !== 0;
5611
5756
  if (!returnsVoid && valueKind(returnType, checker) == null) {
5612
5757
  throw unsupported(declaration.type ?? declaration, { kind: "valueType", typeText: checker.typeToString(returnType) });
5613
5758
  }
5614
- const context = createFunctionContext(sourceFile, checker, functionsBySymbol, scan.bindingsBySymbol, sites, staticAnnotations);
5759
+ const context = createFunctionContext(sourceFile, checker, program, functionsBySymbol, scan.bindingsBySymbol, sites, staticAnnotations, returnsVoid);
5615
5760
  const entry = context.currentBlock;
5616
- for (const parameter of declaration.parameters) {
5617
- if (ts8.isObjectBindingPattern(parameter.name)) {
5618
- const type2 = lowerParameterType(parameter, checker);
5761
+ for (let parameterIndex = 0;parameterIndex < declaration.parameters.length; parameterIndex++) {
5762
+ const parameter = declaration.parameters[parameterIndex];
5763
+ const parameterType = unit.initializer == null ? checker.getTypeAtLocation(parameter) : checker.getTypeOfSymbolAtLocation(signature.parameters[parameterIndex], signature.declaration);
5764
+ if (ts10.isObjectBindingPattern(parameter.name)) {
5765
+ const type2 = lowerParameterType(parameter, parameterType, checker);
5619
5766
  const patternName = parameter.name.getText(sourceFile).replace(/\s+/g, " ");
5620
5767
  if (parameter.initializer != null) {
5621
5768
  throw unsupported(parameter, { kind: "parameterDefaultValue", name: patternName });
@@ -5624,10 +5771,10 @@ function lowerFunction(declaration, staticAnnotations, sourceFile, checker, func
5624
5771
  const bindings = [];
5625
5772
  context.parameters.push({ value: value3, name: patternName, type: type2, site: addSite(context, parameter), bindings });
5626
5773
  for (const element of parameter.name.elements) {
5627
- if (!ts8.isIdentifier(element.name) || element.dotDotDotToken != null || element.initializer != null) {
5774
+ if (!ts10.isIdentifier(element.name) || element.dotDotDotToken != null || element.initializer != null) {
5628
5775
  throw unsupported(element, { kind: "destructuredParameter" });
5629
5776
  }
5630
- const property = element.propertyName == null ? element.name.text : ts8.isIdentifier(element.propertyName) ? element.propertyName.text : null;
5777
+ const property = element.propertyName == null ? element.name.text : ts10.isIdentifier(element.propertyName) ? element.propertyName.text : null;
5631
5778
  if (property == null)
5632
5779
  throw unsupported(element, { kind: "destructuredParameter" });
5633
5780
  bindings.push({ property, local: element.name.text });
@@ -5643,12 +5790,12 @@ function lowerFunction(declaration, staticAnnotations, sourceFile, checker, func
5643
5790
  }
5644
5791
  continue;
5645
5792
  }
5646
- if (!ts8.isIdentifier(parameter.name))
5793
+ if (!ts10.isIdentifier(parameter.name))
5647
5794
  throw unsupported(parameter.name, { kind: "destructuredParameter" });
5648
5795
  if (parameter.dotDotDotToken != null) {
5649
5796
  throw unsupported(parameter, { kind: "parameterType", typeText: `...${checker.typeToString(checker.getTypeAtLocation(parameter))}`, optionalOrRestTuple: false });
5650
5797
  }
5651
- let type = lowerParameterType(parameter, checker);
5798
+ let type = lowerParameterType(parameter, parameterType, checker);
5652
5799
  if (parameter.initializer != null) {
5653
5800
  const default_ = parameterDefaultLiteral(parameter.initializer, checker);
5654
5801
  if (default_ == null || !parameterDefaultFits(default_, type)) {
@@ -5661,7 +5808,16 @@ function lowerFunction(declaration, staticAnnotations, sourceFile, checker, func
5661
5808
  context.parameters.push({ value: value2, name: parameter.name.text, type, site: addSite(context, parameter), bindings: null });
5662
5809
  }
5663
5810
  lowerFiniteInputRequirements(context);
5664
- lowerStatements(declaration.body.statements, context);
5811
+ if (ts10.isBlock(declaration.body)) {
5812
+ lowerStatements(declaration.body.statements, context);
5813
+ } else {
5814
+ const value2 = lowerExpression(declaration.body, context);
5815
+ terminate(context.currentBlock, {
5816
+ kind: "return",
5817
+ value: returnsVoid ? null : value2,
5818
+ site: addSite(context, declaration.body)
5819
+ });
5820
+ }
5665
5821
  if (context.currentBlock.terminator == null) {
5666
5822
  if (!returnsVoid) {
5667
5823
  terminate(context.currentBlock, { kind: "stop", site: addSite(context, declaration), reason: { kind: "missingReturn" } });
@@ -5671,12 +5827,12 @@ function lowerFunction(declaration, staticAnnotations, sourceFile, checker, func
5671
5827
  }
5672
5828
  return {
5673
5829
  kind: "lowered",
5674
- name: declaration.name.text,
5830
+ name: unit.name.text,
5675
5831
  assertions: context.assertions,
5676
5832
  parameters: context.parameters,
5677
5833
  returnPropertyNames: declaredRecordReturnNames(returnType, checker),
5678
5834
  entry: 0,
5679
- blocks: sealBlocks(context.blocks, declaration.name.text)
5835
+ blocks: sealBlocks(context.blocks, unit.name.text)
5680
5836
  };
5681
5837
  }
5682
5838
  function lowerFiniteInputRequirements(context) {
@@ -5710,7 +5866,7 @@ function declaredRecordReturnNames(returnType, checker) {
5710
5866
  if (kind === "object")
5711
5867
  return checker.getPropertiesOfType(returnType).map((property) => property.name);
5712
5868
  if (kind === "nullable" && returnType.isUnion()) {
5713
- const missing = ts8.TypeFlags.Null | ts8.TypeFlags.Undefined;
5869
+ const missing = ts10.TypeFlags.Null | ts10.TypeFlags.Undefined;
5714
5870
  const members = returnType.types.filter((member) => (member.flags & missing) === 0);
5715
5871
  if (members.length > 0 && members.every((member) => valueKind(member, checker) === "object")) {
5716
5872
  const names = new Set;
@@ -5723,8 +5879,7 @@ function declaredRecordReturnNames(returnType, checker) {
5723
5879
  }
5724
5880
  return null;
5725
5881
  }
5726
- function lowerParameterType(parameter, checker) {
5727
- const type = checker.getTypeAtLocation(parameter);
5882
+ function lowerParameterType(parameter, type, checker) {
5728
5883
  const declared = declaredKind(type, checker, []);
5729
5884
  if (declared == null) {
5730
5885
  throw unsupported(parameter, {
@@ -5735,12 +5890,6 @@ function lowerParameterType(parameter, checker) {
5735
5890
  }
5736
5891
  return declared;
5737
5892
  }
5738
- function functionReturnType(declaration, checker) {
5739
- const signature = checker.getSignatureFromDeclaration(declaration);
5740
- if (signature == null)
5741
- throw unsupported(declaration, { kind: "functionWithoutSignature" });
5742
- return checker.getReturnTypeOfSignature(signature);
5743
- }
5744
5893
 
5745
5894
  // src/analyze.ts
5746
5895
  function analyzeCheckedSource(checked, baseDirectory) {
@@ -6505,6 +6654,7 @@ function formatStop(stop, program, analysis) {
6505
6654
  return `reads ${binding.name}, whose value the analysis does not track (read at ${formatSite(program, stop.site)})`;
6506
6655
  case "value":
6507
6656
  case "kind":
6657
+ case "function":
6508
6658
  return `reads ${binding.name} before it is initialized (read at ${formatSite(program, stop.site)})`;
6509
6659
  }
6510
6660
  }
@@ -6563,6 +6713,8 @@ function formatUnsupportedReason(reason) {
6563
6713
  return "node without a TypeScript symbol";
6564
6714
  case "functionWithoutSignature":
6565
6715
  return "function without a TypeScript signature";
6716
+ case "constFunctionSignature":
6717
+ return "a top-level const function whose declared call shape differs from its implementation";
6566
6718
  case "functionWithoutBody":
6567
6719
  return "function declarations need bodies";
6568
6720
  case "destructuredParameter":
@@ -6581,14 +6733,10 @@ function formatUnsupportedReason(reason) {
6581
6733
  return "object spread (list every field explicitly, e.g. {gain: config.gain})";
6582
6734
  case "asyncOrGeneratorFunction":
6583
6735
  return "an async or generator function (the runtime result is a Promise or iterator, not the body's return value)";
6584
- case "typePredicate":
6585
- return "a type predicate (the checker takes the predicate on faith; return a plain boolean and check properties where they are read)";
6586
6736
  case "protoProperty":
6587
6737
  return "a property named __proto__ (prototype-setting syntax at runtime, not a data property)";
6588
6738
  case "enumMemberRead":
6589
6739
  return "an enum member read (replace the enum with plain module consts, e.g. const directionUp = 1)";
6590
- case "prototypeMemberRead":
6591
- return `read of the inherited prototype member ${reason.property} (records carry only their own data properties)`;
6592
6740
  case "binaryOperator":
6593
6741
  return reason.operator === "in" ? "the `in` operator (use a distinct string or boolean tag when property presence distinguishes union variants)" : `binary operator ${reason.operator} (supported: + - * / %, comparisons, and boolean && || !)`;
6594
6742
  case "call":
@@ -6788,7 +6936,7 @@ function formatNumber(value2) {
6788
6936
  }
6789
6937
 
6790
6938
  // src/typescript/diagnostics.ts
6791
- import * as ts9 from "typescript";
6939
+ import * as ts11 from "typescript";
6792
6940
 
6793
6941
  class TypeScriptDiagnosticsError extends Error {
6794
6942
  diagnostics;
@@ -6805,10 +6953,10 @@ class TypeScriptDiagnosticsError extends Error {
6805
6953
  function formatTypeScriptDiagnostics(diagnostics, options, currentDirectory) {
6806
6954
  const host = {
6807
6955
  getCurrentDirectory: () => currentDirectory,
6808
- getCanonicalFileName: ts9.sys.useCaseSensitiveFileNames ? (file) => file : (file) => file.toLowerCase(),
6809
- getNewLine: () => ts9.sys.newLine
6956
+ getCanonicalFileName: ts11.sys.useCaseSensitiveFileNames ? (file) => file : (file) => file.toLowerCase(),
6957
+ getNewLine: () => ts11.sys.newLine
6810
6958
  };
6811
- return usePrettyOutput(options["pretty"]) ? ts9.formatDiagnosticsWithColorAndContext(diagnostics, host) : ts9.formatDiagnostics(diagnostics, host);
6959
+ return usePrettyOutput(options["pretty"]) ? ts11.formatDiagnosticsWithColorAndContext(diagnostics, host) : ts11.formatDiagnostics(diagnostics, host);
6812
6960
  }
6813
6961
  function usePrettyOutput(configured) {
6814
6962
  if (typeof configured === "boolean")
@@ -6819,7 +6967,7 @@ function usePrettyOutput(configured) {
6819
6967
  const forceColor = process.env["FORCE_COLOR"];
6820
6968
  if (forceColor != null && forceColor !== "")
6821
6969
  return true;
6822
- return ts9.sys.writeOutputIsTTY?.() === true;
6970
+ return ts11.sys.writeOutputIsTTY?.() === true;
6823
6971
  }
6824
6972
  function color(code, text) {
6825
6973
  return `\x1B[${code}m${text}\x1B[0m`;
@@ -7046,7 +7194,7 @@ function createFileAudit({ program, analysis }) {
7046
7194
  };
7047
7195
  }
7048
7196
  function formatAuditCoverage(coverage) {
7049
- const parts = coverage.functions === 0 ? ["no named function declarations"] : [`${coverage.analyzed}/${coverage.functions} functions fully analyzed`];
7197
+ const parts = coverage.functions === 0 ? ["no named top-level functions"] : [`${coverage.analyzed}/${coverage.functions} functions fully analyzed`];
7050
7198
  if (coverage.partial > 0)
7051
7199
  parts.push(`${coverage.partial} partially supported`);
7052
7200
  if (coverage.unsupported > 0)
@@ -7141,6 +7289,7 @@ function guidesForUnsupportedReason(reason) {
7141
7289
  case "unknownIdentifier":
7142
7290
  case "missingSymbol":
7143
7291
  case "functionWithoutSignature":
7292
+ case "constFunctionSignature":
7144
7293
  case "functionWithoutBody":
7145
7294
  case "destructuredParameter":
7146
7295
  case "parameterType":
@@ -7150,10 +7299,8 @@ function guidesForUnsupportedReason(reason) {
7150
7299
  case "computedPropertyName":
7151
7300
  case "objectSpread":
7152
7301
  case "asyncOrGeneratorFunction":
7153
- case "typePredicate":
7154
7302
  case "protoProperty":
7155
7303
  case "enumMemberRead":
7156
- case "prototypeMemberRead":
7157
7304
  case "binaryOperator":
7158
7305
  case "callWithFewerArguments":
7159
7306
  case "callWithMoreArguments":
@@ -7211,12 +7358,12 @@ function isCallerInput(expression) {
7211
7358
 
7212
7359
  // src/typescript/check.ts
7213
7360
  import { resolve } from "node:path";
7214
- import * as ts10 from "typescript";
7361
+ import * as ts12 from "typescript";
7215
7362
  var fallbackOptions = {
7216
- target: ts10.ScriptTarget.ESNext,
7217
- module: ts10.ModuleKind.ESNext,
7218
- moduleResolution: ts10.ModuleResolutionKind.Bundler,
7219
- moduleDetection: ts10.ModuleDetectionKind.Force,
7363
+ target: ts12.ScriptTarget.ESNext,
7364
+ module: ts12.ModuleKind.ESNext,
7365
+ moduleResolution: ts12.ModuleResolutionKind.Bundler,
7366
+ moduleDetection: ts12.ModuleDetectionKind.Force,
7220
7367
  strict: true,
7221
7368
  noUncheckedIndexedAccess: true,
7222
7369
  exactOptionalPropertyTypes: true,
@@ -7226,25 +7373,25 @@ var fallbackOptions = {
7226
7373
  };
7227
7374
  function checkFile(file) {
7228
7375
  const absoluteFile = resolve(file);
7229
- const program = ts10.createProgram([absoluteFile], fallbackOptions);
7376
+ const program = ts12.createProgram([absoluteFile], fallbackOptions);
7230
7377
  return checkedSource(program, absoluteFile, fallbackOptions);
7231
7378
  }
7232
7379
  function checkedSource(program, file, options) {
7233
- const diagnostics = ts10.getPreEmitDiagnostics(program);
7380
+ const diagnostics = ts12.getPreEmitDiagnostics(program);
7234
7381
  if (diagnostics.length > 0) {
7235
7382
  throw new TypeScriptDiagnosticsError(diagnostics, options, process.cwd());
7236
7383
  }
7237
7384
  const sourceFile = program.getSourceFile(file);
7238
7385
  if (sourceFile == null)
7239
7386
  throw new Error(`TypeScript did not load ${file}`);
7240
- return { sourceFile, checker: program.getTypeChecker() };
7387
+ return { sourceFile, program };
7241
7388
  }
7242
7389
 
7243
7390
  // src/typescript/project.ts
7244
7391
  import { dirname, isAbsolute, relative as relative2, resolve as resolve2, sep } from "node:path";
7245
- import * as ts11 from "typescript";
7392
+ import * as ts13 from "typescript";
7246
7393
  function findTypeScriptConfig(searchFrom) {
7247
- return ts11.findConfigFile(resolve2(searchFrom), (file) => ts11.sys.fileExists(file), "tsconfig.json") ?? null;
7394
+ return ts13.findConfigFile(resolve2(searchFrom), (file) => ts13.sys.fileExists(file), "tsconfig.json") ?? null;
7248
7395
  }
7249
7396
  function loadTypeScriptProjectGraph(configPath) {
7250
7397
  const loaded = [];
@@ -7261,8 +7408,8 @@ function loadTypeScriptProjectGraph(configPath) {
7261
7408
  const parsed = parseConfig(absoluteConfigPath);
7262
7409
  requireStrictNullChecks(parsed.options, absoluteConfigPath);
7263
7410
  for (const reference of parsed.projectReferences ?? [])
7264
- load(ts11.resolveProjectReferencePath(reference));
7265
- const program = ts11.createProgram({
7411
+ load(ts13.resolveProjectReferencePath(reference));
7412
+ const program = ts13.createProgram({
7266
7413
  rootNames: parsed.fileNames,
7267
7414
  options: parsed.options,
7268
7415
  configFileParsingDiagnostics: parsed.errors,
@@ -7297,8 +7444,8 @@ function projectSources(projects) {
7297
7444
  return [...sources.values()].sort((left, right) => left.sourceFile.fileName.localeCompare(right.sourceFile.fileName));
7298
7445
  }
7299
7446
  function parseConfig(configPath) {
7300
- const parsed = ts11.getParsedCommandLineOfConfigFile(configPath, undefined, {
7301
- ...ts11.sys,
7447
+ const parsed = ts13.getParsedCommandLineOfConfigFile(configPath, undefined, {
7448
+ ...ts13.sys,
7302
7449
  onUnRecoverableConfigFileDiagnostic: (diagnostic) => {
7303
7450
  throw new TypeScriptDiagnosticsError([diagnostic], {}, dirname(configPath));
7304
7451
  }
@@ -7359,7 +7506,7 @@ function analyzeProject(searchFrom) {
7359
7506
  const projects = loadTypeScriptProjectGraph(configPath);
7360
7507
  const rootProject = projects.at(-1);
7361
7508
  const sources = projectSources(projects);
7362
- const diagnostics = uniqueDiagnostics(projects.flatMap((project) => ts12.getPreEmitDiagnostics(project.program)));
7509
+ const diagnostics = uniqueDiagnostics(projects.flatMap((project) => ts14.getPreEmitDiagnostics(project.program)));
7363
7510
  requireNoTypeScriptErrors(diagnostics, rootProject.parsed.options);
7364
7511
  const files = [];
7365
7512
  let analyzed = 0;
@@ -7483,7 +7630,7 @@ function collectLintFindings({ program, analysis }) {
7483
7630
  collectStops(analysis.initializer);
7484
7631
  collectAssertions(analysis.initializer);
7485
7632
  for (const issue of program.staticAnnotationIssues) {
7486
- addError(issue.site, "console-assert", "console.assert is only supported inside a named top-level function declaration");
7633
+ addError(issue.site, "console-assert", "console.assert is only supported inside a named top-level function");
7487
7634
  }
7488
7635
  for (const fn of analysis.functions) {
7489
7636
  collectStops(fn);
@@ -7580,7 +7727,7 @@ function formatLintPrefix(finding, rule, pretty) {
7580
7727
  return formatDiagnosticPrefix(finding, lintLevel(finding), rule, pretty);
7581
7728
  }
7582
7729
  function formatCoverage(coverage) {
7583
- return `coverage: ${coverage.analyzed}/${coverage.functions} named top-level function declarations fully analyzed; ${coverage.partial} partially supported; ${coverage.unsupported} unsupported.`;
7730
+ return `coverage: ${coverage.analyzed}/${coverage.functions} named top-level functions fully analyzed; ${coverage.partial} partially supported; ${coverage.unsupported} unsupported.`;
7584
7731
  }
7585
7732
  function analyzeTargetFile(file) {
7586
7733
  const absoluteFile = resolve3(file);
@@ -7596,7 +7743,7 @@ function analyzeTargetFile(file) {
7596
7743
  if (source == null) {
7597
7744
  throw new Error(`File is not part of the project resolved from ${configPath}: ${absoluteFile}`);
7598
7745
  }
7599
- const diagnostics = ts12.getPreEmitDiagnostics(source.project.program, source.sourceFile);
7746
+ const diagnostics = ts14.getPreEmitDiagnostics(source.project.program, source.sourceFile);
7600
7747
  requireNoTypeScriptErrors(diagnostics, rootProject.parsed.options);
7601
7748
  return {
7602
7749
  detailed: analyzeProjectSource(source, process.cwd()),
@@ -7605,7 +7752,7 @@ function analyzeTargetFile(file) {
7605
7752
  }
7606
7753
  function canonicalFilePath(file) {
7607
7754
  const real = realpathSync.native(file);
7608
- return ts12.sys.useCaseSensitiveFileNames ? real : real.toLowerCase();
7755
+ return ts14.sys.useCaseSensitiveFileNames ? real : real.toLowerCase();
7609
7756
  }
7610
7757
  function analyzeFileAlone(absoluteFile) {
7611
7758
  return {
@@ -7616,13 +7763,13 @@ function analyzeFileAlone(absoluteFile) {
7616
7763
  function analyzeProjectSource(source, reportBaseDirectory) {
7617
7764
  return analyzeCheckedSource({
7618
7765
  sourceFile: source.sourceFile,
7619
- checker: source.project.program.getTypeChecker()
7766
+ program: source.project.program
7620
7767
  }, reportBaseDirectory);
7621
7768
  }
7622
7769
  function uniqueDiagnostics(diagnostics) {
7623
7770
  const seen = new Set;
7624
7771
  return diagnostics.filter((diagnostic) => {
7625
- const message = ts12.flattenDiagnosticMessageText(diagnostic.messageText, `
7772
+ const message = ts14.flattenDiagnosticMessageText(diagnostic.messageText, `
7626
7773
  `);
7627
7774
  const key = `${diagnostic.file?.fileName ?? ""}:${diagnostic.start ?? ""}:${diagnostic.length ?? ""}:${diagnostic.code}:${message}`;
7628
7775
  if (seen.has(key))
@@ -7643,7 +7790,7 @@ function requireNoTypeScriptErrors(diagnostics, options) {
7643
7790
  printTypeScriptDiagnostics(diagnostics, options, process.cwd());
7644
7791
  }
7645
7792
  function hasErrorDiagnostics(diagnostics) {
7646
- return diagnostics.some((diagnostic) => diagnostic.category === ts12.DiagnosticCategory.Error);
7793
+ return diagnostics.some((diagnostic) => diagnostic.category === ts14.DiagnosticCategory.Error);
7647
7794
  }
7648
7795
 
7649
7796
  // fr.ts