Skip to content

fix(styled-components): keep locals in nested css prop member chains - #660

Open
Mitch Follett (mitch-282) wants to merge 2 commits into
swc-project:mainfrom
mitch-282:fix/styled-components-css-prop-nested-member
Open

Mitch Follett (mitch-282) wants to merge 2 commits into
swc-project:mainfrom
mitch-282:fix/styled-components-css-prop-nested-member

Conversation

@mitch-282

@mitch-282 Mitch Follett (mitch-282) commented Sep 25, 2026 •

Copy link
Copy Markdown

Summary

Fixes #659.

A css prop interpolation whose member chain has a local in a computed key past the first step, such as ${SIZES[size].bottom}, was hoisted into the generated styled component. size is out of scope there, so the module threw ReferenceError on load.

is_direct_access found the root (SIZES, top-level) and then checked only the outermost node for a computed key. In SIZES[size].bottom that node is .bottom, so [size] was never looked at. The new has_only_direct_keys walks the whole member/call chain and requires every computed key and call argument to be a direct access itself. Chains that were already classified correctly are unaffected.

Tests

New fixture transpile-css-prop-nested-member:

  • ${SIZES[size].bottom} and ${SIZES.get(size).bottom} now pass through as $_css props.
  • ${SIZES[KEY].bottom} with a module-level KEY is still hoisted.

All 38 styled-components fixture tests pass, and no existing fixture output changed.

Not addressed here: a hoisted styled component is emitted above the module-level consts it reads (_StyledBox3 above SIZES in the fixture output). Its template is evaluated at module load, so that throws a TDZ ReferenceError whenever the const is declared after the imports. That's existing behaviour for any hoisted access, and probably wants its own issue.

is_direct_access treated an interpolation as module-level when the chain's
root was top-level and the outermost node had no local computed key. In
`${SIZES[size].bottom}` the outermost node is `.bottom`, so the inner
`[size]` was never checked and the expression was hoisted out of the
component, where `size` is undefined.

has_only_direct_keys now checks every computed key and call argument along
the member/call chain.

Fixes swc-project#659

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@changeset-bot

changeset-bot Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4ab1d16

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@swc/plugin-styled-components Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

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

None yet

Development

Successfully merging this pull request may close these issues.

styled-components: css prop hoists ${OBJ[local].prop} out of its closure (ReferenceError)

2 participants