Add explicit compatibility for platform specific files under "exports" (#50426)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50426

Prepares [platform-specific extensions](https://reactnative.dev/docs/platform-specific-code) compatibility for subpath imports ahead of D72228547 (`"exports"` field reattempt).

Changelog: [Internal]

Reviewed By: robhogan

Differential Revision: D72235790

fbshipit-source-id: 8e76999c632460fdc4795d56e19db75f327ea126
This commit is contained in:
Alex Hunt
2025-04-03 09:22:50 -07:00
committed by Facebook GitHub Bot
parent 403d609d83
commit 1bb929baed
17 changed files with 368 additions and 92 deletions
@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
import RCTAlertManager from './RCTAlertManager';
export default RCTAlertManager;
@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
import legacySendAccessibilityEvent from './legacySendAccessibilityEvent';
export default legacySendAccessibilityEvent;
@@ -13,8 +13,6 @@ import type {
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
} from '../../../src/private/types/HostInstance';
import type {AccessibilityRole} from '../../Components/View/ViewAccessibility';
import typeof DrawerLayoutAndroidCommon from './DrawerLayoutAndroid.js';
import type {
DrawerLayoutAndroidMethods,
DrawerLayoutAndroidProps,
@@ -305,4 +303,4 @@ const styles = StyleSheet.create({
},
});
export default DrawerLayoutAndroid as $FlowFixMe as DrawerLayoutAndroidCommon;
export default DrawerLayoutAndroid as $FlowFixMe;
@@ -0,0 +1,15 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
'use strict';
import DrawerLayoutAndroidFallback from './DrawerLayoutAndroidFallback';
export default DrawerLayoutAndroidFallback;
@@ -5,73 +5,13 @@
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
* @flow
*/
'use strict';
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
// import typeof DrawerLayoutAndroid from './DrawerLayoutAndroid.android';
import type {
MeasureInWindowOnSuccessCallback,
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
} from '../../../src/private/types/HostInstance';
import type {
DrawerLayoutAndroidMethods,
DrawerLayoutAndroidProps,
DrawerLayoutAndroidState,
} from './DrawerLayoutAndroidTypes';
import DrawerLayoutAndroid from './DrawerLayoutAndroid';
import UnimplementedView from '../UnimplementedViews/UnimplementedView';
import * as React from 'react';
export type {
DrawerLayoutAndroidProps,
DrawerSlideEvent,
} from './DrawerLayoutAndroidTypes';
export default class DrawerLayoutAndroid
extends React.Component<DrawerLayoutAndroidProps, DrawerLayoutAndroidState>
implements DrawerLayoutAndroidMethods
{
render(): React.Node {
return <UnimplementedView {...this.props} />;
}
openDrawer(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
closeDrawer(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
blur(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
focus(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
measure(callback: MeasureOnSuccessCallback): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
measureLayout(
relativeToNativeNode: number,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void,
): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
// $FlowFixMe[unclear-type]
setNativeProps(nativeProps: Object): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
}
export default DrawerLayoutAndroid;
@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
import DrawerLayoutAndroid from './DrawerLayoutAndroidFallback';
export type {
DrawerLayoutAndroidProps,
DrawerSlideEvent,
} from './DrawerLayoutAndroidTypes';
export default DrawerLayoutAndroid;
@@ -0,0 +1,71 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/
'use strict';
import type {
MeasureInWindowOnSuccessCallback,
MeasureLayoutOnSuccessCallback,
MeasureOnSuccessCallback,
} from '../../../src/private/types/HostInstance';
import type {
DrawerLayoutAndroidMethods,
DrawerLayoutAndroidProps,
DrawerLayoutAndroidState,
} from './DrawerLayoutAndroidTypes';
import UnimplementedView from '../UnimplementedViews/UnimplementedView';
import * as React from 'react';
export default class DrawerLayoutAndroid
extends React.Component<DrawerLayoutAndroidProps, DrawerLayoutAndroidState>
implements DrawerLayoutAndroidMethods
{
render(): React.Node {
return <UnimplementedView {...this.props} />;
}
openDrawer(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
closeDrawer(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
blur(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
focus(): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
measure(callback: MeasureOnSuccessCallback): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
measureInWindow(callback: MeasureInWindowOnSuccessCallback): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
measureLayout(
relativeToNativeNode: number,
onSuccess: MeasureLayoutOnSuccessCallback,
onFail?: () => void,
): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
// $FlowFixMe[unclear-type]
setNativeProps(nativeProps: Object): void {
throw new Error('DrawerLayoutAndroid is only available on Android');
}
}
@@ -13,12 +13,22 @@
import typeof ProgressBarAndroidNativeComponentType from './ProgressBarAndroidNativeComponent';
import type {ProgressBarAndroidProps} from './ProgressBarAndroidTypes';
import Platform from '../../Utilities/Platform';
export type {ProgressBarAndroidProps};
export default require('../UnimplementedViews/UnimplementedView')
.default as $FlowFixMe as component(
let ProgressBarAndroid: component(
ref?: React.RefSetter<
React.ElementRef<ProgressBarAndroidNativeComponentType>,
>,
...props: ProgressBarAndroidProps
);
if (Platform.OS === 'android') {
ProgressBarAndroid = require('./ProgressBarAndroid').default;
} else {
ProgressBarAndroid = require('../UnimplementedViews/UnimplementedView')
.default as $FlowFixMe;
}
export default ProgressBarAndroid;
+17
View File
@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
import Image from './Image';
export default Image;
@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
import BaseViewConfig from './BaseViewConfig';
export default BaseViewConfig;
@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
import RCTNetworking from './RCTNetworking';
export default RCTNetworking;
+13 -19
View File
@@ -8,26 +8,20 @@
* @flow
*/
'use strict';
import Platform from '../Utilities/Platform';
const Settings = {
get(key: string): any {
console.warn('Settings is not yet supported on this platform.');
return null;
},
set(settings: Object) {
console.warn('Settings is not yet supported on this platform.');
},
watchKeys(keys: string | Array<string>, callback: () => void): number {
console.warn('Settings is not yet supported on this platform.');
return -1;
},
clearWatch(watchId: number) {
console.warn('Settings is not yet supported on this platform.');
},
let Settings: {
get(key: string): any,
set(settings: Object): void,
watchKeys(keys: string | Array<string>, callback: () => void): number,
clearWatch(watchId: number): void,
...
};
if (Platform.OS === 'ios') {
Settings = require('./Settings').default;
} else {
Settings = require('./SettingsFallback').default;
}
export default Settings;
@@ -0,0 +1,33 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow
*/
'use strict';
const Settings = {
get(key: string): any {
console.warn('Settings is not yet supported on this platform.');
return null;
},
set(settings: Object) {
console.warn('Settings is not yet supported on this platform.');
},
watchKeys(keys: string | Array<string>, callback: () => void): number {
console.warn('Settings is not yet supported on this platform.');
return -1;
},
clearWatch(watchId: number) {
console.warn('Settings is not yet supported on this platform.');
},
};
export default Settings;
@@ -0,0 +1,15 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
export * from './PlatformColorValueTypes';
@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
import BackHandler from './BackHandler';
export default BackHandler;
+17
View File
@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict
*/
// NOTE: This file supports backwards compatibility of subpath (deep) imports
// from 'react-native' with platform-specific extensions. It can be deleted
// once we remove the "./*" mapping from package.json "exports".
import Platform from './Platform';
export default Platform;
@@ -101,6 +101,11 @@ declare export default typeof NativeAlertManager;
"
`;
exports[`public API should not change unintentionally Libraries/Alert/RCTAlertManager.js 1`] = `
"declare export default typeof RCTAlertManager;
"
`;
exports[`public API should not change unintentionally Libraries/Alert/RCTAlertManager.js.flow 1`] = `
"declare export default {
alertWithArgs(
@@ -1476,6 +1481,11 @@ declare export default typeof NativeAccessibilityManager;
"
`;
exports[`public API should not change unintentionally Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.js 1`] = `
"declare export default typeof legacySendAccessibilityEvent;
"
`;
exports[`public API should not change unintentionally Libraries/Components/AccessibilityInfo/legacySendAccessibilityEvent.js.flow 1`] = `
"declare function legacySendAccessibilityEvent(
reactTag: number,
@@ -1573,11 +1583,21 @@ declare export default typeof AndroidDrawerLayoutNativeComponent;
`;
exports[`public API should not change unintentionally Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js 1`] = `
"declare export default typeof DrawerLayoutAndroid;
"
`;
exports[`public API should not change unintentionally Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.js.flow 1`] = `
"export type {
DrawerLayoutAndroidProps,
DrawerSlideEvent,
} from \\"./DrawerLayoutAndroidTypes\\";
declare export default class DrawerLayoutAndroid
declare export default typeof DrawerLayoutAndroid;
"
`;
exports[`public API should not change unintentionally Libraries/Components/DrawerAndroid/DrawerLayoutAndroidFallback.js 1`] = `
"declare export default class DrawerLayoutAndroid
extends React.Component<DrawerLayoutAndroidProps, DrawerLayoutAndroidState>
implements DrawerLayoutAndroidMethods
{
@@ -1820,12 +1840,13 @@ declare export default function useAndroidRippleForView(
exports[`public API should not change unintentionally Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.js 1`] = `
"export type { ProgressBarAndroidProps };
declare export default component(
declare let ProgressBarAndroid: component(
ref?: React.RefSetter<
React.ElementRef<ProgressBarAndroidNativeComponentType>,
>,
...props: ProgressBarAndroidProps
);
declare export default typeof ProgressBarAndroid;
"
`;
@@ -4304,6 +4325,11 @@ declare export function getUrlCacheBreaker(): string;
"
`;
exports[`public API should not change unintentionally Libraries/Image/Image.js 1`] = `
"declare export default typeof Image;
"
`;
exports[`public API should not change unintentionally Libraries/Image/Image.js.flow 1`] = `
"export type {
ImageProgressEventIOS,
@@ -5749,6 +5775,11 @@ declare export default typeof RCTModalHostViewNativeComponent;
"
`;
exports[`public API should not change unintentionally Libraries/NativeComponent/BaseViewConfig.js 1`] = `
"declare export default typeof BaseViewConfig;
"
`;
exports[`public API should not change unintentionally Libraries/NativeComponent/BaseViewConfig.js.flow 1`] = `
"declare const PlatformBaseViewConfig: PartialViewConfigWithoutName;
declare export default typeof PlatformBaseViewConfig;
@@ -5923,6 +5954,11 @@ declare export default typeof NativeNetworkingIOS;
"
`;
exports[`public API should not change unintentionally Libraries/Network/RCTNetworking.js 1`] = `
"declare export default typeof RCTNetworking;
"
`;
exports[`public API should not change unintentionally Libraries/Network/RCTNetworking.js.flow 1`] = `
"declare const RCTNetworking: interface {
addListener<K: $Keys<RCTNetworkingEventDefinitions>>(
@@ -6997,6 +7033,18 @@ declare export default typeof NativeSettingsManager;
`;
exports[`public API should not change unintentionally Libraries/Settings/Settings.js 1`] = `
"declare let Settings: {
get(key: string): any,
set(settings: Object): void,
watchKeys(keys: string | Array<string>, callback: () => void): number,
clearWatch(watchId: number): void,
...
};
declare export default typeof Settings;
"
`;
exports[`public API should not change unintentionally Libraries/Settings/SettingsFallback.js 1`] = `
"declare const Settings: {
get(key: string): any,
set(settings: Object): void,
@@ -7054,6 +7102,11 @@ export type EdgeInsetsOrSizeProp = RectOrSize;
"
`;
exports[`public API should not change unintentionally Libraries/StyleSheet/PlatformColorValueTypes.js 1`] = `
"export * from \\"./PlatformColorValueTypes\\";
"
`;
exports[`public API should not change unintentionally Libraries/StyleSheet/PlatformColorValueTypes.js.flow 1`] = `
"declare export function PlatformColor(...names: Array<string>): ColorValue;
declare export function normalizeColorObject(
@@ -8227,6 +8280,11 @@ declare export function addChangeListener(
"
`;
exports[`public API should not change unintentionally Libraries/Utilities/BackHandler.js 1`] = `
"declare export default typeof BackHandler;
"
`;
exports[`public API should not change unintentionally Libraries/Utilities/BackHandler.js.flow 1`] = `
"export type BackPressEventName = \\"backPress\\" | \\"hardwareBackPress\\";
type TBackHandler = {
@@ -8416,6 +8474,11 @@ declare export default typeof PixelRatio;
"
`;
exports[`public API should not change unintentionally Libraries/Utilities/Platform.js 1`] = `
"declare export default typeof Platform;
"
`;
exports[`public API should not change unintentionally Libraries/Utilities/Platform.js.flow 1`] = `
"declare export default Platform;
"