stylex icon indicating copy to clipboard operation
stylex copied to clipboard

`stylex.create` function-based styles throw "Unsupported expression: FunctionDeclaration" when nested in a namespace or component

Open zaydek opened this issue 3 months ago • 1 comments

Describe the issue

I found a bug with stylex.create calls when nested inside components. I'm using "@stylexjs/postcss-plugin": "^0.15.4",. This is the simplest repro I can think of to demostrate the issue:

Code:

import * as stylex from "@stylexjs/stylex";

export function Repro(): React.ReactNode {
  const styles = stylex.create({
    center: {
      alignItems: "center",
      display: "flex",
      height: "100vh",
      justifyContent: "center",
    },
    foo: (bar: string) => ({
    // ^ This is the issue, specifically the function signature
      backgroundColor: bar,
      height: "100px",
      width: "100px",
    }),
  });

  return (
    <div {...stylex.props(styles.center)}>
      <div {...stylex.props(styles.foo("red"))}>Mew</div>
    </div>
  );
}

Error:

[plugin:vite:css] [postcss] /Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/app/idea/v3/editors/components/mew.tsx: Unsupported expression: FunctionDeclaration


  1 | import * as stylex from "@stylexjs/stylex";
  2 |
> 3 | export function Repro(): React.ReactNode {
    |        ^
  4 |   const styles = stylex.create({
  5 |     center: {
  6 |       alignItems: "center",
    at File.buildError [as buildCodeFrameError] (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/core/src/transformation/file/file.ts:257:12)
    at NodePath.buildCodeFrameError (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/index.ts:157:21)
    at transformStyleXCreate (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@stylexjs/babel-plugin/lib/index.js:7311:29)
    at PluginPass.call (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@stylexjs/babel-plugin/lib/index.js:8706:9)
    at call (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/visitors.ts:303:14)
    at NodePath.call [as _call] (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:36:20)
    at NodePath.call (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:21:18)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:97:31)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitSingle (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:109:19)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:180:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitMultiple (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:99:17)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:178:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitMultiple (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:99:17)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:178:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitSingle (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:109:19)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:180:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitMultiple (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:99:17)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:178:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitSingle (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:109:19)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:180:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitSingle (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:109:19)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:180:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitMultiple (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:99:17)
    at TraversalContext.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:178:19)
    at traverseNode (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/traverse-node.ts:208:17)
    at NodePath.visit (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/path/context.ts:104:33)
    at TraversalContext.visitQueue (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:148:16)
    at TraversalContext.visitSingle (/Users/zaydek/Code/2025/aug-1-make-it-count/frontend/react-router/node_modules/@babel/traverse/src/context.ts:109:19
Click outside, press Esc key, or fix the code to dismiss.
You can also disable this overlay by setting server.hmr.overlay to false in vite.config.ts.

If a fix is worked on, please check that it still works inside of namespaces too, please. 🙏

Code:

import * as stylex from "@stylexjs/stylex";

namespace Repro {
  export function Repro(): React.ReactNode {
    const styles = stylex.create({
      ...
    });

    return (
      ...
    );
  }
}

Thank you! Being able to nest stylex.create calls has been a big help for me.

Expected behavior

Invoking stylex.create with function calls from inside of functions and or namespaces should work the same as if it were invoked globally.

Steps to reproduce

See OP.

Test case

No response

Additional comments

No response

zaydek avatar Sep 19 '25 18:09 zaydek

cc: @nmn looks like a hoisting issue?

mellyeliu avatar Sep 19 '25 20:09 mellyeliu