Skip to content

feat: treeshake namespace aliases via non-reassigned bindings#9578

Draft
IWANABETHATGUY wants to merge 1 commit into
05-26-feat_treeshake_ns_reexportfrom
05-27-feat_treeshake_ns_alias
Draft

feat: treeshake namespace aliases via non-reassigned bindings#9578
IWANABETHATGUY wants to merge 1 commit into
05-26-feat_treeshake_ns_reexportfrom
05-27-feat_treeshake_ns_alias

Conversation

@IWANABETHATGUY

@IWANABETHATGUY IWANABETHATGUY commented May 27, 2026

Copy link
Copy Markdown
Member

Summary

  • Stacked on top of feat: tree-shake export default <namespace> re-exports #9574. Extends the export default <namespace> re-export tree-shaking to named variable exports of the form export <kind> res = ns;, where ns is an import * as ns local.
  • Drops the const-only outer gate in favor of SymbolRefFlags::IsNotReassigned on the declared binding — let/var qualify whenever they have no write references, matching the safety property exactly.
  • When the binding is provably non-reassignable and its initializer is a bare namespace identifier, LocalExport[name].referenced is rewired to the namespace local. The re-export chain in bind_imports_and_exports then propagates downstream, enabling member-expression tree-shaking through res.

REPL repro that motivated this

// middle.js
import * as api from "./api";
export const res = api;

// main.js
import { res } from "./middle";
console.log(res.used);  // `unused` should be tree-shaken — wasn't, before this

Output before: full api_exports namespace object + both used and unused kept. Output after: collapses to console.log("used").

Test plan

  • named_const_export_namespace — basic case from the REPL link
  • named_const_export_namespace_member_writeres.obj.a = 2 resolves through to the underlying binding, matching default_export_namespace_member_write
  • named_let_export_namespacelet with no writes optimizes identically to const
  • named_let_export_namespace_reassignedlet res = api; res = {...} keeps the namespace and respects the post-reassignment value
  • All 1735 integration tests pass

@IWANABETHATGUY
IWANABETHATGUY marked this pull request as draft May 27, 2026 02:24
@IWANABETHATGUY
IWANABETHATGUY force-pushed the 05-27-feat_treeshake_ns_alias branch from 779eacf to 626e391 Compare May 27, 2026 02:25

Copy link
Copy Markdown
Member Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label graphite: merge-when-ready to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@IWANABETHATGUY
IWANABETHATGUY force-pushed the 05-27-feat_treeshake_ns_alias branch 2 times, most recently from 4ceff1a to 41d7aff Compare May 27, 2026 02:39
Extend the `export default <namespace>` re-export tree-shaking to named
variable exports of the form `export <kind> res = ns;` where `ns` is an
`import * as ns` local and `res` is non-reassigned. The reassignment
guard is driven by the existing `SymbolRefFlags::IsNotReassigned`, so
`let`/`var` qualify whenever they have no write references.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant