Skip to content

Anonymous function_expression bodies not visited - AMD/CommonJS modules lose all inner symbols #528

@void-Lu

Description

@void-Lu

Bug Description

When a JavaScript file uses the AMD define() pattern (common in NetSuite SuiteScript, RequireJS, and other AMD-based projects), all named function declarations inside the anonymous callback are lost during extraction.

Example:

define(['N/record', 'N/search'], function(record, search) {
    function getInputData() { /* ... */ }
    function map(context) { /* ... */ }
    function reduce(context) { /* ... */ }
    return { getInputData, map, reduce };
});

Expected: getInputData, map, reduce extracted as function nodes.
Actual: Only the file node is created (node_count: 1). All inner functions are invisible to the graph.

Root Cause

In src/extraction/tree-sitter.ts, extractFunction() returns early when name === '<anonymous>' without visiting the function body:

if (name === '<anonymous>')
    return; // Skip anonymous functions

Since visitNode() already set skipChildren = true before calling extractFunction(), the anonymous function's body (containing named function_declaration nodes) is never traversed.

The isMisparsedFunction branch (a few lines below) correctly handles a similar case — it skips the node but still visits the body. The anonymous case should do the same.

Suggested Fix

Replace:

if (name === '<anonymous>')
    return; // Skip anonymous functions

With:

if (name === '<anonymous>') {
    const body = this.extractor.resolveBody?.(node, this.extractor.bodyField)
        ?? getChildByField(node, this.extractor.bodyField);
    if (body) {
        this.visitFunctionBody(body, '');
    }
    return;
}

This way the anonymous function itself doesn't become a node, but visitFunctionBody will extract any named nested functions (line ~1646-1651 already handles this case).

Impact

Tested on a 107-file SuiteScript project (all AMD define() modules):

Metric Before After
function nodes 39 670
total nodes 146 777
edges 177 2573

The 39 functions that were previously extracted came from files that happened to use top-level function declarations without define().

Environment

  • codegraph v0.9.6
  • Windows 11, Node.js v24.12.0
  • All files are .js with AMD define([], function() { ... }) pattern

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions