ucn 5.2.1 → 5.2.2
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/cli/index.js +3 -0
- package/core/account.js +36 -8
- package/core/cache.js +146 -9
- package/core/callers.js +1183 -115
- package/core/index-ir.js +5 -3
- package/core/ir.js +56 -8
- package/core/project.js +88 -3
- package/languages/c-family.js +19 -17
- package/languages/go.js +170 -42
- package/languages/javascript.js +257 -9
- package/languages/python.js +563 -26
- package/languages/rust.js +1 -0
- package/package.json +1 -1
package/languages/javascript.js
CHANGED
|
@@ -463,6 +463,55 @@ function returnsReceiverSelf(node) {
|
|
|
463
463
|
return sawSelf;
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
+
/**
|
|
467
|
+
* Exact call expression returned by an expression-bodied arrow. This is a
|
|
468
|
+
* syntax proof, not return-type inference: query-time flow resolves the call
|
|
469
|
+
* through its ordinary import/receiver ownership rails. Block bodies,
|
|
470
|
+
* conditionals, and other expressions deliberately stay unmarked.
|
|
471
|
+
*/
|
|
472
|
+
function returnedArrowCallSpan(node) {
|
|
473
|
+
if (node.type !== 'arrow_function') return null;
|
|
474
|
+
let body = node.childForFieldName('body');
|
|
475
|
+
while (body?.type === 'parenthesized_expression' && body.namedChildCount === 1) {
|
|
476
|
+
body = body.namedChild(0);
|
|
477
|
+
}
|
|
478
|
+
if (body?.type !== 'call_expression') return null;
|
|
479
|
+
return { start: body.startIndex, end: body.endIndex };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Exact `this.field...` value returned by a one-statement method body. The
|
|
484
|
+
* deliberately narrow shape proves both that the member path is returned and
|
|
485
|
+
* that no fallthrough/alternate return widens the compiler-inferred type.
|
|
486
|
+
*/
|
|
487
|
+
function returnedReceiverFieldPath(node) {
|
|
488
|
+
const body = node.childForFieldName('body');
|
|
489
|
+
if (!body || body.type !== 'statement_block' || body.namedChildCount !== 1) {
|
|
490
|
+
return null;
|
|
491
|
+
}
|
|
492
|
+
const statement = body.namedChild(0);
|
|
493
|
+
if (statement?.type !== 'return_statement' || statement.namedChildCount !== 1) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
let value = statement.namedChild(0);
|
|
497
|
+
while (value?.type === 'parenthesized_expression' && value.namedChildCount === 1) {
|
|
498
|
+
value = value.namedChild(0);
|
|
499
|
+
}
|
|
500
|
+
const fields = [];
|
|
501
|
+
while (value?.type === 'member_expression') {
|
|
502
|
+
const property = value.childForFieldName('property');
|
|
503
|
+
const object = value.childForFieldName('object');
|
|
504
|
+
if (!property || !object ||
|
|
505
|
+
!['property_identifier', 'private_property_identifier', 'identifier']
|
|
506
|
+
.includes(property.type)) {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
fields.unshift(property.text);
|
|
510
|
+
value = object;
|
|
511
|
+
}
|
|
512
|
+
return value?.type === 'this' && fields.length > 0 ? fields : null;
|
|
513
|
+
}
|
|
514
|
+
|
|
466
515
|
/**
|
|
467
516
|
* Process a node for function extraction (single-pass helper)
|
|
468
517
|
* Returns true if node was matched, false otherwise
|
|
@@ -634,6 +683,7 @@ function _processFunction(node, functions, processedRanges, lines) {
|
|
|
634
683
|
// declaration text, so we double-check the value node directly.
|
|
635
684
|
const valueIsAsync = valueNode.text.trimStart().startsWith('async ');
|
|
636
685
|
const isAsync = valueIsAsync || modifiers.includes('async');
|
|
686
|
+
const returnedCall = returnedArrowCallSpan(valueNode);
|
|
637
687
|
|
|
638
688
|
functions.push({
|
|
639
689
|
name: nameNode.text,
|
|
@@ -648,6 +698,10 @@ function _processFunction(node, functions, processedRanges, lines) {
|
|
|
648
698
|
modifiers,
|
|
649
699
|
...lexicalOwnerRange(node),
|
|
650
700
|
...typeAnno,
|
|
701
|
+
...(returnedCall && {
|
|
702
|
+
returnedCallStart: returnedCall.start,
|
|
703
|
+
returnedCallEnd: returnedCall.end,
|
|
704
|
+
}),
|
|
651
705
|
...(generics && { generics }),
|
|
652
706
|
...(docstring && { docstring })
|
|
653
707
|
});
|
|
@@ -1301,6 +1355,8 @@ function extractClassMembers(classNode, codeOrLines) {
|
|
|
1301
1355
|
const isAsync = text.match(/^\s*(?:(?:public|private|protected)\s+)?(?:static\s+)?(?:override\s+)?async\s/) !== null;
|
|
1302
1356
|
const returnType = extractReturnType(child) ||
|
|
1303
1357
|
(returnsReceiverSelf(child) ? 'this' : null);
|
|
1358
|
+
const returnedReceiverPath = !returnType
|
|
1359
|
+
? returnedReceiverFieldPath(child) : null;
|
|
1304
1360
|
const docstring = extractJSDocstring(code, startLine);
|
|
1305
1361
|
const paramsStructured = parseStructuredParams(paramsNode, 'javascript');
|
|
1306
1362
|
const typeAnno = buildTypeAnnotations(paramsStructured, returnType, code, startLine, true);
|
|
@@ -1329,6 +1385,7 @@ function extractClassMembers(classNode, codeOrLines) {
|
|
|
1329
1385
|
// (fix #230) — pickBestDefinition prefers the implementation.
|
|
1330
1386
|
...(child.type === 'method_signature' && { isSignature: true }),
|
|
1331
1387
|
...typeAnno,
|
|
1388
|
+
...(returnedReceiverPath && { returnedReceiverPath }),
|
|
1332
1389
|
...(docstring && { docstring }),
|
|
1333
1390
|
...(decorators.length > 0 && { decorators }),
|
|
1334
1391
|
...(decoratorsWithArgs.length > 0 && { decoratorsWithArgs })
|
|
@@ -1467,6 +1524,14 @@ function extractClassMembers(classNode, codeOrLines) {
|
|
|
1467
1524
|
const fieldTypeNode = child.childForFieldName('type');
|
|
1468
1525
|
const fieldType = fieldTypeNode
|
|
1469
1526
|
? fieldTypeNode.text.replace(/^:\s*/, '').trim() : undefined;
|
|
1527
|
+
// A direct identifier initializer on a static field keeps
|
|
1528
|
+
// the lexical callable identity available to the IR:
|
|
1529
|
+
// `static create = createSchema`. Resolution remains
|
|
1530
|
+
// same-file and overload-disciplined in createFileIR;
|
|
1531
|
+
// expressions, member accesses, and instance fields do
|
|
1532
|
+
// not receive this proof marker.
|
|
1533
|
+
const callableTarget = isStatic && valueNode?.type === 'identifier'
|
|
1534
|
+
? valueNode.text : undefined;
|
|
1470
1535
|
members.push({
|
|
1471
1536
|
name,
|
|
1472
1537
|
startLine,
|
|
@@ -1474,6 +1539,7 @@ function extractClassMembers(classNode, codeOrLines) {
|
|
|
1474
1539
|
memberType: name.startsWith('#') ? 'private field' : 'field',
|
|
1475
1540
|
...(isStatic && { modifiers: ['static'] }),
|
|
1476
1541
|
...(fieldType && { fieldType }),
|
|
1542
|
+
...(callableTarget && { callableTarget }),
|
|
1477
1543
|
...(fieldDecorators.length > 0 && { decorators: fieldDecorators })
|
|
1478
1544
|
// Not a method - regular field
|
|
1479
1545
|
});
|
|
@@ -1920,13 +1986,120 @@ function findCallsInCode(code, parser) {
|
|
|
1920
1986
|
const tree = parseTree(parser, code);
|
|
1921
1987
|
const calls = [];
|
|
1922
1988
|
const assignedMembers = new Set();
|
|
1989
|
+
const mutatedObjectRoots = new Set();
|
|
1990
|
+
const moduleCompositions = new Map();
|
|
1991
|
+
const unsafeModuleCompositions = new Set();
|
|
1992
|
+
const namespaceAliases = new Set();
|
|
1993
|
+
const accessRoot = (node) => {
|
|
1994
|
+
let current = node;
|
|
1995
|
+
while (current && (current.type === 'member_expression' ||
|
|
1996
|
+
current.type === 'subscript_expression')) {
|
|
1997
|
+
current = current.childForFieldName('object');
|
|
1998
|
+
}
|
|
1999
|
+
return current?.type === 'identifier' ? current.text : undefined;
|
|
2000
|
+
};
|
|
1923
2001
|
traverseTreeCached(tree.rootNode, node => {
|
|
1924
|
-
if (node.type
|
|
1925
|
-
node.
|
|
1926
|
-
|
|
1927
|
-
|
|
2002
|
+
if (node.type === 'namespace_import') {
|
|
2003
|
+
const identifier = node.namedChild(0);
|
|
2004
|
+
if (identifier?.type === 'identifier') namespaceAliases.add(identifier.text);
|
|
2005
|
+
}
|
|
2006
|
+
if (node.type === 'variable_declarator') {
|
|
2007
|
+
const declaration = node.parent;
|
|
2008
|
+
const nameNode = node.childForFieldName('name');
|
|
2009
|
+
const valueNode = node.childForFieldName('value');
|
|
2010
|
+
if (nameNode?.type === 'identifier' && valueNode?.type === 'object' &&
|
|
2011
|
+
declaration?.type === 'lexical_declaration' &&
|
|
2012
|
+
declaration.child(0)?.text === 'const' && isModuleScope(declaration)) {
|
|
2013
|
+
const layers = [];
|
|
2014
|
+
let spreadCandidates = 0;
|
|
2015
|
+
for (let i = 0; i < valueNode.namedChildCount; i++) {
|
|
2016
|
+
const item = valueNode.namedChild(i);
|
|
2017
|
+
if (item.type === 'spread_element') {
|
|
2018
|
+
const value = item.namedChild(0);
|
|
2019
|
+
if (value?.type === 'identifier') {
|
|
2020
|
+
// Namespace imports may legally appear later in
|
|
2021
|
+
// the module. Resolve candidates after this pass
|
|
2022
|
+
// has seen the complete import surface.
|
|
2023
|
+
layers.push({ kind: 'spread-candidate', receiver: value.text });
|
|
2024
|
+
spreadCandidates++;
|
|
2025
|
+
} else {
|
|
2026
|
+
layers.push({ kind: 'unknown' });
|
|
2027
|
+
}
|
|
2028
|
+
continue;
|
|
2029
|
+
}
|
|
2030
|
+
if (item.type === 'pair') {
|
|
2031
|
+
const key = item.childForFieldName('key');
|
|
2032
|
+
const staticKey = key && ['property_identifier', 'identifier', 'string']
|
|
2033
|
+
.includes(key.type)
|
|
2034
|
+
? key.text.replace(/^['"]|['"]$/g, '') : null;
|
|
2035
|
+
layers.push(staticKey
|
|
2036
|
+
? { kind: 'property', name: staticKey }
|
|
2037
|
+
: { kind: 'unknown' });
|
|
2038
|
+
continue;
|
|
2039
|
+
}
|
|
2040
|
+
if (item.type === 'shorthand_property_identifier' ||
|
|
2041
|
+
item.type === 'method_definition') {
|
|
2042
|
+
const name = item.type === 'method_definition'
|
|
2043
|
+
? item.childForFieldName('name')?.text : item.text;
|
|
2044
|
+
layers.push(name
|
|
2045
|
+
? { kind: 'property', name }
|
|
2046
|
+
: { kind: 'unknown' });
|
|
2047
|
+
continue;
|
|
2048
|
+
}
|
|
2049
|
+
layers.push({ kind: 'unknown' });
|
|
2050
|
+
}
|
|
2051
|
+
if (spreadCandidates > 0) moduleCompositions.set(nameNode.text, layers);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
if (node.type === 'assignment_expression' ||
|
|
2055
|
+
node.type === 'augmented_assignment_expression') {
|
|
2056
|
+
const left = node.childForFieldName('left');
|
|
2057
|
+
if (left?.type === 'member_expression') assignedMembers.add(left.text);
|
|
2058
|
+
const root = accessRoot(left);
|
|
2059
|
+
if (root) mutatedObjectRoots.add(root);
|
|
2060
|
+
}
|
|
2061
|
+
// A namespace-spread composite is exact only while the ordinary
|
|
2062
|
+
// object remains private and unmodified. Any use of the object value
|
|
2063
|
+
// itself (export, alias, return, argument, spread, etc.) can expose a
|
|
2064
|
+
// mutation; property reads/calls are the sole accepted uses.
|
|
2065
|
+
if (node.type !== 'identifier' || !moduleCompositions.has(node.text)) return true;
|
|
2066
|
+
const parent = node.parent;
|
|
2067
|
+
if (parent?.type === 'variable_declarator' &&
|
|
2068
|
+
parent.childForFieldName('name')?.id === node.id) return true;
|
|
2069
|
+
if ((parent?.type === 'member_expression' ||
|
|
2070
|
+
parent?.type === 'subscript_expression') &&
|
|
2071
|
+
parent.childForFieldName('object')?.id === node.id) {
|
|
2072
|
+
let access = parent;
|
|
2073
|
+
while ((access.parent?.type === 'member_expression' ||
|
|
2074
|
+
access.parent?.type === 'subscript_expression') &&
|
|
2075
|
+
access.parent.childForFieldName('object')?.id === access.id) {
|
|
2076
|
+
access = access.parent;
|
|
2077
|
+
}
|
|
2078
|
+
const container = access.parent;
|
|
2079
|
+
const assigned = (container?.type === 'assignment_expression' ||
|
|
2080
|
+
container?.type === 'augmented_assignment_expression') &&
|
|
2081
|
+
container.childForFieldName('left')?.id === access.id;
|
|
2082
|
+
const updated = container?.type === 'update_expression';
|
|
2083
|
+
const deleted = container?.type === 'unary_expression' &&
|
|
2084
|
+
container.child(0)?.text === 'delete';
|
|
2085
|
+
if (!assigned && !updated && !deleted) return true;
|
|
2086
|
+
}
|
|
2087
|
+
unsafeModuleCompositions.add(node.text);
|
|
1928
2088
|
return true;
|
|
1929
2089
|
});
|
|
2090
|
+
for (const [name, layers] of moduleCompositions) {
|
|
2091
|
+
const normalized = layers.map(layer => layer.kind === 'spread-candidate'
|
|
2092
|
+
? (namespaceAliases.has(layer.receiver)
|
|
2093
|
+
? { kind: 'spread', receiver: layer.receiver }
|
|
2094
|
+
: { kind: 'unknown' })
|
|
2095
|
+
: layer);
|
|
2096
|
+
if (normalized.some(layer => layer.kind === 'spread')) {
|
|
2097
|
+
moduleCompositions.set(name, normalized);
|
|
2098
|
+
} else {
|
|
2099
|
+
moduleCompositions.delete(name);
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
for (const name of mutatedObjectRoots) unsafeModuleCompositions.add(name);
|
|
1930
2103
|
const functionStack = []; // Stack of { name, startLine, endLine }
|
|
1931
2104
|
// Local aliases with lexical ownership. A flat aliasName→target map leaks
|
|
1932
2105
|
// block locals into the rest of a module (`let effect = batchedEffect`
|
|
@@ -2162,6 +2335,16 @@ function findCallsInCode(code, parser) {
|
|
|
2162
2335
|
|
|
2163
2336
|
const _patternDeclaresName = (pattern, name) => {
|
|
2164
2337
|
if (!pattern) return false;
|
|
2338
|
+
// TypeScript parameter wrappers contain both the runtime binding
|
|
2339
|
+
// pattern and a type annotation. Only the pattern declares names:
|
|
2340
|
+
// `metadata: registries.GlobalMeta` must not make the namespace
|
|
2341
|
+
// identifier `registries` look like a shadowing parameter.
|
|
2342
|
+
if (pattern.type === 'required_parameter' ||
|
|
2343
|
+
pattern.type === 'optional_parameter') {
|
|
2344
|
+
return _patternDeclaresName(
|
|
2345
|
+
pattern.childForFieldName('pattern') ||
|
|
2346
|
+
pattern.childForFieldName('name'), name);
|
|
2347
|
+
}
|
|
2165
2348
|
if ((pattern.type === 'identifier' ||
|
|
2166
2349
|
pattern.type === 'shorthand_property_identifier_pattern') &&
|
|
2167
2350
|
pattern.text === name) return true;
|
|
@@ -2189,6 +2372,60 @@ function findCallsInCode(code, parser) {
|
|
|
2189
2372
|
return false;
|
|
2190
2373
|
};
|
|
2191
2374
|
|
|
2375
|
+
// Bare callback references need to distinguish a module-owned VALUE from
|
|
2376
|
+
// an unbound name. File-level import reachability cannot prove the value's
|
|
2377
|
+
// identity: `const app = express(); use(app)` may live in a file that also
|
|
2378
|
+
// imports the pinned target, but `app` is the factory result rather than a
|
|
2379
|
+
// direct lexical reference to that target. Keep the parser evidence exact
|
|
2380
|
+
// and cheap by collecting only declarations whose lexical owner is the
|
|
2381
|
+
// program/module root (export wrappers included).
|
|
2382
|
+
const moduleValueBindings = new Set();
|
|
2383
|
+
const collectPatternNames = (pattern) => {
|
|
2384
|
+
if (!pattern) return;
|
|
2385
|
+
if (pattern.type === 'identifier' ||
|
|
2386
|
+
pattern.type === 'shorthand_property_identifier_pattern') {
|
|
2387
|
+
moduleValueBindings.add(pattern.text);
|
|
2388
|
+
return;
|
|
2389
|
+
}
|
|
2390
|
+
if (pattern.type === 'pair_pattern' || pattern.type === 'pair') {
|
|
2391
|
+
collectPatternNames(pattern.childForFieldName('value'));
|
|
2392
|
+
return;
|
|
2393
|
+
}
|
|
2394
|
+
if (pattern.type === 'assignment_pattern') {
|
|
2395
|
+
collectPatternNames(
|
|
2396
|
+
pattern.childForFieldName('left') || pattern.childForFieldName('pattern'));
|
|
2397
|
+
return;
|
|
2398
|
+
}
|
|
2399
|
+
for (let i = 0; i < pattern.namedChildCount; i++) {
|
|
2400
|
+
collectPatternNames(pattern.namedChild(i));
|
|
2401
|
+
}
|
|
2402
|
+
};
|
|
2403
|
+
const collectModuleDeclaration = (statement) => {
|
|
2404
|
+
let declaration = statement;
|
|
2405
|
+
if (statement.type === 'export_statement') {
|
|
2406
|
+
declaration = null;
|
|
2407
|
+
for (let i = 0; i < statement.namedChildCount; i++) {
|
|
2408
|
+
const child = statement.namedChild(i);
|
|
2409
|
+
if (child.type === 'lexical_declaration' || child.type === 'variable_declaration') {
|
|
2410
|
+
declaration = child;
|
|
2411
|
+
break;
|
|
2412
|
+
}
|
|
2413
|
+
}
|
|
2414
|
+
}
|
|
2415
|
+
if (!declaration ||
|
|
2416
|
+
(declaration.type !== 'lexical_declaration' &&
|
|
2417
|
+
declaration.type !== 'variable_declaration')) return;
|
|
2418
|
+
for (let i = 0; i < declaration.namedChildCount; i++) {
|
|
2419
|
+
const declarator = declaration.namedChild(i);
|
|
2420
|
+
if (declarator.type === 'variable_declarator') {
|
|
2421
|
+
collectPatternNames(declarator.childForFieldName('name'));
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
};
|
|
2425
|
+
for (let i = 0; i < tree.rootNode.namedChildCount; i++) {
|
|
2426
|
+
collectModuleDeclaration(tree.rootNode.namedChild(i));
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2192
2429
|
// fix #203: is a bare-identifier function REFERENCE shadowed by a
|
|
2193
2430
|
// let/const/var local, for/catch binding, or inner-arrow param in an
|
|
2194
2431
|
// enclosing lexical scope? Block-accurate, declaration-before-use.
|
|
@@ -2241,6 +2478,11 @@ function findCallsInCode(code, parser) {
|
|
|
2241
2478
|
return false;
|
|
2242
2479
|
};
|
|
2243
2480
|
|
|
2481
|
+
const bareReferenceBindingFields = (refNode) => ({
|
|
2482
|
+
...(isShadowedByLocal(refNode, refNode.text) && { localShadow: true }),
|
|
2483
|
+
...(moduleValueBindings.has(refNode.text) && { moduleLocalBinding: true }),
|
|
2484
|
+
});
|
|
2485
|
+
|
|
2244
2486
|
const isConditionalReassignment = node => {
|
|
2245
2487
|
for (let p = node.parent; p && !isFunctionNode(p); p = p.parent) {
|
|
2246
2488
|
if (p.type === 'if_statement') {
|
|
@@ -2429,7 +2671,7 @@ function findCallsInCode(code, parser) {
|
|
|
2429
2671
|
isMethod: false,
|
|
2430
2672
|
isFunctionReference: true,
|
|
2431
2673
|
isPotentialCallback: true,
|
|
2432
|
-
...(
|
|
2674
|
+
...bareReferenceBindingFields(right),
|
|
2433
2675
|
enclosingFunction: getCurrentEnclosingFunction(),
|
|
2434
2676
|
});
|
|
2435
2677
|
}
|
|
@@ -2696,6 +2938,9 @@ function findCallsInCode(code, parser) {
|
|
|
2696
2938
|
const receiverIsModule = !!receiverModuleSpecifier ||
|
|
2697
2939
|
(!!receiver && moduleAliases.has(receiver) &&
|
|
2698
2940
|
!localVarTypes.has(receiver));
|
|
2941
|
+
const receiverModuleComposition = receiver &&
|
|
2942
|
+
!unsafeModuleCompositions.has(receiver)
|
|
2943
|
+
? moduleCompositions.get(receiver) : undefined;
|
|
2699
2944
|
const firstArg = getFirstStringArg(node);
|
|
2700
2945
|
const argCount = getArgCount(node);
|
|
2701
2946
|
let assignedTo = jsAssignmentTargetOf(node);
|
|
@@ -2730,6 +2975,9 @@ function findCallsInCode(code, parser) {
|
|
|
2730
2975
|
}),
|
|
2731
2976
|
...(receiverIsModule && { receiverIsModule: true }),
|
|
2732
2977
|
...(receiverModuleSpecifier && { receiverModuleSpecifier }),
|
|
2978
|
+
...(receiverModuleComposition && {
|
|
2979
|
+
receiverModuleComposition,
|
|
2980
|
+
}),
|
|
2733
2981
|
...(receiver && assignedMembers.has(`${receiver}.${propName}`) && {
|
|
2734
2982
|
receiverMemberAssigned: true,
|
|
2735
2983
|
}),
|
|
@@ -2787,7 +3035,7 @@ function findCallsInCode(code, parser) {
|
|
|
2787
3035
|
line: arg.startPosition.row + 1,
|
|
2788
3036
|
isMethod: false,
|
|
2789
3037
|
isFunctionReference: true,
|
|
2790
|
-
...(
|
|
3038
|
+
...bareReferenceBindingFields(arg),
|
|
2791
3039
|
enclosingFunction
|
|
2792
3040
|
});
|
|
2793
3041
|
} else if (arg.type === 'member_expression') {
|
|
@@ -2832,7 +3080,7 @@ function findCallsInCode(code, parser) {
|
|
|
2832
3080
|
isMethod: false,
|
|
2833
3081
|
isFunctionReference: true,
|
|
2834
3082
|
isPotentialCallback: true,
|
|
2835
|
-
...(
|
|
3083
|
+
...bareReferenceBindingFields(arg),
|
|
2836
3084
|
enclosingFunction
|
|
2837
3085
|
});
|
|
2838
3086
|
}
|
|
@@ -2873,7 +3121,7 @@ function findCallsInCode(code, parser) {
|
|
|
2873
3121
|
isMethod: false,
|
|
2874
3122
|
isFunctionReference: true,
|
|
2875
3123
|
isPotentialCallback: true,
|
|
2876
|
-
...(
|
|
3124
|
+
...bareReferenceBindingFields(val),
|
|
2877
3125
|
enclosingFunction
|
|
2878
3126
|
});
|
|
2879
3127
|
}
|
|
@@ -2977,7 +3225,7 @@ function findCallsInCode(code, parser) {
|
|
|
2977
3225
|
isMethod: false,
|
|
2978
3226
|
isFunctionReference: true,
|
|
2979
3227
|
isPotentialCallback: true,
|
|
2980
|
-
...(
|
|
3228
|
+
...bareReferenceBindingFields(child),
|
|
2981
3229
|
enclosingFunction
|
|
2982
3230
|
});
|
|
2983
3231
|
} else if (child.type === 'member_expression') {
|