styled-components / babel-plugin-styled-components

Improve the debugging experience and add server-side rendering support to styled-components
MIT License
1.07k stars 139 forks source link

Invalid transform result when using css prop with object notation, and a local variable name matches a css keyword #409

Open dersuchmann opened 3 months ago

dersuchmann commented 3 months ago

This plugin gives an invalid transform result when using css={{...}} (i.e., css prop with object notation), and a local variable name matches a css keyword that is present in the object notation.

I use vite v5.0.12, @babel/core v7.24.6, and babel-plugin-styled-components v2.1.4.

Minimal example

This minimal example shows the bug:

import { css } from "styled-components";

const TestComponent1 = () => {
  let position = 1; // assume the variable is used for something else ...
  return <div css={{position: "absolute"}} />;
};

Here, the <div> is transformed to this invalid JavaScript:

var _StyledDiv = _styled("div").withConfig({ /* ... */ })(
  (p) => ({ p.$_css: "absolute" })
);

Correct behavior

These replacements must be restricted to the right side of : as in this example which works correctly:

const TestComponent2 = () => {
  let position = 1;
  return <div css={{gridArea: position + " / 1"}} />;
}

In this case, the div is correctly transformed to valid JavaScript:

var _StyledDiv2 = _styled2("div").withConfig({ /* ... */ })(
  (p) => ({ gridArea: p.$_css2 })
);

Full error message

5:22:47 AM [vite] Internal server error: Transform failed with 1 error:
/home/dersuchmann/test-project/client/src/features/userModel/AnotherNewUISettingScene.tsx:31:66: ERROR: Expected "}" but found "."
  Plugin: vite:esbuild
  File: /home/dersuchmann/test-project/client/src/features/userModel/AnotherNewUISettingScene.tsx:5:20

  Expected "}" but found "."
  29 |  $RefreshReg$(_c, "TestComponent1");
  30 |  $RefreshReg$(_c2, "TestComponent2");
  31 |  */_c2 = TestComponent2;var _StyledDiv = _styled("div")((p) => ({ p.$_css: "absolute" }));var _StyledDiv2 = _styled2("div").withConfig({ displayName: "AnotherNewUISettingScene___StyledDiv2", componentId: "sc-ij9pac-0" })((p) => ({ gridArea: p.$_css2 }));var _c, _c2;$RefreshReg$(_c, "TestComponent1");$RefreshReg$(_c2, "TestComponent2");
     |                                                                    ^
  32 |  if (import.meta.hot && !inWebWorker) {
  33 |    window.$RefreshReg$ = prevRefreshReg;

      at failureErrorWithLog (/home/dersuchmann/test-project/node_modules/esbuild/lib/main.js:1651:15)
      at /home/dersuchmann/test-project/node_modules/esbuild/lib/main.js:849:29
      at responseCallbacks.<computed> (/home/dersuchmann/test-project/distrec/distrec/node_modules/esbuild/lib/main.js:704:9)
      at handleIncomingPacket (/home/dersuchmann/test-project/node_modules/esbuild/lib/main.js:764:9)
      at Socket.readFromStdout (/home/dersuchmann/test-project/node_modules/esbuild/lib/main.js:680:7)
      at Socket.emit (node:events:518:28)
      at addChunk (node:internal/streams/readable:559:12)
      at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)
      at Readable.push (node:internal/streams/readable:390:5)
      at Pipe.onStreamRead (node:internal/stream_base_commons:190:23)