Skip to content

Commit 3d0f647

Browse files
authored
Add fallback names to signal transforms (#960)
Assisted-By: devx/633e51ab-4160-4b2c-a196-017418800531
1 parent ee06f32 commit 3d0f647

5 files changed

Lines changed: 76 additions & 50 deletions

File tree

.changeset/calm-effects-debug.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@preact/signals-preact-transform": patch
3+
"@preact/signals-react-transform": patch
4+
---
5+
6+
Name effects and signal effects during debug transforms, and use their source location when no contextual name can be derived.

packages/preact-transform/src/index.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ function basename(filename: string | undefined): string | undefined {
1919
function isSignalCall(path: NodePath<BabelTypes.CallExpression>): boolean {
2020
const callee = path.get("callee");
2121

22-
// Check direct function calls like signal(), computed(), useSignal(), useComputed()
22+
// Check direct calls to APIs that accept debug names.
2323
if (callee.isIdentifier()) {
2424
const name = callee.node.name;
2525
return (
2626
name === "signal" ||
2727
name === "computed" ||
28+
name === "effect" ||
2829
name === "useSignal" ||
29-
name === "useComputed"
30+
name === "useComputed" ||
31+
name === "useSignalEffect"
3032
);
3133
}
3234

@@ -141,8 +143,24 @@ function getSignalNameFromContext(
141143
currentPath = currentPath.parentPath;
142144
}
143145

144-
const callee = path.get("callee");
145-
return callee.isIdentifier() ? callee.node.name : null;
146+
return null;
147+
}
148+
149+
function getSignalName(
150+
path: NodePath<BabelTypes.CallExpression>,
151+
filename: string | undefined
152+
): string | null {
153+
const contextName = getSignalNameFromContext(path);
154+
const baseName = basename(filename);
155+
const lineNumber = path.node.loc?.start.line;
156+
157+
if (baseName && lineNumber) {
158+
return contextName
159+
? `${contextName} (${baseName}:${lineNumber})`
160+
: `${baseName}:${lineNumber}`;
161+
}
162+
163+
return contextName;
146164
}
147165

148166
function shouldSkipNameInjection(
@@ -174,21 +192,9 @@ function shouldSkipNameInjection(
174192
function injectSignalName(
175193
t: typeof BabelTypes,
176194
path: NodePath<BabelTypes.CallExpression>,
177-
variableName: string,
178-
filename: string | undefined
195+
nameValue: string
179196
): void {
180197
const args = path.get("arguments");
181-
182-
// Create enhanced name with filename and line number
183-
let nameValue = variableName;
184-
if (filename) {
185-
const baseName = basename(filename);
186-
const lineNumber = path.node.loc?.start.line;
187-
if (baseName && lineNumber) {
188-
nameValue = `${variableName} (${baseName}:${lineNumber})`;
189-
}
190-
}
191-
192198
const name = t.stringLiteral(nameValue);
193199

194200
if (args.length === 0) {
@@ -229,10 +235,8 @@ export default function signalsTransform(
229235

230236
// Only inject name if it doesn't already have one
231237
if (!shouldSkipNameInjection(t, args)) {
232-
const signalName = getSignalNameFromContext(path);
233-
if (signalName) {
234-
injectSignalName(t, path, signalName, this.filename);
235-
}
238+
const signalName = getSignalName(path, this.filename);
239+
if (signalName) injectSignalName(t, path, signalName);
236240
}
237241
}
238242
},

packages/preact-transform/test/node/index.test.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,9 @@ describe("Preact Signals Babel Transform", () => {
175175
"const preserved = signal(0, options);",
176176
"const spread = signal(0, {...options});",
177177
"[first] = [signal(0)];",
178+
"effect(() => {});",
179+
"useSignalEffect(() => {});",
180+
'effect(() => {}, {name: "manual"});',
178181
].join("\n");
179182

180183
const output = transformCode(inputCode, DEBUG_OPTIONS, "Models.js");
@@ -189,17 +192,20 @@ describe("Preact Signals Babel Transform", () => {
189192
"label (Models.js:14)",
190193
"0 (Models.js:15)",
191194
"createVisible (Models.js:18)",
192-
"signal (Models.js:20)",
195+
"Models.js:20",
193196
"createSelected (Models.js:21)",
194-
"signal (Models.js:22)",
195-
"computed (Models.js:24)",
196-
"signal (Models.js:28)",
197+
"Models.js:22",
198+
"Models.js:24",
199+
"Models.js:28",
200+
"Models.js:29",
201+
"Models.js:30",
197202
]) {
198203
expect(output).toContain(`name: "${expectedName}"`);
199204
}
200205
expect(output).toContain("const preserved = signal(0, options);");
201206
expect(output).not.toContain("preserved (Models.js:26)");
202207
expect(output).not.toContain("spread (Models.js:27)");
208+
expect(output).toContain('name: "manual"');
203209
});
204210
});
205211
});

