candor-ts 0.5.7 → 0.5.8
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/package.json +1 -1
- package/scan.mjs +20 -1
package/package.json
CHANGED
package/scan.mjs
CHANGED
|
@@ -724,6 +724,17 @@ function edgeToTargets(rec, decls) {
|
|
|
724
724
|
for (const d of decls) { const t = nodeName.get(d); if (t) rec.edges.add(t); }
|
|
725
725
|
}
|
|
726
726
|
|
|
727
|
+
// Callee names that INVOKE a function/method argument (so a fn-reference passed to one is reachable
|
|
728
|
+
// through it). Array/iterable HOFs, the timer/microtask schedulers, and Promise continuations. A
|
|
729
|
+
// STORE/compare/log sink (`set`/`push`/`add`/`includes`/`indexOf`/`concat`/`log`/`stringify`/…) is
|
|
730
|
+
// deliberately ABSENT — edging there would fabricate the fn's effects on a pure path (the cardinal sin).
|
|
731
|
+
const HOF_INVOKERS = new Set([
|
|
732
|
+
"map", "forEach", "filter", "reduce", "reduceRight", "find", "findIndex", "findLast", "findLastIndex",
|
|
733
|
+
"some", "every", "flatMap", "sort", "group", "groupBy", "partition", "mapValues", "flatMapDeep",
|
|
734
|
+
"setTimeout", "setInterval", "setImmediate", "queueMicrotask", "requestAnimationFrame", "requestIdleCallback",
|
|
735
|
+
"then", "catch", "finally", "nextTick",
|
|
736
|
+
]);
|
|
737
|
+
|
|
727
738
|
// ---- pass 2: per call site, the (CLASSIFY)/(EDGE)/(UNKNOWN) resolution of SEMANTICS §4 ------------
|
|
728
739
|
function visitCalls(node) {
|
|
729
740
|
if (ts.isCallExpression(node) || ts.isNewExpression(node)) {
|
|
@@ -761,7 +772,15 @@ function visitCalls(node) {
|
|
|
761
772
|
// the Rust engine's fn-as-value edge. An inline closure is already charged lexically; a non-fn
|
|
762
773
|
// argument resolves to no minted unit (`nodeName` miss) and adds nothing — no fabrication. Gated
|
|
763
774
|
// on a non-local callee so a local callee that merely STORES (never invokes) keeps its precision.
|
|
764
|
-
|
|
775
|
+
// ONLY a callee that actually INVOKES its fn argument makes the reference reachable here. The
|
|
776
|
+
// earlier version edged for ANY non-local callee — fabricating the fn's effects onto a pure path
|
|
777
|
+
// (the cardinal sin) for STORE/compare/log sinks that never call it (`map.set(k, fn)`,
|
|
778
|
+
// `arr.push(fn)`, `arr.includes(fn)`, `console.log(fn)`, `[fn]`). Gate on a known INVOKING HOF by
|
|
779
|
+
// callee name; a custom non-local HOF that invokes its arg is an honest under-report (sound),
|
|
780
|
+
// never a fabrication. (A LOCAL callee keeps its precise callback-flow below.)
|
|
781
|
+
const calleeName = ts.isPropertyAccessExpression(node.expression) ? node.expression.name.text
|
|
782
|
+
: ts.isIdentifier(node.expression) ? node.expression.text : null;
|
|
783
|
+
if (mod !== "<local>" && calleeName && HOF_INVOKERS.has(calleeName)) {
|
|
765
784
|
for (const a of node.arguments ?? []) {
|
|
766
785
|
if (!ts.isIdentifier(a) && !ts.isPropertyAccessExpression(a)) continue;
|
|
767
786
|
const d2 = realDecl(checker.getSymbolAtLocation(a));
|