Skip to content

[eslint-plugin] Catch export specifiers, export *, and aliased exports in enforce-extension - #1998

Open
henryqdineen wants to merge 1 commit into
meta:mainfrom
henryqdineen:hqd-eslint-enforce-extension-export-specifiers
Open

henryqdineen wants to merge 1 commit into
meta:mainfrom
henryqdineen:hqd-eslint-enforce-extension-export-specifiers

Conversation

@henryqdineen

Copy link
Copy Markdown
Collaborator

What changed / motivation ?

We caused a bug while renaming a .stylex.ts export: we kept the old name as an alias (export const theme = themeNested) to support an automated migration of consumers, and forgot that StyleX can't support that. Importing files hash the file name plus the imported name, so everything importing theme compiled to var(--…) references that nothing defines.

enforce-extension would have caught it, except we were still on 0.19.0 and had the rule suppressed in that file waiting for #1743 🤦

Looking into it, we found the rule skips every export without a declaration, so export { themeNested as theme }, export { x } from, and export * aren't checked on any version. When the rule was added in #704, the review stated the goal as "no other exports" but only named ExportNamedDeclaration and ExportDefaultDeclaration, and the implementation only looked at declarations.

This PR checks those forms, and gives aliases of define* results their own error explaining why they break, even with legacyAllowMixedExports.

Linked PR/Issues

Follows up on #1743.

Additional Context

Tests cover each export form, aliases of vars/consts/markers, and type-only exports staying valid.

Open question: the workaround is defining the tokens twice, but class names are hashed from the pre-substitution var(--…) reference, so identical declarations get separate atomic classes (.x14xsx6j{color:red} and .xtml34x{color:red}) for as long as both names are in use. Would first-class support for aliasing be worth considering for renames like this?

Pre-flight checklist

🤖 Generated with Claude Code

…s in enforce-extension

enforce-extension only looked at exports with a declaration, so `export { helper }`, `export { helper } from './helper'`, and `export * from './helpers'` in a `.stylex` file were never reported as mixed exports. The skip dates back to the rule's first version (meta#704).

Aliases need their own error. StyleX hashes variable names from the export name, and importing files never read the `.stylex` file, so importing an alias compiles to `var(--...)` references that nothing defines. The generic "must not export anything else" message doesn't explain that, and `legacyAllowMixedExports` would hide it, so an alias of a `define*` result is now always reported with a message saying why it breaks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 27, 2026
@vercel

vercel Bot commented Oct 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
stylex Ignored Ignored Oct 27, 2026 8:40pm UTC

Request Review

@henryqdineen
henryqdineen marked this pull request as ready for review October 27, 2026 20:42

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

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant