Skip to content

Commit

Permalink
Use function expression name if it has one (#446)
Browse files Browse the repository at this point in the history
Component's like
```js
var render = function App() { ... }
```
will now by transformed by the babel plugin since the function expression has a valid Component name.

Before it would not be transformed because the variable name was not valid because the variable name begins with a lowercase letter.
  • Loading branch information
andrewiggins committed Nov 23, 2023
1 parent 221c884 commit 09f3ed7
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-badgers-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@preact/signals-react-transform": minor
---

Use function expression name to determine if it is a Component and should be transformed.
6 changes: 5 additions & 1 deletion packages/react-transform/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ function getObjectPropertyKey(
* name), return that. Else return null.
*/
function getFunctionNodeName(path: NodePath<FunctionLike>): string | null {
if (path.node.type === "FunctionDeclaration" && path.node.id) {
if (
(path.node.type === "FunctionDeclaration" ||
path.node.type === "FunctionExpression") &&
path.node.id
) {
return path.node.id.name;
} else if (path.node.type === "ObjectMethod") {
return getObjectPropertyKey(path.node);
Expand Down
115 changes: 75 additions & 40 deletions packages/react-transform/test/node/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,15 @@ interface VariableCodeConfig extends CodeConfig {
const codeTitle = (...parts: Array<string | undefined>) =>
parts.filter(Boolean).join(" ");

function expressionComponents(config: CodeConfig): GeneratedCode[] {
function expressionComponents(
config: CodeConfig,
properInlineName?: boolean
): GeneratedCode[] {
const { name: baseName, params } = config;

let components: GeneratedCode[];
if (config.auto) {
return [
components = [
{
name: codeTitle(baseName, "as function without inline name"),
...generateCode({
Expand All @@ -303,15 +308,6 @@ function expressionComponents(config: CodeConfig): GeneratedCode[] {
params,
}),
},
{
name: codeTitle(baseName, "as function with proper inline name"),
...generateCode({
type: "FuncExpComp",
name: "App",
body: "return <div>{signal.value}</div>",
params,
}),
},
{
name: codeTitle(baseName, "as arrow function with statement body"),
...generateCode({
Expand All @@ -332,16 +328,7 @@ function expressionComponents(config: CodeConfig): GeneratedCode[] {
},
];
} else {
return [
{
name: codeTitle(baseName, "as function with bad inline name"),
...generateCode({
type: "FuncExpComp",
name: "app",
body: "return signal.value",
params,
}),
},
components = [
{
name: codeTitle(baseName, "as function with no JSX"),
...generateCode({
Expand Down Expand Up @@ -378,13 +365,46 @@ function expressionComponents(config: CodeConfig): GeneratedCode[] {
},
];
}

if (
(properInlineName != null && properInlineName === false) ||
config.auto === false
) {
components.push({
name: codeTitle(baseName, "as function with bad inline name"),
...generateCode({
type: "FuncExpComp",
name: "app",
body: "return <div>{signal.value}</div>",
params,
}),
});
} else {
components.push({
name: codeTitle(baseName, "as function with proper inline name"),
...generateCode({
type: "FuncExpComp",
name: "App",
body: "return <div>{signal.value}</div>",
params,
}),
});
}

return components;
}

function withCallExpWrappers(config: CodeConfig): GeneratedCode[] {
function withCallExpWrappers(
config: CodeConfig,
properInlineName?: boolean
): GeneratedCode[] {
const codeCases: GeneratedCode[] = [];

// Simulate a component wrapped memo
const memoedComponents = expressionComponents({ ...config, params: 1 });
const memoedComponents = expressionComponents(
{ ...config, params: 1 },
properInlineName
);
for (let component of memoedComponents) {
codeCases.push({
name: component.name + " wrapped in memo",
Expand All @@ -397,7 +417,10 @@ function withCallExpWrappers(config: CodeConfig): GeneratedCode[] {
}

// Simulate a component wrapped in forwardRef
const forwardRefComponents = expressionComponents({ ...config, params: 2 });
const forwardRefComponents = expressionComponents(
{ ...config, params: 2 },
properInlineName
);
for (let component of forwardRefComponents) {
codeCases.push({
name: component.name + " wrapped in forwardRef",
Expand Down Expand Up @@ -607,10 +630,13 @@ export function variableComp(config: VariableCodeConfig): GeneratedCode[] {
// With HoC wrappers, we are testing the logic to find the component name. So
// only generate tests where the function body is correct ("auto" is true) and
// the name is either correct or bad.
const hocComponents = withCallExpWrappers({
...config,
auto: true,
});
const hocComponents = withCallExpWrappers(
{
...config,
auto: true,
},
config.auto
);
const suffix = config.auto ? "" : "with bad variable name";
for (const c of hocComponents) {
codeCases.push({
Expand Down Expand Up @@ -677,10 +703,13 @@ export function assignmentComp(config: CodeConfig): GeneratedCode[] {
// With HoC wrappers, we are testing the logic to find the component name. So
// only generate tests where the function body is correct ("auto" is true) and
// the name is either correct or bad.
const hocComponents = withCallExpWrappers({
...config,
auto: true,
});
const hocComponents = withCallExpWrappers(
{
...config,
auto: true,
},
config.auto
);
const suffix = config.auto ? "" : "with bad variable name";
for (const c of hocComponents) {
codeCases.push({
Expand Down Expand Up @@ -794,10 +823,13 @@ export function objAssignComp(config: CodeConfig): GeneratedCode[] {
// With HoC wrappers, we are testing the logic to find the component name. So
// only generate tests where the function body is correct ("auto" is true) and
// the name is either correct or bad.
const hocComponents = withCallExpWrappers({
...config,
auto: true,
});
const hocComponents = withCallExpWrappers(
{
...config,
auto: true,
},
config.auto
);
const suffix = config.auto ? "" : "with bad variable name";
for (const c of hocComponents) {
codeCases.push({
Expand Down Expand Up @@ -863,10 +895,13 @@ export function objectPropertyComp(config: CodeConfig): GeneratedCode[] {
// With HoC wrappers, we are testing the logic to find the component name. So
// only generate tests where the function body is correct ("auto" is true) and
// the name is either correct or bad.
const hocComponents = withCallExpWrappers({
...config,
auto: true,
});
const hocComponents = withCallExpWrappers(
{
...config,
auto: true,
},
config.auto
);
const suffix = config.auto ? "" : "with bad property name";
for (const c of hocComponents) {
codeCases.push({
Expand Down

0 comments on commit 09f3ed7

Please sign in to comment.