Repository navigation
Reject visitor removal of required children - #65288
Open
Jake Bailey (jakebailey) wants to merge 5 commits into
Open
Jake Bailey (jakebailey) wants to merge 5 commits into
Jake Bailey (jakebailey) wants to merge 5 commits into
Conversation
A visitor returning nil for a required child can leave an invalid tree that only crashes when a later consumer dereferences it. JSDoc import types expose this during type erasure even though emit never prints the affected nodes. Required children must stay present when visited, while absent children from parser error recovery and optional-child/list elision remain valid.
The token case exercises the same path as an ordinary node, and the number annotation does not reproduce the import-type erasure bug.
Member
Author
|
TypeScript Bot (@typescript-bot) perf test this faster |
Contributor
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Valid JavaScript with JSDoc-annotated properties or assignments can panic during emit because the type eraser removes required children from type wrappers instead of erasing the wrappers themselves.
1 open issue
1 file not reviewed
tsc/internal/ast/ast_generated.go: Generated file
What changed in this PR
This PR strengthens the native compiler’s AST visitor contract by rejecting removal of existing required children, while allowing absent recovery nodes and optional-child/list elision.
Changes:
- Add required-child checks to handwritten and generated visitors.
- Adjust type erasure, declaration traversal, and token navigation to preserve the new invariant.
- Add tests for required-child removal, permitted elision, and JSDoc import-type erasure.
| File | Description |
|---|---|
tsc/internal/transformers/tstransforms/typeeraser.go |
Elide import types and clear export-assignment annotations. |
tsc/internal/transformers/tstransforms/typeeraser_test.go |
Test JSDoc import-type erasure on export assignments. |
tsc/internal/transformers/declarations/transform.go |
Preserve nodes when stopping traversal across this contexts. |
tsc/internal/astnav/tokens.go |
Preserve reparsed nodes skipped during token lookup. |
tsc/internal/ast/visitor.go |
Define and document the required-child guard. |
tsc/internal/ast/deepclone_test.go |
Test required-child rejection and permitted elision. |
tsc/internal/ast/ast.go |
Guard required children in handwritten visitors. |
tsc/internal/ast/ast_generated.go |
Apply guards throughout generated visitors. |
tools/scripts/tsc/generate-go-ast.ts |
Generate required-child checks from member metadata. |
Review effort: Balanced
Contributor
|
Jake Bailey (@jakebailey) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Reparsed JSDoc annotations on object properties and assignments can contain wrapper types with required children. Descending into those wrappers during type erasure removes their children and trips the required-child visitor invariant.
Ryan Cavanaugh (RyanCavanaugh)
approved these changes
Nov 3, 2026
Jake Bailey (jakebailey)
enabled auto-merge
November 3, 2026 21:45
The merged schema now permits index signatures without annotations. Regenerating the visitor keeps its required-child checks aligned with that schema and avoids generation drift in the PR merge result.
Jake Bailey (jakebailey)
requested a review
from Ryan Cavanaugh (RyanCavanaugh)
November 3, 2026 22:09
Jake Bailey (jakebailey)
disabled auto-merge
November 3, 2026 22:29
Jake Bailey (jakebailey)
enabled auto-merge
November 3, 2026 22:30
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

A visitor returning nil for a required child can leave an invalid tree that only crashes when a later consumer dereferences it. JSDoc import types expose this during type erasure even though emit never prints the affected nodes.
Required children must stay present when visited, while absent children from parser error recovery and optional-child/list elision remain valid.