From fc56e80040d00d592e9917c2900058cad5746e24 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 afa5cba4..f0cabd51 100644 --- a/src/babel/helpers.ts +++ b/src/babel/helpers.ts @@ -12,7 +12,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, ); }