Skip to content

fix(emotion): merge target/label into non-object-literal styled() options - #648

Open
Pedro Nascimento (lunks) wants to merge 1 commit into
swc-project:mainfrom
lunks:fix/emotion-styled-identifier-options
Open

fix(emotion): merge target/label into non-object-literal styled() options#648
Pedro Nascimento (lunks) wants to merge 1 commit into
swc-project:mainfrom
lunks:fix/emotion-styled-identifier-options

Conversation

@lunks

Copy link
Copy Markdown

When styled(tag, options) gets an identifier or member expression as options, the transform appends target/label as an extra argument instead of merging:

// actual — @emotion/styled takes two arguments, the third is ignored
styled("div", opts, { target: "e18y1z280", label: "Card" })`color: red;`;

// expected (what @emotion/babel-plugin produces)
styled("div", { target: "e18y1z280", label: "Card", ...opts })`color: red;`;

The component silently loses its selector target, so ${Card} component selectors break at runtime.

#202 already fixed this for call expressions (#201); this completes it for the remaining non-literal shapes by giving the _ arm the same spread-wrap treatment, at both injection sites.

  • New fixture styled-non-literal-options — fails on main, passes with the fix.
  • issues/201 output byte-identical; full crate suite + wasm tests green; fmt/clippy clean.
  • Key ordering matches fix(emotion): Support dynamic options #202 and the babel plugin (user options win).
  • Changeset included.

styled('div', someIdentifier) and styled('div', config.opts) emitted the
generated options as a THIRD argument. @emotion/styled reads only two, so
the target was silently dropped and ${Component} selectors broke at
runtime with no build-time signal.

Non-object-literal options now spread into the injected options object,
the same treatment call expressions already received.
@changeset-bot

changeset-bot Bot commented Jul 31, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 05d8404

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-emotion 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

CLAassistant commented Jul 31, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 05d8404c3b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "Codex (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

props.extend(args_props);
}
Expr::Call(_) => {
_ => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve spread arguments when wrapping styled options

When the second argument is itself spread, such as styled("div", ...args)(styles), this arm replaces only its expression while retaining ExprOrSpread.spread. The emitted call becomes styled("div", ...{ target, label, ...args }), and attempting to spread that non-iterable object into the call throws at runtime. Check and handle the argument's spread marker before applying this wrapper; the mirrored tagged-template path has the same issue.

Useful? React with 👍 / 👎.

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.

2 participants