Emit expando properties for functions that only become visible late in declaration emit#4535
Open
UditDewan wants to merge 2 commits into
Open
Emit expando properties for functions that only become visible late in declaration emit#4535UditDewan wants to merge 2 commits into
UditDewan wants to merge 2 commits into
Conversation
…n declaration emit The declaration transformer collects expando assignments in a prepass and dropped any whose host declaration wasn't visible at that point. A non-exported host can still be late-marked visible while printing the type of an exported declaration (e.g. as 'typeof host'), which then emitted the host without its expando namespace. Defer such assignments and process them if their host statement is late-marked visible, instead of dropping them. Fixes microsoft#4461
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes a declaration-emit gap where expando property assignments (e.g. FunctionComponent.propTypes = ...) were dropped if the host declaration was not yet “visible” during the expando-collection prepass, but later became visible during declaration transformation (e.g. via typeof).
Changes:
- Defer expando assignments whose host isn’t visible at collection time, and replay them when the host statement is processed from the late-marked visibility queue.
- Add a compiler regression test covering late-visible expando function properties in both TS and JS inputs.
- Add a cold-emit CLI (tsc-style) regression scenario + reference baseline to validate the emitted
.d.tsshape matches expected merged-namespace output.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| internal/transformers/declarations/transform.go | Defers expando assignments for not-yet-visible hosts and processes them when the host is late-marked visible. |
| internal/execute/tsctests/tsc_test.go | Adds a new declaration-emit CLI regression scenario reproducing the late-visibility expando case. |
| testdata/tests/cases/compiler/declarationEmitLateVisibleExpandoFunction.ts | New compiler test case covering TS+JS variants (function + arrow + unused host). |
| testdata/baselines/reference/compiler/declarationEmitLateVisibleExpandoFunction.js | Expected emit baseline for the new compiler test (includes merged namespace for visible hosts). |
| testdata/baselines/reference/compiler/declarationEmitLateVisibleExpandoFunction.types | Expected types baseline for the new compiler test. |
| testdata/baselines/reference/compiler/declarationEmitLateVisibleExpandoFunction.symbols | Expected symbols baseline for the new compiler test. |
| testdata/baselines/reference/tsc/declarationEmit/expando-function-properties-for-function-only-referenced-via-typeof.js | New CLI baseline ensuring cold emit includes expando namespace for late-visible function host. |
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.
Fixes #4461
Problem
The declaration transformer collects expando property assignments in a prepass over the whole file (#4261), and drops any assignment whose host declaration isn't visible at that point (#3716). But a non-exported host can still become visible during statement transformation: printing the type of an exported declaration can reference it and late-mark its statement visible. The host then gets emitted without its expando properties:
previously emitted:
dropping
propTypes, while TS 6 emits the merged namespace:Fix
Instead of dropping assignments for not-yet-visible hosts, defer them; when a statement is popped off the late-marked queue in
transformAndReplaceLatePaintedStatements, process its deferred expando assignments first. This matches strada's behavior, where the expando namespace is synthesized while transforming the (possibly late-marked) host statement itself, i.e. after visibility has settled. Hosts that never become visible still emit nothing and never get their property types printed, preserving #3686.Notes for review
tsgobuild runs the transform once and hits the bug. The regression test for the broken case is therefore a tsc CLI test (expando function properties for function only referenced via typeof), which runs emit cold; the compiler test locks the emitted shape and covers the arrow/unused-function variants in TS and JS.FunctionComponentWithText(.js/.tsx) andFunctionComponentMemoized(.tsx).FunctionComponentMemoized/.jsalso gains.propTypesthroughtypeof FunctionComponent(TS 6: ❌). That cell can't stay ❌ while fixingFunctionComponentWithText/.js, because both flow through the sametypeof FunctionComponentreference in corsa's JS declaration emit — TS 6 only distinguished them because its JS emit copied expando members onto each exported alias instead of usingtypeof. This seems consistent with the documented JS declaration emit differences in CHANGES.md, but happy to adjust if you'd rather gate this for JS files.Disclosure
This patch was authored with AI assistance (Claude Code), per the CONTRIBUTING.md disclosure request.