candor-ts 0.5.16 → 0.5.17
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 +21 -1
package/package.json
CHANGED
package/scan.mjs
CHANGED
|
@@ -442,6 +442,19 @@ function localName(node) {
|
|
|
442
442
|
}
|
|
443
443
|
return null;
|
|
444
444
|
}
|
|
445
|
+
// True when `node` is lexically inside a FUNCTION body — so its bare local name can collide with a
|
|
446
|
+
// module-level or sibling-scope unit of the same name (see the qual disambiguation below). A namespace/
|
|
447
|
+
// module block and the source file are NOT function scopes (their members are top-level units).
|
|
448
|
+
function isFunctionScoped(node) {
|
|
449
|
+
for (let p = node.parent; p; p = p.parent) {
|
|
450
|
+
if (ts.isSourceFile(p) || ts.isModuleBlock(p)) return false;
|
|
451
|
+
if (ts.isFunctionDeclaration(p) || ts.isFunctionExpression(p) || ts.isArrowFunction(p)
|
|
452
|
+
|| ts.isMethodDeclaration(p) || ts.isConstructorDeclaration(p)
|
|
453
|
+
|| ts.isGetAccessorDeclaration(p) || ts.isSetAccessorDeclaration(p))
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
445
458
|
for (const sf of sources) {
|
|
446
459
|
const mod = moduleOf(sf);
|
|
447
460
|
(function collect(node) {
|
|
@@ -491,8 +504,15 @@ for (const sf of sources) {
|
|
|
491
504
|
const n = localName(node);
|
|
492
505
|
const isCjsExport = _lastCjs; // captured immediately: localName set it for THIS node only
|
|
493
506
|
if (n) {
|
|
494
|
-
const qual = `${mod}.${n}`;
|
|
495
507
|
const { line, character } = sf.getLineAndCharacterOfPosition(node.getStart());
|
|
508
|
+
// Disambiguate FUNCTION-SCOPED local function units by position. A `const persist = () => …` (or a
|
|
509
|
+
// nested `function persist(){}`) inside a fn body shares the bare `mod.name` key with a module-level
|
|
510
|
+
// OR sibling-scope unit of the same name, so the second `fns.set` CLOBBERS the first and a call that
|
|
511
|
+
// resolves (correctly, via the checker) to the LOCAL decl reads the OTHER unit's effects off the
|
|
512
|
+
// shared entry — FABRICATING them onto a pure caller. `nodeName` is keyed by NODE identity, so a
|
|
513
|
+
// per-node-unique key keeps resolution exact; only TOP-LEVEL units need the stable bare name a
|
|
514
|
+
// consumer's hash-join targets (a function-scoped local is never an export, so nothing joins to it).
|
|
515
|
+
const qual = isFunctionScoped(node) ? `${mod}.${n}#${line + 1}:${character + 1}` : `${mod}.${n}`;
|
|
496
516
|
fns.set(qual, { local: n, direct: new Set(), edges: new Set(), hosts: new Set(), tables: new Set(),
|
|
497
517
|
cmds: new Set(), paths: new Set(), blind: new Set(), incomplete: new Set(), why: new Set(), entry: false, isCjsExport,
|
|
498
518
|
loc: `${path.relative(rootDir, sf.fileName)}:${line + 1}:${character + 1}` });
|