From 7b7ed1633362245b98a4464a8eb95df148e92309 Mon Sep 17 00:00:00 2001 From: Yevhenii Date: Sun, 11 Oct 2026 19:48:33 +0300 Subject: [PATCH] fix(babel): leave code transformed without a filename unchanged Babel types PluginPass.filename as string | undefined and leaves it undefined when its caller passes none, so the own-sources guard read .startsWith off undefined and threw. Each visitor now narrows the filename once and rewrites nothing without one. processed.has(path) could never be true, since only the Statement nodes the plugin generates are added; the set is typed WeakSet and the disjunct is gone. --- src/__tests__/babel/no-filename.test.ts | 15 +++++++++++++ src/babel/helpers.ts | 2 +- src/babel/import-plugin.ts | 28 ++++++++++++++----------- 3 files changed, 32 insertions(+), 13 deletions(-) create mode 100644 src/__tests__/babel/no-filename.test.ts diff --git a/src/__tests__/babel/no-filename.test.ts b/src/__tests__/babel/no-filename.test.ts new file mode 100644 index 00000000..5f8776e3 --- /dev/null +++ b/src/__tests__/babel/no-filename.test.ts @@ -0,0 +1,15 @@ +import { transformSync } from "@babel/core"; + +import plugin from "../../babel/import-plugin"; + +test("a file transformed without a filename is left as written", () => { + const source = `import { View } from "react-native";`; + + const output = transformSync(source, { + configFile: false, + babelrc: false, + plugins: [plugin], + })?.code; + + expect(output).toBe(source); +}); diff --git a/src/babel/helpers.ts b/src/babel/helpers.ts index c66f630c..ae3f4089 100644 --- a/src/babel/helpers.ts +++ b/src/babel/helpers.ts @@ -10,7 +10,7 @@ export interface PluginOpts { export interface PluginState { opts?: PluginOpts; - filename: string; + filename: string | undefined; } export function getInteropRequireDefaultSource( diff --git a/src/babel/import-plugin.ts b/src/babel/import-plugin.ts index b199d8ca..4d018070 100644 --- a/src/babel/import-plugin.ts +++ b/src/babel/import-plugin.ts @@ -25,7 +25,7 @@ export default function ({ }: { types: BabelTypes; }): PluginObj { - const processed = new WeakSet(); + const processed = new WeakSet(); const packageRoot = resolve( __dirname, @@ -44,17 +44,19 @@ export default function ({ name: "Rewrite react-native to react-native-css", visitor: { ImportDeclaration(path, state): void { + const { filename } = state; + if ( - processed.has(path) || + filename === undefined || processed.has(path.node) || - isFromThisModule(state.filename) + isFromThisModule(filename) ) { return; } const statements = - handleReactNativeImport(path.node, t, state.filename) ?? - handleReactNativeWebImport(path.node, t, state.filename); + handleReactNativeImport(path.node, t, filename) ?? + handleReactNativeWebImport(path.node, t, filename); if (!statements) { return; @@ -67,10 +69,12 @@ export default function ({ path.replaceWithMultiple(statements); }, VariableDeclaration(path, state): void { + const { filename } = state; + if ( - processed.has(path) || + filename === undefined || processed.has(path.node) || - isFromThisModule(state.filename) + isFromThisModule(filename) ) { return; } @@ -124,14 +128,14 @@ export default function ({ t, id.name, initArg.value, - state.filename, + filename, ) ?? handleReactNativeWebIdentifierRequire( path, t, id.name, initArg.value, - state.filename, + filename, ); } else if ( t.isObjectPattern(id) && @@ -144,14 +148,14 @@ export default function ({ t, id, initArg.value, - state.filename, + filename, ) ?? handleReactNativeWebObjectPatternRequire( path, t, id, initArg.value, - state.filename, + filename, ); } else if ( t.isIdentifier(id) && @@ -168,7 +172,7 @@ export default function ({ id.name, init, source, - state.filename, + filename, ); }