packages/react-transform/src/index.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -404,14 +404,16 @@ function isJSXAlternativeCall(
404404
function isSignalCall(path: NodePath<BabelTypes.CallExpression>): boolean {
405405
const callee = path.get("callee");
406406

407-
// Check direct function calls like signal(), computed(), useSignal(), useComputed()
407+
// Check direct calls to APIs that accept debug names.
408408
if (callee.isIdentifier()) {
409409
const name = callee.node.name;
410410
return (
411411
name === "signal" ||
412412
name === "computed" ||
413+
name === "effect" ||
413414
name === "useSignal" ||
414-
name === "useComputed"
415+
name === "useComputed" ||
416+
name === "useSignalEffect"
415417
);
416418
}
417419

@@ -526,8 +528,24 @@ function getSignalNameFromContext(
526528
currentPath = currentPath.parentPath;
527529
}
528530

529-
const callee = path.get("callee");
530-
return callee.isIdentifier() ? callee.node.name : null;
531+
return null;
532+
}
533+
534+
function getSignalName(
535+
path: NodePath<BabelTypes.CallExpression>,
536+
filename: string | undefined
537+
): string | null {
538+
const contextName = getSignalNameFromContext(path);
539+
const baseName = basename(filename);
540+
const lineNumber = path.node.loc?.start.line;
541+
542+
if (baseName && lineNumber) {
543+
return contextName
544+
? `${contextName} (${baseName}:${lineNumber})`
545+
: `${baseName}:${lineNumber}`;
546+
}
547+
548+
return contextName;
531549
}
532550

533551
function shouldSkipNameInjection(
@@ -559,21 +577,9 @@ function shouldSkipNameInjection(
559577
function injectSignalName(
560578
t: typeof BabelTypes,
561579
path: NodePath<BabelTypes.CallExpression>,
562-
variableName: string,
563-
filename: string | undefined
580+
nameValue: string
564581
): void {
565582
const args = path.get("arguments");
566-
567-
// Create enhanced name with filename and line number
568-
let nameValue = variableName;
569-
if (filename) {
570-
const baseName = basename(filename);
571-
const lineNumber = path.node.loc?.start.line;
572-
if (baseName && lineNumber) {
573-
nameValue = `${variableName} (${baseName}:${lineNumber})`;
574-
}
575-
}
576-
577583
const name = t.stringLiteral(nameValue);
578584

579585
if (args.length === 0) {
@@ -994,10 +1000,8 @@ export default function signalsTransform(
9941000

9951001
// Only inject name if it doesn't already have one
9961002
if (!shouldSkipNameInjection(t, args)) {
997-
const signalName = getSignalNameFromContext(path);
998-
if (signalName) {
999-
injectSignalName(t, path, signalName, this.filename);
1000-
}
1003+
const signalName = getSignalName(path, this.filename);
1004+
if (signalName) injectSignalName(t, path, signalName);
10011005
}
10021006
}
10031007
},

packages/react-transform/test/node/index.test.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,9 @@ describe("React Signals Babel Transform", () => {
10951095
"const preserved = signal(0, options);",
10961096
"const spread = signal(0, {...options});",
10971097
"[first] = [signal(0)];",
1098+
"effect(() => {});",
1099+
"useSignalEffect(() => {});",
1100+
'effect(() => {}, {name: "manual"});',
10981101
].join("\n");
10991102

11001103
const output = transformCode(inputCode, DEBUG_OPTIONS, "Models.js");
@@ -1109,17 +1112,20 @@ describe("React Signals Babel Transform", () => {
11091112
"label (Models.js:14)",
11101113
"0 (Models.js:15)",
11111114
"createVisible (Models.js:18)",
1112-
"signal (Models.js:20)",
1115+
"Models.js:20",
11131116
"createSelected (Models.js:21)",
1114-
"signal (Models.js:22)",
1115-
"computed (Models.js:24)",
1116-
"signal (Models.js:28)",
1117+
"Models.js:22",
1118+
"Models.js:24",
1119+
"Models.js:28",
1120+
"Models.js:29",
1121+
"Models.js:30",
11171122
]) {
11181123
expect(output).toContain(`name: "${expectedName}"`);
11191124
}
11201125
expect(output).toContain("const preserved = signal(0, options);");
11211126
expect(output).not.toContain("preserved (Models.js:26)");
11221127
expect(output).not.toContain("spread (Models.js:27)");
1128+
expect(output).toContain('name: "manual"');
11231129
});
11241130
});
11251131

0 commit comments

Comments
 (0)