Skip to content

Compute CommonJSModuleIndicator in the parser - #65073

Open
Jake Bailey (jakebailey) wants to merge 1 commit into
microsoft:mainfrom
jakebailey:cjs-indicator
Open

Jake Bailey (jakebailey) wants to merge 1 commit into
microsoft:mainfrom
jakebailey:cjs-indicator

Conversation

@jakebailey

@jakebailey Jake Bailey (jakebailey) commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

CommonJSModuleIndicator is read on files when seeing if they can be reused. But, that field is only set when a file has been bound! This means that file reuse is racy, but also inconsistent depending on when something was bound.

Instead of doing something drastic like forcing a bind just to check reuse, move this info gathering to the parser, which can calculate the same thing earlier.

Funnily, the SourceFile type already had CommonJSModuleIndicator in the parser-owned field section, which was wrong.

Unfortunately, CommonJSModuleIndicator depends on JSDoc nodes, so this requires a bit more care. I think it using JSDoc nodes is utterly strange, but, that's what we've always done, even before TS 7.

Arguably, we don't even need to set a node for CommonJSModuleIndicator or have one at all, it's not in the public JS API. I might push again to this PR and just make it a bool or tristate or something. Though it not being there but part of the reuse calculation makes me wonder if it should actually be in the AST API after all?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two critical reparsing defects leave CommonJS module indicators missing or stale, causing binding panics for valid JavaScript inputs.

2 open issues
What changed in this PR

Moves CommonJS module detection from the binder to the parser so program reuse decisions no longer depend on whether a file has been bound.

Changes:

  • Tracks CommonJS constructs during parsing, including reparsed JSDoc nodes.
  • Updates the binder to consume parser-owned metadata while preserving symbol creation order.
  • Adds tests for module detection and program reuse across CommonJS edits.
File Description
tsc/​internal/​parser/​reparser.go Checks cloned JSDoc nodes for CommonJS constructs.
tsc/​internal/​parser/​parser.go Tracks and publishes CommonJS module indicators during parsing.
tsc/​internal/​parser/​parser_test.go Adds CommonJS detection cases.
tsc/​internal/​compiler/​program_test.go Tests reuse across CommonJS edits and script transitions.
tsc/​internal/​binder/​binder.go Uses parser metadata while retaining deferred module symbol creation.

Review effort: Balanced

Comment thread tsc/internal/parser/parser.go Resolved
Comment thread tsc/internal/parser/reparser.go Resolved
@jakebailey

Copy link
Copy Markdown
Member Author

Uh. Interesting

CommonJSModuleIndicator was only set by the binder, so any reader of
an unbound file saw nil and treated a CommonJS JS file as a script.
In particular, canReplaceFileInProgram compares module-ness of the old
(usually bound) file against the freshly parsed new file, so editing
any CommonJS file always rebuilt the whole program, while a script
turning into CommonJS was wrongly reused. The binder also wrote this
field on files shared between programs via the parse cache.

Whether a file is CommonJS is purely syntactic, so the parser now
records it as SourceFile.IsCommonJSModule. Nothing read the indicator
node itself, so a bool is enough. Reparsed JSDoc nodes count too, since
the binder visits them. The binder no longer writes the field, but
still creates the file symbol at the first CommonJS construct to keep
symbol creation order, and asserts that it agrees with the parser.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The parser/binder ownership change requires classification parity across JSDoc and top-level-await reparsing while preserving symbol order, but the necessary compiler, binder regression, and race-test validation is unavailable in this review environment.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

2 participants