Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

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

Aperta
#659 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
72/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
react, rust, typescript

Direzione di ricerca

Run the supplied @swc/core transformSync reproduction on input.tsx, then inspect the css-prop transform's closure check for computed member expressions beyond the root object. Done means the generated styled component receives the expression through $_css, keeps size in Avatar's scope, and does not hoist it above SIZES; add a regression case alongside the existing ${SIZES[size]} handling.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

@swc/plugin-styled-components 14.0.0, @swc/core 1.16.2, cssProp: true.

When a css prop interpolates a member chain whose root is module-scoped but whose computed key is a local, the whole expression is hoisted into the generated styled component instead of being passed through as $_css. At runtime the local is out of scope, so the module throws ReferenceError: size is not defined on load.

Input

import styled from 'styled-components'

const Box = styled.div``
const SIZES = { small: { bottom: '8px' }, large: { bottom: '16px' } }

export const Avatar = ({ size }: { size: 'small' | 'large' }) => (
  <Box css={`bottom: ${SIZES[size].bottom};`} />
)

Output (trimmed)

var _StyledBox = styled(Box).withConfig({ /* … */ })([
    `bottom:`,
    `;`
], SIZES[size].bottom);   // `size` is not in scope here

export const Avatar = ({ size })=>_jsx(_StyledBox, {});

Expected

The same as babel-plugin-styled-components, and as this plugin already does for ${SIZES[size]} (no trailing property access):

var _StyledBox = styled(Box).withConfig({ /* … */ })([`bottom:`, `;`], (p)=>p.$_css);
export const Avatar = ({ size })=>_jsx(_StyledBox, { $_css: SIZES[size].bottom });

It looks like the closure check in the css-prop transform looks only at the root object of a member expression (SIZES, module scope) and misses identifiers in computed properties further along the chain. ${SIZES[size]} is handled correctly, so the fix for #194 appears to cover a computed member on the root but not deeper chains. Hoisting also places the styled component above const SIZES, which would hit the TDZ even for a fully static chain.

Repro

const { transformSync } = require('@swc/core')
console.log(transformSync(require('fs').readFileSync('input.tsx', 'utf8'), {
  filename: 'input.tsx',
  jsc: {
    parser: { syntax: 'typescript', tsx: true },
    target: 'es2022',
    transform: { react: { runtime: 'automatic' } },
    experimental: { plugins: [['@swc/plugin-styled-components', { cssProp: true }]] }
  }
}).code)

We hit this moving a large Vite app from @vitejs/plugin-react + babel-plugin-styled-components to @vitejs/plugin-react-swc; it's the pattern SIZE_MAP[size].linked.bottom in an avatar component that first broke.

Lingua principale
Rust
Stelle
389
Fork
107
Merge medio
10m
PR unite (30g)
1

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di swc-project/plugins

Tutte le issue di swc-project/plugins

Issue simili

Altre issue su Rust

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.