Skip to content

Use native private members in Rush tooling - #5941

Open
Bharat Middha (bmiddha) wants to merge 6 commits into
bmiddha/fix-no-new-null-native-privatefrom
bmiddha/native-private-fields-rush-ecosystem
Open

Use native private members in Rush tooling#5941
Bharat Middha (bmiddha) wants to merge 6 commits into
bmiddha/fix-no-new-null-native-privatefrom
bmiddha/native-private-fields-rush-ecosystem

Conversation

@bmiddha

@bmiddha Bharat Middha (bmiddha) commented Aug 19, 2026

Copy link
Copy Markdown
Member

Summary

  • convert TypeScript-private fields, methods, and accessors across Rush applications, plugins, daemon packages, and extensions to ECMAScript #private members
  • replace private-member destructuring with direct private access
  • keep TypeScript-private members where tests synthesize instances or spy on internals
  • preserve the public PlaywrightBrowserTunnel.status getter while replacing its private setter with #setStatus()
  • keep package behavior and public APIs unchanged

Validation

  • built and tested all 30 affected Rush ecosystem projects and dependents

Dependency

Stacked on #5947, which fixes @rushstack/no-new-null handling for ECMAScript private members. Narrow suppressions remain because these packages consume the released decoupled plugin; they can be removed after the patched plugin is published and adopted.

Convert eligible TS 'private' class property declarations to
ECMAScript #private fields across apps/rush, apps/rush-mcp-server,
apps/lockfile-explorer, apps/playwright-browser-tunnel, apps/zipsync,
apps/rundown, apps/trace-import, apps/cpu-profile-summarizer,
apps/rush-serve-dashboard, libraries/rush-terminal-renderer,
libraries/rush-daemon, libraries/rush-daemon-transport,
libraries/rushell, rush-plugins, repo-scripts/repo-toolbox, and
vscode-extensions. Strips one conventional leading underscore from
each converted field name.

Rewrote an unsupported destructuring assignment in
RedisCobuildLockProvider (const { _terminal: terminal } = this;)
to plain property access so it could be converted.

Retained rush-plugins/rush-buildxl-graph-plugin's test-only
'declare private _configHash' field as TS-private: that mock relies
on Object.setPrototypeOf to backfill a field on a plain object,
which true ECMAScript private fields cannot support.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14
Extend the earlier field-only #private conversion to also cover
private methods and accessors across apps/lockfile-explorer,
apps/playwright-browser-tunnel, apps/rundown, apps/rush-mcp-server,
apps/rush-serve-dashboard, libraries/rush-daemon,
libraries/rush-daemon-transport, libraries/rush-terminal-renderer,
libraries/rushell, rush-plugins, and vscode-extensions. Strips one
conventional leading underscore from each converted member name.

Reverted two members that the symbol-aware tool converted but that
are unsafe in practice:
- rush-buildxl-graph-plugin's test-only 'declare private _configHash'
  cannot use 'declare' with a private identifier (TS18019), matching
  the earlier decision to keep it TS-private for the
  Object.setPrototypeOf mock.
- AmazonS3Client's '_writeWarningLine' is spied on and stubbed via
  '(s3Client as any)._writeWarningLine' in AmazonS3Client.test.ts,
  which requires runtime reflection that true private fields do not
  support.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14
Manually inspect the 9 tool-skipped candidates from the private
member conversion. Getter/setter and method-overload declarations
that share a TypeScript symbol are known false positives in the
symbol-aware codemod: it flags every overload signature as an
'unsupported reference' to every other overload of the same method.

For AmazonS3Client's '_makeSignedRequestAsync' (3 overload
signatures) and HttpBuildCacheProvider's '_tryGetCredentialsAsync'
(4 overload signatures + implementation), a repo-wide search found
only ordinary same-class 'this.method(...)' call sites -- no
bracket access, 'as any' casts, reflection, prototype tricks, or
test spies. Converted every overload declaration and call site to
'#makeSignedRequestAsync' / '#tryGetCredentialsAsync'.

Left PlaywrightBrowserTunnel's 'status' accessor pair (public
getter / private setter) as TS-private: this is not a false
positive. Native ECMAScript private accessors have no way to make
only the setter private while the getter of the same name stays
public -- '#status' would need to be a single accessor pair with
uniform visibility, and it would collide with the existing
'#status' backing field. Converting it would require restructuring
the field name, which is outside the scope of a straightforward
private-to-# conversion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14
Replace the mixed-visibility 'public get status() / private set
status()' accessor pair with a public 'get status()' plus a native
private method '#setStatus(newStatus)'. Native ECMAScript private
accessors require the getter and setter to share one name with
uniform visibility, so the private setter could not be converted to
a same-named '#status' accessor without colliding with the existing
'#status' backing field. Renaming the mutator to a private method
sidesteps that restriction while keeping the public read-only
getter contract unchanged.

Updated all 5 internal 'this.status = <value>' assignments to
'this.#setStatus(<value>)'.

This removes the last remaining TS 'private' class member across
the requested conversion scopes; only the two previously-documented
unsafe members (rush-buildxl-graph-plugin's declare-only
'_configHash' and AmazonS3Client's reflection-accessed
'_writeWarningLine') remain TS-private by design.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14
The decoupled ESLint plugin does not recognize native private methods, causing no-new-null to report a false positive.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8ebd5bf2-c44b-42d5-be25-e7936d4b0a14
@bmiddha Bharat Middha (bmiddha) changed the title Use native private fields in Rush tooling Use native private members in Rush tooling Aug 20, 2026
…rivate' into bmiddha/native-private-fields-rush-ecosystem
@bmiddha
Bharat Middha (bmiddha) changed the base branch from main to bmiddha/fix-no-new-null-native-private August 20, 2026 06:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Needs triage

Development

Successfully merging this pull request may close these issues.

1 participant