From c85c5b5ee6c031d78dee314f6a47de8ab037a9d0 Mon Sep 17 00:00:00 2001 From: Oskar Eichler Date: Mon, 31 Aug 2026 02:48:30 +0300 Subject: [PATCH 1/2] Preserve nested Platform write targets --- .../__tests__/inline-platform-plugin-test.js | 18 ++++++++++ .../src/inline-platform-plugin.js | 34 ++++++++++++++----- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js b/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js index 92bb4aac073..8632b1a7141 100644 --- a/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js +++ b/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js @@ -308,6 +308,24 @@ describe('unsafe positions', () => { expect(output).toContain('delete Platform.OS'); }); + test('does not replace a target nested in an assignment pattern', () => { + expectUnchanged(` + import {Platform} from 'react-native'; + [Platform.OS] = values; + ({os: Platform.OS} = value); + `); + }); + + test('does not replace for-in or for-of assignment targets', () => { + expectUnchanged(` + import {Platform} from 'react-native'; + for (Platform.OS in object) {} + for ([Platform.OS] in nestedObject) {} + for (Platform.OS of values) {} + for ([Platform.OS] of nestedValues) {} + `); + }); + test('does not inline computed access', () => { const output = transform(` import {Platform} from 'react-native'; diff --git a/packages/react-native-babel-preset/src/inline-platform-plugin.js b/packages/react-native-babel-preset/src/inline-platform-plugin.js index c818ff3331d..dae21540364 100644 --- a/packages/react-native-babel-preset/src/inline-platform-plugin.js +++ b/packages/react-native-babel-preset/src/inline-platform-plugin.js @@ -395,15 +395,31 @@ module.exports = function inlinePlatformPlugin( function isWriteTarget( path /*: NodePath */, ) /*: boolean */ { - const {parent, node} = path; - if (parent.type === 'AssignmentExpression' && parent.left === node) { - return true; - } - if (parent.type === 'UpdateExpression' && parent.argument === node) { - return true; - } - if (parent.type === 'UnaryExpression' && parent.operator === 'delete') { - return true; + let child /*: Node */ = path.node; + let parentPath = path.parentPath; + + while (parentPath != null) { + const parent = parentPath.node; + if ( + (parent.type === 'AssignmentExpression' || + parent.type === 'ForInStatement' || + parent.type === 'ForOfStatement') && + parent.left === child + ) { + return true; + } + if (parent.type === 'UpdateExpression' && parent.argument === child) { + return true; + } + if ( + parent.type === 'UnaryExpression' && + parent.operator === 'delete' && + parent.argument === child + ) { + return true; + } + child = parent; + parentPath = parentPath.parentPath; } return false; } From a7af44d27d4c0a693aa891d40e8feda717f13395 Mon Sep 17 00:00:00 2001 From: Oskar Eichler Date: Mon, 31 Aug 2026 17:01:16 +0700 Subject: [PATCH 2/2] Keep reads inside write targets inlineable --- .../src/__tests__/inline-platform-plugin-test.js | 12 ++++++++++++ .../src/inline-platform-plugin.js | 11 +++++++++++ 2 files changed, 23 insertions(+) diff --git a/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js b/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js index 8632b1a7141..c5d32add21c 100644 --- a/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js +++ b/packages/react-native-babel-preset/src/__tests__/inline-platform-plugin-test.js @@ -316,6 +316,18 @@ describe('unsafe positions', () => { `); }); + test('replaces reads nested inside an assignment target', () => { + const output = transform(` + import {Platform} from 'react-native'; + target[Platform.OS] = value; + [target[Platform.OS]] = values; + ({[Platform.OS]: target} = value); + `); + + expect(output).not.toContain('Platform.OS'); + expect(output.match(/"ios"/g)).toHaveLength(3); + }); + test('does not replace for-in or for-of assignment targets', () => { expectUnchanged(` import {Platform} from 'react-native'; diff --git a/packages/react-native-babel-preset/src/inline-platform-plugin.js b/packages/react-native-babel-preset/src/inline-platform-plugin.js index dae21540364..ecc198882ef 100644 --- a/packages/react-native-babel-preset/src/inline-platform-plugin.js +++ b/packages/react-native-babel-preset/src/inline-platform-plugin.js @@ -418,6 +418,17 @@ module.exports = function inlinePlatformPlugin( ) { return true; } + + const nestedWriteTarget = + parent.type === 'ArrayPattern' || + parent.type === 'ObjectPattern' || + (parent.type === 'ObjectProperty' && parent.value === child) || + (parent.type === 'RestElement' && parent.argument === child) || + (parent.type === 'AssignmentPattern' && parent.left === child); + if (!nestedWriteTarget) { + return false; + } + child = parent; parentPath = parentPath.parentPath; }