Skip to content

[babel-plugin] Don't hoist $$css objects that reference local variables#1739

Open
henryqdineen wants to merge 1 commit into
facebook:mainfrom
henryqdineen:hqd-fix-css-object-hoisting-scope
Open

[babel-plugin] Don't hoist $$css objects that reference local variables#1739
henryqdineen wants to merge 1 commit into
facebook:mainfrom
henryqdineen:hqd-fix-css-object-hoisting-scope

Conversation

@henryqdineen

Copy link
Copy Markdown
Collaborator

What changed / motivation ?

We ran into this after upgrading to 0.19.0. The $$css object hoisting added in #1406 (for @stylexjs/atoms) unconditionally hoists any inline object with $$css: true to module scope, even when its property values reference function-scoped variables.

For example, this (admittedly unsupported) pattern:

function Foo({className}) {
  return <div {...stylex.props(styles.root, className && {$$css: true, __: className})}>Hello</div>;
}

Gets compiled to:

const _temp = { $$css: true, __: className }; // className is not in scope here
function Foo({className}) {
  return <div {...stylex.props(styles.root, className && _temp)}>Hello</div>;
}

We acknowledge that using $$css directly like this is unsupported — we're actively working around it and moving away from the pattern. But since it was working before 0.19.0, we thought it would be worth patching in case anyone else hits it.

This adds a canHoistObject check that verifies all identifiers referenced in the object are available at program scope before hoisting.

It might also be worth considering a different approach where the hoisting only targets objects known to come from atoms compilation, rather than pattern-matching on $$css: true in the general stylex.props bailout path. That way this class of issue couldn't arise at all.

Please feel free to close this if you don't think it's worth fixing — it's a pretty major edge case.

Additional Context

Regression test added.

Pre-flight checklist

  • I have read the contributing guidelines
  • Performed a self-review of my code

The $$css object hoisting added for @stylexjs/atoms unconditionally
hoists any inline object with $$css: true to module scope, even when
property values reference function-scoped variables. This adds a scope
check before hoisting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@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 Jun 25, 2026
@vercel

vercel Bot commented Jun 25, 2026

Copy link
Copy Markdown

@henryqdineen is attempting to deploy a commit to the Meta Open Source Team on Vercel.

A member of the Team first needs to authorize it.

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