Repository navigation
[iOS] Modal supportedOrientations can allow orientations it doesn't list (codegen mask props are parsed into an uninitialized value) #59561
Description
Description
On the New Architecture, a <Modal> can allow orientations that its supportedOrientations prop doesn't list. In our app, modals with supportedOrientations={['landscape-left', 'landscape-right']} came out allowing portrait as well, and turned portrait when the iPad was held upright.
The prop is parsed into an uninitialized value:
convertRawPropdeclaresT result;and hands it tofromRawValue(propsConversions.h#L191).- For
supportedOrientations,Tis the generatedModalHostViewSupportedOrientationsMaskWrapped, whose only member has no initializer (GeneratePropsH.js#L274-L276). SoT result;leavesresult.valueindeterminate. - The generated
fromRawValueORs each listed orientation into it withwrapped.value |= …(GeneratePropsH.js#L366), so any bits already in that memory stay in the mask. RCTModalHostViewComponentViewallows every orientation whose bit is set (RCTModalHostViewComponentView.mm#L23-L45, applied at #L290).
Whether a build shows it depends on what is on the stack at that point. In our Release build it was consistent: landscape-only modals also allowed portrait. Apps whose Info.plist lists only landscape won't notice, because that caps every modal. It appeared for us once we listed all four orientations so that one particular modal could rotate.
Any codegen array-of-enum (mask) prop goes through the same struct and convertRawProp, so library components with such props are affected too. The std::optional<T> overload of fromRawValue has the same pattern (T resultValue;, propsConversions.h#L118).
Either change would fix it:
- value-initialize in
convertRawProp(and the optional overload):T result{}; - give the generated member an initializer:
${enumMask} value{};
We've worked around it in our app by capping orientations in application:supportedInterfaceOrientationsForWindow:.
Steps to reproduce
-
On iOS with the New Architecture, list all four orientations under
UISupportedInterfaceOrientationsin Info.plist. -
Render a landscape-only modal:
<Modal visible supportedOrientations={['landscape-left', 'landscape-right']}> <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}> <Text>Landscape only</Text> </View> </Modal>
-
Run on an iPad and hold it upright while the modal is shown. We used a Release build on the iPad mini (A17 Pro) simulator, iPadOS 26.5.
-
Expected: the modal stays landscape. Actual: UIKit is given portrait as a supported orientation, and the modal turns portrait (log below).
Because the starting value is uninitialized, another project or build may happen to start from zero and not show it. Logging newProps.supportedOrientations in RCTModalHostViewComponentView's updateProps: shows the parsed mask directly.
React Native Version
0.87.1. The same code is in 0.88.1 and on main (eaf4c26).
Affected Platforms
Runtime - iOS
Areas
Fabric - The New Renderer, Codegen
Output of npx @react-native-community/cli info
System:
OS: macOS 26.5.1
CPU: (14) arm64 Apple M4 Pro
Memory: 654.38 MB / 24.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 24.16.0
path: ~/.local/share/mise/installs/node/24.16.0/bin/node
Yarn:
version: 1.22.22
path: ~/.local/share/mise/installs/yarn/1/bin/yarn
npm:
version: 11.13.0
path: ~/.local/share/mise/installs/node/24.16.0/bin/npm
Watchman:
version: 2026.05.18.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.17.0
path: ~/.local/share/mise/installs/ruby/3.4.10/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 25.5
- iOS 26.5
- macOS 26.5
- tvOS 26.5
- visionOS 26.5
- watchOS 26.5
Android SDK: Not Found
IDEs:
Android Studio: Not Found
Xcode:
version: 26.6/17F113
path: /usr/bin/xcodebuild
Languages:
Java: Not Found
Ruby:
version: 3.4.10
path: ~/.local/share/mise/installs/ruby/3.4.10/bin/ruby
npmPackages:
"@react-native-community/cli":
installed: 20.2.0
wanted: ^20.2.0
react:
installed: 19.2.3
wanted: 19.2.3
react-native:
installed: 0.87.1
wanted: ^0.87.1
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: Not found
newArchEnabled: Not found
iOS:
hermesEnabled: true
newArchEnabled: true
Stacktrace or Logs
UIKit's orientation log on the simulator, filtered from `log stream`, while a modal with
supportedOrientations={['landscape-left', 'landscape-right']} was presented and the iPad
was held upright. UIKit writes portrait as Pu and landscape left and right as Ll and Lr.
17:07:50.968 Scene updated orientation preferences: ( Lr ) -> ( Pu Ll Lr )
17:07:57.570 Did set interfaceOrientation[1]
interfaceOrientation 1 is UIInterfaceOrientationPortrait.
MANDATORY Reproducer
No standalone reproducer yet. The starting value is uninitialized, so whether a fresh project shows extra orientations depends on what happens to be on the stack. The defect can be read from the lines linked above.
Screenshots and Videos
None.
Activity
react-native-bot commentedon Oct 27, 2026
Warning
Missing reproducer: We could not detect a reproducible example in your issue report. Reproducers are mandatory and we can accept only one of those as a valid reproducer:
You can read more about about it on our website: How to report a bug.